ijkplayer系列12:video_refresh_thread

江枫思渺然 提交于 2019-11-30 04:26:35

video_refresh_thread
该线程负责图像的渲染,先来看下整体流程:
在这里插入图片描述
从上面的流程图可以得知,最终根据格式的差异分成了三个分支,我们先来看下func_display_overlay_l()的源码,然后再继续深入三个分支中。

static int func_display_overlay_l(SDL_Vout *vout, SDL_VoutOverlay *overlay) {
    SDL_Vout_Opaque *opaque = vout->opaque;
    ANativeWindow *native_window = opaque->native_window;

    if (!native_window) {
        if (!opaque->null_native_window_warned) {
            opaque->null_native_window_warned = 1;
            ALOGW("func_display_overlay_l: NULL native_window");
        }
        return -1;
    } else {
        opaque->null_native_window_warned = 1;
    }

    if (!overlay) {
        ALOGE("func_display_overlay_l: NULL overlay");
        return -1;
    }

    if (overlay->w <= 0 || overlay->h <= 0) {
        ALOGE("func_display_overlay_l: invalid overlay dimensions(%d, %d)", overlay->w, overlay->h);
        return -1;
    }

    switch(overlay->format) {
    // Android MediaCodec,渲染直接调用MediaCodec的Java API
    case SDL_FCC__AMC: {
        // only ANativeWindow support
        IJK_EGL_terminate(opaque->egl);
        return SDL_VoutOverlayAMediaCodec_releaseFrame_l(overlay, NULL, true);
    }
    // OPENGL可以直接渲染以下三种格式的图像数据
    case SDL_FCC_RV24:
    case SDL_FCC_I420: //I420,即YUV420P,H.264使用的格式
    case SDL_FCC_I444P10LE: {
        // only GLES support
        if (opaque->egl)
            return IJK_EGL_display(opaque->egl, native_window, overlay);
        break;
    }
    // 这几个是Android中比较常见的格式,使用OPNENGL或ANativeWindow渲染即可
    case SDL_FCC_YV12:
    case SDL_FCC_RV16:
    case SDL_FCC_RV32: {
        // both GLES & ANativeWindow support
        if (vout->overlay_format == SDL_FCC__GLES2 && opaque->egl)
            return IJK_EGL_display(opaque->egl, native_window, overlay);
        break;
    }
    }

    // fallback to ANativeWindow
    IJK_EGL_terminate(opaque->egl);
    return SDL_Android_NativeWindow_display_l(native_window, overlay); 
}

硬解码渲染

在这里插入图片描述
J4AC_android_media_MediaCodec__releaseOutputBuffer()方法最终会调用到Java层的MediaCodec类的releaseOutputBuffer()方法,该方法的作用是根据索引释放对应的缓冲区,将缓冲区内的图像数据渲染到设置的Surface中。

OpenGL渲染

由于本人对opengl并不了解,因此不再过多叙述,有兴趣的同学自行进入ijksdl_egl.c中的IJK_EGL_display()方法中去查看源码。里面的逻辑很简单,主要是对一些opengl API的使用,相信熟悉opengl的同学看起来应该很轻松。

ANativeWindow渲染

源码就不帖出来了,里面也主要是对ANativeWindow一些相关API的使用,通过这些API将图像渲染出来。值得一提的是,其中有这么一句代码
voutDesc->render(&out_buffer, overlay);,
显然又是一个函数指针。根据像素空间不同,render有可能指向三个实现方法,分别为android_render_on_yv12()、android_render_on_rgb565()和android_render_on_rgb8888(),这三个方法均位于android_nativewindow.c中。显然,这三个方法分别代表着对YV12、RGB565和RGB32三种格式的图像的渲染。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!