2014-05-03 143 views
0

我正在創建視頻會議應用程序。我發現攝像頭(至少有3個)爲mJPEG輸出格式提供更高的分辨率和幀速率。到目前爲止,我使用YUY2,在I420中轉換爲X264進行壓縮。要將mJPEG轉碼爲I420,我需要先解碼它。我正在嘗試使用libavcodec從網絡攝像頭解碼圖像。這是我的代碼。用libavcodec解碼mJPEG

初始化:

// mJPEG to I420 conversion 
AVCodecContext * _transcoder = nullptr; 
AVFrame * _outputFrame; 
AVPacket _inputPacket; 

avcodec_register_all(); 
_outputFrame = av_frame_alloc(); 
av_frame_unref(_outputFrame); 
av_init_packet(&_inputPacket); 

AVCodec * codecDecode = avcodec_find_decoder(AV_CODEC_ID_MJPEG); 

_transcoder = avcodec_alloc_context3(codecDecode); 
avcodec_get_context_defaults3(_transcoder, codecDecode); 
_transcoder->flags2 |= CODEC_FLAG2_FAST; 
_transcoder->pix_fmt = AVPixelFormat::AV_PIX_FMT_YUV420P; 
_transcoder->width = width; 
_transcoder->height = height; 
avcodec_open2(_transcoder, codecDecode, nullptr); 

解碼:

_inputPacket.size = size; 
_inputPacket.data = data; 

int got_picture; 
int decompressed_size = avcodec_decode_video2(_transcoder, _outputFrame, &got_picture, &_inputPacket); 

但到目前爲止,我所得到的是一個綠色的屏幕。我錯在哪裏?

UPD: 我已啓用libavcodec日誌記錄,但沒有警告或錯誤。 此外我還發現_outputframe具有AV_PIX_FMT_YUVJ422P作爲格式和色彩空間,它不適合libavcodec枚舉中的任何值(實際值爲156448160)。

+0

1)這是太小的代碼片斷肯定地說。 2)由於解碼格式取決於源碼流,並且會被解碼器覆蓋,因此您無法真正將解碼編碼爲yuv420p(寬度/高度相同)。因此,在查看解碼結果時,請確保使用正確的色彩空間。 3)你是否啓用了ffmpeg/libav logging(av_log_set_callback),看看他們是否輸出錯誤? – nobody555

+0

@ nobody555,感謝您的見解。我用新的信息更新了答案。請讓我知道你需要哪些代碼來更好地理解問題。關於2) - 所以,如果我需要I420作爲輸出,我應該如何設置它?是否有可能通過libavcodec從mJPEG獲得I420,或者我應該尋找其他解決方案? –

+0

如果你需要的I420比你解碼mjpeg的任何libavcodec決定(取決於你的來源),並使用swscale將其轉換爲I420。 – nobody555

回答

0

經過評論建議後,我想出了工作解決方案。

初始化:

av_init_packet(&_inputPacket); 

AVCodec * codecDecode = avcodec_find_decoder(AV_CODEC_ID_MJPEG); 

_transcoder = avcodec_alloc_context3(codecDecode); 
avcodec_get_context_defaults3(_transcoder, codecDecode); 
avcodec_open2(_transcoder, codecDecode, nullptr); 

// swscale contex init 
mJPEGconvertCtx = sws_getContext(width, height, AV_PIX_FMT_YUVJ422P, 
     width, height, AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, nullptr, nullptr, nullptr); 

// x264 pic init 
x264_picture_t _pic_in; 
x264_picture_alloc(&_pic_in, X264_CSP_I420, width, height); 
_pic_in.img.i_csp = X264_CSP_I420 ; 
_pic_in.img.i_plane = 3; 
_pic_in.img.i_stride[0] = width; 
_pic_in.img.i_stride[1] = width/2; 
_pic_in.img.i_stride[2] = width/2; 

_pic_in.i_type = X264_TYPE_AUTO ; 
_pic_in.i_qpplus1 = 0; 

轉碼:

_inputPacket.size = size; 
_inputPacket.data = data; 

int got_picture; 

// decode 
avcodec_decode_video2(_transcoder, _outputFrame, &got_picture, &_inputPacket); 

// transform 
sws_scale(_mJPEGconvertCtx, _outputFrame->data, _outputFrame->linesize, 0, height, 
     _pic_in.img.plane, _pic_in.img.i_stride); 

然後,_pic_in由X264直接使用。圖像很好,但轉碼時間對於更高分辨率來說是可怕的。