问题
在写ffmpeg音视频同步的时候,我是参考了动脑老师的方法,根据音频的时间来同步视频,写完以后发现播放mp4文件音视频同步,流畅度基本上是没有问题的,但是播放直播流就会有问题,有时候音频和视频的差距很大导致视频根本就出不来(因为视频比音频块了很多,这样会让他睡很久,所以没视频),那这里我自己又没有音视频的经验根本解决不了这个问题,这个时候只能去看下ffmpeg提供的ffplay的源码,看看他的音视频同步是怎么做的,这样来解决我自己音视频同步的问题。ffplay还是挺大的,希望自己花几天时间搞明白他,最起码搞明白他音视频同步的方案,他好像三种方案都写了,以视频为基准,以音频为基准和以外部时间为基准。下面我先贴出我当前有问题的音视频同步代码,如果有知道问题的麻烦能不吝赐教。
- 视频里面的代码
//每个画面刷新的时间间隔
double frameDelays = 1.0 / fps;
while (isPlaying) {
frames.pop(frame);
sws_scale(swsContext, frame->data, frame->linesize, 0, codecContext->height, dst_data,
dst_linesize);
//做音视频同步 获取当前视频的时间
double clock = frame->best_effort_timestamp * av_q2d(time_base);
//还有个额外的时间
double extra_delay = frame->repeat_pict / (2 * fps);
//真正的延时
double delays=frameDelays+extra_delay;
double audioClock = audioChannel->clock;
double diff=clock-audioClock;
LOGE("player diff %f audioClock %f videoclock %f",diff,audioChannel->clock,clock);
if(!audioChannel){
// //如果没有音频 就睡这么长时间
av_usleep(delays*1000000);
} else{
if (clock==0){
//刚刚开始
av_usleep(delays*1000000);
} else {
//比较音频和视频
double audioClock = audioChannel->clock;
double diff=clock-audioClock;
if(diff>0){
//视频比音频快
LOGE("player 视频快了");
av_usleep((delays+diff)*1000000);
} else if (diff<0){
LOGE("player 音频快了");
//视频积压太多 就丢包
if(fabs(diff)>=0.05){
releaseAvFrame(&frame);
frames.sync();
continue;
} else{
//不要睡 赶紧去跟上
}
}
}
}
- 音频里面的相关部分代码
int datasize = 0;
AVFrame *avFrame;
int ret = frames.pop(avFrame);
//对avframe 进行重采样
//1、拿到积压的数据
int64_t delays = swr_get_delay(swrContext, avFrame->sample_rate);
//最大能返回多少个数据
int max_samples = av_rescale_rnd(delays + avFrame->nb_samples, out_sample_rate,
avFrame->sample_rate, AV_ROUND_UP);
//返回每个声道的输出数据
int samples = swr_convert(swrContext, &data, max_samples, (const uint8_t **) avFrame->data,
avFrame->nb_samples);
datasize=samples*out_samplesize*out_channels;
//当前音频的时间戳
clock=avFrame->pts*av_q2d(time_base);
主要是通过音频的clock去同步视频的clock,不知道为什么直播流的播放页面会非常卡。
总结
这次主要是记录当前的问题,和我接下来要做的工作,分析ffplay源码,解决音视频同步问题。
网友评论