NDK学习笔记(十三) 使用AVILib+opengl es 2.0创建一个AVI视频播放器

文章目录

  • 1.java代码
  • 2.配置cmake GLESv2
  • 3.原生代码
  • 4.实现效果

demo地址

https://gitee.com/xd_box/AviPlayer

直接上代码

1.java代码

public class OpenGLPlayerActivity extends AbstractPlayerActivity {
     

    private final AtomicBoolean isPlaying = new AtomicBoolean();
    private long instance;
    private GLSurfaceView glSurfaceView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
     
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_open_g_l_player);

        glSurfaceView = findViewById(R.id.glSurfaceView);

        glSurfaceView.setEGLContextClientVersion(2);
        glSurfaceView.setRenderer(renderer);
        //请求时渲染帧
        glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
    }

    @Override
    protected void onStart() {
     
        super.onStart();
        instance = init(avi);
    }


    @Override
    protected void onResume() {
     
        super.onResume();

        glSurfaceView.onResume();
    }

    @Override
    protected void onPause() {
     
        super.onPause();

        glSurfaceView.onPause();
    }

    @Override
    protected void onStop() {
     
        super.onStop();

        free(instance);
    }


    private final Runnable player = new Runnable() {
     
        @Override
        public void run() {
     

            long frameDelay = (long) (1000 / getFrameRate(avi));

            while (isPlaying.get()) {
     

                glSurfaceView.requestRender();

                try {
     

                    Thread.sleep(frameDelay);
                } catch (InterruptedException e) {
     

                    break;
                }
            }
        }
    };


    private final GLSurfaceView.Renderer renderer = new GLSurfaceView.Renderer() {
     
        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
     

            initSurface(instance, avi);
            isPlaying.set(true);
            new Thread(player).start();
        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
     


        }

        @Override
        public void onDrawFrame(GL10 gl) {
     

            if (!render(instance, avi)) {
     

                isPlaying.set(false);
            }
        }
    };


    /**
     * 初始化渲染器
     *
     * @param avi
     * @return
     */
    private native static long init(long avi);


    /**
     * 初始化opengl surface
     *
     * @param instance
     * @param avi
     */
    private native static void initSurface(long instance, long avi);

    /**
     * 用给定文件读取帧渲染
     *
     * @param instance
     * @param avi
     * @return
     */
    private native static boolean render(long instance, long avi);


    /**
     * 释放原生渲染器
     *
     * @param instance
     */
    private native static void free(long instance);

}

2.配置cmake GLESv2

find_library(
        GLESv2-lib
        GLESv2)
        
target_link_libraries( # Specifies the target library.
        native-lib
        # Links the target library to the log library
        # included in the NDK.
        ${
     jnigraphics-lib}#开启jnigraphics
        ${
     log-lib}
        ${
     GLESv2-lib}
        avi-lib)

3.原生代码

extern "C" {
     
#include "avilib/avilib.h"
}

#include "cn_study_aviplayer_OpenGLPlayerActivity.h"
#include "Common.h"
#include 
#include 
#include 

#define POSITION_COMPONENT_COUNT 2
#define BYTES_PER_FLOAT 4
#define TEXTURE_COORDINATES_COMPONENT_COUNT 2
#define STRIDE ((POSITION_COMPONENT_COUNT + TEXTURE_COORDINATES_COMPONENT_COUNT)*BYTES_PER_FLOAT)

GLuint LoadShader(GLenum type, const char *shaderSrc);

static GLuint gProgramObject;

struct Instance {
     
    char *buffer;
    GLuint texture;

    Instance() : buffer(0), texture(0) {
     }
};


char vShaderStr[] = "attribute vec4 a_Position;           \n"
                    "attribute vec2 a_TextureCoordinates;               \n"
                    "varying vec2 v_TextureCoordinates;                 \n"
                    "void main()                                        \n"
                    "{                                                  \n"
                    "    v_TextureCoordinates = a_TextureCoordinates;   \n"
                    "    gl_Position = a_Position;                      \n"
                    "}                                                  \n";

char fShaderStr[] =
        "precision mediump float; \n"
        "uniform sampler2D u_TextureUnit;                   \n"
        "varying vec2 v_TextureCoordinates;                 \n"
        "void main()                                        \n"
        "{                                                  \n"
        "    gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);  \n"
        "}                                                  \n";

extern "C"
JNIEXPORT jlong JNICALL
Java_cn_study_aviplayer_OpenGLPlayerActivity_init(JNIEnv *env, jclass clazz, jlong avi) {
     

    Instance *instance = 0;
    long frameSize = AVI_frame_size((avi_t *) avi, 0);

    if (0 >= frameSize) {
     

        ThrowException(env, "java/io/RuntimeException", "没有获取到帧大小");
        goto exit;
    }

    instance = new Instance();
    instance->buffer = (char *) malloc(frameSize);
    if (0 == instance->buffer) {
     

        ThrowException(env, "java/io/RuntimeException", "申请内存失败");
        delete instance;
        instance = 0;
    }

    exit:
    return (jlong) instance;
}


extern "C"
JNIEXPORT void JNICALL
Java_cn_study_aviplayer_OpenGLPlayerActivity_initSurface(JNIEnv *env, jclass clazz, jlong inst,
                                                         jlong avi) {
     

    Instance *instance = (Instance *) inst;

    GLuint vertexShader;
    GLuint fragmentShader;
    GLuint programObject;
    GLint linked;

    vertexShader = LoadShader(GL_VERTEX_SHADER, vShaderStr);
    fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fShaderStr);

    programObject = glCreateProgram();

    if (programObject == 0) {
     
        return;
    }
    //附着色器
    glAttachShader(programObject, vertexShader);
    glAttachShader(programObject, fragmentShader);
    // 连接program
    glLinkProgram(programObject);


    // 检查链接状态
    glGetProgramiv(programObject, GL_LINK_STATUS, &linked);

    if (!linked) {
     
        GLint infoLen = 0;

        //日志长度
        glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);

        if (infoLen > 1) {
     
            char *infoLog = (char *) malloc(sizeof(char) * infoLen);

            glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);
//            esLogMessage("Error linking program:\n%s\n", infoLog);

            free(infoLog);
        }

        glDeleteProgram(programObject);
        return;
    }

    // 全局
    gProgramObject = programObject;

    glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
    //生成一个纹理对象
    glGenTextures(1, &instance->texture);
    //绑定到生成的纹理上
    glBindTexture(GL_TEXTURE_2D, instance->texture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_cn_study_aviplayer_OpenGLPlayerActivity_render(JNIEnv *env, jclass clazz, jlong inst,
                                                    jlong avi) {
     

    Instance *instance = (Instance *) inst;
    jboolean isFrameRead = JNI_FALSE;

    GLint uTextureUnitLocation;
    GLint aPositionLocation;
    GLint aTextureCoordinatesLocation;
    GLfloat VERTEX_DATA[] = {
     0.0f, 0.0f, 0.5f, 0.5f, -1.0f, -1.0f, 0.0f, 1.0f,
                             1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f,
                             0.0f, -1.0f, -1.0f, 0.0f, 1.0f};
    int x, y;
    int vWidth, vHeight;
    float scale = 1.8;

    int keyFrame = 0;

    long frameSize = AVI_read_frame((avi_t *) avi, instance->buffer, &keyFrame);

    if (0 >= frameSize) {
     

        goto exit;
    }

    isFrameRead = JNI_TRUE;


    vWidth = AVI_video_width((avi_t *) avi) * scale;
    vHeight = AVI_video_height((avi_t *) avi) * scale;

    x = (1080 - vWidth) / 2;
    y = 1920 / 2 - vHeight / 2;

    //设置视频位置及大小
    glViewport(x, y, vWidth, vHeight);
    glClear(GL_COLOR_BUFFER_BIT);
    glUseProgram(gProgramObject);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, AVI_video_width((avi_t *) avi),
                 AVI_video_height((avi_t *) avi), 0, GL_RGB,
                 GL_UNSIGNED_SHORT_5_6_5, instance->buffer);

//    uTextureUnitLocation = glGetUniformLocation(gProgramObject, "u_TextureUnit");
//    setUniforms(uTextureUnitLocation, instance->texture);

    //返回属性变量
    aPositionLocation = glGetAttribLocation(gProgramObject, "a_Position");
    aTextureCoordinatesLocation = glGetAttribLocation(gProgramObject, "a_TextureCoordinates");

    //定义通用顶点属性数据数组
    glVertexAttribPointer((GLuint) aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,
                          0, STRIDE, VERTEX_DATA);
    //启用或禁用通用顶点属性数组
    glEnableVertexAttribArray((GLuint) aPositionLocation);

    glVertexAttribPointer((GLuint) aTextureCoordinatesLocation, POSITION_COMPONENT_COUNT,
                          GL_FLOAT, 0, STRIDE, &VERTEX_DATA[POSITION_COMPONENT_COUNT]);
    glEnableVertexAttribArray((GLuint) aTextureCoordinatesLocation);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 6);

    exit:
    return isFrameRead;
}


extern "C"
JNIEXPORT void JNICALL
Java_cn_study_aviplayer_OpenGLPlayerActivity_free(JNIEnv *env, jclass clazz, jlong inst) {
     

    Instance *instance = (Instance *) inst;
    if (0 != instance) {
     

        free(instance->buffer);
        delete instance;
    }
}


/**
 * 装载着色器
 * @param type
 * @param shaderSrc
 * @return
 */
GLuint LoadShader(GLenum type, const char *shaderSrc) {
     
    GLuint shader;
    GLint compiled;

    // Create the shader object
    shader = glCreateShader(type);

    if (shader == 0) {
     
        return 0;
    }

    // Load the shader source
    glShaderSource(shader, 1, &shaderSrc, NULL);

    // Compile the shader
    glCompileShader(shader);

    // Check the compile status
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);

    if (!compiled) {
     
        GLint infoLen = 0;

        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);

        if (infoLen > 1) {
     
            char *infoLog = (char *) malloc(sizeof(char) * infoLen);

            glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
//            esLogMessage("Error compiling shader:\n%s\n", infoLog);

            free(infoLog);
        }

        glDeleteShader(shader);
        return 0;
    }

    return shader;

}

4.实现效果

NDK学习笔记(十三) 使用AVILib+opengl es 2.0创建一个AVI视频播放器_第1张图片

你可能感兴趣的:(NDK,android,android,studio,ndk,opengles)