ffmpeg 手动添加 sps pps(处理内存泄露问题)

来源:互联网 发布:消息认证算法的简称 编辑:程序博客网 时间:2024/06/05 05:16

分离某些封装格式中的H.264

分离某些封装格式(例如MP4/FLV/MKV等)中的H.264的时候,需要首先写入SPS和PPS,否则会导致分离出来的数据没有SPS、PPS而无法播放。H.264码流的SPS和PPS信息存储在AVCodecContext结构体的extradata中。需要使用ffmpeg中名称为“h264_mp4toannexb”的bitstream filter处理。有两种处理方式:

(1)使用bitstream filter处理每个AVPacket(简单)

把每个AVPacket中的数据(data字段)经过bitstream filter“过滤”一遍。关键函数是av_bitstream_filter_filter()。示例代码如下。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. AVBitStreamFilterContext* h264bsfc =  av_bitstream_filter_init("h264_mp4toannexb");   
  2. while(av_read_frame(ifmt_ctx, &pkt)>=0){  
  3.     if(pkt.stream_index==videoindex){  
  4.         av_bitstream_filter_filter(h264bsfc, ifmt_ctx->streams[videoindex]->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0);  
  5.         fwrite(pkt.data,1,pkt.size,fp_video);  
  6.         //...  
  7.     }  
  8.     av_free_packet(&pkt);  
  9. }  
  10. av_bitstream_filter_close(h264bsfc);    

上述代码中,把av_bitstream_filter_filter()的输入数据和输出数据(分别对应第4,5,6,7个参数)都设置成AVPacket的data字段就可以了。

需要注意的是bitstream filter需要初始化和销毁,分别通过函数av_bitstream_filter_init()和av_bitstream_filter_close()。

经过上述代码处理之后,AVPacket中的数据有如下变化:

*每个AVPacket的data添加了H.264的NALU的起始码{0,0,0,1}

*每个IDR帧数据前面添加了SPS和PPS

(2)手工添加SPS,PPS(稍微复杂)

将AVCodecContext的extradata数据经过bitstream filter处理之后得到SPS、PPS,拷贝至每个IDR帧之前。下面代码示例了写入SPS、PPS的过程。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. FILE *fp=fopen("test.264","ab");  
  2. AVCodecContext *pCodecCtx=...    
  3. unsigned char *dummy=NULL;     
  4. int dummy_len;    
  5. AVBitStreamFilterContext* bsfc =  av_bitstream_filter_init("h264_mp4toannexb");      
  6. av_bitstream_filter_filter(bsfc, pCodecCtx, NULL, &dummy, &dummy_len, NULL, 0, 0);    
  7. fwrite(pCodecCtx->extradata,pCodecCtx-->extradata_size,1,fp);    
  8. av_bitstream_filter_close(bsfc);      
  9. free(dummy);    
然后修改AVPacket的data。把前4个字节改为起始码。示例代码如下所示。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. char nal_start[]={0,0,0,1};  
  2. memcpy(packet->data,nal_start,4);  
经过上述两步也可以得到可以播放的H.264码流,相对于第一种方法来说复杂一些。
0 0
原创粉丝点击