ffmpeg缓冲区未释放

ffmpeg缓冲区未释放,ffmpeg,buffer,release,decoder,Ffmpeg,Buffer,Release,Decoder,因此,我为ffmpeg编写了一个基本解码器,它只读取输入帧的像素数据(使用RGB 8格式存储),并将其直接放入输出缓冲区。(也是RGB 8)问题是,当我在ffmpeg中使用此解码器时,它表示有1个未释放的缓冲区(使用ffmpeg-I Test.犹他测试.png进行测试)。不幸的是,我不确定它所说的缓冲区是什么,因为我没有创建自己的缓冲区。我曾尝试在解码器关闭方法中释放AVContext的编码_帧缓冲区,但这会导致分段错误 任何帮助都将不胜感激 static int decode_frame(AV

因此,我为ffmpeg编写了一个基本解码器,它只读取输入帧的像素数据(使用RGB 8格式存储),并将其直接放入输出缓冲区。(也是RGB 8)问题是,当我在ffmpeg中使用此解码器时,它表示有1个未释放的缓冲区(使用ffmpeg-I Test.犹他测试.png进行测试)。不幸的是,我不确定它所说的缓冲区是什么,因为我没有创建自己的缓冲区。我曾尝试在解码器关闭方法中释放AVContext的编码_帧缓冲区,但这会导致分段错误

任何帮助都将不胜感激

static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
{
    int ret;           /*Hold return from get_buffer */ 
    int skipSize;      /*Number of dummy bytes to skip per line*/
    int fseek=8;       /*Location of the first pixel*/
    int i=0; int j=0;  /*Output buffer seek index/Input Buffer seek index*/
    const uint8_t *buf = avpkt->data; /*Hold a pointer to the input buffer*/
    AVFrame *pict=data; /*Hold a pointer to the output buffer*/

    /*Set the output pixel format to RGB8*/
    avctx->pix_fmt = AV_PIX_FMT_RGB8;

    /*Get the width and height*/
    bytestream_get_le32(&buf);
    avctx->width=bytestream_get_le16(&buf);
    avctx->height=bytestream_get_le16(&buf);

    /*Release the old buffer*/
    if (pict->data[0]) avctx->release_buffer(avctx, pict);

    /*Aquire a large enough data buffer to hold the decompressed picture*/
    if (ret=ff_get_buffer(avctx, pict) < 0) return ret;
    skipSize=pict->linesize[0] - avctx->width; 

    /*Transfer input buffer to output buffer*/
    for(int y=0;y<avctx->height;y++){
        for(int x=0;x<avctx->width;x++){
            pict->data[0][i]=avpkt->data[fseek+j];
            j++;
            i++;
        }
        i+=skipSize;
    }

    /*Inform ffmpeg the output is a key frame and that it is ready for external usage*/
    pict->pict_type        = AV_PICTURE_TYPE_I;
    pict->key_frame        = 1;
    *got_frame=1;
    return 0;
}
static int decode_帧(AVCodecContext*avctx,void*data,int*got_帧,AVPacket*avpkt)
{
int ret;/*从get_buffer返回Hold*/
int skipSize;/*每行要跳过的虚拟字节数*/
int fseek=8;/*第一个像素的位置*/
int i=0;int j=0;/*输出缓冲区搜索索引/输入缓冲区搜索索引*/
const uint8_t*buf=avpkt->data;/*保留指向输入缓冲区的指针*/
AVFrame*pict=data;/*保留指向输出缓冲区的指针*/
/*将输出像素格式设置为RGB8*/
avctx->pix_fmt=AV_pix_fmt_RGB8;
/*获取宽度和高度*/
bytestream_get_le32(&buf);
avctx->width=bytestream\u get\u le16(&buf);
avctx->height=bytestream\u get\u le16(&buf);
/*释放旧的缓冲区*/
如果(pict->data[0])avctx->释放缓冲区(avctx,pict);
/*获取足够大的数据缓冲区来保存解压缩后的图片*/
如果(ret=ff_get_buffer(avctx,pict)<0)返回ret;
skipSize=pict->linesize[0]-avctx->width;
/*将输入缓冲区转移到输出缓冲区*/
for(int y=0;yheight;y++){
用于(int x=0;xwidth;x++){
pict->data[0][i]=avpkt->data[fseek+j];
j++;
i++;
}
i+=滑雪;
}
/*通知ffmpeg输出是一个关键帧,它已准备好供外部使用*/
pict->pict_type=AV_图片_type_I;
pict->关键帧=1;
*got_frame=1;
返回0;
}

您没有发布此解码器对象的.close方法。有吗?在大多数FFmpeg解码器中,其形式为
codecname\u decode\u end()
。此方法/函数在解码完成后调用,使解码器有机会在解码完成后进行清理

我要说的是:

decode_frame call #0: no frame held; frame allocated
decode_frame call #1: free frame allocated during call #0; frame allocated
decode_frame call #2: free frame allocated during call #1; frame allocated
[...]
decode_frame call #n: free frame allocated during call #(n-1); frame allocated

但是当所有这些都完成后,解码器仍然保留在decode#u frame调用#n期间分配的帧
codecname\u decode\u end()
允许解码器释放最后一帧。

这是一堆代码-您认为您可以将其精简到仅相关部分吗?如果你有那么多的代码,用户很难轻松地帮助你。可能会将关键部分分开,并将整个代码块放在问题的底部。我很想进一步减少这段代码,但实际上它是非常简单的。然而,我编辑了它,试图使它尽可能可读。最后一帧存储在哪里?在AVU帧中?我尝试过在关闭方法中释放它,就像这样,如果(avctx->coded_frame->data[0])avctx->release_buffer(avctx,avctx->coded_frame);但这只会导致出现分段错误。我建议运行gdb或Valgrind来快速诊断分段错误(并确保您正在运行ffmpeg的调试版本,即“ffmpeg_g”,以便获得符号)。你熟悉这些工具吗?我对gdb有点熟悉。(足够做堆栈跟踪了)你需要为ffmpeg_g做一个特殊的构建吗?这就足够了。通过gdb运行错误的命令行应该指向崩溃的确切位置。如果它崩溃的原因完全不明显,运行'valgrind ffmpeg_g-i Test.犹他测试.png',看看它是否发现可能导致segfault的内存损坏。好的,在一些调试和测试之后,我发现release_buffer()在编码的_帧上调用时导致崩溃的原因,是因为AvcodeContext编码的_帧为空。(这是有意义的,因为我在直接写入输出缓冲区时从不初始化它。[使用void*数据指针]),但是这又让我回到了我最初的问题:哪个缓冲区没有被释放?有什么想法吗?