1.测试拿过来个视频,发现用ijk播放器与系统播放器(mediaplayer)播放感觉不一样,用ijk播放感觉播放页面卡顿一点,没有系统播放器那么流畅。
下面看一下这个问题,这个问题的原因其实很简单,由于我丢帧值设置的是5,改成1就可以感觉2个播放器在体验上感觉差不多了。(丢5帧人眼就可以看出来差别了!)。
2.在高通660的机器上播放一个4k(30fps)视频,但是无法正常播放,实际一秒的解码帧只有20帧,实际播放只有4帧这样。导致画面卡顿,音视频不同步。
后面发现是由于这个视频,在高通机器上很多帧解码都比较慢,导致视频一直比音频慢,在硬解码丢帧时,判断视频一直比音频慢,导致视频一直在丢帧,也就出现看上去的卡顿。
丢帧原理
首先需要明白丢帧需要丢哪里的帧,丢什么帧呢?
丢帧可以丢解码前的帧也可以丢解码后的帧,
丢解码前的帧需要判断帧类型来丢,可以选择丢b,p帧,如果需要丢I帧就需要把整个gop全部丢掉防止花屏。
丢解码后的帧可以不用按照帧类型来丢,由于帧都是解码后的数据了,如yuv,直接按照pts来判断音视频是否不同步来丢就可以了。
1.ffplay中丢帧设计
我们看下ffplay中丢帧的设计:ffplay丢的是解码后的视频帧
在video_thread解码线程中,我们可以看到get_video_frame函数主要用于解码获取解码后的数据avframe,然后来检测判断丢帧。
static int get_video_frame(VideoState *is, AVFrame *frame)
{
int got_picture;
//解码获取解码后的数据avframe
if ((got_picture = decoder_decode_frame(&is->viddec, frame, NULL)) < 0)
return -1;
if (got_picture) {
double dpts = NAN;
if (frame->pts != AV_NOPTS_VALUE)
dpts = av_q2d(is->video_st->time_base) * frame->pts;//视频的pts转换为ms,也就是当前进度时间
//视频的宽高比
frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame);
//丢帧数大于0且同步不是按照video
if (framedrop>0 || (framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) {
if (frame->pts != AV_NOPTS_VALUE) {
//frame_last_filter_delay 默认是0
//diff小于0,视频比音频慢,丢帧
//diff大于0,视频比音频快,不丢帧
double diff = dpts - get_master_clock(is);
// AV_NOSYNC_THRESHOLD:同步阈值。如果误差太大,则不进行校正,也不丢帧来做同步了
if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD &&
diff - is->frame_last_filter_delay < 0 &&
is->viddec.pkt_serial == is->vidclk.serial &&
is->videoq.nb_packets) {
is->frame_drops_early++;