ffmpeg学习日记22-内存读取avio_alloc_context函数的内存释放问题
·
ffmpeg学习日记22-内存读取avio_alloc_context函数的内存释放问题
在开发内存读写数据过程中,遇到了内存泄露的问题,泄漏点围绕着avio_alloc_context函数,在内存中读写数据参考雷神文章ffmpeg 从内存中读取数据(或将数据输出到内存),在雷神的文章中,只讲述了如何实现内存读写的功能,没有讲到内存释放,或许这根本就不是问题。
// Input
if (!(ifmt_ctx_v = avformat_alloc_context())) {
std::cout << "error!!! ifmt_ctx_v = avformat_alloc_context()" << std::endl;
exit(0);
}
if (!(ifmt_ctx_a = avformat_alloc_context())) {
std::cout << "error!!! ifmt_ctx_a = avformat_alloc_context()" << std::endl;
exit(0);
}
// iobuff_v数据需要释放
unsigned char *iobuff_v = (unsigned char *)av_malloc(INBUF_SIZE); // 32768
if (iobuff_v == NULL) {
std::cout << "error!!! malloc " << std::endl;
exit(0);
}
AVIOContext *avio = avio_alloc_context(iobuff_v, INBUF_SIZE, 0, NULL, fill_iobuff_v, NULL, NULL);
unsigned char *iobuff_a = (unsigned char *)av_malloc(INBUF_SIZE);
if (iobuff_a == NULL) {
std::cout << "error!!! malloc " << std::endl;
exit(0);
}
AVIOContext *avio_a = avio_alloc_context(iobuff_a, INBUF_SIZE, 0, NULL, fill_iobuff_a, NULL, NULL);
ifmt_ctx_v->pb = avio;
ifmt_ctx_v->flags = AVFMT_FLAG_CUSTOM_IO;
ifmt_ctx_a->pb = avio_a;
ifmt_ctx_a->flags = AVFMT_FLAG_CUSTOM_IO;
if ((ret = avformat_open_input(&ifmt_ctx_v, NULL, NULL, NULL)) < 0) {
fprintf(stderr, "Could not open input file.%d", ret);
goto end;
}
std::cout << "before avformat_open_input : " << filename_output << std::endl;
if ((ret = avformat_find_stream_info(ifmt_ctx_v, NULL)) < 0) {
printf("Failed to retrieve input stream information");
goto end;
}
std::cout << "after avformat_open_input " << std::endl;
if ((ret = avformat_open_input(&ifmt_ctx_a, NULL, NULL, NULL)) < 0) {
printf("Could not open input file.");
goto end;
}
if ((ret = avformat_find_stream_info(ifmt_ctx_a, NULL)) < 0) {
printf("Failed to retrieve input stream information");
goto end;
}
上面的代码是从内存中读取数据,申请了iobuff_v空间,iobuff_v和AVIOContext *avio 进行关联,
ifmt_ctx_v->pb = avio;
avio和ifmt_ctx_v->pb进行关联,这样一个关联关系,在进行内存释放的时候,使用如下函数
avio_context_free(&avio_a);
av_free(ifmt_ctx_v->pb);
avio_close(ifmt_ctx_v->pb);
av_free(iobuff_v);
avformat_close_input(&ifmt_ctx_v);
free(iobuff_v);
都不能释放iobuff_v的内存,强行释放就是各种内存错误,在参考了ffmpeg的自带例程之后,发现这个iobuff_v的内存需要这样释放
av_freep(&avio->buffer);
整个内存释放逻辑是:
end:
if (avio) {
av_freep(&avio->buffer);
}
avio_context_free(&avio);
if (avio_a) {
av_freep(&avio_a->buffer);
avio_context_free(&avio_a);
}
if (ifmt_ctx_v) {
// av_free(ifmt_ctx_v->pb);
// avio_close(ifmt_ctx_v->pb);
// av_free(iobuff_v);
avformat_close_input(&ifmt_ctx_v);
// avformat_free_context(ifmt_ctx_v);
}
if (ifmt_ctx_a) {
// av_free(ifmt_ctx_a->pb);
// avio_close(ifmt_ctx_a->pb);
// av_free(iobuff_a);
avformat_close_input(&ifmt_ctx_a);
// avformat_free_context(ifmt_ctx_a);
/* close output */
}
if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE)) avio_close(ofmt_ctx->pb);
avformat_free_context(ofmt_ctx);
if (ret < 0 && ret != AVERROR_EOF) {
printf("Error occurred.\n");
return -1;
}
return 0;
奇怪的地方来了,下另一处,我使用了写内存的方式,写内存的释放内容如下:
cleanup:
if (fifo) av_audio_fifo_free(fifo);
swr_free(&resample_ctx);
if (out_codec_ctx) avcodec_free_context(&out_codec_ctx);
if (out_format_ctx) {
av_free(out_format_ctx->pb);
av_free(outbuff);
avformat_free_context(out_format_ctx);
}
if (in_codec_ctx) avcodec_free_context(&in_codec_ctx);
if (in_format_ctx) avformat_close_input(&in_format_ctx);
return ret;
在此处就可以使用av_free(out_format_ctx->pb);释放pb,上面却不行,真是奇怪的事。这一点还要继续研究验证。
note
此处有一个点需要注意一下,在ffmpeg中,不同函数和类申请内存,需要使用对应的函数和类的释放函数去释放,否则就会出现释放内存不彻底,内存泄露,或者直接报错等等。
更多推荐
所有评论(0)