【问题标题】:Process AVFrame using opencv mat causing encoding error使用 opencv mat 处理 AVFrame 导致编码错误
【发布时间】:2015-01-10 16:41:20
【问题描述】:

我正在尝试使用 ffmpeg 解码视频文件,获取 AVFrame 对象,将其转换为 opencv mat 对象,进行一些处理,然后将其转换回 AVFrame 对象并将其编码回视频文件。

好吧,程序可以运行,但结果不好。

我不断收到错误,例如“顶部块在 7 19 时请求的帧内模式不可用”、“解码 MB 7 19、字节流 358 时出错”、“在 P 帧中隐藏 294 DC、294AC、294 MV 错误”等。

结果视频到处都是闪光。像这样,

我猜这是因为我的 AVFrame 到 Mat 和 Mat 到 AVFrame 方法,他们在这里

//unspecified function
temp_rgb_frame = avcodec_alloc_frame(); 
int numBytes = avpicture_get_size(PIX_FMT_RGB24, width, height); 
uint8_t * frame2_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t)); 
avpicture_fill((AVPicture*)temp_rgb_frame, frame2_buffer, PIX_FMT_RGB24, width, height);

void CoreProcessor::Mat2AVFrame(cv::Mat **input, AVFrame *output)
{
    //create a AVPicture frame from the opencv Mat input image
    avpicture_fill((AVPicture *)temp_rgb_frame,
        (uint8_t *)(*input)->data,
        AV_PIX_FMT_RGB24,
        (*input)->cols,
        (*input)->rows);

    //convert the frame to the color space and pixel format specified in the sws context

    sws_scale(
        rgb_to_yuv_context, 
        temp_rgb_frame->data,
        temp_rgb_frame->linesize,
        0, height, 
        ((AVPicture *)output)->data, 
        ((AVPicture *)output)->linesize);

    (*input)->release();

}

void CoreProcessor::AVFrame2Mat(AVFrame *pFrame, cv::Mat **mat)
{
    sws_scale(
        yuv_to_rgb_context, 
        ((AVPicture*)pFrame)->data, 
        ((AVPicture*)pFrame)->linesize, 
        0, height, 
        ((AVPicture *)temp_rgb_frame)->data,
        ((AVPicture *)temp_rgb_frame)->linesize);

    *mat = new cv::Mat(pFrame->height, pFrame->width, CV_8UC3, temp_rgb_frame->data[0]);
}

void CoreProcessor::process_frame(AVFrame *pFrame)
{
    cv::Mat *mat = NULL;
    AVFrame2Mat(pFrame, &mat);
    Mat2AVFrame(&mat, pFrame);
}

我的记忆有问题吗?因为如果我去掉处理部分,只对帧进行解码再编码,结果是正确的。

【问题讨论】:

  • (*input)->release(); 的动机? temp_rgb_frame 在哪里声明?
  • temp_rgb_frame 在主解码部分开始之前被初始化,就像这样temp_rgb_frame = avcodec_alloc_frame(); int numBytes = avpicture_get_size(PIX_FMT_RGB24, width, height); uint8_t * frame2_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture*)temp_rgb_frame, frame2_buffer, PIX_FMT_RGB24, width, height); 我想释放垫子,所以我在将它转换回 AVFrame 后调用了释放方法
  • 我的错,在我的代码中,我在temp_rgb_frame initialization部分出错,我设置的像素格式错误,应该是PIX_FMT_RGB24,但我设置为PIX_FMT_YUV420P,现在它起作用了!谢谢UmNyobe!!!
  • 请注意,avpicture_fill 不会执行数据的深层复制。它仅根据参数设置指针和线大小。这意味着如果您删除原始数据,您正在对已释放的内存进行操作。
  • 对!,我已经删除了发布代码。谢谢! :)

标签: c++ opencv ffmpeg encode mat


【解决方案1】:

好吧,原来我在初始化temp_rgb_frame时出错了,如果应该是这样,

temp_rgb_frame = avcodec_alloc_frame();
int numBytes = avpicture_get_size(PIX_FMT_RGB24, width, height);
uint8_t * frame2_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture*)temp_rgb_frame, frame2_buffer, PIX_FMT_RGB24, width, height);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-29
    • 2016-02-21
    • 1970-01-01
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    • 2018-02-05
    • 1970-01-01
    相关资源
    最近更新 更多