您的位置:首页 > 移动开发 > Android开发

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

2017-12-21 14:32 435 查看
参考文章: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_unl
4000
ock(&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源码下面编译的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  yuv android 视频