上大学的时候就知道ffmpeg了,不过没去研究,仅仅是知道了,后面工作了从事的是无线通信行业,主要是高通和MTK平台上面的开发,换工作后,偶然的机会开始接触音视频相关的技术,先是了解了WebRTC,现在开始研究FFmpeg。
研究FFmpeg也有一段时间了,最开始是拜读雷神的FFmpeg系列博客,可惜雷神英年早逝,缅怀一下,然后就是学习了李超老师的全套音视频相关课程,包括WebRTC也是跟着李超老师的课程一步一步学习的。学习课程前后也有将近半年的时间了,工作了时间紧张基本都是挤出来的时间去学习,现在课程学习结束,开始用FFmpeg实战一下。
分为三个步骤,第一步把MP4文件转为flv文件,这应该是最简单的,第二步把MP4文件分离成h264视频流文件和aac音频流文件,第三步在进一步解码成yuv文件和pcm文件
第一步很简单,流程如下
用avformat_open_input打开原始MP4文件,并找到对应的流信息
需要转为flv,那就需要建立一个输出文件
根据输入文件的流信息建立输出文件的流信息,主要是编码器参数的拷贝,然后开始循环读取输入文件
每读出一包数据,将读出来的数据复制到输出文件的流中,包括原始数据以及流的相关信息
复制开始前调用avformat_write_header写头信息,复制全部完成后调用av_write_trailer写文件尾,即完成了文件格式的转换
第二步就是把mp4文件分离成两个文件一个是h264视频流,一个是aac音频流
在上一步的基础上,分离出H264流和AAC流之后,将其保存为文件,这里需要注意的是生成H264流需要在每个I帧前加入sps和pps信息,生成aac文件也需要在每个aac帧前加入adts信息,生成H264文件可以参考https://blog.csdn.net/zhaoyun_zzz/article/details/87302600这篇博客写的很详细,唯一有错误的地方就是pps size占了两字节 16bits 而文章中写的是8bits 一字节,这里是不对的。生成adts头文件我引用了李超老师的代码,
前面的流程是一样的都是打开输入文件,循环读取数据,数据读取出来后进行流信息判断,判断当前读出来的数据是音频还是视频,然后对应保存文件
写aac文件比较简单,生成一个adts头,然后在把数据写入
写h264文件稍微麻烦一点,要区分I帧和其他帧,参考前面提到的那片博客,对数据进行处理即可
sps和pps数据保存在 fmt_ctx->streams[pkt->stream_index]->codecpar->extradata 变量中,参考前面的博客即可完成数据的分离,注意pps-size占用两个字节
在这个基础上在进一步把分离出的h264流和aac流进行解码成yuv数据和pcm数据,这时需要创建编解码器了
前面的步骤还是一样打开文件
需要增加的是从流信息中查询使用的编码器类型,并创建解码器,同时将流信息中的编码器参数拷贝到创建的解码器中
流程一样循环读取数据,对每一路流进行判断,不同的流调用不同的解码函数然后保存文件
在decode_frame 中完成解码并保存文件
到此三步操作全部完成,试一下效果,全部正常生成了
ffmepg算是入门了,后面继续深入研究,下一步试试编码操作