Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Unified Diff: webrtc/modules/video_render/android/video_render_opengles20.cc

Issue 1923613003: Revert of Delete video_render module. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/video_render/android/video_render_opengles20.cc
diff --git a/webrtc/modules/video_render/android/video_render_opengles20.cc b/webrtc/modules/video_render/android/video_render_opengles20.cc
new file mode 100644
index 0000000000000000000000000000000000000000..45db56a4f6e6cd93d68abc7d5eb6557f38bb0e43
--- /dev/null
+++ b/webrtc/modules/video_render/android/video_render_opengles20.cc
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "webrtc/modules/video_render/android/video_render_opengles20.h"
+
+//#define ANDROID_LOG
+
+#ifdef ANDROID_LOG
+#include <android/log.h>
+#include <stdio.h>
+
+#undef WEBRTC_TRACE
+#define WEBRTC_TRACE(a,b,c,...) __android_log_print(ANDROID_LOG_DEBUG, "*WEBRTCN*", __VA_ARGS__)
+#else
+#include "webrtc/system_wrappers/include/trace.h"
+#endif
+
+namespace webrtc {
+
+const char VideoRenderOpenGles20::g_indices[] = { 0, 3, 2, 0, 2, 1 };
+
+const char VideoRenderOpenGles20::g_vertextShader[] = {
+ "attribute vec4 aPosition;\n"
+ "attribute vec2 aTextureCoord;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
+ " gl_Position = aPosition;\n"
+ " vTextureCoord = aTextureCoord;\n"
+ "}\n" };
+
+// The fragment shader.
+// Do YUV to RGB565 conversion.
+const char VideoRenderOpenGles20::g_fragmentShader[] = {
+ "precision mediump float;\n"
+ "uniform sampler2D Ytex;\n"
+ "uniform sampler2D Utex,Vtex;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main(void) {\n"
+ " float nx,ny,r,g,b,y,u,v;\n"
+ " mediump vec4 txl,ux,vx;"
+ " nx=vTextureCoord[0];\n"
+ " ny=vTextureCoord[1];\n"
+ " y=texture2D(Ytex,vec2(nx,ny)).r;\n"
+ " u=texture2D(Utex,vec2(nx,ny)).r;\n"
+ " v=texture2D(Vtex,vec2(nx,ny)).r;\n"
+
+ //" y = v;\n"+
+ " y=1.1643*(y-0.0625);\n"
+ " u=u-0.5;\n"
+ " v=v-0.5;\n"
+
+ " r=y+1.5958*v;\n"
+ " g=y-0.39173*u-0.81290*v;\n"
+ " b=y+2.017*u;\n"
+ " gl_FragColor=vec4(r,g,b,1.0);\n"
+ "}\n" };
+
+VideoRenderOpenGles20::VideoRenderOpenGles20(int32_t id) :
+ _id(id),
+ _textureWidth(-1),
+ _textureHeight(-1) {
+ WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "%s: id %d",
+ __FUNCTION__, (int) _id);
+
+ const GLfloat vertices[20] = {
+ // X, Y, Z, U, V
+ -1, -1, 0, 0, 1, // Bottom Left
+ 1, -1, 0, 1, 1, //Bottom Right
+ 1, 1, 0, 1, 0, //Top Right
+ -1, 1, 0, 0, 0 }; //Top Left
+
+ memcpy(_vertices, vertices, sizeof(_vertices));
+}
+
+VideoRenderOpenGles20::~VideoRenderOpenGles20() {
+}
+
+int32_t VideoRenderOpenGles20::Setup(int32_t width, int32_t height) {
+ WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id,
+ "%s: width %d, height %d", __FUNCTION__, (int) width,
+ (int) height);
+
+ printGLString("Version", GL_VERSION);
+ printGLString("Vendor", GL_VENDOR);
+ printGLString("Renderer", GL_RENDERER);
+ printGLString("Extensions", GL_EXTENSIONS);
+
+ int maxTextureImageUnits[2];
+ int maxTextureSize[2];
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, maxTextureImageUnits);
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxTextureSize);
+
+ WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id,
+ "%s: number of textures %d, size %d", __FUNCTION__,
+ (int) maxTextureImageUnits[0], (int) maxTextureSize[0]);
+
+ _program = createProgram(g_vertextShader, g_fragmentShader);
+ if (!_program) {
+ WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
+ "%s: Could not create program", __FUNCTION__);
+ return -1;
+ }
+
+ int positionHandle = glGetAttribLocation(_program, "aPosition");
+ checkGlError("glGetAttribLocation aPosition");
+ if (positionHandle == -1) {
+ WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
+ "%s: Could not get aPosition handle", __FUNCTION__);
+ return -1;
+ }
+
+ int textureHandle = glGetAttribLocation(_program, "aTextureCoord");
+ checkGlError("glGetAttribLocation aTextureCoord");
+ if (textureHandle == -1) {
+ WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
+ "%s: Could not get aTextureCoord handle", __FUNCTION__);
+ return -1;
+ }
+
+ // set the vertices array in the shader
+ // _vertices contains 4 vertices with 5 coordinates.
+ // 3 for (xyz) for the vertices and 2 for the texture
+ glVertexAttribPointer(positionHandle, 3, GL_FLOAT, false,
+ 5 * sizeof(GLfloat), _vertices);
+ checkGlError("glVertexAttribPointer aPosition");
+
+ glEnableVertexAttribArray(positionHandle);
+ checkGlError("glEnableVertexAttribArray positionHandle");
+
+ // set the texture coordinate array in the shader
+ // _vertices contains 4 vertices with 5 coordinates.
+ // 3 for (xyz) for the vertices and 2 for the texture
+ glVertexAttribPointer(textureHandle, 2, GL_FLOAT, false, 5
+ * sizeof(GLfloat), &_vertices[3]);
+ checkGlError("glVertexAttribPointer maTextureHandle");
+ glEnableVertexAttribArray(textureHandle);
+ checkGlError("glEnableVertexAttribArray textureHandle");
+
+ glUseProgram(_program);
+ int i = glGetUniformLocation(_program, "Ytex");
+ checkGlError("glGetUniformLocation");
+ glUniform1i(i, 0); /* Bind Ytex to texture unit 0 */
+ checkGlError("glUniform1i Ytex");
+
+ i = glGetUniformLocation(_program, "Utex");
+ checkGlError("glGetUniformLocation Utex");
+ glUniform1i(i, 1); /* Bind Utex to texture unit 1 */
+ checkGlError("glUniform1i Utex");
+
+ i = glGetUniformLocation(_program, "Vtex");
+ checkGlError("glGetUniformLocation");
+ glUniform1i(i, 2); /* Bind Vtex to texture unit 2 */
+ checkGlError("glUniform1i");
+
+ glViewport(0, 0, width, height);
+ checkGlError("glViewport");
+ return 0;
+}
+
+// SetCoordinates
+// Sets the coordinates where the stream shall be rendered.
+// Values must be between 0 and 1.
+int32_t VideoRenderOpenGles20::SetCoordinates(int32_t zOrder,
+ const float left,
+ const float top,
+ const float right,
+ const float bottom) {
+ if ((top > 1 || top < 0) || (right > 1 || right < 0) ||
+ (bottom > 1 || bottom < 0) || (left > 1 || left < 0)) {
+ WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
+ "%s: Wrong coordinates", __FUNCTION__);
+ return -1;
+ }
+
+ // X, Y, Z, U, V
+ // -1, -1, 0, 0, 1, // Bottom Left
+ // 1, -1, 0, 1, 1, //Bottom Right
+ // 1, 1, 0, 1, 0, //Top Right
+ // -1, 1, 0, 0, 0 //Top Left
+
+ // Bottom Left
+ _vertices[0] = (left * 2) - 1;
+ _vertices[1] = -1 * (2 * bottom) + 1;
+ _vertices[2] = zOrder;
+
+ //Bottom Right
+ _vertices[5] = (right * 2) - 1;
+ _vertices[6] = -1 * (2 * bottom) + 1;
+ _vertices[7] = zOrder;
+
+ //Top Right
+ _vertices[10] = (right * 2) - 1;
+ _vertices[11] = -1 * (2 * top) + 1;
+ _vertices[12] = zOrder;
+
+ //Top Left
+ _vertices[15] = (left * 2) - 1;
+ _vertices[16] = -1 * (2 * top) + 1;
+ _vertices[17] = zOrder;
+
+ return 0;
+}
+
+int32_t VideoRenderOpenGles20::Render(const VideoFrame& frameToRender) {
+ if (frameToRender.IsZeroSize()) {
+ return -1;
+ }
+
+ WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "%s: id %d",
+ __FUNCTION__, (int) _id);
+
+ glUseProgram(_program);
+ checkGlError("glUseProgram");
+
+ if (_textureWidth != (GLsizei) frameToRender.width() ||
+ _textureHeight != (GLsizei) frameToRender.height()) {
+ SetupTextures(frameToRender);
+ }
+ UpdateTextures(frameToRender);
+
+ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, g_indices);
+ checkGlError("glDrawArrays");
+
+ return 0;
+}
+
+GLuint VideoRenderOpenGles20::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);
+ WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
+ "%s: Could not compile shader %d: %s",
+ __FUNCTION__, shaderType, buf);
+ free(buf);
+ }
+ glDeleteShader(shader);
+ shader = 0;
+ }
+ }
+ }
+ return shader;
+}
+
+GLuint VideoRenderOpenGles20::createProgram(const char* pVertexSource,
+ const char* pFragmentSource) {
+ GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
+ if (!vertexShader) {
+ return 0;
+ }
+
+ GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
+ if (!pixelShader) {
+ return 0;
+ }
+
+ GLuint program = glCreateProgram();
+ if (program) {
+ glAttachShader(program, vertexShader);
+ checkGlError("glAttachShader");
+ glAttachShader(program, pixelShader);
+ checkGlError("glAttachShader");
+ glLinkProgram(program);
+ GLint linkStatus = GL_FALSE;
+ glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+ 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);
+ WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
+ "%s: Could not link program: %s",
+ __FUNCTION__, buf);
+ free(buf);
+ }
+ }
+ glDeleteProgram(program);
+ program = 0;
+ }
+ }
+ return program;
+}
+
+void VideoRenderOpenGles20::printGLString(const char *name, GLenum s) {
+ const char *v = (const char *) glGetString(s);
+ WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "GL %s = %s\n",
+ name, v);
+}
+
+void VideoRenderOpenGles20::checkGlError(const char* op) {
+#ifdef ANDROID_LOG
+ for (GLint error = glGetError(); error; error = glGetError()) {
+ WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
+ "after %s() glError (0x%x)\n", op, error);
+ }
+#else
+ return;
+#endif
+}
+
+static void InitializeTexture(int name, int id, int width, int height) {
+ glActiveTexture(name);
+ glBindTexture(GL_TEXTURE_2D, id);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0,
+ GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
+}
+
+void VideoRenderOpenGles20::SetupTextures(const VideoFrame& frameToRender) {
+ WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id,
+ "%s: width %d, height %d", __FUNCTION__,
+ frameToRender.width(), frameToRender.height());
+
+ const GLsizei width = frameToRender.width();
+ const GLsizei height = frameToRender.height();
+
+ glGenTextures(3, _textureIds); //Generate the Y, U and V texture
+ InitializeTexture(GL_TEXTURE0, _textureIds[0], width, height);
+ InitializeTexture(GL_TEXTURE1, _textureIds[1], width / 2, height / 2);
+ InitializeTexture(GL_TEXTURE2, _textureIds[2], width / 2, height / 2);
+
+ checkGlError("SetupTextures");
+
+ _textureWidth = width;
+ _textureHeight = height;
+}
+
+// Uploads a plane of pixel data, accounting for stride != width*bpp.
+static void GlTexSubImage2D(GLsizei width, GLsizei height, int stride,
+ const uint8_t* plane) {
+ if (stride == width) {
+ // Yay! We can upload the entire plane in a single GL call.
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE,
+ GL_UNSIGNED_BYTE,
+ static_cast<const GLvoid*>(plane));
+ } else {
+ // Boo! Since GLES2 doesn't have GL_UNPACK_ROW_LENGTH and Android doesn't
+ // have GL_EXT_unpack_subimage we have to upload a row at a time. Ick.
+ for (int row = 0; row < height; ++row) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, row, width, 1, GL_LUMINANCE,
+ GL_UNSIGNED_BYTE,
+ static_cast<const GLvoid*>(plane + (row * stride)));
+ }
+ }
+}
+
+void VideoRenderOpenGles20::UpdateTextures(const VideoFrame& frameToRender) {
+ const GLsizei width = frameToRender.width();
+ const GLsizei height = frameToRender.height();
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, _textureIds[0]);
+ GlTexSubImage2D(width, height, frameToRender.stride(kYPlane),
+ frameToRender.buffer(kYPlane));
+
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, _textureIds[1]);
+ GlTexSubImage2D(width / 2, height / 2, frameToRender.stride(kUPlane),
+ frameToRender.buffer(kUPlane));
+
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D, _textureIds[2]);
+ GlTexSubImage2D(width / 2, height / 2, frameToRender.stride(kVPlane),
+ frameToRender.buffer(kVPlane));
+
+ checkGlError("UpdateTextures");
+}
+
+} // namespace webrtc

Powered by Google App Engine
This is Rietveld 408576698