[ffmpeg求助]调用avio_alloc_context()自定义write_packet发生内存泄漏

sunhygwjl sunhygwjl 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
劳烦各位大神帮忙看一下下面的代码有什么问题?为什么进程在运行过程中(即while(1)循环中)占用内存一直在不断增加?最终导致系统内存耗尽,无法申请新的内存。是AVIOContext结构的初始化有问题?还是哪里有问题?看了很久也没有找到原因。打印调试发现内存即将耗尽时,进程会阻塞在av_interleaved_write_frame(),最终返回错误推出循环。所以,应该是在该函数中不断申请内存又没有释放,但具体不知道是哪里申请了内存。希望大家能指点一二,感激不尽!!!

int fp_write = -1;

int write_packet(void *opaque, uint8_t *buff, int buf_size)
{
int sentbyte = -1;
if (fp_write != -1)
{
sentbyte = write(fp_write, buff, buf_size);
}

return sentbyte;
}

int main(void)
{
int ret = 0, i;
AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
AVIOContext *avio_out = NULL;
AVPacket pkt;
#define USE_H264BSF
#ifdef USE_H264BSF
AVBitStreamFilterContext *h264bsfc = NULL;
int video_index = -1;
#endif
char *in_filename, *out_filename;
unsigned char *out_buff = NULL;

in_filename = "/tmp/media/mp4.mp4";
out_filename = "/tmp/media/test_video.ts";

av_register_all();

if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0)
{
fprintf(stderr, "Could not open input file '%s'", in_filename);
goto end;
}

if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0)
{
fprintf(stderr, "Failed to retrieve input stream information");
goto end;
}

/* Allocate buffer for output data */
out_buff = (unsigned char *)av_malloc(OUT_BUFF_LEN);
printf("out_buff: 0x%p\n", out_buff);
if (!out_buff)
{
fprintf(stderr, "av_malloc error\n");
goto end;
}

/* Output file for testing */
fp_write = open(out_filename, O_WRONLY | O_CREAT);
if (fp_write == -1)
{
perror("open");
goto end;
}

/* Allocate avformat */
ofmt_ctx = avformat_alloc_context();
if (!ofmt_ctx)
{
fprintf(stderr, "Could not create output context\n");
ret = AVERROR_UNKNOWN;
goto end;
}
ofmt_ctx->oformat = av_guess_format("mpegts", NULL, NULL);
if (!ofmt_ctx->oformat)
{
fprintf(stderr, "Could not set output format\n");
ret = AVERROR_UNKNOWN;
goto end;
}

/* Allocate avio context */
avio_out = avio_alloc_context(out_buff, OUT_BUFF_LEN, 1, NULL, NULL, write_packet, NULL);
if (!avio_out)
{
fprintf(stderr, "Could not create avio context\n");
ret = AVERROR_UNKNOWN;
goto end;
}

/* AVIO struct */
ofmt_ctx->pb = avio_out;
ofmt_ctx->flags = AVFMT_FLAG_CUSTOM_IO;

for (i = 0; i < ifmt_ctx->nb_streams; i++)
{
AVStream *in_stream = ifmt_ctx->streams[i];
AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
if (!out_stream) {
fprintf(stderr, "Failed allocating output stream\n");
ret = AVERROR_UNKNOWN;
goto end;
}

ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
if (ret < 0) {
fprintf(stderr, "Failed to copy context from input to output stream codec context\n");
goto end;
}
out_stream->codec->codec_tag = 0;
if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
{
out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
#ifdef USE_H264BSF
/* mark video index */
if (out_stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
video_index = i;
}
#endif
}

ret = avformat_write_header(ofmt_ctx, NULL);
if (ret < 0)
{
fprintf(stderr, "Error occurred when opening output file\n");
goto end;
}

#ifdef USE_H264BSF
h264bsfc = av_bitstream_filter_init("h264_mp4toannexb");
#endif
while (1) {
AVStream *in_stream, *out_stream;
ret = av_read_frame(ifmt_ctx, &pkt);
if (ret < 0)
{
av_packet_unref(&pkt);
break;
}
#ifdef USE_H264BSF
if (pkt.stream_index == video_index)
{
av_bitstream_filter_filter(h264bsfc, ifmt_ctx->streams[video_index]->codec,
NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0);
}
#endif
in_stream = ifmt_ctx->streams[pkt.stream_index];
out_stream = ofmt_ctx->streams[pkt.stream_index];

/* copy packet */
pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
pkt.pos = -1;

ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
if (ret < 0) {
fprintf(stderr, "Error muxing packet\n");
av_packet_unref(&pkt);
break;
}

av_packet_unref(&pkt);
}

av_write_trailer(ofmt_ctx);

end:
avformat_close_input(&ifmt_ctx);

/* close output */
if (!avio_out && out_buff)
{
av_freep(&out_buff);
}

if (avio_out)
{
av_freep(&avio_out->buffer);
av_freep(&avio_out);

}

if (fp_write != -1)
{
close(fp_write);
}

avformat_free_context(ofmt_ctx);

#ifdef USE_H264BSF
av_bitstream_filter_close(h264bsfc);
#endif

if (ret < 0 && ret != AVERROR_EOF)
{
fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
return 1;
}

return 0;
}



...全文

相关推荐

QT C++ ffmpeg 调用usb 摄像头显示 并录制 H264录制视频

QT C++ ffmpeg 调用usb 摄像头显示 并录制 H264录制视频 FFmpeg版本:n5.1.2

hy5188

FFmpeg转封装核心:avformat_alloc_output_context2深度解析

音视频开发中,容器封装与转封装是流媒体工具链的基础。FFmpeg作为业界标准的多媒体处理库,其libavformat模块抽象了不同格式的差异,AVFormatContext则是输出端的核心句柄。avformat_alloc_output_context2函数负责创建输出上下文,并通过参数优先级自动匹配muxer封装器,大幅简化了初始化流程。深入理解它的内部分配逻辑、内存释放契约以及与avformat_new_stream、avformat_write_header等API的协作方式,能有效避免转封装程序中的

宁南山

C++项目集成FFmpeg:从环境配置到音视频处理核心流程详解

音视频处理是现代软件开发中的常见需求,其核心在于对多媒体数据进行高效的编解码、封装与转换。FFmpeg作为一套功能强大的开源多媒体处理库,提供了完整的解决方案,其价值在于为开发者提供了底层音视频处理的直接控制能力,避免了依赖命令行工具带来的性能损耗和灵活性限制。在工程实践中,将FFmpeg集成到C++项目中,尤其是在Windows平台进行开发时,涉及环境配置、库的获取(包括预编译库下载与自行编译)、CMake项目集成等关键步骤。掌握其核心API,如利用AVFormatContext进行解封装、通过AVCod

weixin_30394981

ffmpeg生成gif动图.pdf

精品资料欢迎下载

赵鲁宾

利用FFmpeg将mkv视频转换为H.264

利用FFmpeg将mkv视频转换为H.264,转换后的视频请用VLC播放。

猫丸余柒
评论 8
收藏 已收藏
分享
返回顶部