FFmpeg学习:FFmpeg4数据结构分析

news2024/11/27 15:56:47

FFmpeg数据结构分析

FFMPEG中结构体很多。最关键的结构体可以分成以下几类:

1、解协议(http,rtsp,rtmp,mms)

AVIOContext,URLProtocol,URLContext主要存储视音频使用的协议的类型以及状态。URLProtocol存储输入视音频使用的封装格式。每种协议都对应一个URLProtocol结构。(注意:FFMPEG中文件也被当做一种协议“file”)

2、解封装(flv,avi,rmvb,mp4)

AVFormatContext主要存储视音频封装格式中包含的信息;AVInputFormat存储输入视音频使用的封装格式。每种视音频封装格式都对应一个AVInputFormat 结构。

3、解码(h264,mpeg2,aac,mp3)

每个AVStream存储一个视频/音频流的相关数据;每个AVStream对应一个AVCodecContext,存储该视频/音频流使用解码方式的相关数据;每个AVCodecContext中对应一个AVCodec,包含该视频/音频对应的解码器。每种解码器都对应一个AVCodec结构。

4、存数据

视频的话,每个结构一般是存一帧;音频可能有好几帧
解码前数据:AVPacket
解码后数据:AVFrame

它们之间的关系如下图所示

AVFormatContext(位于avformat.h)

  • 描述媒体文件或媒体流的构成和基本信息,贯穿ffmpeg使用整个流程,很多函数都要用到它作为参数。它是FFMPEG解封装(flv,mp4,rmvb,avi)功能的结构体。下面看几个主要变量的作用
AVInputFormat *iformat、AVOutputFormat *oformat:输入或者输出流的格式(只能存在一个)
AVIOContext *pb:管理输入输出数据        
unsigned int nb_streams:音视频流的个数
AVStream **streams:音视频流        
char *url:文件名
int64_t duration:时长
int bit_rate:比特率(单位bite/s)
AVDictionary *metadata:元数据(查看元数据:ffprobe filename)
  • 视频的时长可以转换成HH:MM:SS的形式,示例代码如下:
AVFormatContext *pFormatCtx;
CString timelong;
...
//duration是以微秒为单位
//转换成hh:mm:ss形式
int tns, thh, tmm, tss;
tns  = (pFormatCtx->duration)/1000000;
thh  = tns / 3600;
tmm  = (tns % 3600) / 60;
tss  = (tns % 60);
timelong.Format("%02d:%02d:%02d",thh,tmm,tss);
  • 视频的原数据(metadata)信息可以通过AVDictionary获取。元数据存储在AVDictionaryEntry结构体中,如下所示
typedef struct AVDictionaryEntry {
    char *key;
    char *value;
} AVDictionaryEntry;

每一条元数据分为key和value两个属性。
在ffmpeg中通过av_dict_get()函数获得视频的原数据。
下列代码显示了获取元数据并存入meta字符串变量的过程,注意每一条key和value之间有一个"\t:",value之后有一个"\r\n"

//MetaData------------------------------------------------------------
//从AVDictionary获得
//需要用到AVDictionaryEntry对象
//CString author,copyright,description;
CString meta=NULL,key,value;
AVDictionaryEntry *m = NULL;
//使用循环读出
//(需要读取的数据,字段名称,前一条字段(循环时使用),参数)
while(m=av_dict_get(pFormatCtx->metadata,"",m,AV_DICT_IGNORE_SUFFIX)){
	key.Format(m->key);
	value.Format(m->value);
	meta+=key+"\t:"+value+"\r\n" ;
}

AVInputFormat 文件封装格式

char* name:封装格式的名字
char* long_name:封装格式的长名字
char* extensions:文件扩展名

AVIOContext(位于 avio.h)

AVIOContext:文件(协议)操作的顶层对象

  • AVIOContext是FFMPEG管理输入输出数据的结构体。本文将会详细分析一下该结构体里每个变量的含义和作用。
unsigned char *buffer:缓冲开始位置
int buffer_size:缓冲区大小(默认32768)
unsigned char *buf_ptr:当前指针读取到的位置
unsigned char *buf_end:缓存结束的位置
void *opaque:URLContext结构体
(*read_packet)(...):读取音视频数据的函数指针
(*write_packet)(...):写入音视频数据的函数指针
(*read_pause)(...):网络流媒体协议的暂停或恢复播放函数指针

在解码的情况下,buffer用于存储ffmpeg读入的数据。例如打开一个视频文件的时候,先把数据从硬盘读入buffer,然后在送给解码器用于解码。

其中opaque指向了URLContext。注意,这个结构体并不在FFMPEG提供的头文件中,而是在FFMPEG的源代码中。

URLContext:每种协议,有一个协议操作对象和一个关联的协议对象

char* name:协议名称
const struct URLProtocol *prot:协议操作对象(ff_file_protocol、ff_librtmp_protocol...)
void *priv_data:协议对象(FileContext、LibRTMPContext)

URLContext结构体中还有一个结构体URLProtocol。注:每种协议(rtp,rtmp,file等)对应一个URLProtocol。这个结构体也不在FFMPEG提供的头文件中。

URLProtocol:协议操作对象

从FFMPEG源代码中翻出其的定义:

typedef struct URLProtocol {
	const char *name;
	int (*url_open)(URLContext *h, const char *url, int flags);
	int (*url_read)(URLContext *h, unsigned char *buf, int size);
	int (*url_write)(URLContext *h, const unsigned char *buf, int size);
	int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);
	int (*url_close)(URLContext *h);
	struct URLProtocol *next;
	int (*url_read_pause)(URLContext *h, int pause);
	int64_t (*url_read_seek)(URLContext *h, int stream_index,
		int64_t timestamp, int flags);
	int (*url_get_file_handle)(URLContext *h);
	int priv_data_size;
	const AVClass *priv_data_class;
	int flags;
	int (*url_check)(URLContext *h, int mask);
} URLProtocol;

在这个结构体中,除了一些回调函数接口之外,有一个变量const char *name,该变量存储了协议的名称。每一种输入协议都对应这样一个结构体。

AVStream

  • AVStream是存储每一个视频/音频流信息的结构体
int index:音频流或视频流的索引
AVRational time_base:计算pts或dts是使用的时间戳基本单位(显示时间:pt = av_q2d(video_stream->time_base) * frame->pts)
int64_t duration:该视频/音频流长度
AVRational avg_frame_rate:平均帧率(对于视频来说,frame_rate=avg_frame_rate.num / avg_frame_rate.den)
AVCodecParameters *codecpar:解码器参数

AVCodecParameter 和 AVCodecContext

  • 新的 ffmpeg 中 AVStream.codecpar(struct AVCodecParameter) 代替 AVStream.codec(struct AVCodecContext):AVCodecParameter 是由 AVCodecContext 分离出来的,AVCodecParameter中没有函数
  • AVCodecContext 结构体仍然是编解码时不可或缺的结构体:avcodec_send_packet 和 avcodec_receive_frame 使用 AVCodecContext
  • AVCodecContext 和 AVCodec 的获取方法
//=============== new version code ===============
char filePath[] = "test.mp4";
AVFormatContext  *pFormatCtx;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
pFormatCtx = avformat_alloc_context();
 
av_register_all();
avformat_network_init();
avformat_open_input(&pFormatCtx, filePath, NULL, NULL);
avformat_find_stream_info(pFormatCtx, NULL);
for (int i = 0; i < pFormatCtx->nb_streams; i++)
{
    AVStream *pStream = pFormatCtx->streams[i];
    pCodec = avcodec_find_decoder(pStream->codecpar->codec_id);
    pCodecCtx = avcodec_alloc_context3(pCodec);
    avcodec_parameters_to_context(pCodecCtx, pStream->codecpar);
}
  • AVCodecContext关键参数:可参考 avcodec_parameters_to_context 源码
num AVMediaType codec_type:编解码器的类型(视频,音频...)
enum AVCodecID codec_id:标示特定的编码器
AVCodecContext:struct AVCodec *codec:采用的解码器AVCodec(H.264,MPEG2...)
int bit_rate:平均比特率
uint8_t *extradata; int extradata_size:针对特定编码器包含的附加信息(例如对于H.264解码器来说,存储SPS,PPS等)
AVCodecContext:enum AVPixelFormat pix_fmt:像素格式(视频)
int width, height:宽和高(视频)
AVCodecContext:enum AVSampleFormat sample_fmt:采样格式(音频)
int sample_rate:采样率(音频)
int channels:声道数(音频)
uint64_t channel_layout:声道格式
AVCodecParameters:int format:像素格式(视频)/采样格式(音频)

AVCodec:编解码器结构体

  • AVCodec是存储编解码器信息的结构体
  • 关键成员变量如下:
const char *name:编解码器短名字(形如:"h264")
const char *long_name:编解码器全称(形如:"H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10")
enum AVMediaType type:媒体类型:视频、音频或字母
enum AVCodecID id:标示特定的编码器
const AVRational *supported_framerates:支持的帧率(仅视频)
const enum AVPixelFormat *pix_fmts:支持的像素格式(仅视频)
const int *supported_samplerates:支持的采样率(仅音频)
const enum AVSampleFormat *sample_fmts:支持的采样格式(仅音频)
const uint64_t *channel_layouts:支持的声道数(仅音频)

enum AVMediaType type

  • AVMediaType定义如下:
enum AVMediaType {
    AVMEDIA_TYPE_UNKNOWN = -1,  ///< Usually treated as AVMEDIA_TYPE_DATA
    AVMEDIA_TYPE_VIDEO,
    AVMEDIA_TYPE_AUDIO,
    AVMEDIA_TYPE_DATA,          ///< Opaque data information usually continuous
    AVMEDIA_TYPE_SUBTITLE,
    AVMEDIA_TYPE_ATTACHMENT,    ///< Opaque data information usually sparse
    AVMEDIA_TYPE_NB
};

enum AVCodecID id

  • AVCodecID定义如下:
enum AVCodecID {
    AV_CODEC_ID_NONE,
 
    /* video codecs */
    AV_CODEC_ID_MPEG1VIDEO,
    AV_CODEC_ID_MPEG2VIDEO, ///< preferred ID for MPEG-1/2 video decoding
    AV_CODEC_ID_MPEG2VIDEO_XVMC,
    AV_CODEC_ID_H261,
    AV_CODEC_ID_H263,
    AV_CODEC_ID_RV10,
    AV_CODEC_ID_RV20,
    AV_CODEC_ID_MJPEG,
    AV_CODEC_ID_MJPEGB,
    AV_CODEC_ID_LJPEG,
    AV_CODEC_ID_SP5X,
    AV_CODEC_ID_JPEGLS,
    AV_CODEC_ID_MPEG4,
    AV_CODEC_ID_RAWVIDEO,
    AV_CODEC_ID_MSMPEG4V1,
    AV_CODEC_ID_MSMPEG4V2,
    AV_CODEC_ID_MSMPEG4V3,
    AV_CODEC_ID_WMV1,
    AV_CODEC_ID_WMV2,
    AV_CODEC_ID_H263P,
    AV_CODEC_ID_H263I,
    AV_CODEC_ID_FLV1,
    AV_CODEC_ID_SVQ1,
    AV_CODEC_ID_SVQ3,
    AV_CODEC_ID_DVVIDEO,
    AV_CODEC_ID_HUFFYUV,
    AV_CODEC_ID_CYUV,
    AV_CODEC_ID_H264,
    ...(代码太长,略)
}

const enum AVPixelFormat *pix_fmts

  • AVPixelFormat定义如下:
enum AVPixelFormat {
    AV_PIX_FMT_NONE = -1,
    AV_PIX_FMT_YUV420P,   ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
    AV_PIX_FMT_YUYV422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
    AV_PIX_FMT_RGB24,     ///< packed RGB 8:8:8, 24bpp, RGBRGB...
    AV_PIX_FMT_BGR24,     ///< packed RGB 8:8:8, 24bpp, BGRBGR...
    AV_PIX_FMT_YUV422P,   ///< planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
    AV_PIX_FMT_YUV444P,   ///< planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
    AV_PIX_FMT_YUV410P,   ///< planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples)
    AV_PIX_FMT_YUV411P,   ///< planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
    AV_PIX_FMT_GRAY8,     ///<        Y        ,  8bpp
    AV_PIX_FMT_MONOWHITE, ///<        Y        ,  1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb
    AV_PIX_FMT_MONOBLACK, ///<        Y        ,  1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb
    AV_PIX_FMT_PAL8,      ///< 8 bit with PIX_FMT_RGB32 palette
    AV_PIX_FMT_YUVJ420P,  ///< planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV420P and setting color_range
    AV_PIX_FMT_YUVJ422P,  ///< planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV422P and setting color_range
    AV_PIX_FMT_YUVJ444P,  ///< planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of PIX_FMT_YUV444P and setting color_range
    AV_PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing
    AV_PIX_FMT_XVMC_MPEG2_IDCT,
    ...(代码太长,略)
}

AVPacket(位于avcodec.h文件中)

  • AVPacket是存储压缩编码数据相关信息的结构体
  • 关键成员变量
AVBufferRef *buf:管理data指向的数据
uint8_t *data:压缩编码的数据
int size:data的大小
int64_t pts:显示时间戳
int64_t dts:解码时间戳
int stream_index:标识该AVPacket所属的视频/音频流
  • AVPacket内存管理:AVPacket本身并不包含压缩的数据,通过data指针引用数据的缓存空间
  • 多个AVPacket共享同一个数据缓存(AVBufferRef、AVBuffer)
  • AVBuffer拥有独立的数据缓存

AVBuffer 关键成员变量

uint8_t *data:压缩编码的数据
size_t size:数据长度
atomic_uint refcount:引用计数,如果引用计数为0,则释放数据缓存空间

AVFrame(位于avcodec.h)详细链接

  • AVFrame是包含码流参数较多的结构体,存储解码后数据的结构体。
uint8_t *data[AV_NUM_DATA_POINTERS]:解码后原始数据(对视频来说是YUV,RGB,对音频来说是PCM)
int linesize[AV_NUM_DATA_POINTERS]:data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。
int width, height:视频帧宽和高(1920x1080,1280x720...)
int nb_samples:音频的一个AVFrame中可能包含多个音频帧,在此标记包含了几个
int format:解码后原始数据类型(YUV420,YUV422,RGB24...)
int key_frame:是否是关键帧
enum AVPictureType pict_type:帧类型(I,B,P...)
AVRational sample_aspect_ratio:图像宽高比(16:9,4:3...)
int64_t pts:显示时间戳
int coded_picture_number:编码帧序号
int display_picture_number:显示帧序号

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【软件工程题库】第一章 软件工程概述

&#x1f57a;作者&#xff1a; 迷茫的启明星 学习路线C语言从0到1C初阶数据结构从0到1 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

View的事件分发机制

View的事件分发机制 View的事件分发机制主要分为三点 ,第一点是Activity将点击事件分发给ViewGroup 第二点是ViewGroup将事件自己处理或者分发给子View 第三点便是子View自行处理,或者子View处理不了转交给ViewGroup 现在依次来看 Activity对点击事件的分发过程 Activit…

运用go语言的模板(template)写的第一个程序示例

一、模板&#xff08;template&#xff09;与渲染 模板其实就相当于一个简历模板&#xff0c;上面的格式都是已经确定了的渲染就是往对应的地方填写相应的数据 二、模板 模板文件通常定义为.tmpl和.tpl为后缀&#xff08;也可以使用其他的后缀&#xff09;&#xff0c;必须…

手把手带你利用苹果手机使用美区礼品卡升级ChatGPT Plus,轻松搞定!

大家好&#xff0c;我是五竹。 昨天用苹果手机尝试了一下&#xff0c;借助App Store&#xff08;苹果应用商店&#xff09;升级 Plus&#xff0c;成功了&#xff01;一共升级了三个号&#xff01;有两个一气呵成&#xff0c;轻松搞定。最后一个可能触发风控了&#xff0c;但第…

OOB配对原理及应用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言一、OOB是啥&#xff1f;二、OOB配对实践总结 前言 本文先简单介绍OOB配对的流程&#xff0c;然后结合CC2652蓝牙芯片调试OOB配对 一、OOB是啥&#xff1f; OOB就是…

博客系统后端设计(六) -实现登录页面要求强制登录功能

文章目录 实现页面要求强制登录实现思路1.约定前后端交互接口2.实现后端代码3.修改前端代码 实现页面要求强制登录 当用户访问列表页/详情页/编辑页的时候&#xff0c;要求用户已经是登录的状态了&#xff0c; 如果用户还没登录&#xff0c;就会强制跳转到登录页面。 实现思路…

一文盘点PoseiSwap近期的生态利好

PoseiSwap 是 Nautilus Chain 上首个 DEX&#xff0c;其继承了 Nautilus Chain 的模块化、Layer3 以及 Zk-rollup 所带来的优势&#xff08;TPS 在 2000&#xff09;&#xff0c;包括吞吐量、安全度、隐私性等。基于 Nautilus Chain&#xff0c;PoseiSwap 也将具备基于 Zk 的隐…

Ceph crush运行图

Crush map介绍 ceph集群中由monitor负责维护的运行图包括&#xff1a; Monitor map&#xff1a;监视器运行图osd map&#xff1a;osd运行图PG map&#xff1a;PG运行图Crush map&#xff1a;crush运行图Mds map&#xff1a;mds运行图 crush map是ceph集群物理拓扑的抽象&…

HTML、PHP实战:搭建一个网页登录页面。

一、实验环境。 MySQL5.7.26 FTP0.9.60 Apache2.4.39 我这里用的是PHPstudy小皮一键搭建的。 数据库 二、登录页面。 登录页面前端代码 文件名&#xff1a;denglu.html <html> <head> <meta charset"UTF-8"> <title>登录界面</ti…

StarRocks 极速全场景 MPP 数据库介绍及使用

一、简介 StarRocks 是一款高性能分析型数据仓库&#xff0c;使用向量化、MPP 架构、CBO、智能物化视图、可实时更新的列式存储引擎等技术实现多维、实时、高并发的数据分析。既支持从各类实时和离线的数据源高效导入数据&#xff0c;也支持直接分析数据湖上各种格式的数据。兼…

Linux基本指令3

目录 一.基本常用指令 指令1&#xff1a;find命令&#xff1a; 指令2&#xff1a;which命令&#xff1a; 指令3&#xff1a;alias命令&#xff1a; 指令4&#xff1a;whereis which&#xff0c;find&#xff0c;whereis这三个搜索命令的区别&#xff1a; 指令5&#xff…

Vue初始

一、Vue的概述 Vue 发音类似 view Vue 游雨溪 鱿鱼须 鱿鱼须不懂Vue Vue历史 Angular React Vue 2013 Seed 2013 Seed命名为Vue 2014 Vue正式发布 0.8 - 0.10 2015 6.13 0.12 2015下半年 vue-cli vueRouter vueX 版本好1.0 vue正式跨入大众 渐进式框架(JQuery) 2016国…

[CTF/网络安全]攻防世界unserialize3解题详析及php序列化反序列化实例讲解

[CTF/网络安全]攻防世界unserialize3解题详析及php序列化反序列化实例讲解 _wakeup()及php序列化反序列化序列化字符串结构分析_wakeup()的利用 解题思路伪属性数量绕过 解题姿势总结 _wakeup()及php序列化反序列化 序列化是指将数据结构或对象转换为可传输或可存储的格式的过…

14.Kafka系列之K8S部署集群

1. 部署方式选择 基于Kafka3.X后的集群搭建方式主要分为两种&#xff0c;一种是基于Zookeeper管理方式&#xff0c;一种是基于KRaft模式&#xff0c;本文主要介绍Kafka-KRaft集群模式搭建 纠正文章1.Kafka系列之K8S部署单节点中基于Zookeeper方式的部署方式错误&#xff0c;其…

Godot引擎 4.0 文档 - 入门介绍 - Godot设计理念

本文为Google Translate英译中结果&#xff0c;DrGraph在此基础上加了一些校正。英文原版页面&#xff1a; Godots design philosophy — Godot Engine (stable) documentation in English Godot设计理念 既然你已经了解了&#xff0c;让我们来谈谈 Godot 的设计。 每个游戏…

(转载)MATLAB智能算法30个案例分析(1)——遗传算法工具箱

以下内容大部分来源于《MATLAB智能算法30个案例分析》&#xff0c;仅为学习交流所用。 1理论基础 1.1遗传算法概述 遗传算法(genetic algorithm,GA)是一种进化算法,其基本原理是仿效生物界中的“物竞天择、适者生存”的演化法则。遗传算法是把问题参数编码为染色体,再利用迭代…

第11届蓝桥杯Scratch选拔赛真题集锦

目录 一、编程题 第11届蓝桥杯Scratch选拔赛真题集锦 一、编程题 第 1 题 问答题 马克思的手稿 题目说明 背景信息: 马克思手稿中有一道趣味数学问题: 有30个人&#xff0c;其中有男人、女人和小孩。在一家饭馆吃饭共花了50先令;每个男人花了3先令&#xff0c;每个女人花了…

draw.io如何绘制带箭头的弧线

好长时间没有写draw.io相关的技巧了。今天再补充一个小技巧。 如何绘制像下图中蓝色的带箭头的弧线&#xff1f; 本来以为这个问题应该很简单&#xff0c;但是在仔细研究了很久之后我发现这个问题并没有想像得那么容易。 众所周知&#xff0c;draw.io中带箭头的线叫作“connect…

软件工程 | 期末复习习题

一、软件工程概述 1、选择 软件有无可行性和不可控性 软件工程是一门工程性学科 软件生存周期常见模型&#xff1a;螺旋模型、增量模型、瀑布模型、原型模型、融合模型、快速应用开发模型、敏捷模型 软件生存周期中时间最长的阶段是维护阶段 瀑布模型是一种软件生存周期模…

微搭低代码实现aad的sso

微搭低代码平台是一种可帮助您快速构建和部署应用程序的工具&#xff0c;而无需手动编写大量代码。要在微搭低代码平台上实现Azure Active Directory&#xff08;AAD&#xff09;的单点登录&#xff08;SSO&#xff09;&#xff0c;您需要遵循以下步骤&#xff1a; 注册Azure …