android平台源码编译,播放yuv的视频

参考文章:http://blog.csdn.net/wangchenggggdn/article/details/8896453

GLUtil.h:

#include <include/SoftwareRenderer.h>

#include <cutils/memory.h>

#include <unistd.h>
#include <utils/Log.h>

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>

#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/ISurfaceComposer.h>
#include <ui/DisplayInfo.h>
#include <android/native_window.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
#include <media/stagefright/foundation/AMessage.h>


#include <ui/GraphicBuffer.h>
#include <gui/Surface.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>

#ifndef NATIVEGLESVIEW_GLUTIL_H
#define NATIVEGLESVIEW_GLUTIL_H

#include <GLES2/gl2.h>
#include <android/log.h>
//#define LOGI(level, ...) __android_log_print(ANDROID_LOG_INFO, "NATIVE_LOG", __VA_ARGS__)
#define LOGI(level, format, ...) printf("[%s: %d]" format, __FILE__, __LINE__, ##__VA_ARGS__)

using namespace android;

class GLUtil
{

public:
    static int compileShader(int type, const char* shaderCode);
    static int createProgram(const char * vertexShaderCode, const char * fragmentShaderCode);

    EGLNativeWindowType getNativeWindow(int width, int hight);
    void disposeNativeWindow(void);
    
private:
    sp<SurfaceComposerClient>  mComposerClient;
    sp<SurfaceControl>   mSurfaceControl;
};

#endif 

GLUtil.cpp:

#include "GLUtil.h"

int GLUtil::compileShader(int type, const char * shaderCode)
{

    int shader = glCreateShader(type);
    if (shader == 0)
    {
        printf("Create Sharder error %d", glGetError());
        return 0;
    }

    glShaderSource(shader, 1, &shaderCode, NULL);
    glCompileShader(shader);
    GLint compileStatus = 0;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
    if (!compileStatus)
    {
        glDeleteShader(shader);
        LOGI(1, "compile shader error");
        return 0;
    }

    return shader;
}

int GLUtil::createProgram(const char *vertexShaderCode, const char *fragmentShaderCode)
{
    GLint program = glCreateProgram();
    if (0 == program)
    {
        LOGI(1, "create program error");
        return 0;
    }

    LOGI(1, "create program success");
    int vertexShaderID = compileShader(GL_VERTEX_SHADER, vertexShaderCode);
    int fragmentShaderID = compileShader(GL_FRAGMENT_SHADER,
            fragmentShaderCode);

    glAttachShader(program, vertexShaderID);
    glAttachShader(program, fragmentShaderID);
    glLinkProgram(program);
    GLint linkStatus;
    glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
    if (0 == linkStatus)
    {
        glDeleteProgram(program);
        LOGI(1, "link program error");
        return 0;
    }

    return program;
}

EGLNativeWindowType GLUtil::getNativeWindow(int width, int hight)
{
    DisplayInfo dinfo;
    
    mComposerClient = new SurfaceComposerClient();
    sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));

    status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
    printf("w=%d,h=%d,xdpi=%f,ydpi=%f,fps=%f,ds=%f\n", 
                dinfo.w, dinfo.h, dinfo.xdpi, dinfo.ydpi, dinfo.fps, dinfo.density);

    mSurfaceControl = mComposerClient->createSurface(
        String8("Test Surface"),
        dinfo.w, dinfo.h,
        PIXEL_FORMAT_RGBA_8888, 0);

    SurfaceComposerClient::openGlobalTransaction();
    mSurfaceControl->setLayer(INT_MAX);//设定Z坐标
    mSurfaceControl->setPosition((dinfo.w - width) / 2, (dinfo.h - hight) / 2);
    mSurfaceControl->setSize(width, hight);

    SurfaceComposerClient::closeGlobalTransaction();

    sp<ANativeWindow> window = mSurfaceControl->getSurface();

    return window.get();
}


void GLUtil::disposeNativeWindow(void)
{
    if (mComposerClient != NULL) 
    {
        mComposerClient->dispose();
        mComposerClient = NULL;
        mSurfaceControl = NULL;
    }
}

show_yuv.h

#ifndef __SHOW_YUV_H__
#define __SHOW_YUV_H__

#include <pthread.h>
#include <android/native_window.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
class Renderer_yuv
{
public:
    Renderer_yuv();
    virtual ~Renderer_yuv();

    void requestInitEGL(EGLNativeWindowType pWindow);
    void requestRenderFrame(int surface_width, int surface_height);
    void requestDestroy();

    //void nativeSurfaceCreated();

    //void nativeSurfaceChanged(EGLint width, EGLint height);

    //void nativeDraw();
    unsigned char * readYUV(const char *path, int width, int height);
    void gl_initialize(void);
    void gl_uninitialize(void);
    void gl_set_framebuffer(const unsigned char* buffer, int buffersize, int width, int height);
    void gl_render_frame(int surface_width, int surface_height);
    void renderFrame(void);
    GLuint bindTexture(GLuint texture, const char *buffer, GLuint w , GLuint h);
    
    GLUtil * glutil;
private:
    enum RenderEvent
    {
        RE_NONE = 0, RE_SURFACE_CREATED, RE_SURFACE_CHANGED, RE_DRAW_FRAME, RE_EXIT
    };

    volatile enum RenderEvent mEnumRenderEvent;
    pthread_t mThread;
    //pthread_mutex_t mMutex;
    //pthread_cond_t mCondVar;

    EGLNativeWindowType mWindow;

    EGLDisplay mDisplay;
    EGLSurface mSurface;
    EGLContext mContext;
    
    static void *startRenderThread(void *);

    void initEGL();

    EGLint mWidth;
    EGLint mHeight;

    void terminateDisplay();

    bool mISRenderering;

    //int aColorLocation;
    //int aPositionLocation;
};


#endif

show_yuv.cpp:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <sys/prctl.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <GLES3/gl3.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>

#include "GLUtil.h"
#include "show_yuv.h"

static const char* FRAG_SHADER =  
    "varying lowp vec2 tc;\n"  
    "uniform sampler2D SamplerY;\n"  
    "uniform sampler2D SamplerU;\n"  
    "uniform sampler2D SamplerV;\n"  
    "void main(void)\n"  
    "{\n"  
        "mediump vec3 yuv;\n"  
        "lowp vec3 rgb;\n"  
        "yuv.x = texture2D(SamplerY, tc).r;\n"  
        "yuv.y = texture2D(SamplerU, tc).r - 0.5;\n"  
        "yuv.z = texture2D(SamplerV, tc).r - 0.5;\n"  
        "rgb = mat3( 1,   1,   1,\n"  
                    "0,       -0.39465,  2.03211,\n"  
                    "1.13983,   -0.58060,  0) * yuv;\n"  
        "gl_FragColor = vec4(rgb, 1);\n"  
    "}\n";  

//Shader.vert文件内容  
static const char* VERTEX_SHADER =    
      "attribute vec4 vPosition;    \n"  
      "attribute vec2 a_texCoord;   \n"  
      "varying vec2 tc;     \n"  
      "void main()                  \n"  
      "{                            \n"  
      "   gl_Position = vPosition;  \n"  
      "   tc = a_texCoord;  \n"  
      "}                            \n";

Renderer_yuv::Renderer_yuv()
{
    //pthread_mutex_init(&mMutex, NULL);
    //pthread_cond_init(&mCondVar, NULL);
    mDisplay = EGL_NO_DISPLAY;
    mSurface = EGL_NO_SURFACE;
    mContext = EGL_NO_CONTEXT;
    glutil = new GLUtil();
}

Renderer_yuv::~Renderer_yuv()
{
    //pthread_mutex_destroy(&mMutex);
    //pthread_cond_destroy(&mCondVar);
}

void Renderer_yuv::requestInitEGL(EGLNativeWindowType pWindow)
{
    //pthread_mutex_lock(&mMutex);
    mWindow = pWindow;
    //mEnumRenderEvent = RE_SURFACE_CHANGED;
    initEGL();
    //nativeSurfaceCreated();
    //nativeSurfaceChanged(mWidth, mHeight);
    gl_initialize();
    
    //pthread_mutex_unlock(&mMutex);
    //pthread_cond_signal(&mCondVar);
}
void Renderer_yuv::requestRenderFrame(int surface_width, int surface_height)
{
    //pthread_mutex_lock(&mMutex);
    mEnumRenderEvent = RE_DRAW_FRAME;
    gl_render_frame(surface_width, surface_height);
    eglSwapBuffers(mDisplay, mSurface);
    //pthread_mutex_unlock(&mMutex);
    //pthread_cond_signal(&mCondVar);
}

void Renderer_yuv::requestDestroy()
{
    //pthread_mutex_lock(&mMutex);
    //mEnumRenderEvent = RE_EXIT;
    terminateDisplay();
    mISRenderering = false;
    //pthread_mutex_unlock(&mMutex);
    //pthread_cond_signal(&mCondVar);
}

void Renderer_yuv::initEGL()
{
    const EGLint attribs[] =
    { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
            EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE };
    EGLint width, height, format;
    EGLint numConfigs;
    EGLConfig config;
    EGLSurface surface;
    EGLContext context;

    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

    eglInitialize(display, 0, 0);

    eglChooseConfig(display, attribs, &config, 1, &numConfigs);

    //instance->surface = eglCreateWindowSurface(instance->display, instance->config[0], WindowTypes, NULL);
    surface = eglCreateWindowSurface(display, config, mWindow, NULL);
    EGLint attrs[] =
    { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
    context = eglCreateContext(display, config, NULL, attrs);

    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
    {
        printf("------EGL-FALSE\n");
        return;
    }

    eglQuerySurface(display, surface, EGL_WIDTH, &width);
    eglQuerySurface(display, surface, EGL_HEIGHT, &height);

    mDisplay = display;
    mSurface = surface;
    mContext = context;
    mWidth = width;
    mHeight = height;
    printf("width:%d, height:%d\n", mWidth, mHeight);

}

void Renderer_yuv::terminateDisplay()
{
    if (mDisplay != EGL_NO_DISPLAY)
    {
        eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
                EGL_NO_CONTEXT);
        if (mContext != EGL_NO_CONTEXT)
        {
            eglDestroyContext(mDisplay, mContext);
        }
        if (mSurface != EGL_NO_SURFACE)
        {
            eglDestroySurface(mDisplay, mSurface);
        }
        eglTerminate(mDisplay);
    }

    mDisplay = EGL_NO_DISPLAY;
    mSurface = EGL_NO_SURFACE;
    mContext = EGL_NO_CONTEXT;

    gl_uninitialize();
}

#if 0
int program = 0;
int aColorLocation;
int aPositionLocation;

void Renderer::nativeSurfaceCreated()
{
    glClearColor(0.0f, 0.0f, 0.0f, 0.3f);
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    program = glutil->createProgram(VERTEX_SHADER, FRAGMENT_SHADER);

    glUseProgram(program);
    //uColorLocation = glGetUniformLocation(program, U_COLOR);
    aColorLocation = glGetAttribLocation(program, A_COLOR);
    aPositionLocation = glGetAttribLocation(program, A_POSITION);
    glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT, false, STRIDE, tableVerticesWithTriangles);
    
    glEnableVertexAttribArray(aPositionLocation);
    glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GL_FLOAT, false, STRIDE, tableVerticesWithTriangles + POSITION_COMPONENT_COUNT);
    glEnableVertexAttribArray(aColorLocation);
}

void Renderer::nativeSurfaceChanged(EGLint width, EGLint height)
{
    glViewport(0, 0, width, height);
}

void Renderer::nativeDraw()
{
    glClear(GL_COLOR_BUFFER_BIT);
    // Draw the table.
    //glUniform4f(uColorLocation, 0.5f, 0.5f, 0.5f, 1.0f);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 6);

    // Draw the center dividing line.
    //glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
    glDrawArrays(GL_LINES, 6, 2);

    // Draw the first mallet blue.
    //glUniform4f(uColorLocation, 0.0f, 0.0f, 1.0f, 1.0f);
    glDrawArrays(GL_POINTS, 8, 2);

    // Draw the second mallet red.
    //glUniform4f(uColorLocation, 1.0f, 0.0f, 0.0f, 1.0f);
    glDrawArrays(GL_POINTS, 9, 1);
}
#endif

enum {  
    ATTRIB_VERTEX,  
    ATTRIB_TEXTURE,  
};  

static GLuint g_texYId;  
static GLuint g_texUId;  
static GLuint g_texVId;  
static GLuint simpleProgram;  
  
static char *              g_buffer = NULL;  
static int                 g_width = 0;  
static int                 g_height = 0;  

unsigned char * Renderer_yuv::readYUV(const char *path, int width, int height)  
{
    FILE *fp = NULL;  
    unsigned char * buffer = NULL;
    long size = width * height * 3 / 2;
  
    if((fp = fopen(path, "rb")) == NULL)
    {  
        printf("cant open the file");
        return NULL;
    }  
  
    buffer = (unsigned char *)malloc(size);  
    memset(buffer,'\0', size);
    long len = fread(buffer, 1, size, fp);  
    //PRINTF("read data size:%ld", len);
    fclose(fp);
    
    return buffer;  
}  

void Renderer_yuv::gl_initialize(void)
{  
    g_buffer = NULL;  
  
    simpleProgram = glutil->createProgram(VERTEX_SHADER, FRAG_SHADER);
    printf("##### simpleProgram: %d\n", simpleProgram);
    glUseProgram(simpleProgram);  
    glGenTextures(1, &g_texYId);  
    glGenTextures(1, &g_texUId);  
    glGenTextures(1, &g_texVId);
}  

void Renderer_yuv::gl_uninitialize(void)
{
    g_width = 0;  
    g_height = 0;  
  
    if (g_buffer)  
    {  
        free(g_buffer);  
        g_buffer = NULL;  
    }  
}  

void Renderer_yuv::gl_set_framebuffer(const unsigned char* buffer, int buffersize, int width, int height)  
{
    if (g_width != width || g_height != height)  
    {  
        if (g_buffer)  
            free(g_buffer);  
  
        g_width = width;  
        g_height = height;  
  
        g_buffer = (char *)malloc(buffersize);  
    }  

    if (g_buffer)  
        memcpy(g_buffer, buffer, buffersize);  
  
}

void Renderer_yuv::gl_render_frame(int surface_width, int surface_height)  
{  
    if (0 == g_width || 0 == g_height)  
        return;  
  
#if 0
    int width = 448;
    int height = 336;
    static unsigned char *buffer = NULL;
  
    if (NULL == buffer)  
    {  
        char filename[128] = {0};  
        strcpy(filename, "/sdcard/yuv_448_336.yuv");  
        buffer = readYUV(filename);  
    }  
  
#else  
    const char *buffer = g_buffer;  
    int width = g_width;
    int height = g_height;  
#endif  
    glViewport((surface_width - width) / 2, (surface_height - height) / 2, width, height);
    bindTexture(g_texYId, buffer, width, height);  
    bindTexture(g_texUId, buffer + width * height, width/2, height/2);  
    bindTexture(g_texVId, buffer + width * height * 5 / 4, width/2, height/2);  
    renderFrame();   
}

void Renderer_yuv::renderFrame(void) 
{  
#if 1
    // Galaxy Nexus 4.2.2  
    static GLfloat squareVertices[] = {  
        -1.0f, -1.0f,  
        1.0f, -1.0f,
        -1.0f,  1.0f,
        1.0f,  1.0f,
    };  
  
    static GLfloat coordVertices[] = {  
        0.0f, 1.0f,  
        1.0f, 1.0f,  
        0.0f,  0.0f,  
        1.0f,  0.0f,
    };  
#else
 // HUAWEIG510-0010 4.1.1  
    static GLfloat squareVertices[] = {  
        0.0f, 0.0f,  
        1.0f, 0.0f,  
        0.0f,  1.0f,  
        1.0f,  1.0f,
    };  
  
    static GLfloat coordVertices[] = {  
            0.0f, 1.0f,
            0.0f, 0.0f,
            1.0f, 0.0f,
            1.0f, 1.0f
    };  
#endif  
  
    glClearColor(0.5f, 0.5f, 0.5f, 0.5);  
    glClear(GL_COLOR_BUFFER_BIT);
    //PRINTF("setsampler %d %d %d", g_texYId, g_texUId, g_texVId);  
    GLint tex_y = glGetUniformLocation(simpleProgram, "SamplerY");  
    GLint tex_u = glGetUniformLocation(simpleProgram, "SamplerU");  
    GLint tex_v = glGetUniformLocation(simpleProgram, "SamplerV");  
  
  
    glBindAttribLocation(simpleProgram, ATTRIB_VERTEX, "vPosition");  
    glBindAttribLocation(simpleProgram, ATTRIB_TEXTURE, "a_texCoord");  
  
    glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);  
    glEnableVertexAttribArray(ATTRIB_VERTEX);  
  
    glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, coordVertices);  
    glEnableVertexAttribArray(ATTRIB_TEXTURE);  
  
    glActiveTexture(GL_TEXTURE0);  
    glBindTexture(GL_TEXTURE_2D, g_texYId);  
    glUniform1i(tex_y, 0);  
  
    glActiveTexture(GL_TEXTURE1);  
    glBindTexture(GL_TEXTURE_2D, g_texUId);  
    glUniform1i(tex_u, 1);  
  
    glActiveTexture(GL_TEXTURE2);  
    glBindTexture(GL_TEXTURE_2D, g_texVId);  
    glUniform1i(tex_v, 2);  
  
    //glEnable(GL_TEXTURE_2D);  
    //checkGlError("glEnable");  
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);  
}

GLuint Renderer_yuv::bindTexture(GLuint texture, const char *buffer, GLuint w , GLuint h)
{  
//  GLuint texture;
//  glGenTextures ( 1, &texture );  
    glBindTexture ( GL_TEXTURE_2D, texture );  
    glTexImage2D ( GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer);  
    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );  
    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );  
    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );  
    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );  
    //glBindTexture(GL_TEXTURE_2D, 0);  

    return texture;
}

main.cpp:

/*main.cpp*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <sys/prctl.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>

#include "GLUtil.h"
//#include "Renderer.h"
#include "show_yuv.h"

using namespace android;
#if 0
int main(void)
{
    Renderer * mRenderer = NULL;
    
    mRenderer = new Renderer();

    //mRenderer->start();
    EGLNativeWindowType WindowTypes = (EGLNativeWindowType) mRenderer->glutil->getNativeWindow(800, 600, 100, 100);
    mRenderer->requestInitEGL(WindowTypes);

    while(1)
        mRenderer->requestRenderFrame();
    
    mRenderer->requestDestroy();
    ANativeWindow_release(WindowTypes);
    delete mRenderer;
    
    return 0;
}

#else

int getYV12Data(FILE * fp, unsigned char * pYUVData, int size, int offset)
{
    int ret = -1;
    //FILE *fp = fopen(path,"rb");
    if(fp == NULL)
    {
        printf("fp == NULL!\n");
        return -1;
    }
    
    //ret = fseek(fp, size * offset, SEEK_SET);
    printf("### offset: %d\n", offset);
    ret = fseek(fp, size, SEEK_CUR);
    if(ret != 0)
    {
        return -1;
    }
    
    ret = fread(pYUVData, size, 1, fp);
    if(ret == 0)
    {
        return -1;
    }
    //fclose(fp);

    return 0;
}

int main(void)
{
    int i = 0;
    int ret = 0;
    FILE * fp = NULL;
    unsigned char * buffer = NULL;
    Renderer_yuv * mRenderer = NULL;
    mRenderer = new Renderer_yuv();
    int win_width = 1600;
    int win_height = 900;
    //mRenderer->start();
    EGLNativeWindowType WindowTypes = (EGLNativeWindowType) mRenderer->glutil->getNativeWindow(win_width, win_height);
    mRenderer->requestInitEGL(WindowTypes);

    fp = fopen("/data/temp/dota2_output_yuv.yuv", "rb");
    buffer = (unsigned char *)malloc(480 * 320 * 3 / 2);

    for(i = 1; ret >= 0; i++)
    {
        ret = getYV12Data(fp, buffer, 480 * 320 * 3 / 2, i);
        if(ret < 0)

        {
            printf("play end!\n");
            break;
        }
        mRenderer->gl_set_framebuffer(buffer, 480 * 320 * 3 / 2, 480, 320);
        mRenderer->requestRenderFrame(win_width, win_height);
    }

    fclose(fp);
    /*
    unsigned char * buffer = mRenderer->readYUV("/data/temp/dota2_output_yuv.yuv", 480, 320);
    mRenderer->gl_set_framebuffer(buffer, 480 * 320 * 3 / 2, 480, 320);
    
    while(1)
    {
        mRenderer->requestRenderFrame(1600, 900);
        
    }*/
    
    mRenderer->requestDestroy();
    //ANativeWindow_release(WindowTypes);
    delete mRenderer;
    
    return 0;
}

#endif

Android.mk:

# Build the unit tests.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk

LOCAL_MODULE := opengl_c

LOCAL_MODULE_TAGS := opengl_c

LOCAL_SRC_FILES := \
	GLUtil.cpp \
	show_yuv.cpp \
	main.cpp 

LOCAL_SHARED_LIBRARIES := \
	libEGL \
	libGLESv2 \
	libbinder \
	libcutils \
	libgui \
	libmedia \
	libstagefright \
	libstagefright_foundation \
	libstagefright_omx \
	libsync \
	libui \
	libutils \
	liblog

LOCAL_C_INCLUDES := \
	frameworks/av/media/libstagefright \
	frameworks/av/media/libstagefright/include \
	$(TOP)/frameworks/native/include/media/openmax \

#LOCAL_CFLAGS += -Werror -Wall
LOCAL_CLANG := true

LOCAL_32_BIT_ONLY := true

include $(BUILD_EXECUTABLE)  

这个是直接将yuv视频或者图片显示在自己创建的窗口中,我把窗口放在了中央,yuv显示放在了窗口中央。显示速度有点快,没有做时间的控制。

距离一个完整的播放器还缺少demux和decoder,本来想使用omx来完成decoder过程,但是比较忙,以后有时间慢慢研究。

代码需要在android源码环境下编译,我是在android6.0源码下面编译的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值