简介:CSDN博客专家、《Android系统多媒体进阶实战》作者
博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中……】🚀
Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中……】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课🚀
专题四:Android15快速自定义与集成音效实战课🚀
专题五:Android15音频策略实战课🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例)🚀
人生格言:人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
点击获取二维码
🍉🍉🍉文章目录🍉🍉🍉
- 🌻1.前言
- 🌻2.应用场景和用法
- 2.1在参数对象之间复制编码信息
- 2.2函数原型与返回语义
- 🌻3.调用流程剖析
- 3.1重置目标并复制字段
- 3.2复制结果进入转封装或编码流程
- 🌻4.实战案例
- 4.1准备源参数和目标对象
- 4.2执行深拷贝并检查字段
- 4.3完整代码
- 🌻5.总结
🌻1.前言
本篇目的:理解
avcodec_parameters_copy()如何把一个AVCodecParameters对象的参数复制到另一个对象,并通过实战检查动态数据是否独立。
封装格式中的AVStream通过codecpar保存流的编码参数。转封装或创建过滤器链时,常常需要把一条流的参数复制到另一对象。
avcodec_parameters_copy()会先重置目标对象,再复制参数,并为外部数据分配独立存储。它不复制音视频帧,也不负责把参数写入容器。
🌻2.应用场景和用法
2.1在参数对象之间复制编码信息
该接口适合复制源流的编解码参数到另一个AVCodecParameters,例如转封装时从输入流复制到输出流,或把参数复制到码流过滤器的输入参数对象。
| 场景 | 复制目标 | 复制后仍需处理的内容 |
|---|---|---|
| 转封装 | 输入流codecpar到输出流codecpar | 根据输出容器要求处理codec_tag等字段 |
| 码流过滤器 | 流参数到过滤器par_in | 初始化过滤器并处理其输出参数 |
| 参数快照 | 当前参数对象到新分配的对象 | 管理新对象的释放 |
| 初始化编码上下文 | 不应直接用此函数 | 使用avcodec_parameters_to_context() |
2.2函数原型与返回语义
intavcodec_parameters_copy(AVCodecParameters*dst,constAVCodecParameters*src);| 参数或返回值 | 含义 |
|---|---|
dst | 已分配的目标参数对象 |
src | 要复制的源参数对象 |
| 返回值 | 成功返回非负值,失败返回负的AVERROR错误码 |
函数会先释放目标对象已持有的动态数据,再复制结构字段。extradata、编码侧数据和AVChannelLayout等需要管理的内容会建立目标侧自己的存储。函数不接管源对象,也不改变源对象的所有权。
目标对象应由avcodec_parameters_alloc()创建,并在使用后通过avcodec_parameters_free()释放。若目标需要变成AVCodecContext,应使用avcodec_parameters_to_context();反向从上下文生成参数则使用avcodec_parameters_from_context()。
🌻3.调用流程剖析
3.1重置目标并复制字段
源码先调用内部重置逻辑清理目标对象,再把源结构中的字段复制到目标。随后将动态字段指针置空,避免目标对象沿用源对象的地址。
对于extradata,函数按extradata_size分配带输入缓冲区填充空间的新内存并复制字节。它还复制编码侧附加数据,并通过av_channel_layout_copy()建立独立声道布局。
复制不是合并:目标原有参数会被重置,之后由源对象的内容替代。实现先重置目标再读取源字段,因此源和目标必须是不同对象,不能把同一个指针同时作为dst和src。
3.2复制结果进入转封装或编码流程
转封装时,常见关系是in_stream->codecpar复制到out_stream->codecpar。复制成功后,应用还可能根据输出容器要求调整codec_tag,并设置输出流时间基,再写入容器头。
参数复制本身不执行码流转换。若编码格式、分辨率或采样格式需要改变,应进入解码、处理和重新编码流程,而不是只复制参数对象。
🌻4.实战案例
4.1准备源参数和目标对象
案例构造AAC音频参数,设置采样率、码率、声道布局和两字节AudioSpecificConfig,再分别分配源对象与目标对象。
4.2执行深拷贝并检查字段
调用avcodec_parameters_copy()后检查返回值、基本字段、声道布局和extradata内容。目标extradata应有自己的分配空间,释放目标对象不会释放源对象的数据。
4.3完整代码
#include<libavcodec/codec_par.h>#include<libavcodec/avcodec.h>#include<libavutil/mem.h>#include<string.h>intmain(void){AVCodecParameters*src=NULL;AVCodecParameters*dst=NULL;intret=1;constuint8_taac_config[2]={0x12,0x10};src=avcodec_parameters_alloc();dst=avcodec_parameters_alloc();if(src==NULL||dst==NULL)gotodone;/* 设置源对象的基本AAC音频参数 */src->codec_type=AVMEDIA_TYPE_AUDIO;src->codec_id=AV_CODEC_ID_AAC;src->format=AV_SAMPLE_FMT_FLTP;src->sample_rate=44100;src->bit_rate=128000;av_channel_layout_default(&src->ch_layout,2);/* 准备带FFmpeg要求填充空间的codec extradata */src->extradata=av_mallocz(sizeof(aac_config)+AV_INPUT_BUFFER_PADDING_SIZE);if(src->extradata==NULL)gotodone;memcpy(src->extradata,aac_config,sizeof(aac_config));src->extradata_size=sizeof(aac_config);/* 将源参数复制到独立目标对象 */if(avcodec_parameters_copy(dst,src)<0)gotodone;/* 检查普通字段和动态extradata是否正确复制 */if(dst->codec_id!=src->codec_id||dst->sample_rate!=src->sample_rate||dst->bit_rate!=src->bit_rate||dst->extradata_size!=src->extradata_size||dst->extradata==src->extradata||memcmp(dst->extradata,src->extradata,src->extradata_size)!=0)gotodone;ret=0;done:/* 两个参数对象分别拥有各自的动态数据 */avcodec_parameters_free(&dst);avcodec_parameters_free(&src);returnret;}🌻5.总结
avcodec_parameters_copy()重置目标并复制源参数,为动态字段建立独立存储,不处理音视频帧或容器写入。