短视频app源码开发,音视频同步简单实例代码

在短视频app源码开发中,音视频同步的实现关系着用户的体验,今天就要介绍一个简单的音视频同步实例代码。

代码参考ffplay实现方式,同时加入自己的修改。以audio为参考时钟,video同步到音频的示例代码:

1、获取当前要显示的video PTS,减去上一帧视频PTS,则得出上一帧视频应该显示的时长delay;
2、当前video PTS与参考时钟当前audio PTS比较,得出短视频app源码开发中音视频差距diff;
3、获取同步阈值sync_threshold,为一帧视频差距,范围为10ms-100ms;
4、diff小于sync_threshold,则认为不需要同步;否则delay+diff值,则是正确纠正delay;
5、如果超过sync_threshold,且视频落后于音频,那么需要减小delay(FFMAX(0, delay + diff)),让当前帧尽快显示。
如果在短视频app源码开发中视频落后超过1秒,且之前10次都快速输出视频帧,那么需要反馈给音频源减慢,同时反馈视频源进行丢帧处理,让视频尽快追上音频。因为这很可能是视频解码跟不上了,再怎么调整delay也没用。
6、如果超过sync_threshold,且视频快于音频,那么需要加大delay,让当前帧延迟显示。
将delay*2慢慢调整差距,这是为了平缓调整差距,因为直接delay+diff,会让画面画面迟滞。
如果短视频app源码中视频前一帧本身显示时间很长,那么直接delay+diff一步调整到位,因为这种情况再慢慢调整也没太大意义。
7、考虑到渲染的耗时,还需进行调整。frame_timer为一帧显示的系统时间,frame_timer+delay- curr_time,则得出正在需要延迟显示当前帧的时间。

{
    video->frameq.deQueue(&video->frame);
    //获取上一帧需要显示的时长delay
    double current_pts = *(double *)video->frame->opaque;
    double delay = current_pts - video->frame_last_pts;
    if (delay <= 0 || delay >= 1.0)
    {
        delay = video->frame_last_delay;
    }
   
    // 根据视频PTS和参考时钟调整delay
    double ref_clock = audio->get_audio_clock();
    double diff = current_pts - ref_clock;// diff < 0 :video slow,diff > 0 :video fast
    //一帧视频时间或10ms,10ms音视频差距无法察觉
    double sync_threshold = FFMAX(MIN_SYNC_THRESHOLD, FFMIN(MAX_SYNC_THRESHOLD, delay)) ;
    
    audio->audio_wait_video(current_pts,false);
    video->video_drop_frame(ref_clock,false);
    if (!isnan(diff) && fabs(diff) < NOSYNC_THRESHOLD) // 不同步
    {
        if (diff <= -sync_threshold)//视频比音频慢,加快
        {
            delay = FFMAX(0,  delay + diff);
            static int last_delay_zero_counts = 0;
            if(video->frame_last_delay <= 0)
            {
                last_delay_zero_counts++;
            }
            else
            {
                last_delay_zero_counts = 0;
            }
            if(diff < -1.0 && last_delay_zero_counts >= 10)
            {
                printf("maybe video codec too slow, adjust video&audio\n");
                #ifndef DORP_PACK
                audio->audio_wait_video(current_pts,true);//差距较大,需要反馈音频等待视频
                #endif          
                video->video_drop_frame(ref_clock,true);//差距较大,需要视频丢帧追上
            }
        }    
        //视频比音频快,减慢
        else if (diff >= sync_threshold && delay > SYNC_FRAMEDUP_THRESHOLD)
            delay = delay + diff;//音视频差距较大,且一帧的超过帧最常时间,一步到位
        else if (diff >= sync_threshold)
            delay = 2 * delay;//音视频差距较小,加倍延迟,逐渐缩小
    }

    video->frame_last_delay = delay;
    video->frame_last_pts = current_pts;

    double curr_time = static_cast<double>(av_gettime()) / 1000000.0;
    if(video->frame_timer == 0)
    {
        video->frame_timer = curr_time;//show first frame ,set frame timer
    }

    double actual_delay = video->frame_timer + delay - curr_time;
    if (actual_delay <= MIN_REFRSH_S)
    {
        actual_delay = MIN_REFRSH_S;
    }
    usleep(static_cast<int>(actual_delay * 1000 * 1000));
    //printf("actual_delay[%lf] delay[%lf] diff[%lf]\n",actual_delay,delay,diff);
    // Display
    SDL_UpdateTexture(video->texture, &(video->rect), video->frame->data[0], video->frame->linesize[0]);
    SDL_RenderClear(video->renderer);
    SDL_RenderCopy(video->renderer, video->texture, &video->rect, &video->rect);
    SDL_RenderPresent(video->renderer);
    video->frame_timer = static_cast<double>(av_gettime()) / 1000000.0 ;
    
    av_frame_unref(video->frame);
    
    //update next frame
    schedule_refresh(media, 1);
}

以上就是短视频app源码开发,音视频同步简单实例代码的全部内容了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值