Linux FFmpeg深度解析之avcodec_alloc_context3调用流程与实战(十四)

简介: CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀

Android Audio工程师专栏地址:Audio工程师进阶系列【原创干货持续更新中...... 】🚀

Android多媒体专栏地址:多媒体系统工程师系列【原创干货持续更新中...... 】🚀

专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀

专题三:Android14 Binder之HIDL与AIDL通信实战课 🚀

专题四:Android15快速自定义与集成音效实战课 🚀

专题五:Android15音频策略实战课 🚀

专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例) 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
更多原创,欢迎关注:Android系统攻城狮

点击获取二维码

🍉🍉🍉文章目录🍉🍉🍉

🌻1.前言

本篇目的:理解avcodec_alloc_context3()如何创建并初始化AVCodecContext,明确传入AVCodec与传入NULL时的差别,并通过最小程序检查新Context的初始状态。

AVCodecContext是编解码器的配置和运行状态对象。调用avcodec_alloc_context3()会分配这个对象并设置通用默认值;如果传入具体AVCodec,还会初始化对应的编解码器私有数据和默认选项。该函数不会打开编解码器,也不会开始收发Packet或Frame。
#mermaid-svg-d1Swq7KYT6ROO33w{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-d1Swq7KYT6ROO33w .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-d1Swq7KYT6ROO33w .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-d1Swq7KYT6ROO33w .error-icon{fill:#552222;}#mermaid-svg-d1Swq7KYT6ROO33w .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-d1Swq7KYT6ROO33w .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-d1Swq7KYT6ROO33w .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-d1Swq7KYT6ROO33w .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-d1Swq7KYT6ROO33w .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-d1Swq7KYT6ROO33w .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-d1Swq7KYT6ROO33w .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-d1Swq7KYT6ROO33w .marker{fill:#333333;stroke:#333333;}#mermaid-svg-d1Swq7KYT6ROO33w .marker.cross{stroke:#333333;}#mermaid-svg-d1Swq7KYT6ROO33w svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-d1Swq7KYT6ROO33w p{margin:0;}#mermaid-svg-d1Swq7KYT6ROO33w .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-d1Swq7KYT6ROO33w .cluster-label text{fill:#333;}#mermaid-svg-d1Swq7KYT6ROO33w .cluster-label span{color:#333;}#mermaid-svg-d1Swq7KYT6ROO33w .cluster-label span p{background-color:transparent;}#mermaid-svg-d1Swq7KYT6ROO33w .label text,#mermaid-svg-d1Swq7KYT6ROO33w span{fill:#333;color:#333;}#mermaid-svg-d1Swq7KYT6ROO33w .node rect,#mermaid-svg-d1Swq7KYT6ROO33w .node circle,#mermaid-svg-d1Swq7KYT6ROO33w .node ellipse,#mermaid-svg-d1Swq7KYT6ROO33w .node polygon,#mermaid-svg-d1Swq7KYT6ROO33w .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-d1Swq7KYT6ROO33w .rough-node .label text,#mermaid-svg-d1Swq7KYT6ROO33w .node .label text,#mermaid-svg-d1Swq7KYT6ROO33w .image-shape .label,#mermaid-svg-d1Swq7KYT6ROO33w .icon-shape .label{text-anchor:middle;}#mermaid-svg-d1Swq7KYT6ROO33w .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-d1Swq7KYT6ROO33w .rough-node .label,#mermaid-svg-d1Swq7KYT6ROO33w .node .label,#mermaid-svg-d1Swq7KYT6ROO33w .image-shape .label,#mermaid-svg-d1Swq7KYT6ROO33w .icon-shape .label{text-align:center;}#mermaid-svg-d1Swq7KYT6ROO33w .node.clickable{cursor:pointer;}#mermaid-svg-d1Swq7KYT6ROO33w .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-d1Swq7KYT6ROO33w .arrowheadPath{fill:#333333;}#mermaid-svg-d1Swq7KYT6ROO33w .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-d1Swq7KYT6ROO33w .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-d1Swq7KYT6ROO33w .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d1Swq7KYT6ROO33w .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-d1Swq7KYT6ROO33w .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d1Swq7KYT6ROO33w .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-d1Swq7KYT6ROO33w .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-d1Swq7KYT6ROO33w .cluster text{fill:#333;}#mermaid-svg-d1Swq7KYT6ROO33w .cluster span{color:#333;}#mermaid-svg-d1Swq7KYT6ROO33w div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-d1Swq7KYT6ROO33w .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-d1Swq7KYT6ROO33w rect.text{fill:none;stroke-width:0;}#mermaid-svg-d1Swq7KYT6ROO33w .icon-shape,#mermaid-svg-d1Swq7KYT6ROO33w .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d1Swq7KYT6ROO33w .icon-shape p,#mermaid-svg-d1Swq7KYT6ROO33w .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-d1Swq7KYT6ROO33w .icon-shape .label rect,#mermaid-svg-d1Swq7KYT6ROO33w .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d1Swq7KYT6ROO33w .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-d1Swq7KYT6ROO33w .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-d1Swq7KYT6ROO33w :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} AVCodec或NULL
avcodec_alloc_context3
分配AVCodecContext
初始化通用默认值
按需初始化编解码器私有数据
返回可配置的Context

🌻2.应用场景和用法

2.1创建编解码器配置对象

编解码流程需要一个AVCodecContext保存参数,例如编码宽高、像素格式、码率、音频采样率和声道布局。avcodec_alloc_context3()负责创建这个对象,让调用者能够继续配置并交给avcodec_open2()初始化。

传入已找到的编解码器时,Context会按该编解码器设置类型、ID和私有默认值。传入NULL时,只初始化通用默认值;调用者之后仍可以通过avcodec_open2()指定Codec,但编码器可能缺少与特定实现相关的默认设置。

用法 传入参数 得到的对象状态
创建解码Context avcodec_find_decoder()返回的AVCodec 设置解码器类型与ID,并准备相关私有默认值
创建编码Context avcodec_find_encoder()返回的AVCodec 设置编码器类型与ID,并准备相关私有默认值
延后选择Codec NULL 只创建通用Context,后续再指定Codec
分配失败 合法的Codec或NULL 返回NULL,没有可用Context
2.2函数原型与返回语义

函数原型如下:

c 复制代码
AVCodecContext *
avcodec_alloc_context3 (const AVCodec *codec);

参数codec可以是解码器、编码器对象,也可以是NULL。成功时返回新分配的AVCodecContext,失败时返回NULL。返回对象的释放责任属于调用者,应使用avcodec_free_context(),不能只对Context调用av_free()。

同一个Context一旦按某个非空Codec创建,后续调用avcodec_open2()时必须使用相同Codec或传入NULL让FFmpeg沿用已关联的Codec。这个函数只创建并初始化配置对象,不会选择文件流、不解析压缩数据,也不创建AVPacket或AVFrame。

🌻3.调用流程剖析

3.1分配内存并设置通用默认值

avcodec_alloc_context3()先分配AVCodecContext结构体内存。分配成功后调用内部初始化函数,把对象清零,设置AVClass,再根据传入Codec设置codec_type和codec_id。

初始化还会设置一组通用选项和默认回调,例如默认缓冲区申请函数、像素格式和采样格式初值、时间基初值以及声道布局状态。若传入Codec,函数会根据Codec类别配置音频、视频或字幕相关选项。
#mermaid-svg-WItaL8GRwZtBLQbg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WItaL8GRwZtBLQbg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WItaL8GRwZtBLQbg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WItaL8GRwZtBLQbg .error-icon{fill:#552222;}#mermaid-svg-WItaL8GRwZtBLQbg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WItaL8GRwZtBLQbg .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WItaL8GRwZtBLQbg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WItaL8GRwZtBLQbg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WItaL8GRwZtBLQbg .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WItaL8GRwZtBLQbg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WItaL8GRwZtBLQbg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WItaL8GRwZtBLQbg .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WItaL8GRwZtBLQbg .marker.cross{stroke:#333333;}#mermaid-svg-WItaL8GRwZtBLQbg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WItaL8GRwZtBLQbg p{margin:0;}#mermaid-svg-WItaL8GRwZtBLQbg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WItaL8GRwZtBLQbg .cluster-label text{fill:#333;}#mermaid-svg-WItaL8GRwZtBLQbg .cluster-label span{color:#333;}#mermaid-svg-WItaL8GRwZtBLQbg .cluster-label span p{background-color:transparent;}#mermaid-svg-WItaL8GRwZtBLQbg .label text,#mermaid-svg-WItaL8GRwZtBLQbg span{fill:#333;color:#333;}#mermaid-svg-WItaL8GRwZtBLQbg .node rect,#mermaid-svg-WItaL8GRwZtBLQbg .node circle,#mermaid-svg-WItaL8GRwZtBLQbg .node ellipse,#mermaid-svg-WItaL8GRwZtBLQbg .node polygon,#mermaid-svg-WItaL8GRwZtBLQbg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WItaL8GRwZtBLQbg .rough-node .label text,#mermaid-svg-WItaL8GRwZtBLQbg .node .label text,#mermaid-svg-WItaL8GRwZtBLQbg .image-shape .label,#mermaid-svg-WItaL8GRwZtBLQbg .icon-shape .label{text-anchor:middle;}#mermaid-svg-WItaL8GRwZtBLQbg .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WItaL8GRwZtBLQbg .rough-node .label,#mermaid-svg-WItaL8GRwZtBLQbg .node .label,#mermaid-svg-WItaL8GRwZtBLQbg .image-shape .label,#mermaid-svg-WItaL8GRwZtBLQbg .icon-shape .label{text-align:center;}#mermaid-svg-WItaL8GRwZtBLQbg .node.clickable{cursor:pointer;}#mermaid-svg-WItaL8GRwZtBLQbg .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WItaL8GRwZtBLQbg .arrowheadPath{fill:#333333;}#mermaid-svg-WItaL8GRwZtBLQbg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WItaL8GRwZtBLQbg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WItaL8GRwZtBLQbg .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WItaL8GRwZtBLQbg .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WItaL8GRwZtBLQbg .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WItaL8GRwZtBLQbg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WItaL8GRwZtBLQbg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WItaL8GRwZtBLQbg .cluster text{fill:#333;}#mermaid-svg-WItaL8GRwZtBLQbg .cluster span{color:#333;}#mermaid-svg-WItaL8GRwZtBLQbg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-WItaL8GRwZtBLQbg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WItaL8GRwZtBLQbg rect.text{fill:none;stroke-width:0;}#mermaid-svg-WItaL8GRwZtBLQbg .icon-shape,#mermaid-svg-WItaL8GRwZtBLQbg .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WItaL8GRwZtBLQbg .icon-shape p,#mermaid-svg-WItaL8GRwZtBLQbg .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WItaL8GRwZtBLQbg .icon-shape .label rect,#mermaid-svg-WItaL8GRwZtBLQbg .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WItaL8GRwZtBLQbg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WItaL8GRwZtBLQbg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WItaL8GRwZtBLQbg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 传入Codec指针
分配Context内存
清零结构体并设置AVClass
设置Codec类别和ID
初始化通用选项和默认回调
返回Context指针

3.2按Codec初始化私有数据

传入具体Codec后,初始化逻辑会检查该Codec是否有私有数据空间;如果有,就为priv_data分配内存,并应用Codec私有选项的默认值。Codec还可以定义一组默认参数,初始化函数会将其写入Context。

因此,传入Codec与传入NULL的区别不只是Context里是否有一个Codec指针。前者能提前获得针对该实现的默认配置,后者只具备公共的基础状态。编码器尤其可能依赖实现级默认值。

分配或私有数据初始化失败时,函数会释放已分配的Context并返回NULL。返回非空对象表示创建成功,但不代表Codec已经完成初始化。真正的打开动作由avcodec_open2()负责。

🌻4.实战案例

4.1选择解码器并准备Context

示例选择H.264解码器,并把其AVCodec对象传给avcodec_alloc_context3()。此时Context已关联解码器类型和ID,但尚未打开,也没有开始解码。

4.2检查初始状态和释放对象

程序检查Codec查找和Context分配是否成功,再确认Context中的Codec ID与选择的解码器一致。最后使用avcodec_free_context()释放对象,该接口会将指针置为NULL。

4.3完整代码
c 复制代码
#include <libavcodec/avcodec.h>

int
main (void)
{
  const AVCodec *decoder;
  AVCodecContext *context;

  /* 查找H.264解码器实现 */
  decoder = avcodec_find_decoder (AV_CODEC_ID_H264);
  if (decoder == NULL)
    return 1;

  /* 分配并初始化与该解码器关联的Context */
  context = avcodec_alloc_context3 (decoder);
  if (context == NULL)
    return 1;

  /* 检查分配结果,Context此时还没有打开 */
  if (context->codec_id != AV_CODEC_ID_H264 ||
      context->codec_type != AVMEDIA_TYPE_VIDEO) {
    avcodec_free_context (&context);
    return 1;
  }

  /* 使用配套接口释放Context及其关联资源 */
  avcodec_free_context (&context);

  return context == NULL ? 0 : 1;
}

🌻5.总结

avcodec_alloc_context3()负责分配并初始化AVCodecContext,传入具体Codec时还会准备相应的私有默认值,但它不会打开编解码器。

相关推荐
老李IT笔记2 小时前
抹除之后机器上的受管应用可以留下:这一步省掉的是哪段时间
运维·服务器
自由彩虹2 小时前
靶场通关15--bossplayersctf
linux·服务器·网络·安全·web安全·网络安全
叼烟扛炮2 小时前
Linux 学习笔记(四十五):Web 安全基石——Cookie、Session 与 HTTPS 原理解析
linux·前端·网络·笔记·学习·tcp/ip·安全
李纲明3 小时前
WordPress 定时发布不准点或备份/邮件从不跑:先分清 WP-Cron 触发与 DISABLE_WP_CRON,再查回环与系统 Cron
运维·性能优化·wordpress·定时任务·devdiy·wp-cron
菜鸟小芯3 小时前
【Quectel Pi M2 实战】Day3 USB 摄像头图像采集:拍照、录像与踩坑记录(V4L2 + FFmpeg)
ffmpeg·嵌入式
Decay__3 小时前
01_MySQL 体系架构全解 —— 连接层、SQL 层、存储引擎层与 InnoDB 深入
运维·数据库·sql·mysql·架构
Linux_cy3 小时前
nginx 502 排查手册:九种原因分类、定位命令与检查顺序
linux·运维·服务器·网络·数据库·nginx·ssh
椒颜皮皮虾྅3 小时前
模型部署不再卡在环境上:DeploySharp 四大推理引擎与 Windows/Linux 离线交付实战
linux·运维·开发语言·人工智能·windows·计算机视觉·cuda
垆边人似月.3 小时前
Ubuntu 配置 Samba 共享文件夹并映射到 Windows 完整指南
linux·windows·ubuntu