summaryrefslogtreecommitdiffstats
path: root/jni/feature_mos
diff options
context:
space:
mode:
authormbansal <mayank.bansal@sri.com>2011-08-16 10:01:20 -0400
committerWei-Ta Chen <weita@google.com>2011-08-18 14:39:33 -0700
commit1e762b1f935c9d4a06af6dd56121590ca81d48b1 (patch)
treeb7177cb69ece87e1d55f587779a53f213255592d /jni/feature_mos
parent362928c00ad4ecc0466c353d942c6d6c7cc5f5ee (diff)
downloadLegacyCamera-1e762b1f935c9d4a06af6dd56121590ca81d48b1.zip
LegacyCamera-1e762b1f935c9d4a06af6dd56121590ca81d48b1.tar.gz
LegacyCamera-1e762b1f935c9d4a06af6dd56121590ca81d48b1.tar.bz2
Updates to allow the viewfinder to slide across the UI with device panning. Also, rendering updates for color conversion using GPU.
1) Refactored the SurfaceTextureRenderer and WarpRenderer classes to inherit from a new base class Renderer. 2) Fixed a minor bug in the Blend class and added a helper function to create the mosaic in middle frame coordinate system [no changes in run-time behavior]. 3) Added a flip-flop gPreviewFBO to allow panning the viewfinder across the UI when the user pans the device. 4) Fixed the size of the viewfinder and preview mosaic to match the UI layout height. 5) The viewfinder in the preview stage is now aligned with the viewfinder in the capture stage. 6) Added new class YVURenderer that converts from RGB to YVU data using GLSL shaders. 7) Modified the rendering pipeline to use GPU for RGB to YVU conversion. The processing thread now only performs conversion from YVUA interlaced to YVU planar format. 8) Updates following Wei-Ta's code-review comments. Change-Id: I6c18df3b57d1c2d78d55da8a8f3b9cd970c8d903
Diffstat (limited to 'jni/feature_mos')
-rw-r--r--jni/feature_mos/src/mosaic/Blend.cpp23
-rw-r--r--jni/feature_mos/src/mosaic/Blend.h1
-rwxr-xr-xjni/feature_mos/src/mosaic_renderer/Renderer.cpp216
-rwxr-xr-xjni/feature_mos/src/mosaic_renderer/Renderer.h65
-rwxr-xr-xjni/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp297
-rwxr-xr-xjni/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.h45
-rwxr-xr-xjni/feature_mos/src/mosaic_renderer/WarpRenderer.cpp303
-rwxr-xr-xjni/feature_mos/src/mosaic_renderer/WarpRenderer.h44
-rwxr-xr-xjni/feature_mos/src/mosaic_renderer/YVURenderer.cpp149
-rwxr-xr-xjni/feature_mos/src/mosaic_renderer/YVURenderer.h35
10 files changed, 594 insertions, 584 deletions
diff --git a/jni/feature_mos/src/mosaic/Blend.cpp b/jni/feature_mos/src/mosaic/Blend.cpp
index eb0275e..46a4410 100644
--- a/jni/feature_mos/src/mosaic/Blend.cpp
+++ b/jni/feature_mos/src/mosaic/Blend.cpp
@@ -70,6 +70,25 @@ int Blend::initialize(int blendingType, int frame_width, int frame_height)
return BLEND_RET_OK;
}
+void Blend::AlignToMiddleFrame(MosaicFrame **frames, int frames_size)
+{
+ // Unwarp this frame and Warp the others to match
+ MosaicFrame *mb = NULL;
+ MosaicFrame *ref = frames[int(frames_size/2)]; // Middle frame
+
+ double invtrs[3][3];
+ inv33d(ref->trs, invtrs);
+
+ for(int mfit = 0; mfit < frames_size; mfit++)
+ {
+ mb = frames[mfit];
+ double temp[3][3];
+ mult33d(temp, invtrs, mb->trs);
+ memcpy(mb->trs, temp, sizeof(temp));
+ normProjMat33d(mb->trs);
+ }
+}
+
int Blend::runBlend(MosaicFrame **frames, int frames_size, ImageType &imageMosaicYVU, int &mosaicWidth, int &mosaicHeight)
{
int ret;
@@ -872,8 +891,8 @@ void Blend::ComputeBlendParameters(MosaicFrame **frames, int frames_size, int is
MosaicFrame *last = frames[frames_size-1];
MosaicFrame *mb;
- double lxpos = last->trs[0][2], lypos = last->trs[1][5];
- double fxpos = first->trs[0][2], fypos = first->trs[1][5];
+ double lxpos = last->trs[0][2], lypos = last->trs[1][2];
+ double fxpos = first->trs[0][2], fypos = first->trs[1][2];
// Calculate warp to produce proper stitching.
// get x, y displacement
diff --git a/jni/feature_mos/src/mosaic/Blend.h b/jni/feature_mos/src/mosaic/Blend.h
index 9998aa6..3e5b17c 100644
--- a/jni/feature_mos/src/mosaic/Blend.h
+++ b/jni/feature_mos/src/mosaic/Blend.h
@@ -98,6 +98,7 @@ protected:
void MosaicToFrame(double trs[3][3], double x, double y, double &wx, double &wy);
void FrameToMosaicRect(int width, int height, double trs[3][3], BlendRect &brect);
void ClipBlendRect(CSite *csite, BlendRect &brect);
+ void AlignToMiddleFrame(MosaicFrame **frames, int frames_size);
int DoMergeAndBlend(MosaicFrame **frames, int nsite, int width, int height, YUVinfo &imgMos, MosaicRect &rect, MosaicRect &cropping_rect);
void ComputeMask(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, int site_idx);
diff --git a/jni/feature_mos/src/mosaic_renderer/Renderer.cpp b/jni/feature_mos/src/mosaic_renderer/Renderer.cpp
new file mode 100755
index 0000000..93049cb
--- /dev/null
+++ b/jni/feature_mos/src/mosaic_renderer/Renderer.cpp
@@ -0,0 +1,216 @@
+#include "Renderer.h"
+
+#include <GLES2/gl2ext.h>
+
+#include <android/log.h>
+#define LOG_TAG "Renderer"
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+
+Renderer::Renderer()
+ : mGlProgram(0),
+ mInputTextureName(-1),
+ mInputTextureWidth(0),
+ mInputTextureHeight(0),
+ mSurfaceWidth(0),
+ mSurfaceHeight(0)
+{
+ InitializeGLContext();
+}
+
+Renderer::~Renderer() {
+}
+
+GLuint Renderer::loadShader(GLenum shaderType, const char* pSource) {
+ GLuint shader = glCreateShader(shaderType);
+ if (shader) {
+ glShaderSource(shader, 1, &pSource, NULL);
+ glCompileShader(shader);
+ GLint compiled = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+ if (!compiled) {
+ GLint infoLen = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen) {
+ char* buf = (char*) malloc(infoLen);
+ if (buf) {
+ glGetShaderInfoLog(shader, infoLen, NULL, buf);
+ LOGE("Could not compile shader %d:\n%s\n",
+ shaderType, buf);
+ free(buf);
+ }
+ glDeleteShader(shader);
+ shader = 0;
+ }
+ }
+ }
+ return shader;
+}
+
+GLuint Renderer::createProgram(const char* pVertexSource, const char* pFragmentSource)
+{
+ GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
+ if (!vertexShader)
+ {
+ return 0;
+ }
+ LOGI("VertexShader Loaded!");
+
+ GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
+ if (!pixelShader)
+ {
+ return 0;
+ }
+ LOGI("FragmentShader Loaded!");
+
+ GLuint program = glCreateProgram();
+ if (program)
+ {
+ glAttachShader(program, vertexShader);
+ checkGlError("glAttachShader");
+ glAttachShader(program, pixelShader);
+ checkGlError("glAttachShader");
+
+ LOGI("Shaders Attached!");
+
+ glLinkProgram(program);
+ GLint linkStatus = GL_FALSE;
+ glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+
+ LOGI("Program Linked!");
+
+ if (linkStatus != GL_TRUE)
+ {
+ GLint bufLength = 0;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
+ if (bufLength)
+ {
+ char* buf = (char*) malloc(bufLength);
+ if (buf)
+ {
+ glGetProgramInfoLog(program, bufLength, NULL, buf);
+ LOGE("Could not link program:\n%s\n", buf);
+ free(buf);
+ }
+ }
+ glDeleteProgram(program);
+ program = 0;
+ }
+ }
+ return program;
+}
+
+// Set this renderer to use the default frame-buffer (screen) and
+// set the viewport size to be the given width and height (pixels).
+bool Renderer::SetupGraphics(int width, int height)
+{
+ bool succeeded = false;
+ do {
+ if (mGlProgram == 0)
+ {
+ if (!InitializeGLProgram())
+ {
+ break;
+ }
+ }
+ glUseProgram(mGlProgram);
+ if (!checkGlError("glUseProgram")) break;
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ mFrameBuffer = NULL;
+ mSurfaceWidth = width;
+ mSurfaceHeight = height;
+
+ glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
+ if (!checkGlError("glViewport")) break;
+ succeeded = true;
+ } while (false);
+
+ return succeeded;
+}
+
+
+// Set this renderer to use the specified FBO and
+// set the viewport size to be the width and height of this FBO.
+bool Renderer::SetupGraphics(FrameBuffer* buffer)
+{
+ bool succeeded = false;
+ do {
+ if (mGlProgram == 0)
+ {
+ if (!InitializeGLProgram())
+ {
+ break;
+ }
+ }
+ glUseProgram(mGlProgram);
+ if (!checkGlError("glUseProgram")) break;
+
+ glBindFramebuffer(GL_FRAMEBUFFER, buffer->GetFrameBufferName());
+
+ mFrameBuffer = buffer;
+ mSurfaceWidth = mFrameBuffer->GetWidth();
+ mSurfaceHeight = mFrameBuffer->GetHeight();
+
+ glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
+ if (!checkGlError("glViewport")) break;
+ succeeded = true;
+ } while (false);
+
+ return succeeded;
+}
+
+bool Renderer::Clear(float r, float g, float b, float a)
+{
+ bool succeeded = false;
+ do {
+ bool rt = (mFrameBuffer == NULL)?
+ SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
+ SetupGraphics(mFrameBuffer);
+
+ if(!rt)
+ break;
+
+ glClearColor(r, g, b, a);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ succeeded = true;
+ } while (false);
+ return succeeded;
+
+}
+
+void Renderer::InitializeGLContext()
+{
+ if(mFrameBuffer != NULL)
+ {
+ delete mFrameBuffer;
+ mFrameBuffer = NULL;
+ }
+
+ mInputTextureName = -1;
+ mInputTextureType = GL_TEXTURE_2D;
+ mGlProgram = 0;
+}
+
+int Renderer::GetTextureName()
+{
+ return mInputTextureName;
+}
+
+void Renderer::SetInputTextureName(GLuint textureName)
+{
+ mInputTextureName = textureName;
+}
+
+void Renderer::SetInputTextureType(GLenum textureType)
+{
+ mInputTextureType = textureType;
+}
+
+void Renderer::SetInputTextureDimensions(int width, int height)
+{
+ mInputTextureWidth = width;
+ mInputTextureHeight = height;
+}
diff --git a/jni/feature_mos/src/mosaic_renderer/Renderer.h b/jni/feature_mos/src/mosaic_renderer/Renderer.h
new file mode 100755
index 0000000..a43e802
--- /dev/null
+++ b/jni/feature_mos/src/mosaic_renderer/Renderer.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include "FrameBuffer.h"
+
+#include <GLES2/gl2.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+class Renderer {
+ public:
+ Renderer();
+ virtual ~Renderer();
+
+ // Initialize OpenGL resources
+ // @return true if successful
+ virtual bool InitializeGLProgram() = 0;
+
+ bool SetupGraphics(FrameBuffer* buffer);
+ bool SetupGraphics(int width, int height);
+
+ bool Clear(float r, float g, float b, float a);
+
+ int GetTextureName();
+ void SetInputTextureName(GLuint textureName);
+ void SetInputTextureDimensions(int width, int height);
+ void SetInputTextureType(GLenum textureType);
+
+ void InitializeGLContext();
+
+ protected:
+
+ GLuint loadShader(GLenum shaderType, const char* pSource);
+ GLuint createProgram(const char*, const char* );
+
+ int SurfaceWidth() const { return mSurfaceWidth; }
+ int SurfaceHeight() const { return mSurfaceHeight; }
+
+ // Source code for shaders.
+ virtual const char* VertexShaderSource() const = 0;
+ virtual const char* FragmentShaderSource() const = 0;
+
+ // Redefine this to use special texture types such as
+ // GL_TEXTURE_EXTERNAL_OES.
+ GLenum InputTextureType() const { return mInputTextureType; }
+
+ GLuint mGlProgram;
+ GLuint mInputTextureName;
+ GLenum mInputTextureType;
+ int mInputTextureWidth;
+ int mInputTextureHeight;
+
+ // Attribute locations
+ GLint mScalingtransLoc;
+ GLint maPositionHandle;
+ GLint maTextureHandle;
+
+
+ int mSurfaceWidth; // Width of target surface.
+ int mSurfaceHeight; // Height of target surface.
+
+ FrameBuffer *mFrameBuffer;
+};
+
diff --git a/jni/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp b/jni/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp
index fb124aa..e37406c 100755
--- a/jni/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp
+++ b/jni/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.cpp
@@ -7,29 +7,6 @@
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
-static const char gVertexShader[] =
-"uniform mat4 uSTMatrix;\n"
-"uniform mat4 u_scalingtrans; \n"
-"attribute vec4 aPosition;\n"
-"attribute vec4 aTextureCoord;\n"
-"varying vec2 vTextureCoord;\n"
-"varying vec2 vTextureNormCoord;\n"
-"void main() {\n"
-" gl_Position = u_scalingtrans * aPosition;\n"
-" vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n"
-" vTextureNormCoord = aTextureCoord.xy;\n"
-"}\n";
-
-static const char gFragmentShader[] =
-"#extension GL_OES_EGL_image_external : require\n"
-"precision mediump float;\n"
-"varying vec2 vTextureCoord;\n"
-"varying vec2 vTextureNormCoord;\n"
-"uniform samplerExternalOES sTexture;\n"
-"void main() {\n"
-" gl_FragColor = texture2D(sTexture, vTextureNormCoord);\n"
-"}\n";
-
const GLfloat g_vVertices[] = {
-1.f, -1.f, 0.0f, 1.0f, // Position 0
0.0f, 1.0f, // TexCoord 0
@@ -46,110 +23,51 @@ const int GL_TEXTURE_EXTERNAL_OES_ENUM = 0x8D65;
const int VERTEX_STRIDE = 6 * sizeof(GLfloat);
-SurfaceTextureRenderer::SurfaceTextureRenderer()
- : mGlProgram(0),
- mInputTextureName(-1),
- mInputTextureWidth(0),
- mInputTextureHeight(0),
- mSurfaceWidth(0),
- mSurfaceHeight(0)
-{
+SurfaceTextureRenderer::SurfaceTextureRenderer() : Renderer() {
memset(mSTMatrix, 0.0, 16*sizeof(float));
mSTMatrix[0] = 1.0f;
mSTMatrix[5] = 1.0f;
mSTMatrix[10] = 1.0f;
mSTMatrix[15] = 1.0f;
-
- InitializeGLContext();
}
SurfaceTextureRenderer::~SurfaceTextureRenderer() {
}
-void SurfaceTextureRenderer::SetSTMatrix(float *stmat)
+void SurfaceTextureRenderer::SetViewportMatrix(int w, int h, int W, int H)
{
- memcpy(mSTMatrix, stmat, 16*sizeof(float));
-}
-
-GLuint SurfaceTextureRenderer::loadShader(GLenum shaderType, const char* pSource) {
- GLuint shader = glCreateShader(shaderType);
- if (shader) {
- glShaderSource(shader, 1, &pSource, NULL);
- glCompileShader(shader);
- GLint compiled = 0;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
- if (!compiled) {
- GLint infoLen = 0;
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
- if (infoLen) {
- char* buf = (char*) malloc(infoLen);
- if (buf) {
- glGetShaderInfoLog(shader, infoLen, NULL, buf);
- LOGE("Could not compile shader %d:\n%s\n",
- shaderType, buf);
- free(buf);
- }
- glDeleteShader(shader);
- shader = 0;
- }
- }
+ for(int i=0; i<16; i++)
+ {
+ mViewportMatrix[i] = 0.0f;
}
- return shader;
+
+ mViewportMatrix[0] = float(w)/float(W);
+ mViewportMatrix[5] = float(h)/float(H);
+ mViewportMatrix[10] = 1.0f;
+ mViewportMatrix[12] = -1.0f + float(w)/float(W);
+ mViewportMatrix[13] = -1.0f + float(h)/float(H);
+ mViewportMatrix[15] = 1.0f;
}
-GLuint SurfaceTextureRenderer::createProgram(const char* pVertexSource, const char* pFragmentSource)
+void SurfaceTextureRenderer::SetScalingMatrix(float xscale, float yscale)
{
- GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
- if (!vertexShader)
- {
- return 0;
- }
- LOGI("VertexShader Loaded!");
-
- GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
- if (!pixelShader)
+ for(int i=0; i<16; i++)
{
- return 0;
+ mScalingMatrix[i] = 0.0f;
}
- LOGI("FragmentShader Loaded!");
- GLuint program = glCreateProgram();
- if (program)
- {
- glAttachShader(program, vertexShader);
- checkGlError("glAttachShader");
- glAttachShader(program, pixelShader);
- checkGlError("glAttachShader");
-
- LOGI("Shaders Attached!");
-
- glLinkProgram(program);
- GLint linkStatus = GL_FALSE;
- glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
-
- LOGI("Program Linked!");
+ mScalingMatrix[0] = xscale;
+ mScalingMatrix[5] = yscale;
+ mScalingMatrix[10] = 1.0f;
+ mScalingMatrix[15] = 1.0f;
+}
- if (linkStatus != GL_TRUE)
- {
- GLint bufLength = 0;
- glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
- if (bufLength)
- {
- char* buf = (char*) malloc(bufLength);
- if (buf)
- {
- glGetProgramInfoLog(program, bufLength, NULL, buf);
- LOGE("Could not link program:\n%s\n", buf);
- free(buf);
- }
- }
- glDeleteProgram(program);
- program = 0;
- }
- }
- return program;
+void SurfaceTextureRenderer::SetSTMatrix(float *stmat)
+{
+ memcpy(mSTMatrix, stmat, 16*sizeof(float));
}
+
bool SurfaceTextureRenderer::InitializeGLProgram()
{
bool succeeded = false;
@@ -186,115 +104,6 @@ bool SurfaceTextureRenderer::InitializeGLProgram()
return succeeded;
}
-void SurfaceTextureRenderer::SetViewportMatrix(int w, int h, int W, int H)
-{
- for(int i=0; i<16; i++)
- {
- mViewportMatrix[i] = 0.0f;
- }
-
- mViewportMatrix[0] = float(w)/float(W);
- mViewportMatrix[5] = float(h)/float(H);
- mViewportMatrix[10] = 1.0f;
- mViewportMatrix[12] = -1.0f + float(w)/float(W);
- mViewportMatrix[13] = -1.0f + float(h)/float(H);
- mViewportMatrix[15] = 1.0f;
-}
-
-void SurfaceTextureRenderer::SetScalingMatrix(float xscale, float yscale)
-{
- for(int i=0; i<16; i++)
- {
- mScalingMatrix[i] = 0.0f;
- }
-
- mScalingMatrix[0] = xscale;
- mScalingMatrix[5] = yscale;
- mScalingMatrix[10] = 1.0f;
- mScalingMatrix[15] = 1.0f;
-}
-
-// Set this renderer to use the default frame-buffer (screen) and
-// set the viewport size to be the given width and height (pixels).
-bool SurfaceTextureRenderer::SetupGraphics(int width, int height)
-{
- bool succeeded = false;
- do {
- if (mGlProgram == 0)
- {
- if (!InitializeGLProgram())
- {
- break;
- }
- }
- glUseProgram(mGlProgram);
- if (!checkGlError("glUseProgram")) break;
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- mFrameBuffer = NULL;
- mSurfaceWidth = width;
- mSurfaceHeight = height;
-
- glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
- if (!checkGlError("glViewport")) break;
- succeeded = true;
- } while (false);
-
- return succeeded;
-}
-
-
-// Set this renderer to use the specified FBO and
-// set the viewport size to be the width and height of this FBO.
-bool SurfaceTextureRenderer::SetupGraphics(FrameBuffer* buffer)
-{
- bool succeeded = false;
- do {
- if (mGlProgram == 0)
- {
- if (!InitializeGLProgram())
- {
- break;
- }
- }
- glUseProgram(mGlProgram);
- if (!checkGlError("glUseProgram")) break;
-
- glBindFramebuffer(GL_FRAMEBUFFER, buffer->GetFrameBufferName());
-
- mFrameBuffer = buffer;
- mSurfaceWidth = mFrameBuffer->GetWidth();
- mSurfaceHeight = mFrameBuffer->GetHeight();
-
- glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
- if (!checkGlError("glViewport")) break;
- succeeded = true;
- } while (false);
-
- return succeeded;
-}
-
-bool SurfaceTextureRenderer::Clear(float r, float g, float b, float a)
-{
- bool succeeded = false;
- do {
- bool rt = (mFrameBuffer == NULL)?
- SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
- SetupGraphics(mFrameBuffer);
-
- if(!rt)
- break;
-
- glClearColor(r, g, b, a);
- glClear(GL_COLOR_BUFFER_BIT);
-
- succeeded = true;
- } while (false);
- return succeeded;
-
-}
-
bool SurfaceTextureRenderer::DrawTexture(GLfloat *affine)
{
bool succeeded = false;
@@ -336,47 +145,35 @@ bool SurfaceTextureRenderer::DrawTexture(GLfloat *affine)
return succeeded;
}
-void SurfaceTextureRenderer::InitializeGLContext()
-{
- if(mFrameBuffer != NULL)
- {
- delete mFrameBuffer;
- mFrameBuffer = NULL;
- }
-
- mInputTextureName = -1;
- mInputTextureType = GL_TEXTURE_EXTERNAL_OES_ENUM;
- mGlProgram = 0;
-}
-
-int SurfaceTextureRenderer::GetTextureName()
-{
- return mInputTextureName;
-}
-
-void SurfaceTextureRenderer::SetInputTextureName(GLuint textureName)
-{
- mInputTextureName = textureName;
-}
-
-void SurfaceTextureRenderer::SetInputTextureType(GLenum textureType)
-{
- mInputTextureType = textureType;
-}
-
-void SurfaceTextureRenderer::SetInputTextureDimensions(int width, int height)
-{
- mInputTextureWidth = width;
- mInputTextureHeight = height;
-}
-
-
const char* SurfaceTextureRenderer::VertexShaderSource() const
{
+ static const char gVertexShader[] =
+ "uniform mat4 uSTMatrix;\n"
+ "uniform mat4 u_scalingtrans; \n"
+ "attribute vec4 aPosition;\n"
+ "attribute vec4 aTextureCoord;\n"
+ "varying vec2 vTextureCoord;\n"
+ "varying vec2 vTextureNormCoord;\n"
+ "void main() {\n"
+ " gl_Position = u_scalingtrans * aPosition;\n"
+ " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n"
+ " vTextureNormCoord = aTextureCoord.xy;\n"
+ "}\n";
+
return gVertexShader;
}
const char* SurfaceTextureRenderer::FragmentShaderSource() const
{
+ static const char gFragmentShader[] =
+ "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "varying vec2 vTextureCoord;\n"
+ "varying vec2 vTextureNormCoord;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(sTexture, vTextureNormCoord);\n"
+ "}\n";
+
return gFragmentShader;
}
diff --git a/jni/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.h b/jni/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.h
index e74bd64..ea2b81a 100755
--- a/jni/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.h
+++ b/jni/feature_mos/src/mosaic_renderer/SurfaceTextureRenderer.h
@@ -1,6 +1,7 @@
#pragma once
#include "FrameBuffer.h"
+#include "Renderer.h"
#include <GLES2/gl2.h>
@@ -8,8 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
-//TODO: Add a base class Renderer for WarpRenderer and SurfaceTextureRenderer.
-class SurfaceTextureRenderer {
+class SurfaceTextureRenderer: public Renderer {
public:
SurfaceTextureRenderer();
virtual ~SurfaceTextureRenderer();
@@ -18,46 +18,16 @@ class SurfaceTextureRenderer {
// @return true if successful
bool InitializeGLProgram();
- bool SetupGraphics(FrameBuffer* buffer);
- bool SetupGraphics(int width, int height);
-
- bool Clear(float r, float g, float b, float a);
+ bool DrawTexture(GLfloat *affine);
void SetViewportMatrix(int w, int h, int W, int H);
void SetScalingMatrix(float xscale, float yscale);
- bool DrawTexture(GLfloat *affine);
-
- int GetTextureName();
- void SetInputTextureName(GLuint textureName);
- void SetInputTextureDimensions(int width, int height);
- void SetInputTextureType(GLenum textureType);
-
- void InitializeGLContext();
-
void SetSTMatrix(float *stmat);
- protected:
-
- GLuint loadShader(GLenum shaderType, const char* pSource);
- GLuint createProgram(const char*, const char* );
-
- int SurfaceWidth() const { return mSurfaceWidth; }
- int SurfaceHeight() const { return mSurfaceHeight; }
-
private:
// Source code for shaders.
- virtual const char* VertexShaderSource() const;
- virtual const char* FragmentShaderSource() const;
-
- // Redefine this to use special texture types such as
- // GL_TEXTURE_EXTERNAL_OES.
- virtual GLenum InputTextureType() const { return mInputTextureType; }
-
- GLuint mGlProgram;
- GLuint mInputTextureName;
- GLenum mInputTextureType;
- int mInputTextureWidth;
- int mInputTextureHeight;
+ const char* VertexShaderSource() const;
+ const char* FragmentShaderSource() const;
// Attribute locations
GLint mScalingtransLoc;
@@ -67,11 +37,8 @@ class SurfaceTextureRenderer {
GLfloat mViewportMatrix[16];
GLfloat mScalingMatrix[16];
- GLfloat mSTMatrix[16];
- int mSurfaceWidth; // Width of target surface.
- int mSurfaceHeight; // Height of target surface.
+ GLfloat mSTMatrix[16];
- FrameBuffer *mFrameBuffer;
};
diff --git a/jni/feature_mos/src/mosaic_renderer/WarpRenderer.cpp b/jni/feature_mos/src/mosaic_renderer/WarpRenderer.cpp
index b2ca8d4..f1d5883 100755
--- a/jni/feature_mos/src/mosaic_renderer/WarpRenderer.cpp
+++ b/jni/feature_mos/src/mosaic_renderer/WarpRenderer.cpp
@@ -7,40 +7,14 @@
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
-
-static const char gVertexShader[] =
-"uniform mat4 u_affinetrans; \n"
-"uniform mat4 u_viewporttrans; \n"
-"uniform mat4 u_scalingtrans; \n"
-"attribute vec4 a_position; \n"
-"attribute vec2 a_texCoord; \n"
-"varying vec2 v_texCoord; \n"
-"void main() \n"
-"{ \n"
-" gl_Position = u_scalingtrans * u_viewporttrans * u_affinetrans * a_position; \n"
-" v_texCoord = a_texCoord; \n"
-"} \n";
-
-static const char gFragmentShader[] =
-"precision mediump float; \n"
-"varying vec2 v_texCoord; \n"
-"uniform sampler2D s_texture; \n"
-"void main() \n"
-"{ \n"
-" vec4 color; \n"
-" color = texture2D(s_texture, v_texCoord); \n"
-" gl_FragColor = color; \n"
-"} \n";
-
-
const GLfloat g_vVertices[] = {
- -1.f, -1.f, 0.0f, 1.0f, // Position 0
+ -1.f, 1.f, 0.0f, 1.0f, // Position 0
0.0f, 1.0f, // TexCoord 0
- 1.f, -1.f, 0.0f, 1.0f, // Position 1
+ 1.f, 1.f, 0.0f, 1.0f, // Position 1
1.0f, 1.0f, // TexCoord 1
- -1.f, 1.f, 0.0f, 1.0f, // Position 2
+ -1.f, -1.f, 0.0f, 1.0f, // Position 2
0.0f, 0.0f, // TexCoord 2
- 1.f, 1.f, 0.0f, 1.0f, // Position 3
+ 1.f, -1.f, 0.0f, 1.0f, // Position 3
1.0f, 0.0f // TexCoord 3
};
@@ -48,97 +22,39 @@ const int VERTEX_STRIDE = 6 * sizeof(GLfloat);
GLushort g_iIndices[] = { 0, 1, 2, 3 };
-WarpRenderer::WarpRenderer()
- : mGlProgram(0),
- mInputTextureName(-1),
- mInputTextureWidth(0),
- mInputTextureHeight(0),
- mSurfaceWidth(0),
- mSurfaceHeight(0)
- {
- InitializeGLContext();
+WarpRenderer::WarpRenderer() : Renderer()
+ {
}
WarpRenderer::~WarpRenderer() {
}
-GLuint WarpRenderer::loadShader(GLenum shaderType, const char* pSource) {
- GLuint shader = glCreateShader(shaderType);
- if (shader) {
- glShaderSource(shader, 1, &pSource, NULL);
- glCompileShader(shader);
- GLint compiled = 0;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
- if (!compiled) {
- GLint infoLen = 0;
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
- if (infoLen) {
- char* buf = (char*) malloc(infoLen);
- if (buf) {
- glGetShaderInfoLog(shader, infoLen, NULL, buf);
- LOGE("Could not compile shader %d:\n%s\n",
- shaderType, buf);
- free(buf);
- }
- glDeleteShader(shader);
- shader = 0;
- }
- }
- }
- return shader;
-}
-
-GLuint WarpRenderer::createProgram(const char* pVertexSource, const char* pFragmentSource)
+void WarpRenderer::SetViewportMatrix(int w, int h, int W, int H)
{
- GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
- if (!vertexShader)
+ for(int i=0; i<16; i++)
{
- return 0;
+ mViewportMatrix[i] = 0.0f;
}
- LOGI("VertexShader Loaded!");
- GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
- if (!pixelShader)
- {
- return 0;
- }
- LOGI("FragmentShader Loaded!");
+ mViewportMatrix[0] = float(w)/float(W);
+ mViewportMatrix[5] = float(h)/float(H);
+ mViewportMatrix[10] = 1.0f;
+ mViewportMatrix[12] = -1.0f + float(w)/float(W);
+ mViewportMatrix[13] = -1.0f + float(h)/float(H);
+ mViewportMatrix[15] = 1.0f;
+}
- GLuint program = glCreateProgram();
- if (program)
+void WarpRenderer::SetScalingMatrix(float xscale, float yscale)
+{
+ for(int i=0; i<16; i++)
{
- glAttachShader(program, vertexShader);
- checkGlError("glAttachShader");
- glAttachShader(program, pixelShader);
- checkGlError("glAttachShader");
-
- LOGI("Shaders Attached!");
-
- glLinkProgram(program);
- GLint linkStatus = GL_FALSE;
- glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
-
- LOGI("Program Linked!");
-
- if (linkStatus != GL_TRUE)
- {
- GLint bufLength = 0;
- glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
- if (bufLength)
- {
- char* buf = (char*) malloc(bufLength);
- if (buf)
- {
- glGetProgramInfoLog(program, bufLength, NULL, buf);
- LOGE("Could not link program:\n%s\n", buf);
- free(buf);
- }
- }
- glDeleteProgram(program);
- program = 0;
- }
+ mScalingMatrix[i] = 0.0f;
}
- return program;
+
+ mScalingMatrix[0] = xscale;
+ mScalingMatrix[5] = yscale;
+ mScalingMatrix[10] = 1.0f;
+ mScalingMatrix[15] = 1.0f;
}
bool WarpRenderer::InitializeGLProgram()
@@ -178,115 +94,6 @@ bool WarpRenderer::InitializeGLProgram()
return succeeded;
}
-void WarpRenderer::SetViewportMatrix(int w, int h, int W, int H)
-{
- for(int i=0; i<16; i++)
- {
- mViewportMatrix[i] = 0.0f;
- }
-
- mViewportMatrix[0] = float(w)/float(W);
- mViewportMatrix[5] = float(h)/float(H);
- mViewportMatrix[10] = 1.0f;
- mViewportMatrix[12] = -1.0f + float(w)/float(W);
- mViewportMatrix[13] = -1.0f + float(h)/float(H);
- mViewportMatrix[15] = 1.0f;
-}
-
-void WarpRenderer::SetScalingMatrix(float xscale, float yscale)
-{
- for(int i=0; i<16; i++)
- {
- mScalingMatrix[i] = 0.0f;
- }
-
- mScalingMatrix[0] = xscale;
- mScalingMatrix[5] = yscale;
- mScalingMatrix[10] = 1.0f;
- mScalingMatrix[15] = 1.0f;
-}
-
-// Set this renderer to use the default frame-buffer (screen) and
-// set the viewport size to be the given width and height (pixels).
-bool WarpRenderer::SetupGraphics(int width, int height)
-{
- bool succeeded = false;
- do {
- if (mGlProgram == 0)
- {
- if (!InitializeGLProgram())
- {
- break;
- }
- }
- glUseProgram(mGlProgram);
- if (!checkGlError("glUseProgram")) break;
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
- mFrameBuffer = NULL;
- mSurfaceWidth = width;
- mSurfaceHeight = height;
-
- glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
- if (!checkGlError("glViewport")) break;
- succeeded = true;
- } while (false);
-
- return succeeded;
-}
-
-
-// Set this renderer to use the specified FBO and
-// set the viewport size to be the width and height of this FBO.
-bool WarpRenderer::SetupGraphics(FrameBuffer* buffer)
-{
- bool succeeded = false;
- do {
- if (mGlProgram == 0)
- {
- if (!InitializeGLProgram())
- {
- break;
- }
- }
- glUseProgram(mGlProgram);
- if (!checkGlError("glUseProgram")) break;
-
- glBindFramebuffer(GL_FRAMEBUFFER, buffer->GetFrameBufferName());
-
- mFrameBuffer = buffer;
- mSurfaceWidth = mFrameBuffer->GetWidth();
- mSurfaceHeight = mFrameBuffer->GetHeight();
-
- glViewport(0, 0, mSurfaceWidth, mSurfaceHeight);
- if (!checkGlError("glViewport")) break;
- succeeded = true;
- } while (false);
-
- return succeeded;
-}
-
-bool WarpRenderer::Clear(float r, float g, float b, float a)
-{
- bool succeeded = false;
- do {
- bool rt = (mFrameBuffer == NULL)?
- SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
- SetupGraphics(mFrameBuffer);
-
- if(!rt)
- break;
-
- glClearColor(r, g, b, a);
- glClear(GL_COLOR_BUFFER_BIT);
-
- succeeded = true;
- } while (false);
- return succeeded;
-
-}
-
bool WarpRenderer::DrawTexture(GLfloat *affine)
{
bool succeeded = false;
@@ -337,48 +144,36 @@ bool WarpRenderer::DrawTexture(GLfloat *affine)
return succeeded;
}
-void WarpRenderer::InitializeGLContext()
-{
- if(mFrameBuffer != NULL)
- {
- delete mFrameBuffer;
- mFrameBuffer = NULL;
- }
-
- mInputTextureName = -1;
- mInputTextureType = GL_TEXTURE_2D;
- mGlProgram = 0;
- mTexHandle = 0;
-}
-
-int WarpRenderer::GetTextureName()
-{
- return mInputTextureName;
-}
-
-void WarpRenderer::SetInputTextureName(GLuint textureName)
-{
- mInputTextureName = textureName;
-}
-
-void WarpRenderer::SetInputTextureType(GLenum textureType)
-{
- mInputTextureType = textureType;
-}
-
-void WarpRenderer::SetInputTextureDimensions(int width, int height)
-{
- mInputTextureWidth = width;
- mInputTextureHeight = height;
-}
-
-
const char* WarpRenderer::VertexShaderSource() const
{
+ static const char gVertexShader[] =
+ "uniform mat4 u_affinetrans; \n"
+ "uniform mat4 u_viewporttrans; \n"
+ "uniform mat4 u_scalingtrans; \n"
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = u_scalingtrans * u_viewporttrans * u_affinetrans * a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+
return gVertexShader;
}
const char* WarpRenderer::FragmentShaderSource() const
{
+ static const char gFragmentShader[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 color; \n"
+ " color = texture2D(s_texture, v_texCoord); \n"
+ " gl_FragColor = color; \n"
+ "} \n";
+
return gFragmentShader;
}
diff --git a/jni/feature_mos/src/mosaic_renderer/WarpRenderer.h b/jni/feature_mos/src/mosaic_renderer/WarpRenderer.h
index 774b33f..8e9a694 100755
--- a/jni/feature_mos/src/mosaic_renderer/WarpRenderer.h
+++ b/jni/feature_mos/src/mosaic_renderer/WarpRenderer.h
@@ -1,6 +1,7 @@
#pragma once
#include "FrameBuffer.h"
+#include "Renderer.h"
#include <GLES2/gl2.h>
@@ -8,7 +9,7 @@
#include <stdio.h>
#include <stdlib.h>
-class WarpRenderer {
+class WarpRenderer: public Renderer {
public:
WarpRenderer();
virtual ~WarpRenderer();
@@ -17,45 +18,15 @@ class WarpRenderer {
// @return true if successful
bool InitializeGLProgram();
- bool SetupGraphics(FrameBuffer* buffer);
- bool SetupGraphics(int width, int height);
-
- bool Clear(float r, float g, float b, float a);
-
void SetViewportMatrix(int w, int h, int W, int H);
void SetScalingMatrix(float xscale, float yscale);
- bool DrawTexture(GLfloat *affine);
-
- int GetTextureName();
- void SetInputTextureName(GLuint textureName);
- void SetInputTextureDimensions(int width, int height);
- void SetInputTextureType(GLenum textureType);
-
- void InitializeGLContext();
-
- protected:
-
- GLuint loadShader(GLenum shaderType, const char* pSource);
- GLuint createProgram(const char*, const char* );
- int SurfaceWidth() const { return mSurfaceWidth; }
- int SurfaceHeight() const { return mSurfaceHeight; }
+ bool DrawTexture(GLfloat *affine);
private:
// Source code for shaders.
- virtual const char* VertexShaderSource() const;
- virtual const char* FragmentShaderSource() const;
-
- // Redefine this to use special texture types such as
- // GL_TEXTURE_EXTERNAL_OES.
- virtual GLenum InputTextureType() const { return mInputTextureType; }
-
-
- GLuint mGlProgram;
- GLuint mInputTextureName;
- GLenum mInputTextureType;
- int mInputTextureWidth;
- int mInputTextureHeight;
+ const char* VertexShaderSource() const;
+ const char* FragmentShaderSource() const;
GLuint mTexHandle; // Handle to s_texture.
GLuint mTexCoordHandle; // Handle to a_texCoord.
@@ -73,10 +44,5 @@ class WarpRenderer {
// Sampler location
GLint mSamplerLoc;
-
- int mSurfaceWidth; // Width of target surface.
- int mSurfaceHeight; // Height of target surface.
-
- FrameBuffer *mFrameBuffer;
};
diff --git a/jni/feature_mos/src/mosaic_renderer/YVURenderer.cpp b/jni/feature_mos/src/mosaic_renderer/YVURenderer.cpp
new file mode 100755
index 0000000..e244ccf
--- /dev/null
+++ b/jni/feature_mos/src/mosaic_renderer/YVURenderer.cpp
@@ -0,0 +1,149 @@
+#include "YVURenderer.h"
+
+#include <GLES2/gl2ext.h>
+
+#include <android/log.h>
+#define LOG_TAG "YVURenderer"
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+
+const GLfloat g_vVertices[] = {
+ -1.f, 1.f, 0.0f, 1.0f, // Position 0
+ 0.0f, 1.0f, // TexCoord 0
+ 1.f, 1.f, 0.0f, 1.0f, // Position 1
+ 1.0f, 1.0f, // TexCoord 1
+ -1.f, -1.f, 0.0f, 1.0f, // Position 2
+ 0.0f, 0.0f, // TexCoord 2
+ 1.f, -1.f, 0.0f, 1.0f, // Position 3
+ 1.0f, 0.0f // TexCoord 3
+};
+
+const int VERTEX_STRIDE = 6 * sizeof(GLfloat);
+
+GLushort g_iIndices3[] = { 0, 1, 2, 3 };
+
+YVURenderer::YVURenderer() : Renderer()
+ {
+}
+
+YVURenderer::~YVURenderer() {
+}
+
+bool YVURenderer::InitializeGLProgram()
+{
+ bool succeeded = false;
+ do {
+ GLuint glProgram;
+ glProgram = createProgram(VertexShaderSource(),
+ FragmentShaderSource());
+ if (!glProgram) {
+ break;
+ }
+
+ glUseProgram(glProgram);
+ if (!checkGlError("glUseProgram")) break;
+
+ // Get attribute locations
+ mPositionLoc = glGetAttribLocation(glProgram, "a_Position");
+ mTexCoordLoc = glGetAttribLocation(glProgram, "a_texCoord");
+
+ // Get sampler location
+ mSamplerLoc = glGetUniformLocation(glProgram, "s_texture");
+
+ mGlProgram = glProgram;
+ succeeded = true;
+ } while (false);
+
+ if (!succeeded && (mGlProgram != 0))
+ {
+ glDeleteProgram(mGlProgram);
+ checkGlError("glDeleteProgram");
+ mGlProgram = 0;
+ }
+ return succeeded;
+}
+
+bool YVURenderer::DrawTexture()
+{
+ bool succeeded = false;
+ do {
+ bool rt = (mFrameBuffer == NULL)?
+ SetupGraphics(mSurfaceWidth, mSurfaceHeight) :
+ SetupGraphics(mFrameBuffer);
+
+ if(!rt)
+ break;
+
+ glDisable(GL_BLEND);
+
+ glActiveTexture(GL_TEXTURE0);
+ if (!checkGlError("glActiveTexture")) break;
+
+ const GLenum texture_type = InputTextureType();
+ glBindTexture(texture_type, mInputTextureName);
+ if (!checkGlError("glBindTexture")) break;
+
+ // Set the sampler texture unit to 0
+ glUniform1i(mSamplerLoc, 0);
+
+ // Load the vertex position
+ glVertexAttribPointer(mPositionLoc, 4, GL_FLOAT,
+ GL_FALSE, VERTEX_STRIDE, g_vVertices);
+
+ // Load the texture coordinate
+ glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT,
+ GL_FALSE, VERTEX_STRIDE, &g_vVertices[4]);
+
+ glEnableVertexAttribArray(mPositionLoc);
+ glEnableVertexAttribArray(mTexCoordLoc);
+
+ // And, finally, execute the GL draw command.
+ glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, g_iIndices3);
+
+ checkGlError("glDrawElements");
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ succeeded = true;
+ } while (false);
+ return succeeded;
+}
+
+const char* YVURenderer::VertexShaderSource() const
+{
+ // All this really does is copy the coordinates into
+ // variables for the fragment shader to pick up.
+ static const char gVertexShader[] =
+ "attribute vec4 a_Position;\n"
+ "attribute vec2 a_texCoord;\n"
+ "varying vec2 v_texCoord;\n"
+ "void main() {\n"
+ " gl_Position = a_Position;\n"
+ " v_texCoord = a_texCoord;\n"
+ "}\n";
+
+ return gVertexShader;
+}
+
+const char* YVURenderer::FragmentShaderSource() const
+{
+ static const char gFragmentShader[] =
+ "precision mediump float;\n"
+ "uniform sampler2D s_texture;\n"
+ "const vec4 coeff_y = vec4(0.257, 0.594, 0.098, 0.063);\n"
+ "const vec4 coeff_v = vec4(0.439, -0.368, -0.071, 0.500);\n"
+ "const vec4 coeff_u = vec4(-0.148, -0.291, 0.439, 0.500);\n"
+ "varying vec2 v_texCoord;\n"
+ "void main() {\n"
+ " vec4 p;\n"
+ " p = texture2D(s_texture, v_texCoord);\n"
+ " gl_FragColor[0] = dot(p, coeff_y);\n"
+ " p = texture2D(s_texture, v_texCoord);\n"
+ " gl_FragColor[1] = dot(p, coeff_v);\n"
+ " p = texture2D(s_texture, v_texCoord);\n"
+ " gl_FragColor[2] = dot(p, coeff_u);\n"
+ " p = texture2D(s_texture, v_texCoord);\n"
+ " gl_FragColor[3] = dot(p, coeff_y);\n"
+ "}\n";
+
+ return gFragmentShader;
+}
diff --git a/jni/feature_mos/src/mosaic_renderer/YVURenderer.h b/jni/feature_mos/src/mosaic_renderer/YVURenderer.h
new file mode 100755
index 0000000..d14a4b9
--- /dev/null
+++ b/jni/feature_mos/src/mosaic_renderer/YVURenderer.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "FrameBuffer.h"
+#include "Renderer.h"
+
+#include <GLES2/gl2.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+class YVURenderer: public Renderer {
+ public:
+ YVURenderer();
+ virtual ~YVURenderer();
+
+ // Initialize OpenGL resources
+ // @return true if successful
+ bool InitializeGLProgram();
+
+ bool DrawTexture();
+
+ private:
+ // Source code for shaders.
+ const char* VertexShaderSource() const;
+ const char* FragmentShaderSource() const;
+
+ // Attribute locations
+ GLint mPositionLoc;
+ GLint mTexCoordLoc;
+
+ // Sampler location
+ GLint mSamplerLoc;
+};
+