首页 > 系统相关 >音视频八股文(6)-- ffmpeg大体介绍和内存模型

音视频八股文(6)-- ffmpeg大体介绍和内存模型

时间:2023-04-26 23:07:06浏览次数:35  
标签:AVPacket ffmpeg -- 音频 音视频 frame av 编解码器 FFmpeg

播放器框架

音视频八股文(6)-- ffmpeg大体介绍和内存模型_引用计数

常用音视频术语

• 容器/文件(Conainer/File):即特定格式的多媒体文件, 比如mp4、flv、mkv等。

• 媒体流(Stream):表示时间轴上的一段连续数据,如一 段声音数据、一段视频数据或一段字幕数据,可以是压缩 的,也可以是非压缩的,压缩的数据需要关联特定的编解 码器(有些码流音频他是纯PCM)。

• 数据帧/数据包(Frame/Packet):通常,一个媒体流是 由大量的数据帧组成的,对于压缩数据,帧对应着编解码 器的最小处理单元,分属于不同媒体流的数据帧交错存储 于容器之中。

• 编解码器:编解码器是以帧为单位实现压缩数据和原始数 据之间的相互转换的。

常用概念-复用器

音视频八股文(6)-- ffmpeg大体介绍和内存模型_编解码器_02

常用概念-编解码器

音视频八股文(6)-- ffmpeg大体介绍和内存模型_引用计数_03

FFmpeg的整体结构

音视频八股文(6)-- ffmpeg大体介绍和内存模型_编解码器_04

FFMPEG有8个常用库

• AVUtil:核心工具库,下面的许多其他模块都会依赖该库做一些基本的音视频处理操作。

• AVFormat:文件格式和协议库,该模块是最重要的模块之一,封装了Protocol层和Demuxer、Muxer层,使得协议和格式对于开发者来说是透明的。

• AVCodec:编解码库,封装了Codec层,但是有一些Codec是具备自己的License的,FFmpeg是不会默认添加像libx264、FDK-AAC等库的,但是FFmpeg就像一个平台一样,可以将其他的第三方的Codec以插件的方式添加进来,然后为开发者提供统一的接口。

• AVFilter:音视频滤镜库,该模块提供了包括音频特效和视频特效的处理,在使用FFmpeg的API进行编解码的过程中,直接使用该模块为音视频数据做特效处理是非常方便同时也非常高效的一种方式。

• AVDevice:输入输出设备库,比如,需要编译出播放声音或者视频的工具ffplay,就需要确保该模块是打开的,同时也需要SDL的预先编译,因为该设备模块播放声音与播放视频使用的都是SDL库。

• SwrRessample:该模块可用于音频重采样,可以对数字音频进行声道数、数据格式、采样率等多种基本信息的转换。

• SWScale:该模块是将图像进行格式转换的模块,比如,可以将YUV的数据转换为RGB的数据,缩放尺寸由1280720变为800480。

• PostProc:该模块可用于进行后期处理,当我们使用AVFilter的时候需要打开该模块的开关,因为Filter中会使用到该模块的一些基础函数。

FFmpeg函数简介

◼ av_register_all():注册所有组件,4.0已经弃用

◼ avdevice_register_all()对设备进行注册,比如V4L2等。

◼ avformat_network_init();初始化网络库以及网络加密协议相关的库(比如openssl)

FFmpeg函数简介-封装格式相关

◼ avformat_alloc_context();负责申请一个AVFormatContext结构的内存,并进行简单初始化

◼ avformat_free_context();释放该结构里的所有东西以及该结构本身

◼ avformat_close_input();关闭解复用器。关闭后就不再需要使用avformat_free_context 进行释放。

◼ avformat_open_input();打开输入视频文件

◼ avformat_find_stream_info():获取音视频文件信息

◼ av_read_frame(); 读取音视频包

◼ avformat_seek_file(); 定位文件

◼ av_seek_frame():定位文件

音视频八股文(6)-- ffmpeg大体介绍和内存模型_数据_05

FFmpeg解码函数简介-解码器相关

• avcodec_alloc_context3(): 分配解码器上下文

• avcodec_find_decoder():根据ID查找解码器

• avcodec_find_decoder_by_name():根据解码器名字

• avcodec_open2(): 打开编解码器

• avcodec_decode_video2():解码一帧视频数据

• avcodec_decode_audio4():解码一帧音频数据

• avcodec_send_packet(): 发送编码数据包

• avcodec_receive_frame(): 接收解码后数据

• avcodec_free_context():释放解码器上下文,包含了avcodec_close()

• avcodec_close():关闭解码器

音视频八股文(6)-- ffmpeg大体介绍和内存模型_编解码器_06

FFmpeg 3.x 组件注册方式

我们使用ffmpeg,首先要执行av_register_all,把全局的解码器、编码器等结构体注册到各自全局的对象链表里,以便后面查找调用。

音视频八股文(6)-- ffmpeg大体介绍和内存模型_引用计数_07

FFmpeg 4.x 组件注册方式

FFmpeg内部去做,不需要用户调用API去注册。 以codec编解码器为例:

  1. 在configure的时候生成要注册的组件./configure:7203:print_enabled_components libavcodec/codec_list.c AVCodec codec_list $CODEC_LIST这里会生成一个codec_list.c 文件,里面只有static const AVCodec * const codec_list[]数组。
  2. 在libavcodec/allcodecs.c将static const AVCodec * const codec_list[]的编解码器用链表的方式组织起来。

Ffmpeg 4.0.2 组件注册方式

FFmepg内部去做,不需要用户调用API去注册。

对于demuxer/muxer(解复用器,也称容器)则对应

  1. libavformat/muxer_list.c libavformat/demuxer_list.c 这两个文件也是在configure的时候生成,也就是说直接下载源码是没有这两个文件的。
  2. 在libavformat/allformats.c将demuxer_list[]和muexr_list[]以链表的方式组织。

其他组件也是类似的方式

FFmpeg数据结构简介

AVFormatContext 封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息。

AVInputFormat demuxer 每种封装格式(例如FLV, MKV, MP4, AVI)对应一个该结构体。

AVOutputFormat muxer

AVStream 视频文件中每个视频(音频)流对应一个该结构体。

AVCodecContext 编解码器上下文结构体,保存了视频(音频)编解码相关信息。

AVCodec 每种视频(音频)编解码器(例如H.264解码器)对应一个该结构体。

AVPacket 存储一帧压缩编码数据。

AVFrame 存储一帧解码后像素(采样)数据。

如果上下文数据保存在解码器里面? 多路解码的时候数据肯定有冲突。

FFmpeg数据结构之间的关系

AVFormatContext和AVInputFormat之间的关系

AVFormatContext API调用 AVInputFormat 主要是FFMPEG内部调用

音视频八股文(6)-- ffmpeg大体介绍和内存模型_数据_08

AVCodecContext和AVCodec之间的关系

AVCodecContext 编码器上下文结构体 struct AVCodec *codec;

AVCodec 每种视频(音频)编解码器 int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt); int (*encode2)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr);

AVFormatContext, AVStream和AVCodecContext之间的关系

音视频八股文(6)-- ffmpeg大体介绍和内存模型_数据_09

区分不同的码流

◼ AVMEDIA_TYPE_VIDEO视频流

video_index = av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,-1,-1, NULL, 0)

◼ AVMEDIA_TYPE_AUDIO音频流

audio_index = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,-1,-1, NULL, 0)

AVPacket 里面也有一个index的字段

FFmpeg数据结构分析

◼ AVFormatContext

• iformat:输入媒体的AVInputFormat,比如指向AVInputFormat ff_flv_demuxer

• nb_streams:输入媒体的AVStream 个数

• streams:输入媒体的AVStream []数组

• duration:输入媒体的时长(以微秒为单位),计算方式可以参 考av_dump_format()函数。

• bit_rate:输入媒体的码率

◼ AVInputFormat

• name:封装格式名称

• extensions:封装格式的扩展名

• id:封装格式ID

• 一些封装格式处理的接口函数,比如read_packet()

◼ AVStream

• index:标识该视频/音频流

• time_base:该流的时基,PTS*time_base=真正的时间(秒)

• avg_frame_rate: 该流的帧率

• duration:该视频/音频流长度

• codecpar:编解码器参数属性

◼ AVCodecParameters

• codec_type:媒体类型,比如AVMEDIA_TYPE_VIDEO AVMEDIA_TYPE_AUDIO等

• codec_id:编解码器类型, 比如AV_CODEC_ID_H264 AV_CODEC_ID_AAC等。

◼ AVCodecContext

• codec:编解码器的AVCodec,比如指向AVCodec ff_aac_latm_decoder

• width, height:图像的宽高(只针对视频)

• pix_fmt:像素格式(只针对视频)

• sample_rate:采样率(只针对音频)

• channels:声道数(只针对音频)

• sample_fmt:采样格式(只针对音频)

◼ AVCodec

• name:编解码器名称

• type:编解码器类型

• id:编解码器ID

• 一些编解码的接口函数,比如int (*decode)()

◼ AVCodecContext

• codec:编解码器的AVCodec,比如指向AVCodec ff_aac_latm_decoder

• width, height:图像的宽高(只针对视频)

• pix_fmt:像素格式(只针对视频)

• sample_rate:采样率(只针对音频)

• channels:声道数(只针对音频)

• sample_fmt:采样格式(只针对音频)

◼ AVCodec

• name:编解码器名称

• type:编解码器类型

• id:编解码器ID

• 一些编解码的接口函数,比如int (*decode)()

AVPacket

• pts:显示时间戳

• dts:解码时间戳

• data:压缩编码数据

• size:压缩编码数据大小

• pos:数据的偏移地址

• stream_index:所属的AVStream

AVFrame

• data:解码后的图像像素数据(音频采样数据)

• linesize:对视频来说是图像中一行像素的大小;对音频来说是整个音频帧的大小

• width, height:图像的宽高(只针对视频)

• key_frame:是否为关键帧(只针对视频) 。

• pict_type:帧类型(只针对视频) 。例如I, P, B

• sample_rate:音频采样率(只针对音频)

• nb_samples:音频每通道采样数(只针对音频)

• pts:显示时间

FFmpeg内存模型

◼ 从现有的Packet拷贝一个新Packet的时候,有两种情况:

• ①两个Packet的buf引用的是同一数据缓存空间,这时 候要注意数据缓存空间的释放问题;

• ②两个Packet的buf引用不同的数据缓存空间,每个 Packet都有数据缓存空间的copy;

音视频八股文(6)-- ffmpeg大体介绍和内存模型_引用计数_10

音视频八股文(6)-- ffmpeg大体介绍和内存模型_数据_11

音视频八股文(6)-- ffmpeg大体介绍和内存模型_引用计数_12

◼ 对于多个AVPacket共享同一个缓存空间,FFmpeg使用的引用计数的机制(reference-count):

◼◼ 初始化引用计数为0,只有真正分配AVBuffer的时候,引用计数初始化为1;

◼◼ 当有新的Packet引用共享的缓存空间时,就将引用计数+1;

◼◼ 当释放了引用共享空间的Packet,就将引用计数-1;引用计数为0时,就释放掉引用的缓存空间AVBuffer。

◼ AVFrame也是采用同样的机制。

AVPacket常用API

AVPacket *av_packet_alloc(void); 分配AVPacket这个时候和buffer没有关系

void av_packet_free(AVPacket **pkt); 释放AVPacket和_alloc对应

void av_init_packet(AVPacket *pkt); 初始化AVPacket只是单纯初始化pkt字段

int av_new_packet(AVPacket *pkt, int size); 给AVPacket的buf分配内存,引用计数初始化为1

int av_packet_ref(AVPacket *dst, const AVPacket *src); 增加引用计数

void av_packet_unref(AVPacket *pkt); 减少引用计数

void av_packet_move_ref(AVPacket *dst, AVPacket *src); 转移引用计数

AVPacket *av_packet_clone(const AVPacket *src); 等于av_packet_alloc()+av_packet_ref()

AVFrame *av_frame_alloc(void); 分配AVFrame

void av_frame_free(AVFrame **frame); 释放AVFrame

int av_frame_ref(AVFrame *dst, const AVFrame *src); 增加引用计数

void av_frame_unref(AVFrame *frame); 减少引用计数

void av_frame_move_ref(AVFrame *dst, AVFrame *src); 转移引用计数

int av_frame_get_buffer(AVFrame *frame, int align); 根据AVFrame分配内存

AVFrame *av_frame_clone(const AVFrame *src); 等于av_frame_alloc()+av_frame_ref()

标签:AVPacket,ffmpeg,--,音频,音视频,frame,av,编解码器,FFmpeg
From: https://blog.51cto.com/u_14891145/6229017

相关文章

  • leetcode-350-两个数组的交集 II 题解
    题目给定两个数组,编写一个函数来计算它们的交集。示例1:输入:nums1=[1,2,2,1],nums2=[2,2]输出:[2,2]示例2:输入:nums1=[4,9,5],nums2=[9,4,9,8,4]输出:[4,9]说明:输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。我们可以不考虑输出结果......
  • IPv6域名软件
    目前有许多不同的DNS域名服务软件,且每种软件有不同的特性,例如接口、平台支持、打包和其他功能等,大部分域名服务软件支持IPv6。1、BINDBIND(BerkeleyInternetNameDomain)是一款实现DNS服务的开源软件。BIND于1980年初在加州大学伯克利分校设计,最早由4个学生编写,目前仍在不断升级,现......
  • Linux的FTP服务及配置
     8.3.1 FTP简介FTP用户授权 本地用户 本地用户可以通过输入自己的账号和密码进行登录。当登录成功后,其登录目录为系统提供给该用户的根目录($HOME),如/home/user1,用户利用FTP访问该目录如同在本地一样,可以下载及上传文件。Guest用户某些特定用户提供公共账号和密码,且此账号......
  • 【LeeCode】547. 省份数量--unknow
    【题目描述】有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。给你一个 nxn 的矩阵 isConnected ,其中 isC......
  • 国产BI进入发展繁荣期,瓴羊Quick BI连续四年入选魔力象限ABI报告
    最近,瓴羊QuickBI连续第四次获得了国际权威信息技术研究和分析公司Gartner的认可,成功入选了Gartner魔力象限ABI报告,并跃升至挑战者象限,引发国内BI界关注。我们知道,Gartner作为行业权威,对于IT行业各平台、各应用有着一整套客观专业的评价体系,同时每年都会针对各分支领域发布魔力象限......
  • 关于超级App,你是否了解过?
    Superapp(“超级App”)最近甚嚣尘上,甚至在香港科技周专门组织了一个围绕superapp的圆桌论坛,很可能是这个概念出现以来,首次在金融行业的严肃讨论。怎么国内市场“司空见惯”的超级App,成了Gartner的2023年十大战略技术趋势预测中的一种。超级App是指一种综合性的应用程序,允许用户在同一......
  • 在 Linux 环境下模拟实现命令解释器
    访问【WRITE-BUG数字空间】_[内附完整源码和文档]操作系统大作业Linux命令行,在Linux环境下模拟实现命令解释器。在指定的一个目录及其子目录中查找指定的文件和目录,并输出查找到的文件和目录的绝对路径,并指明是文件还是目录。详细设计见md文件。一.程序概述1.完成的任务:1)显示当......
  • 路线
    ......
  • 数据存储与访问——文件存储读写
    本节给大家介绍的是Android数据存储与访问方式中的一个——文件存储与读写,当然除了这种方式外,我们可以存到SharedPreference,数据库,或者Application中。1.Android文件的操作模式学过Java的同学都知道,我们新建文件,然后就可以写入数据了,但是Android却不一样,因为Android是基于Linux的,我......
  • 【LeeCode】130. 被围绕的区域
    【题目描述】给你一个 mxn 的矩阵 board ,由若干字符 'X' 和 'O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。https://leetcode.cn/problems/surrounded-regions/description/【示例】【代码】leecodepackagecom.company;importjava.util.......