1
2
3
4
5
typedef struct MyAVPacketList {//Packet链表 不使用AVPacketList
AVPacket pkt;
struct MyAVPacketList *next;
int serial;
} MyAVPacketList;
1
2
3
4
5
6
7
8
9
10
typedef struct PacketQueue {//packet队列
MyAVPacketList *first_pkt, *last_pkt;
int nb_packets; // 包数量,也就是队列元素数量
int size; // 队列所有元素的数据大小总和
int64_t duration; // 队列所有元素的数据播放持续时间
int abort_request; // 用户退出请求标志
int serial; // 播放序列,所谓播放序列就是一段连续的播放动作,一个seek操作会启动一段新的播放序列
SDL_mutex *mutex; // 互斥量
SDL_cond *cond; // 条件变量 产生阻塞
} PacketQueue;
1
2
3
4
5
6
7
8
9
10
11
12
typedef struct FrameQueue {
Frame queue[FRAME_QUEUE_SIZE];
int rindex; // 读索引。待播放时读取此帧进行播放,播放后此帧成为上一帧
int windex; // 写索引
int size; // 总帧数
int max_size; // 队列可存储最大帧数
int keep_last; // 是否保留已播放的最后一帧使能标志
int rindex_shown; // 是否保留已播放的最后一帧实现手段
SDL_mutex *mutex;
SDL_cond *cond;
PacketQueue *pktq; // 指向对应的packet_queue
} FrameQueue;
1
2
3
4
5
6
7
8
typedef struct AudioParams {//音频参数
int freq; // 采样率
int channels; // 通道数
int64_t channel_layout; // 通道布局,比如2.1声道,5.1声道等
enum AVSampleFormat fmt; // 音频采样格式,比如AV_SAMPLE_FMT_S16表示为有符号16bit深度,交错排列模式。
int frame_size; // 一个采样单元占用的字节数(比如2通道时,则左右通道各采样一次合成一个采样单元)
int bytes_per_sec; // 一秒时间的字节数,比如采样率48Khz,2 channel,16bit,则一秒48000*2*16/8=192000
} AudioParams;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef struct Clock {
// 当前帧(待播放)显示时间戳,播放后,当前帧变成上一帧
double pts; /* clock base */
// 当前帧显示时间戳与当前系统时钟时间的差值
double pts_drift; /* clock base minus time at which we updated the clock */
// 当前时钟(如视频时钟)最后一次更新时间,也可称当前时钟时间
double last_updated;
// 时钟速度控制,用于控制播放速度
double speed;
// 播放序列,所谓播放序列就是一段连续的播放动作,一个seek操作会启动一段新的播放序列
int serial; /* clock is based on a packet with this serial */
// 暂停标志
int paused;
// 指向packet_serial
int *queue_serial; /* pointer to the current packet queue serial, used for obsolete clock detection */
} Clock;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef struct Frame {//帧
AVFrame *frame; // 指向数据帧
AVSubtitle sub; // 用于字幕
int serial; // 帧序列,在seek的操作时serial会变化
double pts; // 时间戳,单位为秒
double duration; // 该帧持续时间,单位为秒
int64_t pos; // 该帧在输入文件中的字节位置
int width; // 图像宽度
int height; // 图像高读
int format; // 对于图像为(enum AVPixelFormat),对于声音则为(enum AVSampleFormat)
AVRational sar; // 图像的宽高比,如果未知或未指定则为0/1
int uploaded; // 用来记录该帧是否已经显示过?
int flip_v; // =1则旋转180, = 0则正常播放
} Frame;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef struct Decoder {
AVPacket pkt;
PacketQueue *queue; // 数据包队列
AVCodecContext *avctx; // 解码器上下文
int pkt_serial; // 包序列
int finished; // 0即解码器处于工作状态
int packet_pending; // 0即解码器处于异常状态,需要考虑重置解码器;1即解码器处于正常状态
SDL_cond *empty_queue_cond; // 检查到packet队列空时发送 signal缓存read_thread读取数据
int64_t start_pts; // 初始化时是stream的start time
AVRational start_pts_tb; // 初始化时是stream的time_base
int64_t next_pts; // 记录最近一次解码后的frame的pts,当解出来的部分帧没有有效的pts时则使用next_pts进行推算
AVRational next_pts_tb; // next_pts的单位
SDL_Thread *decoder_tid; // 线程句柄
} Decoder;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
typedef struct VideoState {
SDL_Thread *read_tid; // demux解复用线程
AVInputFormat *iformat;
int abort_request;
int force_refresh;
int paused;
int last_paused;
int queue_attachments_req;
int seek_req; // 标识一次SEEK请求
int seek_flags; // SEEK标志,诸如AVSEEK_FLAG_BYTE等
int64_t seek_pos; // SEEK的目标位置(当前位置+增量)
int64_t seek_rel; // 本次SEEK的位置增量
int read_pause_return;
AVFormatContext *ic;
int realtime;

Clock audclk; // 音频时钟
Clock vidclk; // 视频时钟
Clock extclk; // 外部时钟

FrameQueue pictq; // 视频frame队列
FrameQueue subpq; // 字幕frame队列
FrameQueue sampq; // 音频frame队列

Decoder auddec; // 音频解码器
Decoder viddec; // 视频解码器
Decoder subdec; // 字幕解码器

int audio_stream; // 音频流索引

int av_sync_type;

double audio_clock; // 每个音频帧更新一下此值,以pts形式表示
int audio_clock_serial; // 播放序列,seek可改变此值
double audio_diff_cum; /* used for AV difference average computation */
double audio_diff_avg_coef;
double audio_diff_threshold;
int audio_diff_avg_count;
AVStream *audio_st; // 音频流
PacketQueue audioq; // 音频packet队列
int audio_hw_buf_size; // SDL音频缓冲区大小(单位字节)
uint8_t *audio_buf; // 指向待播放的一帧音频数据,指向的数据区将被拷入SDL音频缓冲区。若经过重采样则指向audio_buf1,否则指向frame中的音频
uint8_t *audio_buf1; // 音频重采样的输出缓冲区
unsigned int audio_buf_size; /* in bytes */ // 待播放的一帧音频数据(audio_buf指向)的大小
unsigned int audio_buf1_size; // 申请到的音频缓冲区audio_buf1的实际尺寸
int audio_buf_index; /* in bytes */ // 当前音频帧中已拷入SDL音频缓冲区的位置索引(指向第一个待拷贝字节)
int audio_write_buf_size; // 当前音频帧中尚未拷入SDL音频缓冲区的数据量,audio_buf_size = audio_buf_index + audio_write_buf_size
int audio_volume; // 音量
int muted; // 静音状态
struct AudioParams audio_src; // 音频frame的参数
#if CONFIG_AVFILTER
struct AudioParams audio_filter_src;
#endif
struct AudioParams audio_tgt; // SDL支持的音频参数,重采样转换:audio_src->audio_tgt
struct SwrContext *swr_ctx; // 音频重采样context
int frame_drops_early; // 丢弃视频packet计数
int frame_drops_late; // 丢弃视频frame计数

enum ShowMode {
SHOW_MODE_NONE = -1, SHOW_MODE_VIDEO = 0, SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB
} show_mode;
int16_t sample_array[SAMPLE_ARRAY_SIZE];
int sample_array_index;
int last_i_start;
RDFTContext *rdft;
int rdft_bits;
FFTSample *rdft_data;
int xpos;
double last_vis_time;
SDL_Texture *vis_texture;
SDL_Texture *sub_texture;
SDL_Texture *vid_texture;

int subtitle_stream; // 字幕流索引
AVStream *subtitle_st; // 字幕流
PacketQueue subtitleq; // 字幕packet队列

double frame_timer; // 记录最后一帧播放的时刻
double frame_last_returned_time;
double frame_last_filter_delay;
int video_stream;
AVStream *video_st; // 视频流
PacketQueue videoq; // 视频队列
double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity
struct SwsContext *img_convert_ctx;
struct SwsContext *sub_convert_ctx;
int eof;

char *filename;
int width, height, xleft, ytop;
int step;

#if CONFIG_AVFILTER
int vfilter_idx;
AVFilterContext *in_video_filter; // the first filter in the video chain
AVFilterContext *out_video_filter; // the last filter in the video chain
AVFilterContext *in_audio_filter; // the first filter in the audio chain
AVFilterContext *out_audio_filter; // the last filter in the audio chain
AVFilterGraph *agraph; // audio filter graph
#endif

int last_video_stream, last_audio_stream, last_subtitle_stream;

SDL_cond *continue_read_thread;
} VideoState;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
static const struct TextureFormatEntry {//sdl音频输出有限 需要重采样
enum AVPixelFormat format;
int texture_fmt;
} sdl_texture_format_map[] = {
{ AV_PIX_FMT_RGB8, SDL_PIXELFORMAT_RGB332 },
{ AV_PIX_FMT_RGB444, SDL_PIXELFORMAT_RGB444 },
{ AV_PIX_FMT_RGB555, SDL_PIXELFORMAT_RGB555 },
{ AV_PIX_FMT_BGR555, SDL_PIXELFORMAT_BGR555 },
{ AV_PIX_FMT_RGB565, SDL_PIXELFORMAT_RGB565 },
{ AV_PIX_FMT_BGR565, SDL_PIXELFORMAT_BGR565 },
{ AV_PIX_FMT_RGB24, SDL_PIXELFORMAT_RGB24 },
{ AV_PIX_FMT_BGR24, SDL_PIXELFORMAT_BGR24 },
{ AV_PIX_FMT_0RGB32, SDL_PIXELFORMAT_RGB888 },
{ AV_PIX_FMT_0BGR32, SDL_PIXELFORMAT_BGR888 },
{ AV_PIX_FMT_NE(RGB0, 0BGR), SDL_PIXELFORMAT_RGBX8888 },
{ AV_PIX_FMT_NE(BGR0, 0RGB), SDL_PIXELFORMAT_BGRX8888 },
{ AV_PIX_FMT_RGB32, SDL_PIXELFORMAT_ARGB8888 },
{ AV_PIX_FMT_RGB32_1, SDL_PIXELFORMAT_RGBA8888 },
{ AV_PIX_FMT_BGR32, SDL_PIXELFORMAT_ABGR8888 },
{ AV_PIX_FMT_BGR32_1, SDL_PIXELFORMAT_BGRA8888 },
{ AV_PIX_FMT_YUV420P, SDL_PIXELFORMAT_IYUV },
{ AV_PIX_FMT_YUYV422, SDL_PIXELFORMAT_YUY2 },
{ AV_PIX_FMT_UYVY422, SDL_PIXELFORMAT_UYVY },
{ AV_PIX_FMT_NONE, SDL_PIXELFORMAT_UNKNOWN },
};
1
2
3
4
5
enum {//音视频同步方式枚举
AV_SYNC_AUDIO_MASTER, // 以音频为基准
AV_SYNC_VIDEO_MASTER, // 以视频为基准
AV_SYNC_EXTERNAL_CLOCK, // 以外部时钟为基准,synchronize to an external clock */
};