FFmpeg常用结构体分析

简介: FFmpeg常用结构体分析



1.AVFormatConext


AVFormatConext是一个贯穿全局地数据结构,AVFormatConext结构包含很多信息,很多函数都要用它作为参数。

初始化AVFormatConext示例代码:

AVFormatContext *pFormatCtx;
pFormatCtx=avformat_alloc_context();

2.AVInputFormat


AVInputFormat是FFmpeg的解复用器对象,AVInputFormat是类似COM接口地数据结构,表示输入文件容器格式,着重于功能类型,一种文件容器格式对应一个AVInputFormat结构,在程序运行时有多个案例。

3.AVStream


AVStream是存储每一个视频/音频流信息的结构体。解复用器的目的就是从容器中分离(解析出来)不同的流,FFmpeg中的流对象为AVStream,它是由解复用器的read_header函数创建的,并保存在AVFormatConext的nb_streams(容器中的流条数)及stream数组中。

4.AVCodecContext


AVCodecContext是一个描述编解码器上下文的数据结构,包含了众多编解码器需要的参数信息。

初始化示例代码:

AVCodecContext *mAvContext = NULL;
 mAvContext = avcodec_alloc_context3(mVcodec);

5.AVPacket


       FFmpeg 用AVPacket 来存放编码后的视频数据,AVPacket 保存了解复用之后、解码前的数据(仍然是压缩后的数据)和关于这些数据的一些附加信息,如显示时间戳(PTS)解码时间戳(DTS)数据时长、所在媒体流的索引等。

       对于视频(Video)来说,AVPacket 通常包含一个压缩的,而音频 (Audio)则有可能包含多个压缩的帧。并且,一个 Packet 有可能是空的,不包含任何压缩数据,只含有 side dat(side data 指的是容器提供的关于 Packet 的一些附加信息。例如,在编码结束的时候更新一些流的参数)。

申请AVPacket:

AVPacket *packet = (AVPacket *) av_malloc(sizeof(AVPacket));

AVPacket源码解析:

typedef struct AVPacket {
    AVBufferRef *buf;//AVBufferRef类型的指针,用来管理data指针引用的数据缓存
    int64_t pts;//显示时间戳
    int64_t dts;//解码时间戳
    uint8_t *data;//指向保存压缩数据的指针,这就是AVPacket实际的数据
    int   size;
    int   stream_index;//流索引
    int   flags;//带有AV_PKT_FLAG属性的组合
    AVPacketSideData *side_data;//填充容器的一些附加数据
    int side_data_elems;
    int64_t duration;//Packet的时长
    int64_t pos;//Packet的位置                           
#if FF_API_CONVERGENCE_DURATION
    attribute_deprecated
    int64_t convergence_duration;
#endif
} AVPacket;

6.AVCodec


AVCodec是存储编解码器信息的结构体,AVCodec Codec通过avcodec_find_decoder(codec_id)找到对应的Codec。

初始化AVCodec示例代码:

AVCodec *mVcodec = NULL;
 mVcodec = avcodec_find_decoder(codec_id);

7.AVFrame


AVFrame结构体一般用于存储原始数据(即非压缩数据,例如对视频来说是YUV、RGB,对音频来说是PCM),此外还包含了一些相关信息。

创建AVFrame

AVFrame *frame = av_frame_alloc();//分配一个AVFrame结构体,AVFrame结构体一般用于存储原始数据,指向解码后的原始帧

在解码过程中使用了两个AVFrame,这两个AVFrame分配缓存空间的方法不同:

  • 一个AVFrame用来存放从AVPacket中解码出来的原始数据,这个AVFrame的数据缓存空间通过调用 avcodec_receive_frame(mAvContext, frame)来分配和填充。
result = avcodec_receive_frame(mAvContext, frame);
  • 另一个AVFrame用来存放将解码出来的原始数据变换为需要的数据格式(例如RGB、RGBA)的数据,这个AVFrame需要手动分配数据缓存空间,代码如下:
AVFrame *rgb_frame = av_frame_alloc();//分配一个AVFrame结构体,指向存放转换成rgb后的帧
    //缓存区
    uint8_t  *out_buffer= (uint8_t *)av_malloc(avpicture_get_size(AV_PIX_FMT_RGBA,
                                                                  mAvContext->width,mAvContext->height));
    //与缓存区相关联,设置rgb_frame缓存区
    avpicture_fill((AVPicture *)rgb_frame,out_buffer,AV_PIX_FMT_RGBA,mAvContext->width,mAvContext->height);

释放AVFrame

av_frame_free(&frame);
 av_frame_free(&rgb_frame);

AVFrame源码解析:

typedef struct AVFrame {
#define AV_NUM_DATA_POINTERS 8
    uint8_t *data[AV_NUM_DATA_POINTERS];
    int linesize[AV_NUM_DATA_POINTERS];
    uint8_t **extended_data;//扩展的数据
    int width, height;//视频的宽和高
    int nb_samples;//每个信道的音频采样点个数
    int format;//帧的像素格式
    int key_frame;//1表示关键帧 0表示非关键帧
    enum AVPictureType pict_type;//帧的图像类型
    AVRational sample_aspect_ratio;//视频帧的采样率
    int64_t pts;//显示时间戳
#if FF_API_PKT_PTS
    attribute_deprecated
    int64_t pkt_pts;//从AVPacket中复制的PTS
#endif
    int64_t pkt_dts;//从AVPacket中复制的DTS
    int coded_picture_number;//按解码排序后的图像数
    int display_picture_number;//按显示位置排序的图像数
    int quality;//在1~FF_LAMBDA_MAX(256*128-1)之间取值
    void *opaque;//私有数据
#if FF_API_ERROR_FRAME
    attribute_deprecated
    uint64_t error[AV_NUM_DATA_POINTERS];
#endif
    int repeat_pict;//解码时有多少个图像被延迟,extra_delay=repeat_pict/(2*fps)
    int interlaced_frame;//交错帧,表示图像内容是交错的
    int top_field_first;
    int palette_has_changed;
    int64_t reordered_opaque;
    int sample_rate;//音频数据的采样率
    uint64_t channel_layout;//音频信道布局
    AVBufferRef *buf[AV_NUM_DATA_POINTERS];
    AVBufferRef **extended_buf;
    int        nb_extended_buf;
    AVFrameSideData **side_data;
    int            nb_side_data;
#define AV_FRAME_FLAG_CORRUPT       (1 << 0)
#define AV_FRAME_FLAG_DISCARD   (1 << 2)
    int flags;
    enum AVColorRange color_range;
    enum AVColorPrimaries color_primaries;
    enum AVColorTransferCharacteristic color_trc;
    enum AVColorSpace colorspace;//YUV颜色空间类型
    enum AVChromaLocation chroma_location;
    int64_t best_effort_timestamp;
    int64_t pkt_pos;//记录上一包输出解码器时Packet的位置
    int64_t pkt_duration;//Packet的时长
    AVDictionary *metadata;
    int decode_error_flags;
    int channels;//音频信道个数
    int pkt_size;//Packet的大小
#if FF_API_FRAME_QP
    attribute_deprecated
    int8_t *qscale_table;
    attribute_deprecated
    int qstride;
    attribute_deprecated
    int qscale_type;
    attribute_deprecated
    AVBufferRef *qp_table_buf;
#endif
    AVBufferRef *hw_frames_ctx;
    AVBufferRef *opaque_ref;
    size_t crop_top;
    size_t crop_bottom;
    size_t crop_left;
    size_t crop_right;
    AVBufferRef *private_ref;
} AVFrame;

8.AVIOContext


协议(文件)操作的顶层结构式AVIOContext,这个对象实现了带缓冲的读/写操作。FFmpeg的输入对象AVFormat的pb字段指向一个AVIOContext。

典型应用如下:

AVFormatContext *ic=NULL;
ic=avformat_alloc_context();
unsigned char *iobuffer=(unsigned char*)av_malloc(32768);
AVIOContext *avio=avio_alloc_context(iobuffer,32768,0,buffer,fill_iobuffer,NULL,NULL);
ic->pb=avio;
err=avformat_open_input(&ic,is->filename,is->iformat,&format_opts);

9.URLProtocol


URLProtocol是FFmpeg操作文件的结构(包括文件、网络数据流等),包括open、close、read、write、seek等操作。URLProtocol为协议操作对象,针对每种协议会有一个这样的对象,每个协议操作对象和一个协议对象关联。

10.URLContext


URLContext对象封装了协议对象及协议操作对象,URLContext在avio.c中通过url_alloc_for_protocol进行初始化。并且分配空间(使用av_malloc(sizeof(URLContext)+strlen(filename)+1)函数)。


参考:Android 音视频开发(何俊林 著)

目录
相关文章
|
5月前
|
编解码
FFmpeg开发笔记(三十三)分析ZLMediaKit对H.264流的插帧操作
《FFmpeg开发实战》书中3.4.3节讲解如何将H.264流封装成MP4。H.264流通常以SPS→PPS→IDR帧开始,这一说法通过雷霄骅的H264分析器得到验证。分析器能解析H.264文件但不支持MP4。ZLMediaKit服务器在遇到I帧时会自动插入SPS和PPS配置帧,确保流符合标准格式。若缺少这些帧,客户端拉流时会报错。FFmpeg开发实战:从零基础到短视频上线》书中提供了更多FFmpeg开发细节。
129 0
FFmpeg开发笔记(三十三)分析ZLMediaKit对H.264流的插帧操作
|
4月前
|
编解码
FFmpeg开发笔记(三十七)分析SRS对HLS协议里TS包的插帧操作
《FFmpeg开发实战》书中讲解了音视频封装格式,重点介绍了TS,因其固定长度和独立解码特性,常用于HLS协议。HLS通过m3u8文件指示客户端播放TS分片。SRS服务器在转换MP4至TS时,会在每个TS包头添加SPS和PPS帧,保证解码完整性。这一过程在SrsIngestHlsOutput::on_ts_video函数中体现,调用write_h264_sps_pps和write_h264_ipb_frame完成。详细实现涉及SrsRawH264Stream::mux_sequence_header函数,遵循ISO标准写入SPS和PPS NAL单元。
80 0
FFmpeg开发笔记(三十七)分析SRS对HLS协议里TS包的插帧操作
|
6月前
|
存储 编解码 索引
了解FFmpeg音频通道布局结构:AVChannelLayout结构体解析
了解FFmpeg音频通道布局结构:AVChannelLayout结构体解析
229 1
|
6月前
|
编解码 网络协议 API
ffmpeg命令行工具源码之结构体分析1-命令行参数(未完结,持续更新)
ffmpeg作为多媒体文件转换工具,至少需要有一个要转换的输入文件信息(不仅仅是普通文件,还可以是摄像头设备,网络流等),和通常至少需要一个输出格式的文件(输出文件不仅仅指普通的文件,网络协议比如RTP协议,RTSP协议都可以理解为输出文件),ffmpeg的文件的转换过程主要由以下几个流程 (1)解封装 (2)解码 (3)过滤器 (4)编码 (5)封装 因此ffmpeg工具涉及的结构体主要就从这几个方面来说明这些结构体的含义。
75 0
[笔记]音视频学习之ffmpeg实践《一》常用结构体及裁剪画面思路(下)
[笔记]音视频学习之ffmpeg实践《一》常用结构体及裁剪画面思路(下)
|
存储 数据格式
[笔记]音视频学习之ffmpeg实践《一》常用结构体及裁剪画面思路(上)
[笔记]音视频学习之ffmpeg实践《一》常用结构体及裁剪画面思路
|
存储 Android开发 索引
【Android FFMPEG 开发】FFMPEG 获取 AVStream 音视频流 ( AVFormatContext 结构体 | 获取音视频流信息 | 获取音视频流个数 | 获取音视频流 )
【Android FFMPEG 开发】FFMPEG 获取 AVStream 音视频流 ( AVFormatContext 结构体 | 获取音视频流信息 | 获取音视频流个数 | 获取音视频流 )
257 0

热门文章

最新文章