AVFrame到RGB - 解码工件

时间:2013-01-08 13:01:51

标签: image ffmpeg h.264 libavcodec libavformat

我想以编程方式将mp4视频文件(使用h264编解码器)转换为单个RGB图像。使用命令行,它看起来像:

ffmpeg -i test1080.mp4 -r 30 image-%3d.jpg

使用此命令可生成一组很好的图片。但是当我尝试以编程方式执行相同的操作时,一些图像(可能是B帧和P帧)看起来很奇怪(例如,有一些带有不同信息的失真区域等)。阅读和转换代码如下:

AVFrame *frame = avcodec_alloc_frame();
AVFrame *frameRGB = avcodec_alloc_frame();

AVPacket packet;

int buffer_size=avpicture_get_size(PIX_FMT_RGB24, m_codecCtx->width,
    m_codecCtx->height);
uint8_t *buffer = new uint8_t[buffer_size];

avpicture_fill((AVPicture *)frameRGB, buffer, PIX_FMT_RGB24,
    m_codecCtx->width, m_codecCtx->height);

while (true)
{
    // Read one packet into `packet`
    if (av_read_frame(m_formatCtx, &packet) < 0) {
        break;  // End of stream. Done decoding.
    }

    if (avcodec_decode_video(m_codecCtx, frame, &buffer_size, packet.data, packet.size) < 1) {
        break;  // Error in decoding
    }

    if (!buffer_size) {
        break;
    }

    // Convert
    img_convert((AVPicture *)frameRGB, PIX_FMT_RGB24, (AVPicture*)frame,
        m_codecCtx->pix_fmt, m_codecCtx->width, m_codecCtx->height);

    // RGB data is now available in frameRGB for further processing
}

如何转换视频流,以便每个最终图像显示所有图像数据,以便来自B帧和P帧的信息包含在所有帧中?

[编辑:] 显示工件的示例图片位于:http://imageshack.us/photo/my-images/201/sampleq.jpg/

此致

1 个答案:

答案 0 :(得分:0)

如果avcodec_decode_video的第三个参数返回空值,则不表示错误。这意味着框架尚未准备好。您需要继续读取帧,直到值变为非零。

if (!buffer_size) {
    continue;
}

<强> UPD

尝试添加检查并仅显示关键帧,这有助于隔离问题。

while (true)
{
  // Read one packet into `packet`
  if (av_read_frame(m_formatCtx, &packet) < 0) {
    break;  // End of stream. Done decoding.
  }

  if (avcodec_decode_video(m_codecCtx, frame, &buffer_size,
      packet.data, packet.size) < 1)
  {
    break;  // Error in decoding
  }

  if (!buffer_size) {
    continue; // <-- It's important!
  }

  // check for key frame
  if (packet.flags & AV_PKT_FLAG_KEY)
  {
    // Convert
    img_convert((AVPicture *)frameRGB, PIX_FMT_RGB24, (AVPicture*)frame,
      m_codecCtx->pix_fmt, m_codecCtx->width, m_codecCtx->height);
  } 
}