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

sunhygwjl 2017-02-03 11:55:36
劳烦各位大神帮忙看一下下面的代码有什么问题?为什么进程在运行过程中(即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;
}



...全文
2708 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
XP_online 2019-06-27
  • 打赏
  • 举报
回复
av_packet_unref只是给avpacket重新置空,并不会析构avpacket中data的内存。要不自己析构,要不调用av_free_packet去析构。
sunhygwjl 2019-05-07
  • 打赏
  • 举报
回复
最后没有做下去了。。。
CyberLogix 2018-04-06
  • 打赏
  • 举报
回复
估计是那块vbuffer没有释放导致, av_packet_unref(&pkt); out_buff = (unsigned char *)av_malloc(OUT_BUFF_LEN); /* Allocate avio context */ avio_out = avio_alloc_context(out_buff, OUT_BUFF_LEN, 1, NULL, NULL, write_packet, NULL);
百灵工作室 2018-01-04
  • 打赏
  • 举报
回复
pkt定义为指针AVPacket*试试
fangshy 2017-12-28
  • 打赏
  • 举报
回复
楼主解决了 分享下思路,我也遇到了
qige26 2017-03-02
  • 打赏
  • 举报
回复
顶起,我也遇到相同问题
rightorwrong 2017-02-07
  • 打赏
  • 举报
回复
看看demo程序对那几个结构体怎么释放的

2,553

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧