ffmpeg源码分析01(结构体)
AVFormatContext(位于avformat.h中)
typedef struct AVFormatContext {
const AVClass *av_class;
//桥接AVOption,方便给结构体变量赋值
struct AVInputFormat *iformat;
//输入数据的封装格式
struct AVOutputFormat *oformat;
//输出数据的封装格式
void *priv_data;
AVIOContext *pb;
//输入数据的缓存
int ctx_flags;
unsigned int nb_streams;
//音视频流的个数
AVStream **streams;
//音视频流(比如video\audio)
char filename[1024];
//输入或输出数据的文件名
int64_t start_time;
//第一帧的位置
int64_t duration;
//流的持续时间(单位:微秒us,转换为秒需要除以1000000)
int bit_rate;
//总流比特率(bit / s),如果不可用则为0。
unsigned int probesize;
//从输入读取的用于确定输入容器格式的数据的最大大小。
AVDictionary *metadata;
//元数据
AVFormatInternal *internal;
AVCodec *video_codec;
//视频编解码器
AVCodec *audio_codec;
//音频编解码器
AVCodec *subtitle_codec;
//字母编解码器
} AVFormatContext;
AVInputFormat(位于avformat.h中)
AVInputFormat 是类似COM 接口的数据结构,表示输入文件容器格式,着重于功能函数,一种文件容器格式对应一个AVInputFormat 结构,在程序运行时有多个实例,位于avoformat.h文件中。
const char *name;
//格式名列表.也可以分配一个新名字。
const char *long_name;
//格式的描述性名称,意味着比名称更易于阅读。
int flags;
//可用的flag有: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS,
AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH,
AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK, AVFMT_SEEK_TO_PTS.
const char *extensions;
//文件扩展名
const AVClass *priv_class;
//一个模拟类型列表.用来在probe的时候check匹配的类型。
struct AVInputFormat *next;
//用于把所有支持的输入文件容器格式连接成链表,便于遍历查找。
int priv_data_size;
//标示具体的文件容器格式对应的Context 的大小。
int (*read_probe)(AVProbeData *);
//判断一个给定的文件是否有可能被解析为这种格式。 给定的buf足够大,所以你没有必要去检查它,除非你需要更多 。
int (*read_header)(struct AVFormatContext *);
//读取format头并初始化AVFormatContext结构体,如果成功,返回0。创建新的流需要调用avformat_new_stream。
int (*read_header2)(struct AVFormatContext *, AVDictionary **options);
//新加的函数指针,用于打开进一步嵌套输入的格式。
int (*read_packet)(struct AVFormatContext *, AVPacket *pkt);
//读取一个数据包并将其放在“pkt”中。 pts和flag也被设置。
int (*read_close)(struct AVFormatContext *);
//关闭流。 AVFormatContext和Streams不会被此函数释放。
int (*read_seek)(struct AVFormatContext *, int stream_index, int64_t timestamp, int flags);
int64_t (*read_timestamp)(struct AVFormatContext *s, int stream_index, int64_t *pos, int64_t pos_limit);
//获取stream [stream_index] .time_base单位中的下一个时间戳。
int (*read_play)(struct AVFormatContext *);
//开始/继续播放 - 仅当使用基于网络的(RTSP)格式时才有意义。
int (*read_pause)(struct AVFormatContext *);
//暂停播放 - 仅当使用基于网络的(RTSP)格式时才有意义。
int (*read_seek2)(struct AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags);
//寻求时间戳ts。
int (*get_device_list)(struct AVFormatContext *s, struct AVDeviceInfoList *device_list);
返回设备列表及其属性。
int (*create_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
//初始化设备能力子模块。
int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
//释放设备能力子模块。
AVInputFormat(位于avformat.h中)
AVOutputFormat 结构主要包含的信息有:封装名称描述,编码格式信息(video/audio 默认编码格式,支持的编码格式列表),一些对封装的操作函数(write_header,write_packet,write_tailer等)
const char *name;
const char *long_name;
//格式的描述性名称,易于阅读。
enum AVCodecID audio_codec;
//默认的音频编解码器
enum AVCodecID video_codec;
//默认的视频编解码器
enum AVCodecID subtitle_codec;
//默认的字幕编解码器
struct AVOutputFormat *next;
int (*write_header)(struct AVFormatContext *);
int (*write_packet)(struct AVFormatContext *, AVPacket *pkt);
//写一个数据包。 如果在标志中设置AVFMT_ALLOW_FLUSH,则pkt可以为NULL。
int (*write_trailer)(struct AVFormatContext *);
int (*interleave_packet)(struct AVFormatContext *, AVPacket *out, AVPacket *in, int flush);
int (*control_message)(struct AVFormatContext *s, int type, void *data, size_t data_size);
//允许从应用程序向设备发送消息。
int (*write_uncoded_frame)(struct AVFormatContext *, int stream_index,AVFrame **frame, unsigned flags);
//写一个未编码的AVFrame。
int (*init)(struct AVFormatContext *);
//初始化格式。 可以在此处分配数据,并设置在发送数据包之前需要设置的任何AVFormatContext或AVStream参数。
void (*deinit)(struct AVFormatContext *);
//取消初始化格式。
int (*check_bitstream)(struct AVFormatContext *, const AVPacket *pkt);
//设置任何必要的比特流过滤,并提取全局头部所需的任何额外数据。
AVIOContent(位于avio.h中)
AVIOContent是FFmpeg管理输入输出数据的结构体.例如打开一个视频文件的时候,先把数据从硬盘读入buffer,然后在送给解码器用于解码。
unsigned char *buffer;
//缓存开始位置。
int buffer_size;
//缓冲区的大小。
unsigned char *buf_ptr;
//当前指针在缓冲区中的位置,即当前指针读取到的位置。
unsigned char *buf_end;
//缓存结束的位置void *opaque;
//一个私有指针,传递给read / write / seek / ...函数。
opaque指向了URLContext。URLContext结构体中还有一个结构体URLProtocol。
ps:每种协议(rtp,rtmp,file等)对应一个URLProtocol。int64_t pos;
//当前缓冲区在文件中的位置。
int must_flush;
//如果下一次seek需要刷新则为真。
int eof_reached;
//是否读到eof,文件结尾。
int (*read_pause)(void *opaque, int pause);
//暂停或恢复播放网络流媒体协议 - 例如 MMS。
int64_t (*read_seek)(void *opaque, int stream_index, int64_t timestamp, int flags);
//使用指定的stream_index查找流中给定的时间戳(对于不支持寻找字节位置的网络流协议)。
其中opaque指向了URLContext。
typedef struct URLContext {
const AVClass *av_class;
///< information for av_log(). Set by url_open().
struct URLProtocol *prot;
int flags;
int is_streamed;
/**< true if streamed (no seek possible), default = false */
int max_packet_size;
/**< if non zero, the stream is packetized with this max packet size */
void *priv_data;
char *filename;
/**< specified URL */
int is_connected;
AVIOInterruptCB interrupt_callback;
} URLContext;
URLContext结构体中还有一个结构体URLProtocol。注:每种协议(rtp,rtmp,file等)对应一个URLProtocol。
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,该变量存储了协议的名称。每一种输入协议都对应这样一个结构体。
比如说,文件协议中代码如下(file.c):
URLProtocol ff_file_protocol = {
.name= "file",
.url_open= file_open,
.url_read= file_read,
.url_write= file_write,
.url_seek= file_seek,
.url_close= file_close,
.url_get_file_handle = file_get_handle,
.url_check= file_check,
};
libRTMP中代码如下(libRTMP.c):
URLProtocol ff_rtmp_protocol = {
.name= "rtmp",
.url_open= rtmp_open,
.url_read= rtmp_read,
.url_write= rtmp_write,
.url_close= rtmp_close,
.url_read_pause= rtmp_read_pause,
.url_read_seek= rtmp_read_seek,
.url_get_file_handle = rtmp_get_file_handle,
.priv_data_size= sizeof(RTMP),
.flags= URL_PROTOCOL_FLAG_NETWORK,
};
udp协议代码如下(udp.c):
URLProtocol ff_udp_protocol = {
.name= "udp",
.url_open= udp_open,
.url_read= udp_read,
.url_write= udp_write,
.url_close= udp_close,
.url_get_file_handle = udp_get_file_handle,
.priv_data_size= sizeof(UDPContext),
.flags= URL_PROTOCOL_FLAG_NETWORK,
};
等号右边的函数是完成具体读写功能的函数。可以看一下file协议的几个函数(其实就是读文件,写文件这样的操作)(file.c):
/* standard file protocol */
static int file_read(URLContext *h, unsigned char *buf, int size)
{
int fd = (intptr_t) h->priv_data;
int r = read(fd, buf, size);
return (-1 == r)?AVERROR(errno):r;
}
static int file_write(URLContext *h, const unsigned char *buf, int size)
{
int fd = (intptr_t) h->priv_data;
int r = write(fd, buf, size);
return (-1 == r)?AVERROR(errno):r;
}
【ffmpeg源码分析01(结构体)】AVStream(位于avformat.h中)
是存储每一个视频/音频流信息的结构体
int index;
//在AVFormatContext中的索引,这个数字是自动生成的,可以通过这个数字从AVFormatContext::streams表中索引到该流。标识该视频/音频流
int id;
//流的标识,依赖于具体的容器格式。解码:由libavformat设置。编码:由用户设置,如果未设置则由libavformat替换。
AVCodecContext *codec;
//指向该流对应的AVCodecContext结构,调用avformat_open_input时生成。
AVRational time_base;
//这是表示帧时间戳的基本时间单位(以秒为单位)。该流中媒体数据的pts和dts都将以这个时间基准为粒度。
int64_t start_time;
//流的起始时间,以流的时间基准为单位。如需设置,100%确保你设置它的值真的是第一帧的pts。
int64_t duration;
//解码:流的持续时间。如果源文件未指定持续时间,但指定了比特率,则将根据比特率和文件大小估计该值。
int64_t nb_frames;
//此流中的帧数(如果已知)或0。
enum AVDiscard discard;
//选择哪些数据包可以随意丢弃,不需要去demux。
AVRational sample_aspect_ratio;
//样本长宽比(如果未知,则为0)。
AVDictionary *metadata;
//元数据信息。
AVRational avg_frame_rate;
//平均帧速率。解封装:可以在创建流时设置为libavformat,也可以在avformat_find_stream_info()中设置。封装:可以由调用者在avformat_write_header()之前设置。
AVPacket attached_pic;
//附带的图片。比如说一些MP3,AAC音频文件附带的专辑封面。
int probe_packets;
//编解码器用于probe的包的个数。
int codec_info_nb_frames;
//在av_find_stream_info()期间已经解封装的帧数。
int request_probe;
//流探测状态,1表示探测完成,0表示没有探测请求,rest 执行探测。
int skip_to_keyframe;
//表示应丢弃直到下一个关键帧的所有内容。
int skip_samples;
//在从下一个数据包解码的帧开始时要跳过的采样数。
int64_t start_skip_samples;
//如果不是0,则应该从流的开始跳过的采样的数目。
int64_t first_discard_sample;
//如果不是0,则应该从流中丢弃第一个音频样本。int64_t pts_reorder_error[MAX_REORDER_DELAY+1];
uint8_t pts_reorder_error_count[MAX_REORDER_DELAY+1];
//内部数据,从pts生成dts。int64_t last_dts_for_order_check;
uint8_t dts_ordered;
uint8_t dts_misordered;
//内部数据,用于分析dts和检测故障mpeg流。
AVRational display_aspect_ratio;
//显示宽高比。
AVCodecContent(位于avcodec.h文件中)
AVCodecContext 结构表示程序运行的当前Codec使用的上下文,着重于所有Codec共有的属性(并且是在程序运行时才能确定其值)和关联其他结构的字段。extradata和extradata_size两个字段表述了相应Codec使用的私有数据;codec字段关联相应的编解码器;priv_data字段关联各个具体编解码器独有的属性context,和AVCodec结构中的priv_data_size配对使用。
enum AVMediaType codec_type:编解码器的类型(视频,音频...)
struct AVCodec*codec:采用的解码器AVCodec(H.264,MPEG2...)
int bit_rate:平均比特率
uint8_t *extradata;
int extradata_size:针对特定编码器包含的附加信息(例如对于H.264解码器来说,存储SPS,PPS等)
AVRational time_base:根据该参数,可以把PTS转化为实际的时间(单位为秒s)
int width, height:如果是视频的话,代表宽和高
int refs:运动估计参考帧的个数(H.264的话会有多帧,MPEG2这类的一般就没有了)
int sample_rate:采样率(音频)
int channels:声道数(音频)
enum AVSampleFormat sample_fmt:采样格式
int profile:型(H.264里面就有,其他编码标准应该也有)
int level:级(和profile差不太多)
int delay;
//编码:从编码器输入到解码器输出的帧延迟数。解码:除了规范中规定的标准解码器外产生的帧延迟数。
int sample_rate;
//采样率(仅音频)。
int channels;
//声道数(仅音频)。
int frame_size;
//音频帧中每个声道的采样数。编码:由libavcodec在avcodec_open2()中设置。 解码:可以由一些解码器设置以指示恒定的帧大小.
int frame_number;
//帧计数器,由libavcodec设置。解码:从解码器返回的帧的总数。编码:到目前为止传递给编码器的帧的总数。
uint64_t channel_layout;
//音频声道布局。编码:由用户设置。解码:由用户设置,可能被libavcodec覆盖。
enum AVAudioServiceType audio_service_type;
//音频流传输的服务类型。编码:由用户设置。解码:由libavcodec设置。
1.codec_type:编解码器类型有以下几种
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
};
2.sample_fmt:在FFMPEG中音频采样格式有以下几种:
enum AVSampleFormat {
AV_SAMPLE_FMT_NONE = -1,
AV_SAMPLE_FMT_U8,///< unsigned 8 bits
AV_SAMPLE_FMT_S16,///< signed 16 bits
AV_SAMPLE_FMT_S32,///< signed 32 bits
AV_SAMPLE_FMT_FLT,///< float
AV_SAMPLE_FMT_DBL,///< double
AV_SAMPLE_FMT_U8P,///< unsigned 8 bits, planar
AV_SAMPLE_FMT_S16P,///< signed 16 bits, planar
AV_SAMPLE_FMT_S32P,///< signed 32 bits, planar
AV_SAMPLE_FMT_FLTP,///< float, planar
AV_SAMPLE_FMT_DBLP,///< double, planar
AV_SAMPLE_FMT_NB///< Number of sample formats. DO NOT USE if linking dynamically
};
3.profile:在FFMPEG中型有以下几种,可以看出AAC,MPEG2,H.264,VC-1,MPEG4都有型的概念。
#define FF_PROFILE_UNKNOWN -99
#define FF_PROFILE_RESERVED -100
#define FF_PROFILE_AAC_MAIN 0
#define FF_PROFILE_AAC_LOW1
#define FF_PROFILE_AAC_SSR2
#define FF_PROFILE_AAC_LTP3
#define FF_PROFILE_AAC_HE4
#define FF_PROFILE_AAC_HE_V2 28
#define FF_PROFILE_AAC_LD22
#define FF_PROFILE_AAC_ELD38
#define FF_PROFILE_DTS20
#define FF_PROFILE_DTS_ES30
#define FF_PROFILE_DTS_96_2440
#define FF_PROFILE_DTS_HD_HRA50
#define FF_PROFILE_DTS_HD_MA60
#define FF_PROFILE_MPEG2_4220
#define FF_PROFILE_MPEG2_HIGH1
#define FF_PROFILE_MPEG2_SS2
#define FF_PROFILE_MPEG2_SNR_SCALABLE3
#define FF_PROFILE_MPEG2_MAIN4
#define FF_PROFILE_MPEG2_SIMPLE 5
#define FF_PROFILE_H264_CONSTRAINED(1<<9)// 8+1;
constraint_set1_flag
#define FF_PROFILE_H264_INTRA(1<<11) // 8+3;
constraint_set3_flag
#define FF_PROFILE_H264_BASELINE66
#define FF_PROFILE_H264_CONSTRAINED_BASELINE (66|FF_PROFILE_H264_CONSTRAINED)
#define FF_PROFILE_H264_MAIN77
#define FF_PROFILE_H264_EXTENDED88
#define FF_PROFILE_H264_HIGH100
#define FF_PROFILE_H264_HIGH_10110
#define FF_PROFILE_H264_HIGH_10_INTRA(110|FF_PROFILE_H264_INTRA)
#define FF_PROFILE_H264_HIGH_422122
#define FF_PROFILE_H264_HIGH_422_INTRA(122|FF_PROFILE_H264_INTRA)
#define FF_PROFILE_H264_HIGH_444144
#define FF_PROFILE_H264_HIGH_444_PREDICTIVE244
#define FF_PROFILE_H264_HIGH_444_INTRA(244|FF_PROFILE_H264_INTRA)
#define FF_PROFILE_H264_CAVLC_44444
#define FF_PROFILE_VC1_SIMPLE0
#define FF_PROFILE_VC1_MAIN1
#define FF_PROFILE_VC1_COMPLEX2
#define FF_PROFILE_VC1_ADVANCED 3
#define FF_PROFILE_MPEG4_SIMPLE0
#define FF_PROFILE_MPEG4_SIMPLE_SCALABLE1
#define FF_PROFILE_MPEG4_CORE2
#define FF_PROFILE_MPEG4_MAIN3
#define FF_PROFILE_MPEG4_N_BIT4
#define FF_PROFILE_MPEG4_SCALABLE_TEXTURE5
#define FF_PROFILE_MPEG4_SIMPLE_FACE_ANIMATION6
#define FF_PROFILE_MPEG4_BASIC_ANIMATED_TEXTURE7
#define FF_PROFILE_MPEG4_HYBRID8
#define FF_PROFILE_MPEG4_ADVANCED_REAL_TIME9
#define FF_PROFILE_MPEG4_CORE_SCALABLE10
#define FF_PROFILE_MPEG4_ADVANCED_CODING11
#define FF_PROFILE_MPEG4_ADVANCED_CORE12
#define FF_PROFILE_MPEG4_ADVANCED_SCALABLE_TEXTURE 13
#define FF_PROFILE_MPEG4_SIMPLE_STUDIO14
#define FF_PROFILE_MPEG4_ADVANCED_SIMPLE15
AVCodec(位于avcodec.h文件中)
是存储编解码器信息的结构体
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:私有数据的大小
1,enum AVCodecID id
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,
...(代码太长,略)
}
2,const enum AVPixelFormat *pix_fmts
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,///
AVPacket(位于avcodec.h文件中)
是存储压缩编码数据相关信息的结构体
AVPacket中的字段可分为两部分:数据的缓存及管理和数据的属性。
关于数据的属性有以下字段:
pts: (int64_t)显示时间,结合AVStream->time_base转换成时间戳
dts: (int64_t)解码时间,结合AVStream->time_base转换成时间戳
size: (int)data的大小stream_index: (int)packet在stream的index位置
flags: (int)标示,结合AV_PKT_FLAG使用,其中最低为1表示该数据是一个关键帧。
#define AV_PKT_FLAG_KEY0x0001 //关键帧
#define AV_PKT_FLAG_CORRUPT 0x0002 //损坏的数据
#define AV_PKT_FLAG_DISCARD0x0004 /丢弃的数据
side_data_elems: (int)边缘数据元数个数
duration: (int64_t)数据的时长,以所属媒体流的时间基准为单位,未知则值为默认值0
pos: (int64_t )数据在流媒体中的位置,未知则值为默认值-1
convergence_duration:该字段已deprecated,不在使用
关于数据缓存,AVPacket本身只是个容器,不直接的包含数据,而是通过数据缓存的指针引用数据。AVPacket包含两种数据
uint8_t *data:指向保存压缩数据的指针,这就是AVPacket的实际数据。例如对于H.264来说。1个AVPacket的data通常对应一个NAL。
注意:在这里只是对应,而不是一模一样。他们之间有微小的差别:使用FFMPEG类库分离出多媒体文件中的H.264码流(https://blog.csdn.net/leixiaohua1020/article/details/11800877)
因此在使用FFMPEG进行视音频处理的时候,常常可以将得到的AVPacket的data数据直接写成文件,从而得到视音频的码流文件。
AVPacketSideData *side_data:容器提供的一些附加数据
AVBufferRef *buf:用来管理data指针引用的数据缓存,其使用在后面介绍。
AVFrame(位于frame.h文件中)
解压缩数据(包含了yuv和pcm数据)的结构体
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:显示帧序号
int8_t *qscale_table:QP表
uint8_t *mbskip_table:跳过宏块表
int16_t (*motion_val[2])[2]:运动矢量表
uint32_t *mb_type:宏块类型表
short *dct_coeff:DCT系数,这个没有提取过
int8_t *ref_index[2]:运动估计参考帧列表(貌似H.264这种比较新的标准才会涉及到多参考帧)
int interlaced_frame:是否是隔行扫描
uint8_t motion_subsample_log2:一个宏块中的运动矢量采样个数,取log的
1.data[]
对于packed格式的数据(例如RGB24),会存到data[0]里面。
对于planar格式的数据(例如YUV420P),则会分开成data[0],data[1],data[2]...(YUV420P中data[0]存Y,data[1]存U,data[2]存V
2.pict_type
enum AVPictureType {
AV_PICTURE_TYPE_NONE = 0, ///< Undefined
AV_PICTURE_TYPE_I,///< Intra
AV_PICTURE_TYPE_P,///< Predicted
AV_PICTURE_TYPE_B,///< Bi-dir predicted
AV_PICTURE_TYPE_S,///< S(GMC)-VOP MPEG4
AV_PICTURE_TYPE_SI,///< Switching Intra
AV_PICTURE_TYPE_SP,///< Switching Predicted
AV_PICTURE_TYPE_BI,///< BI type
};
3.sample_aspect_ratio
/**
* rational number numerator/denominator
*/
typedef struct AVRational{
int num;
///< numerator
int den;
///< denominator
} AVRational;
4.qscale_table
QP表指向一块内存,里面存储的是每个宏块的QP值。宏块的标号是从左往右,一行一行的来的。每个宏块对应1个QP。
qscale_table[0]就是第1行第1列宏块的QP值;qscale_table[1]就是第1行第2列宏块的QP值;qscale_table[2]就是第1行第3列宏块的QP值。以此类推...
宏块的个数用下式计算:
注:宏块大小是16x16的。
每行宏块数:
int mb_stride = pCodecCtx->width/16+1
宏块的总数:
int mb_sum = ((pCodecCtx->height+15)>>4)*(pCodecCtx->width/16+1)
5.motion_subsample_log2
1个运动矢量所能代表的画面大小(用宽或者高表示,单位是像素),注意,这里取了log2。
代码注释中给出以下数据:
4->16x16, 3->8x8, 2-> 4x4, 1-> 2x2
即1个运动矢量代表16x16的画面的时候,该值取4;1个运动矢量代表8x8的画面的时候,该值取3...以此类推
6.motion_val
运动矢量表存储了一帧视频中的所有运动矢量。
7.mb_type
宏块类型表存储了一帧视频中的所有宏块的类型。其存储方式和QP表差不多。只不过其是uint32类型的,而QP表是uint8类型的。每个宏块对应一个宏块类型变量。
推荐阅读
- 如何寻找情感问答App的分析切入点
- D13|D13 张贇 Banner分析
- 自媒体形势分析
- 2020-12(完成事项)
- Android事件传递源码分析
- Python数据分析(一)(Matplotlib使用)
- Quartz|Quartz 源码解析(四) —— QuartzScheduler和Listener事件监听
- 泽宇读书会——如何阅读一本书笔记
- Java内存泄漏分析系列之二(jstack生成的Thread|Java内存泄漏分析系列之二:jstack生成的Thread Dump日志结构解析)
- [源码解析]|[源码解析] NVIDIA HugeCTR,GPU版本参数服务器---(3)