5-stream_open和stream_close
进⼀步掌握:
- ijkmp_prepare_async处理逻辑
- ijkmp_stop处理逻辑
stream_open
stream_open主要⼯作内容:
- 初始化SDL以允许⾳频输出;
- 初始化帧Frame队列
- 初始化包Packet队列
- 初始化时钟Clock
- 初始化⾳量
- 创建解复⽤读取线程read_thread
- 创建视频刷新线程video_refresh_thread
这⾥需要注意的是我们只是列举了主要的逻辑,还有其他逻辑在后续不断优化的时候添加。
stream_close
stream_close主要⼯作内容:
- 请求关闭read_thread线程
- 关闭解复⽤器
- 关闭stream,⽐如调⽤stream_component_close,该函数实现的时候涉及到:
- 关闭解码线程
- 释放解码器资源
- 关闭对应的⾳频、视频设备
- 消耗包队列
- 消耗帧队列
释放其他资源
6-解复⽤、数据读取read_thread设计
read_thread线程
实现解复⽤
stream_component_open
打开对应的解码器并做初始化
创建和启动解码线程
初始化⾳频或视频输出设备
stream_component_close
关闭解码器线程
释放解码器资源
关闭⾳频或视频输出设备
7-解码线程Decoder封装
- stream_component_open
- decoder_init
- decoder_start
- stream_component_close
- decoder_abort
- decoder_destroy
int audio_thread(void* arg); // ffplayer
int video_thread(void* arg);// ffplayer
8-⾳频输出
我们采⽤SDL作为⾳频输出。
- ⾳频设备初始化
- ⾳频设备输出回调函数
- 重采样
- buffer管理
9-视频渲染输出
⽬前使⽤qt输出, ui模块需要传⼊qt输出画⾯的回调。
重点内容
- 创建视频刷新线程video_refresh_thread,然后调⽤输出画⾯的回调函数。
- 设置视频刷新回调函数 从MainWind-> IjkMediaPlayer -> FFPlayer
- av_read_frame的video packet发给video packet queue
- 在DisplayWind 渲染画⾯
- 在调⽤stream_component_close的时候记得关闭 视频刷新线程video_refresh_thread
10-基本的⾳视频同步
难点
- ⾳视频同步采⽤以⾳频为基准的⽅式。
- ⾳频维系时间轴 视频时间戳怎么去对⽐⾳频时钟?
- NaN(Not a Number,⾮数)是计算机科学中数值数据类型的⼀类值,表示未定义或不可表示的值。常在浮点数运 算中使⽤。
步骤
- 时钟结构设计和API设计
// 这⾥讲的系统时钟 是通过av_gettime_relative()获取到的时钟,单位为微妙
typedef struct Clock {
double pts; // 时钟基础, 当前帧(待播放)显示时间戳,播放后,当前帧变成上⼀帧
// 当前pts与当前系统时钟的差值, audio、video对于该值是独⽴的
double pts_drift; // clock base minus time at which we updated the clock
// 当前时钟(如视频时钟)最后⼀次更新时间,也可称当前时钟时间
double last_updated; // 最后⼀次更新的系统时钟
} Clock;
- stream_open中初始化时钟init_clock(&vidclk); init_clock(&audclk);
- 设置audio的时钟,在audio_decode_frame设置audio_clock, 然后在sdl_audio_callback设置audio时钟set_clock(&is->audclk, is->audio_clock);
- video时间戳⽐对audio时钟,在video_refresh
// 对⽐audio的时间戳
double diff = vp->pts - get_master_clock();
std::cout << __FUNCTION__ << "vp->pts:" << vp->pts << " - af->pts:" <<
get_master_clock() << ", diff:" << diff << std::endl;
if(diff > 0) {
*remaining_time = FFMIN(*remaining_time, diff);
return;
}
练习
- 实现控制⽂件的⼤⼩
- 实现暂停功能
- 实现seek功能
网友评论