[ffmpeg] avcodec_alloc_context3 解析

背景

ffmpeg 通过 avcodec_alloc_context3 解析编码器,本文主要来解析一下,这个函数主要做了什么。

具体代码分析

主要是创建了 AVCodecContext ,并给结构体参数赋予初值。
初值设置主要分成两块,1. 所有编码器都相同的部分;2.每个编码器独有的参数设置。
接下来主要分析后者是如何设置的。

AVCodecContext *avcodec_alloc_context3(const AVCodec *codec)
{
    AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));

    if (!avctx)
        return NULL;

    if (init_context_defaults(avctx, codec) < 0) {
        av_free(avctx);
        return NULL;
    }

    return avctx;
}

static int init_context_defaults(AVCodecContext *s, const AVCodec *codec)
{
    const FFCodec *const codec2 = ffcodec(codec);
    int flags=0;
    memset(s, 0, sizeof(AVCodecContext));

    s->av_class = &av_codec_context_class;

    s->codec_type = codec ? codec->type : AVMEDIA_TYPE_UNKNOWN;
    if (codec) {
        s->codec = codec;
        s->codec_id = codec->id;
    }

    if(s->codec_type == AVMEDIA_TYPE_AUDIO)
        flags= AV_OPT_FLAG_AUDIO_PARAM;
    else if(s->codec_type == AVMEDIA_TYPE_VIDEO)
        flags= AV_OPT_FLAG_VIDEO_PARAM;
    else if(s->codec_type == AVMEDIA_TYPE_SUBTITLE)
        flags= AV_OPT_FLAG_SUBTITLE_PARAM;
    av_opt_set_defaults2(s, flags, flags);

    av_channel_layout_uninit(&s->ch_layout);

    s->time_base           = (AVRational){0,1};
    s->framerate           = (AVRational){ 0, 1 };
    s->pkt_timebase        = (AVRational){ 0, 1 };
    s->get_buffer2         = avcodec_default_get_buffer2;
    s->get_format          = avcodec_default_get_format;
    s->get_encode_buffer   = avcodec_default_get_encode_buffer;
    s->execute             = avcodec_default_execute;
    s->execute2            = avcodec_default_execute2;
    s->sample_aspect_ratio = (AVRational){0,1};
    s->ch_layout.order     = AV_CHANNEL_ORDER_UNSPEC;
    s->pix_fmt             = AV_PIX_FMT_NONE;
    s->sw_pix_fmt          = AV_PIX_FMT_NONE;
    s->sample_fmt          = AV_SAMPLE_FMT_NONE;

    s->reordered_opaque    = AV_NOPTS_VALUE;
    if(codec && codec2->priv_data_size){
        s->priv_data = av_mallocz(codec2->priv_data_size);
        if (!s->priv_data)
            return AVERROR(ENOMEM);
        if(codec->priv_class){
            *(const AVClass**)s->priv_data = codec->priv_class;
            av_opt_set_defaults(s->priv_data);
        }
    }
    if (codec && codec2->defaults) {
        int ret;
        const FFCodecDefault *d = codec2->defaults;
        while (d->key) {
            ret = av_opt_set(s, d->key, d->value, 0);
            av_assert0(ret >= 0);
            d++;
        }
    }
    return 0;
}

每个编码器独有参数设置

avcodec_alloc_context3 时,会将 codec2->priv_data_size 创建大小的内存赋值给 priv_data,并将 codec 的priv_class 赋值给 priv_data。
av_opt_set_defaults 会把 options 中的默认值,设置到 priv_data 中,相当于给编码器的参数结构体设置了默认值。

if(codec && codec2->priv_data_size){
        s->priv_data = av_mallocz(codec2->priv_data_size);
        if (!s->priv_data)
            return AVERROR(ENOMEM);
        if(codec->priv_class){
            *(const AVClass**)s->priv_data = codec->priv_class;
            av_opt_set_defaults(s->priv_data);
        }
    }

为啥 codec 的priv_class 可以直接赋值给 priv_data。以 aacenc 为例,codec 的 priv_class 为 &aacenc_class,而 codec 的 priv_data_size 为 sizeof(AACEncContext)。所有相当于 AVCodecContext 创建了 sizeof(AACEncContext) 大小的 priv_data。之所以可以这样,是因为 AACEncContext 第一个参数就是 AVClass*。相当于这也是 ffmpeg 的小技巧,应该所有的编码器变量结构体,第一个参数都是 AVClass* (看了一下 nvenc.h 也是这样的)。

static const AVClass aacenc_class = {
    .class_name = "AAC encoder",
    .item_name  = av_default_item_name,
    .option     = aacenc_options,
    .version    = LIBAVUTIL_VERSION_INT,
};

const FFCodec ff_aac_encoder = {
    .p.name         = "aac",
    CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
    .p.type         = AVMEDIA_TYPE_AUDIO,
    .p.id           = AV_CODEC_ID_AAC,
    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
                      AV_CODEC_CAP_SMALL_LAST_FRAME,
    .priv_data_size = sizeof(AACEncContext),
    .init           = aac_encode_init,
    FF_CODEC_ENCODE_CB(aac_encode_frame),
    .close          = aac_encode_end,
    .defaults       = aac_encode_defaults,
    .p.supported_samplerates = ff_mpeg4audio_sample_rates,
    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
    .p.sample_fmts  = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
                                                     AV_SAMPLE_FMT_NONE },
    .p.priv_class   = &aacenc_class,
};


typedef struct AACEncContext {
    AVClass *av_class;
    AACEncOptions options;                       ///< encoding options
    PutBitContext pb;
    FFTContext mdct1024;                         ///< long (1024 samples) frame transform context
    FFTContext mdct128;                          ///< short (128 samples) frame transform context
    AVFloatDSPContext *fdsp;
    AACPCEInfo pce;                              ///< PCE data, if needed
    float *planar_samples[16];                   ///< saved preprocessed input

    int profile;                                 ///< copied from avctx
    int needs_pce;                               ///< flag for non-standard layout
    LPCContext lpc;                              ///< used by TNS
    int samplerate_index;                        ///< MPEG-4 samplerate index
    int channels;                                ///< channel count
    const uint8_t *reorder_map;                  ///< lavc to aac reorder map
    const uint8_t *chan_map;                     ///< channel configuration map

    ChannelElement *cpe;                         ///< channel elements
    FFPsyContext psy;
    struct FFPsyPreprocessContext* psypp;
    const AACCoefficientsEncoder *coder;
    int cur_channel;                             ///< current channel for coder context
    int random_state;
    float lambda;
    int last_frame_pb_count;                     ///< number of bits for the previous frame
    float lambda_sum;                            ///< sum(lambda), for Qvg reporting
    int lambda_count;                            ///< count(lambda), for Qvg reporting
    enum RawDataBlockType cur_type;              ///< channel group type cur_channel belongs to

    AudioFrameQueue afq;
    DECLARE_ALIGNED(16, int,   qcoefs)[96];      ///< quantized coefficients
    DECLARE_ALIGNED(32, float, scoefs)[1024];    ///< scaled coefficients

    uint16_t quantize_band_cost_cache_generation;
    AACQuantizeBandCostCacheEntry quantize_band_cost_cache[256][128]; ///< memoization area for quantize_band_cost

    void (*abs_pow34)(float *out, const float *in, const int size);
    void (*quant_bands)(int *out, const float *in, const float *scaled,
                        int size, int is_signed, int maxval, const float Q34,
                        const float rounding);

    struct {
        float *samples;
    } buffer;
} AACEncContext;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/223682.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot MyBatis连接数据库 查询数据(注解方式)

创建项目时选择依赖 配置数据库连接 在resources中的 application.properties 配置文件进行连接的配置 #驱动名称 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver#连接地址 spring.datasource.urljdbc:mysql://10.20.22.11:26954/canteen#数据库用户名 spring.d…

国内AI大模型已近80个,哪个最有前途?

目前&#xff0c;国内已经推出了近80个人工智能大模型&#xff0c;这些大模型各有优势&#xff0c;难以直接判断哪个最有前途。然而&#xff0c;以下几个大模型值得关注&#xff1a; 1、华为云盘古大模型&#xff1a;盘古大模型聚焦于为行业服务&#xff0c;包括自然语言、视觉…

从认识到精通,一文读懂Memcached知识文集

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

yolov1网络结构

YOLO神经网络结构如下图所示。把一幅480x480的原图分割成7x749个网格&#xff0c;每个网格要预测两个预选框&#xff08;bounding box&#xff09;的坐标&#xff08;x&#xff0c;y&#xff0c;w&#xff0c;h&#xff09;&#xff0c;其中x和y表示box中心点与该格子边界的相对…

Vue学习计划-Vue2--Vue核心(七)生命周期

抛出问题&#xff1a;一进入页面就开启一个定时器&#xff0c;每隔1秒count就加1&#xff0c;如何实现 示例&#xff1a; <body> <div id"app">{{ n }}<button click"add">执行</button> </div><script>let vm new …

实战oj题——设计循环队列

前言&#xff1a;今天我们来实现循环队列。 各个接口的实现 创建队列&#xff1a; typedef struct {int* a;int front;int back;int k;} MyCircularQueue;我们的队列是由数组储存的&#xff0c;所以我们队列中得定义一个数组&#xff0c;front代表我们的首元素&#xff0c;ba…

flink中处理kafka分区的消息顺序

背景 kafka分区的消息是有序的&#xff0c;那么flink在消费kafka分区的时候消息的顺序是怎么样的呢&#xff1f;还能保持这个有序性吗&#xff0c;本文就来记录下 flink消费kafka分区的顺序性 从上图可知&#xff0c;flink的转换算子比如map&#xff0c;flatMap&#xff0c;f…

表单修改时取消disabled snippet

前言 有时候开发&#xff0c;表单编辑时有些字段不可更改&#xff0c;比如用户管理的用户名&#xff0c;修改时不可编辑。但是有时候就会有这么一种情况&#xff0c;希望他修改时也可编辑。所以就可以在浏览器–控制台里面写一个snippet&#xff0c;修改时运行。 当然&#xf…

Java零基础——Redis篇

1.【熟悉】NoSQL的简介 1.1 什么是NoSQL NoSQL 是 Not Only SQL 的缩写&#xff0c;意即"不仅仅是SQL"的意思&#xff0c;泛指非关系型的数据库。强调Key-Value Stores和文档数据库的优点。 NoSQL产品是传统关系型数据库的功能阉割版本&#xff0c;通过减少用不到或…

【办公软件】Win10/Win11复制粘贴必须刷新才能显示

更换了新的一台电脑&#xff0c;但是发现新建文件夹或是复制粘贴文件时&#xff0c;不管是在桌面还是在其他磁盘中都需要右击刷新一下才显示。让人很郁闷&#xff0c;比如新建一个文件夹不显示以为没有新建成功&#xff0c;导致重复建了好几个。 如何解决&#xff1f; 使用Wi…

数据结构与算法编程题43

无向无权图的邻接矩阵编程 //参考博客&#xff1a;https://blog.csdn.net/qq_54162207/article/details/117414707#include <iostream> using namespace std;#define Maxsize 100 #define VertexmMaxNum 20 #define ERROR 0 #define OK 1 typedef string VertexType…

Python代码将txt里面多行json字符串转成excel文件

python 代码 将txt里面的多行json字符串转成excel history.txt文件json代码样例 Json转换Excel代码 import json import pandas as pddef json_out(file_path,excel_path):all_list[]with open(file_path, "r", encodingutf-8) as f:for line in f:all_list.append…

实验一:MIPS指令系统和MIPS体系结构

MIPS架构 MIPS架构&#xff08;英语&#xff1a;MIPS architecture&#xff0c;为Microprocessor without interlocked piped stages architecture的缩写&#xff0c;亦为Millions of Instructions Per Second的双关语&#xff09;&#xff0c;是一种采取精简指令集&#xff0…

Unity中Batching优化的GPU实例化(1)

文章目录 前言一、GPU实例化的规则1、必须满足 Mesh 网格一样2、只有OpenGL es 3.0及以上才支持&#xff08;3.0及以上有部分硬件可能也不支持&#xff09; 二、GPU实例化的应用场景1、公开几个成员属性&#xff0c;用于存放可以调整的数据2、用Random.insideUnitCircle随机生成…

ansible常用模块介绍

ansible运行模块的两种方式 Ad - Hoc 利用 ansible 命令直接完成管理 &#xff0c; 主要用于临时命令使用场景 ansible westos -m shell -a ls /mnt playbook ansible 脚本 &#xff0c; 主要用于大型项目场景 &#xff0c; 需要前期的规划 vim test.yml - hosts: all task…

【后端】JVM 远程调试

前言 再好的代码,也还是有瑕疵的,不是代码不给力,是线上问题太牛逼太玄幻。这不刚部署就出现了问题,幸好还是测试的时候,早点发现早点解决,不给任何人带来不必要的损失,是我做人的原则,只要钱到位,任何问题都不是问题。 JVM 远程调试 不得不说 IDEA 和 宝塔配合是真…

Windows驱动中使用数字签名验证控制设备访问权限

1. 背景 在一般的驱动开发时&#xff0c;创建了符号链接后在应用层就可以访问打开我们的设备并进行通讯。 但我们有时候不希望非自己的进程访问我们的设备并进行交互&#xff0c;虽然可以使用 IoCreateDeviceSecure 来创建有安全描述符的设备&#xff0c;但大数的用户账户为了方…

多人聊天室

1.创建服务面板 package yiduiy;import java.awt.BorderLayout; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Has…

STM32串口接收数据包(自定义帧头帧尾)

1、基本概述 本实验基于stm32c8t6单片机&#xff0c;串口作为基础且重要的外设&#xff0c;具有广泛的应用。本文主要理解串口数据包的发送与接收是如何实现的&#xff0c;重要的是理解程序的实现思路。 2、关键程序 定义好需要用到的变量&#xff1a; uint8_t rxd_buf[4];//…

Gti GUI添加标签

通过Git Gui打开项目&#xff0c;通过菜单打开分支历史&#xff0c;我这里是名为"develop"的分支 选中需要打标签的commit&#xff0c;右键-Create tag即可 但貌似无法删除标签&#xff0c;只能通过git bash
最新文章