libavcodec返回的损坏的AVFrame

时间:2014-12-30 08:47:53

标签: c++ multithreading ffmpeg libavcodec libav

作为一个更大项目的一部分,我试图同时解码许多HD(1920x1080)视频流。每个视频流以原始yuv420p格式存储在AVI容器中。我有一个 Decoder 类,我在其中创建了不同线程中的多个对象(每个线程一个对象)。解码器中的两个主要方法是decode()getNextFrame(),我在下面提供了实现。

当我分离解码逻辑并使用它来解码单个流时,一切正常。但是,当我使用多线程代码时,我得到一个分段错误,程序在解码循环中的处理代码中崩溃。经过一些调查,我意识到填充AVFrame的{​​{1}}的数据数组包含超出范围的地址(根据gdb)。

我真的迷失在这里!我没有做任何会改变我代码中getNextFrame()内容的事情。我尝试访问AVFrame的唯一地方是当我调用AVFrame来转换颜色格式时,由于损坏的sws_scale(),在第二种情况下发生分段错误的地方。任何关于为什么会发生这种情况的建议都非常感谢。提前谢谢。

AVFrame方法:

decode()

void decode() { QString filename("video.avi"); AVFormatContext* container = 0; if (avformat_open_input(&container, filename.toStdString().c_str(), NULL, NULL) < 0) { fprintf(stderr, "Could not open %s\n", filename.toStdString().c_str()); exit(1); } if (avformat_find_stream_info(container, NULL) < 0) { fprintf(stderr, "Could not find file info..\n"); } // find a video stream int stream_id = -1; for (unsigned int i = 0; i < container->nb_streams; i++) { if (container->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { stream_id = i; break; } } if (stream_id == -1) { fprintf(stderr, "Could not find a video stream..\n"); } av_dump_format(container, stream_id, filename.toStdString().c_str(), false); // find the appropriate codec and open it AVCodecContext* codec_context = container->streams[stream_id]->codec; // Get a pointer to the codec context for the video stream AVCodec* codec = avcodec_find_decoder(codec_context->codec_id); // Find the decoder for the video stream if (codec == NULL) { fprintf(stderr, "Could not find a suitable codec..\n"); return -1; // Codec not found } // Inform the codec that we can handle truncated bitstreams -- i.e., // bitstreams where frame boundaries can fall in the middle of packets if (codec->capabilities & CODEC_CAP_TRUNCATED) codec_context->flags |= CODEC_FLAG_TRUNCATED; fprintf(stderr, "Codec: %s\n", codec->name); // open the codec int ret = avcodec_open2(codec_context, codec, NULL); if (ret < 0) { fprintf(stderr, "Could not open the needed codec.. Error: %d\n", ret); return -1; } // allocate video frame AVFrame *frame = avcodec_alloc_frame(); // deprecated, should use av_frame_alloc() instead if (!frame) { fprintf(stderr, "Could not allocate video frame..\n"); return -1; } int frameNumber = 0; // as long as there are remaining frames in the stream while (getNextFrame(container, codec_context, stream_id, frame)) { // Processing logic here... // AVFrame data array contains three addresses which are out of range } // freeing resources av_free(frame); avcodec_close(codec_context); avformat_close_input(&container); } 方法:

getNextFrame()

锁管理回调函数:

bool getNextFrame(AVFormatContext *pFormatCtx,
                  AVCodecContext *pCodecCtx,
                  int videoStream,
                  AVFrame *pFrame) {

    uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];

    char buf[1024];

    int len;

    int got_picture;
    AVPacket avpkt;

    av_init_packet(&avpkt);

    memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);

    // read data from bit stream and store it in the AVPacket object
    while(av_read_frame(pFormatCtx, &avpkt) >= 0) {

        // check the stream index of the read packet to make sure it is a video stream
        if(avpkt.stream_index == videoStream) {

            // decode the packet and store the decoded content in the AVFrame object and set the flag if we have a complete decoded picture
            avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &avpkt);

            // if we have completed decoding an entire picture (frame), return true
            if(got_picture) {

                av_free_packet(&avpkt);

                return true;
            }
        }

        // free the AVPacket object that was allocated by av_read_frame
        av_free_packet(&avpkt);
    }

    return false;

}

1 个答案:

答案 0 :(得分:0)

我找出了问题的原因。在获得解码帧时返回之前是av_free_packet()调用。我评论说,电话和程序工作!我仍然不太确定为什么这会影响填充的AVFrame

我也不确定删除该调用是否会导致代码中出现内存泄漏。

希望 libavcodec 专家可以对此有所了解,并解释我做错了什么。