ffmpeg解码相关

本文详细介绍了FFmpeg解码过程中涉及的结构体、函数及其重要变量,包括AVStream、AVPacket、AVFrame和AVCodecContext等。通过解封装、初始化解码器上下文、解码函数的使用,阐述了视频和音频解码的步骤。同时,提供了解码完成后资源的释放方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要用于个人记忆,大量引用了别人的文章内容,不一定正确,如有错误,欢迎指正

本文主要讲述解封装获得记录了流信息AVStream的解封转上下文后,如何从解封转上下文中获取AVPacket数据,并将AVPacket数据解码为AVFrame数据。

其中AVPacket数据是存放解码前的数据的,AVFrame是存放解码后的数据(PCM数据或YUV/RBG数据)的

对于视频来说一般一个AVPacket对应一个AVFrame(也就是一帧),音频一般一个AVPacket对应多个AVFrame

目录

 解码用到的结构体

解码用到的函数 

 参考文章


 解码用到的结构体

 AVStream 存放视频/音频流信息的结构体

AVPacket 存放压缩编码数据相关的结构体

AVFrame 存放解码后数据的结构体

AVCodecContext 编/解码上下文,在解码全程都会用到

AVCodec 存放编/解码器信息的结构体

AVStream包含的重要变量:

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

AVCodecContext *codec:指向该视频/音频流的AVCodecContext

AVRational time_base:时基。通过该值可以把PTS,DTS转化为真正的时间。

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

AVDictionary *metadata:元数据信息

AVRational avg_frame_rate:帧率(不能直接使用需要用分子/分母)

AVPacket attached_pic:附带的图片。比如说一些MP3,AAC音频文件附带的专辑封面。

AVPacket包含的重要变量:

uint8_t *data:压缩编码的数据。

int   size:data的大小

int64_t pts:显示时间戳

int64_t dts:解码时间戳

int   stream_index:标识该AVPacket所属的视频/音频流。

AVFrame包含的当前用到的重要变量:

uint8_t *data[AV_NUM_DATA_POINTERS]:解码后原始数据(对视频来说是YUV,RGB,对音频来说是PCM)对于是否是packed格式有不同的存放方式

int linesize[AV_NUM_DATA_POINTERS]:data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。

int width, height:视频帧宽和高(1920x1080,1280x720...)

int nb_samples:音频的一个AVFrame中可能包含多个音频帧,在此标记包含了几个

int format:解码后原始数据类型(YUV420,YUV422,RGB24...)

int key_frame:是否是关键帧

AVRational sample_aspect_ratio:宽高比(16:9,4:3...)

int64_t pts:显示时间戳

AVCodec包含的当前用到的重要变量:

const char *name:编解码器的名字,比较短

const char *long_name:编解码器的名字,全称,比较长

enum AVMediaType type:指明了类型,是视频,音频,还是字幕

enum AVCodecID id:ID,不重复

const AVRational *supported_framerates:支持的帧率(仅视频)

const enum AVPixelFormat *pix_fmts:支持的像素格式(仅视频)

const int *supported_samplerates:支持的采样率(仅音频)

const enum AVSampleFormat *sample_fmts:支持的采样格式(仅音频)

const uint64_t *channel_layouts:支持的声道数(仅音频)

int priv_data_size:私有数据的大小

AVCodecContext包含的当前用到的重要变量:

enum AVMediaType codec_type:编解码器的类型(视频,音频...)

struct AVCodec  *codec:采用的解码器AVCodec(H.264,MPEG2...)

int bit_rate:平均比特率

AVRational time_base:根据该参数,可以把PTS转化为实际的时间(单位为秒s)

int width, height:如果是视频的话,代表宽和高

int sample_rate:采样率(音频)

int channels:声道数(音频)

enum AVSampleFormat sample_fmt:采样格式

解码用到的函数 

在解码之前首先需要初始化解码相关的结构体

1、通过解封转上下文找到需要的音频或视频流信息,返回对应的流编号

int av_find_best_stream(AVFormatContext *ic,

                        enum AVMediaType type,

                        int wanted_stream_nb,

                        int related_stream,

                        const AVCodec **decoder_ret,

                        int flags);

2、通过流中的解码器id找到当前流最适合的解码器

const AVCodec *avcodec_find_decoder(enum AVCodecID id);

3、初始化解码器上下文并传入解码器

AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);

4、从流中拷贝参数到解码器上下文

int avcodec_parameters_to_context(AVCodecContext *codec,

                                  const AVCodecParameters *par);

5、打开解码器

int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

6、从解封装上下文中读取AVPacket

int av_read_frame(AVFormatContext *s, AVPacket *pkt);

7、解码和解封装最好在不同的线程执行,将AVPacket按照音频包和视频包发送到各自的队列中,等待音频解码线程和视频解码线程进行解码

视频解码:

视频解码需要在另外的线程进行,通过锁和队列取得AVPacket

1、将AVPacket发送给解码器

int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);

2、释放AVPacket包避免内存泄漏

void av_packet_unref(AVPacket *pkt);

3、初始化AVFrame

AVFrame *av_frame_alloc(void);

4、从解码器中读取帧数据(由于可能不止一帧所以要用whlie直到读到AVERROR(EAGAIN) 或AVERROR_EOF)(注意该函数在调用时会先释放AVFrame中data的数据)

int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);

音频解码:

音频解码需要在另外的线程进行,通过锁和队列取得AVPacket

1、  将AVPacket发送给解码器

int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);

2、  释放AVPacket包避免内存泄漏

void av_packet_unref(AVPacket *pkt);

3、初始化AVFrame

AVFrame *av_frame_alloc(void);

4、从解码器中读取帧数据(由于可能不止一帧所以要用whlie直到读到AVERROR(EAGAIN) 或AVERROR_EOF)

int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);

解码完成后需要释放解码所用到的变量:

1、释放解码上下文:

void avcodec_free_context(AVCodecContext **avctx);

2、释放帧数据

void av_frame_free(AVFrame **frame);

 参考文章

FFMPEG结构体分析:AVStream_雷霄骅的博客-优快云博客 FFMPEG结构体分析:AVStream

FFMPEG结构体分析:AVCodec_雷霄骅的博客-优快云博客_ffmpeg雷霄骅 FFMPEG结构体分析:AVCodec

FFMPEG结构体分析:AVFrame_雷霄骅的博客-优快云博客_avcodec是什么意思 FFMPEG结构体分析:AVFrame

FFMPEG结构体分析:AVCodecContext_雷霄骅的博客-优快云博客_avcodeccontext FFMPEG结构体分析:AVCodecContext

FFMPEG结构体分析:AVPacket_雷霄骅的博客-优快云博客 FFMPEG结构体分析:AVPacket

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值