美文网首页
ijkplayer学习笔记(六)——视频渲染

ijkplayer学习笔记(六)——视频渲染

作者: 程序媛的程 | 来源:发表于2021-09-22 17:53 被阅读0次

第四篇中可以看到,stream_open中涉及到两个线程read_thread和video_refresh_thread的创建,在第五篇中,我着重学习了read_thread中的核心函数stream_component_open,那么在这一篇中,则着重学习视频渲染相关的线程。

video_refresh_thread

video_refresh_thread.png

video_refresh

video_refresh_thread—>video_refresh—>video_display2—>video_image_display2

static void video_refresh(FFPlayer *opaque, double *remaining_time)
{
    ......
    if (is->video_st) {
retry:
        if (frame_queue_nb_remaining(&is->pictq) == 0) {
            // nothing to do, no picture to display in the queue
        } else {
            double last_duration, duration, delay;
            Frame *vp, *lastvp;

            /* dequeue the picture */
            //先获取最早的frame
            lastvp = frame_queue_peek_last(&is->pictq);
            vp = frame_queue_peek(&is->pictq);

            /* compute nominal last_duration */
            // 获取距离下一帧的时间(用来处理音视频同步的。根据同步的方式,获取修正过后的下一帧时间。)
            last_duration = vp_duration(is, lastvp, vp);
            delay = compute_target_delay(ffp, last_duration, is);

            ......

            if (frame_queue_nb_remaining(&is->pictq) > 1) {
                Frame *nextvp = frame_queue_peek_next(&is->pictq);
                duration = vp_duration(is, vp, nextvp);
                if(!is->step && (ffp->framedrop > 0 || (ffp->framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) && time > is->frame_timer + duration) {
                    // 确定要显示下一帧之后,才调用frame_queue_next把下一帧推到队列关键位,即索引rindex指定的位置。
                    frame_queue_next(&is->pictq);
                    goto retry;
                }
            }
        }
display:
        /* display picture */
        if (!ffp->display_disable && is->force_refresh && is->show_mode == SHOW_MODE_VIDEO && is->pictq.rindex_shown)
              // video_display2最终到了SDL_Vout的display_overlay函数。和前面一样,到了显示层,在这做了解耦处理,SDL_Vout对象是ffp->vout,也是在IJKFFMoviePlayerControllerinit里构建的
            video_display2(ffp);
    }
    is->force_refresh = 0;
    ......
}

video_image_display2

static void video_image_display2(FFPlayer *ffp)
{
   VideoState *is = ffp->is;
   Frame *vp;
   Frame *sp = NULL;
   //调用frame_queue_peek_last从pictq中读取当前需要显示视频帧
   vp = frame_queue_peek_last(&is->pictq);
   ......
   // 调用SDL_VoutDisplayYUVOverlay进行绘制
   SDL_VoutDisplayYUVOverlay(ffp->vout, vp->bmp);
   ......
}

SDL_VoutDisplayYUVOverlay

int SDL_VoutDisplayYUVOverlay(SDL_Vout *vout, SDL_VoutOverlay     *overlay)
 {
       if (vout && overlay && vout->display_overlay)
           return vout->display_overlay(vout, overlay);
 
     return -1;
 }

display_overlay函数指针在前面初始化流程有介绍过,它在SDL_Vout
SDL_VoutIos_CreateForGLES2()
方法中被赋值为vout_display_overlay,该方法就是调用OpengGL绘制图像

相关文章

网友评论

      本文标题:ijkplayer学习笔记(六)——视频渲染

      本文链接:https://www.haomeiwen.com/subject/dohggltx.html