【问题标题】:Decoding mJPEG with libavcodec使用 libavcodec 解码 mJPEG
【发布时间】:2014-06-20 00:49:10
【问题描述】:

我正在创建视频会议应用程序。我发现网络摄像头(我至少有 3 个)为 mJPEG 输出格式提供了更高的分辨率和帧速率。到目前为止,我使用的是 YUY2,在 I420 中转换以使用 X264 进行压缩。要将 mJPEG 转码为 I420,我需要先对其进行解码。我正在尝试使用 libavcodec 解码来自网络摄像头的图像。这是我的代码。

初始化:

// 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);

但到目前为止,我得到的是绿屏。我哪里错了?

更新: 我已启用 libavcodec 日志记录,但没有警告或错误。 我还发现 _outputframe 具有 AV_PIX_FMT_YUVJ422P 作为格式和色彩空间,它不适合 libavcodec 枚举中的任何值(实际值为 156448160)。

【问题讨论】:

  • 1) 这是太小的 sn-ps 代码,无法确定。 2)您不能真正将解码硬编码为 yuv420p(宽度/高度相同),因为解码格式取决于源流并且将被解码器覆盖。因此,请确保在查看解码结果时使用正确的色彩空间。 3) 你是否启用了 ffmpeg/libav 日志记录 (av_log_set_callback) 也查看它们是否输出任何错误?
  • @nobody555,感谢您的见解。我已经用新信息更新了答案。请让我知道您需要哪些代码才能更好地理解问题。关于 2) - 那么,如果我需要 I420 作为输出,我应该如何设置它?是否可以使用 libavcodec 从 mJPEG 获取 I420,或者我应该寻找其他解决方案?
  • 如果您需要 I420,而不是根据 libavcodec 决定的内容(取决于您的来源)解码 mjpeg,然后使用 swscale 将其转换为 I420。
  • 非常感谢,帮了大忙,虽然解压时间比较长。

标签: c++ ffmpeg decoding libavcodec


【解决方案1】:

根据 cmets 的建议,我想出了可行的解决方案。

初始化:

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 直接使用。图像很好,但更高分辨率的转码时间太可怕了。

【讨论】:

    猜你喜欢
    • 2015-03-08
    • 2019-01-21
    • 2017-05-26
    • 2011-08-26
    • 2020-12-11
    • 1970-01-01
    • 1970-01-01
    • 2012-04-05
    • 2013-01-16
    相关资源
    最近更新 更多