FFMPEG解封装后的AVPACKET存储为可播放的h264文件

转载:https://blog.csdn.net/u010289908/article/details/46314869

rtsp流:

在使用FFMPEG的类库进行编程的过程中,可以直接输出解复用之后的的视频数据码流。只需要在每次调用av_read_frame()之后将得到的视频的AVPacket存为本地文件即可。据网上说TS(MPEG2 Transport Stream)也是可以正常播放。以下是我将AVPacket前几个字节打印出来的数据,是标准的h264数据:
FFMPEG解封装后的AVPACKET存储为可播放的h264文件_第1张图片

RTMP流

像rtsp那样解复用,通过av_read_frame得到的AVPacket存为本地文件。发现只能播放自己的rtmp流解封装出来的h264文件,别人的播放不了。把AVPacket前面几个字节打印出来,可知并没有h264的头数据,网上搜索可知FLV,MP4这些属于“特殊容器”,需要经过处理才能得到可播放的H.264码流。以下是我将AVPacket前几个字节打印出来的数据:
FFMPEG解封装后的AVPACKET存储为可播放的h264文件_第2张图片

处理

这个处理完之后直接保存成h264文件,可以直接播放。但将数据打印出来也不是标准的h264数据(也可能是本人水平有限,看不出来)

AVBitStreamFilterContext* h264bsfc =  av_bitstream_filter_init("h264_mp4toannexb");
uint8_t* outbuf = NULL;
int outlen = 0;
av_bitstream_filter_filter(h264bsfc, pThis->m_pFmtCtx->streams[Pkt.stream_index]->codec, NULL,
                                                       &outbuf, &outlen, Pkt.data, Pkt.size, 0);
av_bitstream_filter_close(h264bsfc);

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

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

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

第二种方法

通过查看FFMPEG源代码我们发现,AVPacket中的数据起始处没有分隔符(0x00000001), 也不是0x65、0x67、0x68、0x41等字节,所以可以AVPacket肯定这不是标准的nalu。其实,AVPacket前4个字表示的是nalu的长度,从第5个字节开始才是nalu的数据。所以直接将AVPacket前4个字节替换为0x00000001即可得到标准的nalu数据。
但经过测试这种方法直接保存成264文件不能播放,可能是由于没有spspps,要手动添加

你可能感兴趣的:(FFMPEG解封装后的AVPACKET存储为可播放的h264文件)