stream_open主要流程
stream_open 流程主要负责播放器运行过程中相关上下文和队列的初始化,以及码流读取线程的创建。
也就是从这个函数开始,播放器就真正开始运行起来了。
本次主要还是介绍这个过程中使用到的结构体。
比较重要的后面单独解析。
stream_open源码
static VideoState *stream_open(const char *filename,
const AVInputFormat *iformat)
{
//创建VideoState结构体,这个结构体是ffplay的核心上下文,贯穿整个播放流程
VideoState *is;
is = av_mallocz(sizeof(VideoState));
if (!is)
return NULL;
//初始化is,保存filename和iformat
is->last_video_stream = is->video_stream = -1;
is->last_audio_stream = is->audio_stream = -1;
is->last_subtitle_stream = is->subtitle_stream = -1;
is->filename = av_strdup(filename);
if (!is->filename)
goto fail;
is->iformat = iformat;
is->ytop = 0;
is->xleft = 0;
/*初始化帧缓存队列,视频初始化,大小如下
VIDEO_PICTURE_QUEUE_SIZE 3
SUBPICTURE_QUEUE_SIZE 16
SAMPLE_QUEUE_SIZE 9 */
if (frame_queue_init(&is->pictq, &is->videoq, VIDEO_PICTURE_QUEUE_SIZE, 1) < 0)
goto fail;
if (frame_queue_init(&is->subpq, &is->subtitleq, SUBPICTURE_QUEUE_SIZE, 0) < 0)
goto fail;
if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0)
goto fail;
/*
初始化包缓存队列
*/
if (packet_queue_init(&is->videoq) < 0 ||
packet_queue_init(&is->audioq) < 0 ||
packet_queue_init(&is->subtitleq) < 0)
goto fail;
// 创建SDL条件变量,这个条件变量用于read_thread线程,为了防止没有数据时线程空转。
if (!(is->continue_read_thread = SDL_CreateCond())) {
av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError());
goto fail;
}
//创建音频、视频、外部时钟
init_clock(&is->vidclk, &is->videoq.serial);
init_clock(&is->audclk, &is->audioq.serial);
init_clock(&is->extclk, &is->extclk.serial);
is->audio_clock_serial = -1;
if (startup_volume < 0)
av_log(NULL, AV_LOG_WARNING, "-volume=%d < 0, setting to 0\n", startup_volume);
if (startup_volume > 100)
av_log(NULL, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", startup_volume);
startup_volume = av_clip(startup_volume, 0, 100);
startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, SDL_MIX_MAXVOLUME);
is->audio_volume = startup_volume;
is->muted = 0;
is->av_sync_type = av_sync_type;
//创建收包线程
is->read_tid = SDL_CreateThread(read_thread, "read_thread", is);
if (!is->read_tid) {
av_log(NULL, AV_LOG_FATAL, "SDL_CreateThread(): %s\n", SDL_GetError());
fail:
stream_close(is);
return NULL;
}
return is;
}
VideoStatu结构体
typedef struct VideoState {
SDL_Thread *read_tid;
const AVInputFormat *iformat;//ffmpeg输入格式
int abort_request; //stream停止请求
int force_refresh; //强制刷新
int paused;//暂停
int last_paused;//上一次暂停状态,播放器的开始和暂停状态由内部控制,即调用者不用关心本次调的是开始还是暂停
int queue_attachments_req;//缩略图请求
//seek相关,后续会详细讲解
int seek_req;
int seek_flags;
int64_t seek_pos;
int64_t seek_rel;
int read_pause_return; //网络中的暂停消息
AVFormatContext *ic;//ffmpeg核心上下文
int realtime;//是否实时(缓存策略等处理不同)
//音视频同步相关,后续会详细讲解
Clock audclk;
Clock vidclk;
Clock extclk;
//Frame数据缓存
FrameQueue pictq;
FrameQueue subpq;
FrameQueue sampq;
//解码器
Decoder auddec;
Decoder viddec;
Decoder subdec;
int audio_stream;//音频流id
int av_sync_type;//音视频同步方式
double audio_clock;//音频时钟,根据pts计算
int audio_clock_serial;//音频序列号,跳转后会更新
//用于音频同步视频的情况
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;//音频队列
int audio_hw_buf_size;//音频硬件缓存buffer大小
//音频播放Ringbuffer
uint8_t *audio_buf;
//临时buffer
uint8_t *audio_buf1;
unsigned int audio_buf_size; /* in bytes */
unsigned int audio_buf1_size;
int audio_buf_index; /* in bytes */
int audio_write_buf_size;
int audio_volume;//音量
int muted;//静音标识
//音频转码相关
struct AudioParams audio_src;
struct AudioParams audio_filter_src;
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;
AVTXContext *rdft;
av_tx_fn rdft_fn;
int rdft_bits;
float *real_data;
AVComplexFloat *rdft_data;
int xpos;
double last_vis_time;
SDL_Texture *vis_texture;
SDL_Texture *sub_texture; //字幕显示纹理
SDL_Texture *vid_texture; //视频显示纹理
int subtitle_stream; //字幕流id
AVStream *subtitle_st;//字幕流
PacketQueue subtitleq;//字幕队列
double frame_timer;//视频当前播放时间
double frame_last_returned_time;
double frame_last_filter_delay;
int video_stream;//视频流id
AVStream *video_st; //视频流
PacketQueue videoq;//视频流队列
double max_frame_duration; //最大帧间隔,如果超过将会丢弃数据
struct SwsContext *sub_convert_ctx;
int eof;
char *filename;
int width, height, xleft, ytop;
int step;
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
int last_video_stream, last_audio_stream, last_subtitle_stream;
SDL_cond *continue_read_thread;//读数据线程条件变量
} VideoState;
系列文章目录
ffplay源码分析(一)主函数
未完待续…