数据结构分析
VideoState
其实主要作用和800行代码写一个播放器作用中一样 就是一个主要封装类 保存 其中各项的主要内容
个人觉得比较需要注意到的 几个非重点常用对象
1 abort_request 就是判断这个时候有没有 退出播放 如果退出了 那就一系列退出操作
2 force_refresh 视频播放时候用的
3 av_sync_type ffplay 支持3种同步方式
typedef struct VideoState {
SDL_Thread *read_tid;
AVInputFormat *iformat;
int abort_request;
int force_refresh;
int paused;
int last_paused;
int queue_attachments_req;
int seek_req;
int seek_flags;
int64_t seek_pos;
int64_t seek_rel;
int read_pause_return;
AVFormatContext *ic;
int realtime;
Clock audclk;
Clock vidclk;
Clock extclk;
FrameQueue pictq;
FrameQueue subpq;
FrameQueue sampq;
Decoder auddec;
Decoder viddec;
Decoder subdec;
int audio_stream ;
int av_sync_type;
double audio_clock;
int audio_clock_serial;
double audio_diff_cum;
double audio_diff_avg_coef;
double audio_diff_threshold;
int audio_diff_avg_count;
AVStream *audio_st;
PacketQueue audioq;
int audio_hw_buf_size;
uint8_t *audio_buf;
uint8_t *audio_buf1;
unsigned int audio_buf_size;
unsigned int audio_buf1_size;
int audio_buf_index;
int audio_write_buf_size;
int audio_volume;
int muted;
struct AudioParams audio_src;
#if CONFIG_AVFILTER
struct AudioParams audio_filter_src;
#endif
struct AudioParams audio_tgt;
struct SwrContext *swr_ctx;
int frame_drops_early;
int frame_drops_late;
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;
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;
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;
AVFilterContext *out_video_filter;
AVFilterContext *in_audio_filter;
AVFilterContext *out_audio_filter;
AVFilterGraph *agraph;
#endif
int last_video_stream, last_audio_stream, last_subtitle_stream;
SDL_cond *continue_read_thread;
} VideoState;
MyAVPacketList
和名字一样 就是 解封装出来的packet 用链表的形式开始保存 啦啦啦啦 可以理解为是队列的?个节点。可以通过其 next 字段访问下?个节点
重点!!! 1 serial
ffplay中多处?到serial的概念,主要?来区分是否连续 数据,每做?次seek,该serial都会做+1的递增,以区分不同的播放序列。
说人话就是: 就是 seek 一次以后 以前的队列中的东西当然就不能用了呗 应该放弃的放弃 要free 的 free
typedef struct MyAVPacketList {
AVPacket pkt;
struct MyAVPacketList *next;
int serial;
} MyAVPacketList;
PacketQueue
这里这个packeQueue 逻辑和前面800行代码播放器 逻辑一样 保存一些基本信息
这个packetqueue 是 同时作用于 视频 音频 和 字幕的 ?频、视频、字幕流都有??独?的PacketQueue
这?也看到了serial字段, MyAVPacketList的serial字段的赋值来?PacketQueue的serial,每个PacketQueue的serial是独?的。
typedef struct PacketQueue {
MyAVPacketList *first_pkt, *last_pkt;
int nb_packets;
int size;
int64_t duration;
int abort_request;
int serial;
SDL_mutex *mutex;
SDL_cond *cond;
} PacketQueue;
PacketQueue的函数们
太多了 写了一篇新的 连接在这里
Frame
真正存储解码后?视频数据的结构体为AVFrame ,存储字幕则使?AVSubtitle,该Frame的设计是为了?频、视频、字幕帧通?,所以Frame结构体的设计类似AVFrame,部分成员变量只对不同类型有作?,? 如sar只对视频有作?。 ??也包含了serial播放序列(每次seek时都切换serial),sar(图像的宽??(16:9,4:3…),该值来 ?AVFrame的sample_aspect_ratio变量。
typedef struct Frame {
AVFrame *frame;
AVSubtitle sub;
int serial;
double pts;
double duration;
int64_t pos;
int width;
int height;
int format;
AVRational sar;
int uploaded;
int flip_v;
} Frame;
FrameQueue
FrameQueue是?个环形缓冲区(ring buffer),是?数组实现的?个FIFO。数组?式的环形缓冲区适合于 事先明确了缓冲区的最?容量的情形。 ffplay中创建了三个frame_queue:?频frame_queue,视频frame_queue,字幕frame_queue。每? 个frame_queue?个写端?个读端,写端位于解码线程,读端位于播放线程。
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;
} FrameQueue;
FrameQueue的设计?如PacketQueue复杂,引?了读取节点但节点不出队列的操作、读取下?节点也不出队列等等的操作,FrameQueue具体操作函数见连接xxx
在这里插入代码片
AudioParams
int bytes_per_sec; // 一秒时间的字节数,比如采样率48Khz,2 channel,16bit,则一秒48000*2*16/8=192000
typedef struct AudioParams {
int freq;
int channels;
int64_t channel_layout;
enum AVSampleFormat fmt;
int frame_size;
int bytes_per_sec;
} AudioParams;
struct Decoder解码器封装
typedef struct Decoder {
AVPacket pkt;
PacketQueue *queue;
AVCodecContext *avctx;
int pkt_serial;
int finished;
int packet_pending;
SDL_cond *empty_queue_cond;
int64_t start_pts;
AVRational start_pts_tb;
int64_t next_pts;
AVRational next_pts_tb;
SDL_Thread *decoder_tid;
} Decoder;
|