一般来说,进度条的实现都是用dts或者pts来做参考实现
但是我现在用一种更加简单的方法去获取总时长和当前播放时间来做进度条。
获取总时长的函数:
if(avformat_open_input(&pFormatCtx, is->filename, NULL, NULL)!=0)
//获取总时长
times = pFormatCtx->duration/1000000.0;//转化为秒
获取当前的时间:
float current_times;
current_times = get_master_clock(is);//获取当前播放进度时间,is是VideoState结构体
上面的函数get_master_clock相关继续看下面
不知道大家有没有注意到ffplay在播放视频的时候有打印7个参数
这8个参数代表的意思是:
第一个参数和上面的那个总时长参数就可以拿来做播放进度条了
5.52 表示从开始播放到现在的时间(单位为秒)
A-V 表示既A就是音频,V就是视频,意思是既有音频流也有视频流
-0.000 音频和视频时间戳相减的差值
fd= (frame dropped) 丢帧数量
aq= 当前音频帧大小
vq= 当前视频帧大小
sq= 当前字幕帧大小
f= 时间戳纠错率
下面看看着打印这8个参数的源码:
av_log(NULL, AV_LOG_INFO,
"%7.2f %s:%7.3f fd=%4d aq=%5dKB vq=%5dKB sq=%5dB f=%"PRId64"/%"PRId64" \r",
get_master_clock(is),//这个就是获出当前时间的
(is->audio_st && is->video_st) ? "A-V" : (is->video_st ? "M-V" : (is->audio_st ? "M-A" : " ")),
av_diff,
is->frame_drops_early + is->frame_drops_late,
aqsize / 1024,
vqsize / 1024,
sqsize,
is->video_st ? is->viddec.avctx->pts_correction_num_faulty_dts : 0,
is->video_st ? is->viddec.avctx->pts_correction_num_faulty_pts : 0)
ffplay.c中的VideoState结构体
// 视频状态结构
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; // 音频码流Id
int av_sync_type; // 同步类型
double audio_clock; // 音频时钟
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;
uint8_t *audio_buf;
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;
#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; // 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;
详细请看
用上面说的方法在QT中-进度条的实现:https://blog.csdn.net/weixin_38890593/article/details/98875369
获取总时长:
https://blog.csdn.net/weixin_38890593/article/details/97143201