ffmpeg新手成长之路——关于flv转封装过程中编码器信息变化如何处理(困扰已久的avc sequence header更新问题)

ffmpeg新手成长之路
——关于flv转封装过程中编码器信息变化如何处理(困扰已久的avc sequence header更新问题)

一、背景介绍

	私有协议传输H264裸流,进行录制,使用ffmpeg做flv封装。受限于网络情况或者实际录制需求,H264裸流数据源发生变化,编码信息肯定也要更新咯!
	比如说,刚开始视频源是个1920*1080的,但是数据源作为数据发送方通过网络带宽统计,得知当前网络丢包严重,画面需要降质,分辨率调整为720*576,接收过程中识别到视频源编码信息发生了变化,需要把编码信息变化实时更新到flv容器中。
	在flv封装格式中,主要通过一个avc sequence header的Tag来更新H264编码信息,那么问题来了,如何把识别到的编码信息变化写到这个结构中呢,下面来追本溯源。

二、AVCodecContext中的extradata结构

	编解码上下文信息中的extradata结构记录了一些额外的编码信息,这部分信息是avcodec需要用到的。注意看这个变量名extradata,后续另外一个地方也出现了extradata。
	通过查阅网上很多用例,不难看出,h264编码中很重的sps和pps信息就存储在extradata中。
	 /**
     * some codecs need / can use extradata like Huffman tables.
     * MJPEG: Huffman tables
     * rv10: additional flags
     * MPEG-4: global headers (they can be in the bitstream or here)
     * The allocated memory should be AV_INPUT_BUFFER_PADDING_SIZE bytes larger
     * than extradata_size to avoid problems if it is read with the bitstream reader.
     * The bytewise contents of extradata must not depend on the architecture or CPU endianness.
     * - encoding: Set/allocated/freed by libavcodec.
     * - decoding: Set/allocated/freed by user.
     */
    uint8_t *extradata;
    int extradata_size;

三、AVPacket中的AVPacketSideData结构

	笔者苦苦追寻更新avc sequence header的方法,一直以为这个信息是avcodec范畴修改才能才能更新的,曾经尝试更新AVCodecContext,无果……想来想去,ffmpeg不至于这么狠,不给用户开放修改的接口,但是苦于初学入门,不知道ffmpeg博大精深啊。很久以后,无意无意间发现AVPacket有这么side_data一个变量,很纳闷,想要了解一下。
	/**
     * Additional packet data that can be provided by the container.
     * Packet can contain several types of side information.
     */
    AVPacketSideData *side_data;
	通过注释,还是可以看出,这个变量存储的信息,可能封装时容器会用到。(~正中下怀啊)
	再细看,AVPacketSideDataType 枚举中还有个AV_PKT_DATA_NEW_EXTRADATA类型。(~是不是很眼熟,extradata, extradata)。灵光一闪,莫不是我要找的答案???
	typedef struct AVPacketSideData {
	    uint8_t *data;
	    int      size;
	    enum AVPacketSideDataType type;
	} AVPacketSideData;

	/**
	 * @defgroup lavc_packet AVPacket
	 *
	 * Types and functions for working with AVPacket.
	 * @{
	 */
	enum AVPacketSideDataType {
	   ...
	
	    /**
	     * The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format
	     * that the extradata buffer was changed and the receiving side should
	     * act upon it appropriately. The new extradata is embedded in the side
	     * data buffer and should be immediately used for processing the current
	     * frame or packet.
	     */
	    AV_PKT_DATA_NEW_EXTRADATA,
	
	 ...
	};
	写的多清楚,这个信息用于通知编解码器或者格式封装处理,有写编码信息发生变化了。试想,播放器解析到封装数据、编解码信息中的信息变化,是该做出重置解码器的动作了,Binggo~~~

四、如何更新AVPacketSideData

	给AVPacket添加side_data信息,信息内容当然是sps和pps了
	uint8_t* side_data = av_packet_new_side_data(&AVPacket_, AV_PKT_DATA_NEW_EXTRADATA, sps_ppslen);
	if (side_data)
	{
		memcpy(side_data, sps_pps, sps_ppslen);
	}
	看下函数声明,这个函数自动给AVPacket分配了side_data的空间,而av_packet_free_side_data函数则可以释放分配的空间。
/**
 * Allocate new information of a packet.
 *
 * @param pkt packet
 * @param type side information type
 * @param size side information size
 * @return pointer to fresh allocated data or NULL otherwise
 */
uint8_t* av_packet_new_side_data(AVPacket *pkt, enum AVPacketSideDataType type,
                                 int size);
/**
 * Convenience function to free all the side data stored.
 * All the other fields stay untouched.
 *
 * @param pkt packet
 */
void av_packet_free_side_data(AVPacket *pkt);

FFmpeg是一个用于处理多媒体数据的开源框架,其包含了众多的编解码库,可以支持各种音视频格式的码、处理和播放。其,libfdk-aac是一个高质量的AAC音频编码库,它的优势在于输出的音频质量非常高,而且编码速度也比其他编码库要快。 在使用FFmpeg进行音频编码时,默认情况下使用的是libmp3lame编码库,但是在有些情况下,比如需要输出更高质量的音频数据时,就可以考虑使用libfdk-aac编码库,以获得更好的音频输出效果。 下面是使用FFmpeg编译安装libfdk-aac编码库的步骤: 1. 下载libfdk-aac源代码 可以在官网(https://github.com/mstorsjo/fdk-aac)下载最新的libfdk-aac源代码,也可以选择在其他开源镜像网站上下载。 2. 编译安装libfdk-aac 通过以下命令进入libfdk-aac源代码目录,执行configure和make命令进行编译和安装: ``` $ cd /path/to/libfdk-aac $ ./configure --prefix=/usr/local --enable-shared $ make && sudo make install ``` 其,--prefix=/usr/local表示将libfdk-aac安装到系统默认的库目录下,--enable-shared表示编译生成共享库文件。 3. 配置FFmpeg编译选项 在FFmpeg编译时,需要指定使用libfdk-aac编码库,可以通过以下命令进行配置: ``` $ ./configure --enable-gpl --enable-libfdk-aac --enable-nonfree $ make && sudo make install ``` 其,--enable-gpl表示启用GPL协议,--enable-libfdk-aac表示启用libfdk-aac编码库,--enable-nonfree表示启用非免费的编码库。 4. 使用libfdk-aac进行音频编码 在FFmpeg进行音频编码时,需要指定使用libfdk-aac编码库,可以通过以下命令进行操作: ``` $ ffmpeg -i input.wav -c:a libfdk_aac -b:a 128k output.aac ``` 其,-c:a libfdk_aac表示使用libfdk-aac编码库进行音频编码,-b:a 128k表示设置输出音频的比特率为128kbps。 通过以上步骤,就可以成功地使用libfdk-aac扩展FFmpeg的编码功能,获得更高质量的音频输出效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值