summaryrefslogtreecommitdiffstats
path: root/libvideoeditor/lvpp/NativeWindowRenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libvideoeditor/lvpp/NativeWindowRenderer.cpp')
-rwxr-xr-xlibvideoeditor/lvpp/NativeWindowRenderer.cpp620
1 files changed, 0 insertions, 620 deletions
diff --git a/libvideoeditor/lvpp/NativeWindowRenderer.cpp b/libvideoeditor/lvpp/NativeWindowRenderer.cpp
deleted file mode 100755
index 8b362ef..0000000
--- a/libvideoeditor/lvpp/NativeWindowRenderer.cpp
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "NativeWindowRenderer"
-#include "NativeWindowRenderer.h"
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <cutils/log.h>
-#include <gui/GLConsumer.h>
-#include <gui/Surface.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include "VideoEditorTools.h"
-
-#define CHECK_EGL_ERROR CHECK(EGL_SUCCESS == eglGetError())
-#define CHECK_GL_ERROR CHECK(GLenum(GL_NO_ERROR) == glGetError())
-
-//
-// Vertex and fragment programs
-//
-
-// The matrix is derived from
-// frameworks/base/media/libstagefright/colorconversion/ColorConverter.cpp
-//
-// R * 255 = 1.164 * (Y - 16) + 1.596 * (V - 128)
-// G * 255 = 1.164 * (Y - 16) - 0.813 * (V - 128) - 0.391 * (U - 128)
-// B * 255 = 1.164 * (Y - 16) + 2.018 * (U - 128)
-//
-// Here we assume YUV are in the range of [0,255], RGB are in the range of
-// [0, 1]
-#define RGB2YUV_MATRIX \
-"const mat4 rgb2yuv = mat4("\
-" 65.52255, -37.79398, 111.98732, 0.00000,"\
-" 128.62729, -74.19334, -93.81088, 0.00000,"\
-" 24.92233, 111.98732, -18.17644, 0.00000,"\
-" 16.00000, 128.00000, 128.00000, 1.00000);\n"
-
-#define YUV2RGB_MATRIX \
-"const mat4 yuv2rgb = mat4("\
-" 0.00456, 0.00456, 0.00456, 0.00000,"\
-" 0.00000, -0.00153, 0.00791, 0.00000,"\
-" 0.00626, -0.00319, 0.00000, 0.00000,"\
-" -0.87416, 0.53133, -1.08599, 1.00000);\n"
-
-static const char vSrcNormal[] =
- "attribute vec4 vPosition;\n"
- "attribute vec2 vTexPos;\n"
- "uniform mat4 texMatrix;\n"
- "varying vec2 texCoords;\n"
- "varying float topDown;\n"
- "void main() {\n"
- " gl_Position = vPosition;\n"
- " texCoords = (texMatrix * vec4(vTexPos, 0.0, 1.0)).xy;\n"
- " topDown = vTexPos.y;\n"
- "}\n";
-
-static const char fSrcNormal[] =
- "#extension GL_OES_EGL_image_external : require\n"
- "precision mediump float;\n"
- "uniform samplerExternalOES texSampler;\n"
- "varying vec2 texCoords;\n"
- "void main() {\n"
- " gl_FragColor = texture2D(texSampler, texCoords);\n"
- "}\n";
-
-static const char fSrcSepia[] =
- "#extension GL_OES_EGL_image_external : require\n"
- "precision mediump float;\n"
- "uniform samplerExternalOES texSampler;\n"
- "varying vec2 texCoords;\n"
- RGB2YUV_MATRIX
- YUV2RGB_MATRIX
- "void main() {\n"
- " vec4 rgb = texture2D(texSampler, texCoords);\n"
- " vec4 yuv = rgb2yuv * rgb;\n"
- " yuv = vec4(yuv.x, 117.0, 139.0, 1.0);\n"
- " gl_FragColor = yuv2rgb * yuv;\n"
- "}\n";
-
-static const char fSrcNegative[] =
- "#extension GL_OES_EGL_image_external : require\n"
- "precision mediump float;\n"
- "uniform samplerExternalOES texSampler;\n"
- "varying vec2 texCoords;\n"
- RGB2YUV_MATRIX
- YUV2RGB_MATRIX
- "void main() {\n"
- " vec4 rgb = texture2D(texSampler, texCoords);\n"
- " vec4 yuv = rgb2yuv * rgb;\n"
- " yuv = vec4(255.0 - yuv.x, yuv.y, yuv.z, 1.0);\n"
- " gl_FragColor = yuv2rgb * yuv;\n"
- "}\n";
-
-static const char fSrcGradient[] =
- "#extension GL_OES_EGL_image_external : require\n"
- "precision mediump float;\n"
- "uniform samplerExternalOES texSampler;\n"
- "varying vec2 texCoords;\n"
- "varying float topDown;\n"
- RGB2YUV_MATRIX
- YUV2RGB_MATRIX
- "void main() {\n"
- " vec4 rgb = texture2D(texSampler, texCoords);\n"
- " vec4 yuv = rgb2yuv * rgb;\n"
- " vec4 mixin = vec4(15.0/31.0, 59.0/63.0, 31.0/31.0, 1.0);\n"
- " vec4 yuv2 = rgb2yuv * vec4((mixin.xyz * topDown), 1);\n"
- " yuv = vec4(yuv.x, yuv2.y, yuv2.z, 1);\n"
- " gl_FragColor = yuv2rgb * yuv;\n"
- "}\n";
-
-namespace android {
-
-NativeWindowRenderer::NativeWindowRenderer(sp<ANativeWindow> nativeWindow,
- int width, int height)
- : mNativeWindow(nativeWindow)
- , mDstWidth(width)
- , mDstHeight(height)
- , mLastVideoEffect(-1)
- , mNextTextureId(100)
- , mActiveInputs(0)
- , mThreadCmd(CMD_IDLE) {
- createThread(threadStart, this);
-}
-
-// The functions below run in the GL thread.
-//
-// All GL-related work is done in this thread, and other threads send
-// requests to this thread using a command code. We expect most of the
-// time there will only be one thread sending in requests, so we let
-// other threads wait until the request is finished by GL thread.
-
-int NativeWindowRenderer::threadStart(void* self) {
- ALOGD("create thread");
- ((NativeWindowRenderer*)self)->glThread();
- return 0;
-}
-
-void NativeWindowRenderer::glThread() {
- initializeEGL();
- createPrograms();
-
- Mutex::Autolock autoLock(mLock);
- bool quit = false;
- while (!quit) {
- switch (mThreadCmd) {
- case CMD_IDLE:
- mCond.wait(mLock);
- continue;
- case CMD_RENDER_INPUT:
- render(mThreadRenderInput);
- break;
- case CMD_RESERVE_TEXTURE:
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, mThreadTextureId);
- CHECK_GL_ERROR;
- break;
- case CMD_DELETE_TEXTURE:
- glDeleteTextures(1, &mThreadTextureId);
- break;
- case CMD_QUIT:
- terminateEGL();
- quit = true;
- break;
- }
- // Tell the requester that the command is finished.
- mThreadCmd = CMD_IDLE;
- mCond.broadcast();
- }
- ALOGD("quit");
-}
-
-void NativeWindowRenderer::initializeEGL() {
- mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- CHECK_EGL_ERROR;
-
- EGLint majorVersion;
- EGLint minorVersion;
- eglInitialize(mEglDisplay, &majorVersion, &minorVersion);
- CHECK_EGL_ERROR;
-
- EGLConfig config;
- EGLint numConfigs = -1;
- EGLint configAttribs[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_NONE
- };
- eglChooseConfig(mEglDisplay, configAttribs, &config, 1, &numConfigs);
- CHECK_EGL_ERROR;
-
- mEglSurface = eglCreateWindowSurface(mEglDisplay, config,
- mNativeWindow.get(), NULL);
- CHECK_EGL_ERROR;
-
- EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
- mEglContext = eglCreateContext(mEglDisplay, config, EGL_NO_CONTEXT,
- contextAttribs);
- CHECK_EGL_ERROR;
-
- eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
- CHECK_EGL_ERROR;
-}
-
-void NativeWindowRenderer::terminateEGL() {
- eglDestroyContext(mEglDisplay, mEglContext);
- eglDestroySurface(mEglDisplay, mEglSurface);
- eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglTerminate(mEglDisplay);
-}
-
-void NativeWindowRenderer::createPrograms() {
- GLuint vShader;
- loadShader(GL_VERTEX_SHADER, vSrcNormal, &vShader);
-
- const char* fSrc[NUMBER_OF_EFFECTS] = {
- fSrcNormal, fSrcSepia, fSrcNegative, fSrcGradient
- };
-
- for (int i = 0; i < NUMBER_OF_EFFECTS; i++) {
- GLuint fShader;
- loadShader(GL_FRAGMENT_SHADER, fSrc[i], &fShader);
- createProgram(vShader, fShader, &mProgram[i]);
- glDeleteShader(fShader);
- CHECK_GL_ERROR;
- }
-
- glDeleteShader(vShader);
- CHECK_GL_ERROR;
-}
-
-void NativeWindowRenderer::createProgram(
- GLuint vertexShader, GLuint fragmentShader, GLuint* outPgm) {
-
- GLuint program = glCreateProgram();
- CHECK_GL_ERROR;
-
- glAttachShader(program, vertexShader);
- CHECK_GL_ERROR;
-
- glAttachShader(program, fragmentShader);
- CHECK_GL_ERROR;
-
- glLinkProgram(program);
- CHECK_GL_ERROR;
-
- GLint linkStatus = GL_FALSE;
- glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
- if (linkStatus != GL_TRUE) {
- GLint infoLen = 0;
- glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
- if (infoLen) {
- char* buf = (char*) malloc(infoLen);
- if (buf) {
- glGetProgramInfoLog(program, infoLen, NULL, buf);
- ALOGE("Program link log:\n%s\n", buf);
- free(buf);
- }
- }
- glDeleteProgram(program);
- program = 0;
- }
-
- *outPgm = program;
-}
-
-void NativeWindowRenderer::loadShader(GLenum shaderType, const char* pSource,
- GLuint* outShader) {
- GLuint shader = glCreateShader(shaderType);
- CHECK_GL_ERROR;
-
- glShaderSource(shader, 1, &pSource, NULL);
- CHECK_GL_ERROR;
-
- glCompileShader(shader);
- CHECK_GL_ERROR;
-
- GLint compiled = 0;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
- if (!compiled) {
- GLint infoLen = 0;
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
- char* buf = (char*) malloc(infoLen);
- if (buf) {
- glGetShaderInfoLog(shader, infoLen, NULL, buf);
- ALOGE("Shader compile log:\n%s\n", buf);
- free(buf);
- }
- glDeleteShader(shader);
- shader = 0;
- }
- *outShader = shader;
-}
-
-NativeWindowRenderer::~NativeWindowRenderer() {
- CHECK(mActiveInputs == 0);
- startRequest(CMD_QUIT);
- sendRequest();
-}
-
-void NativeWindowRenderer::render(RenderInput* input) {
- sp<GLConsumer> ST = input->mST;
- sp<Surface> STC = input->mSTC;
-
- if (input->mIsExternalBuffer) {
- queueExternalBuffer(STC.get(), input->mBuffer,
- input->mWidth, input->mHeight);
- } else {
- queueInternalBuffer(STC.get(), input->mBuffer);
- }
-
- ST->updateTexImage();
- glClearColor(0, 0, 0, 0);
- glClear(GL_COLOR_BUFFER_BIT);
-
- calculatePositionCoordinates(input->mRenderingMode,
- input->mWidth, input->mHeight);
-
- const GLfloat textureCoordinates[] = {
- 0.0f, 1.0f,
- 0.0f, 0.0f,
- 1.0f, 0.0f,
- 1.0f, 1.0f,
- };
-
- updateProgramAndHandle(input->mVideoEffect);
-
- glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0,
- mPositionCoordinates);
- CHECK_GL_ERROR;
-
- glEnableVertexAttribArray(mPositionHandle);
- CHECK_GL_ERROR;
-
- glVertexAttribPointer(mTexPosHandle, 2, GL_FLOAT, GL_FALSE, 0,
- textureCoordinates);
- CHECK_GL_ERROR;
-
- glEnableVertexAttribArray(mTexPosHandle);
- CHECK_GL_ERROR;
-
- GLfloat texMatrix[16];
- ST->getTransformMatrix(texMatrix);
- glUniformMatrix4fv(mTexMatrixHandle, 1, GL_FALSE, texMatrix);
- CHECK_GL_ERROR;
-
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, input->mTextureId);
- CHECK_GL_ERROR;
-
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(
- GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(
- GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- CHECK_GL_ERROR;
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- CHECK_GL_ERROR;
-
- eglSwapBuffers(mEglDisplay, mEglSurface);
-}
-
-void NativeWindowRenderer::queueInternalBuffer(ANativeWindow *anw,
- MediaBuffer* buffer) {
- int64_t timeUs;
- CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
- native_window_set_buffers_timestamp(anw, timeUs * 1000);
- status_t err = anw->queueBuffer(anw, buffer->graphicBuffer().get(), -1);
- if (err != 0) {
- ALOGE("queueBuffer failed with error %s (%d)", strerror(-err), -err);
- return;
- }
-
- sp<MetaData> metaData = buffer->meta_data();
- metaData->setInt32(kKeyRendered, 1);
-}
-
-void NativeWindowRenderer::queueExternalBuffer(ANativeWindow* anw,
- MediaBuffer* buffer, int width, int height) {
- native_window_set_buffers_geometry(anw, width, height,
- HAL_PIXEL_FORMAT_YV12);
- native_window_set_usage(anw, GRALLOC_USAGE_SW_WRITE_OFTEN);
-
- ANativeWindowBuffer* anb;
- CHECK(NO_ERROR == native_window_dequeue_buffer_and_wait(anw, &anb));
- CHECK(anb != NULL);
-
- // Copy the buffer
- uint8_t* img = NULL;
- sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
- buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
- copyI420Buffer(buffer, img, width, height, buf->getStride());
- buf->unlock();
- CHECK(NO_ERROR == anw->queueBuffer(anw, buf->getNativeBuffer(), -1));
-}
-
-void NativeWindowRenderer::copyI420Buffer(MediaBuffer* src, uint8_t* dst,
- int srcWidth, int srcHeight, int stride) {
- int strideUV = (stride / 2 + 0xf) & ~0xf;
- uint8_t* p = (uint8_t*)src->data() + src->range_offset();
- // Y
- for (int i = srcHeight; i > 0; i--) {
- memcpy(dst, p, srcWidth);
- dst += stride;
- p += srcWidth;
- }
- // The src is I420, the dst is YV12.
- // U
- p += srcWidth * srcHeight / 4;
- for (int i = srcHeight / 2; i > 0; i--) {
- memcpy(dst, p, srcWidth / 2);
- dst += strideUV;
- p += srcWidth / 2;
- }
- // V
- p -= srcWidth * srcHeight / 2;
- for (int i = srcHeight / 2; i > 0; i--) {
- memcpy(dst, p, srcWidth / 2);
- dst += strideUV;
- p += srcWidth / 2;
- }
-}
-
-void NativeWindowRenderer::updateProgramAndHandle(uint32_t videoEffect) {
- if (mLastVideoEffect == videoEffect) {
- return;
- }
-
- mLastVideoEffect = videoEffect;
- int i;
- switch (mLastVideoEffect) {
- case VIDEO_EFFECT_NONE:
- i = 0;
- break;
- case VIDEO_EFFECT_SEPIA:
- i = 1;
- break;
- case VIDEO_EFFECT_NEGATIVE:
- i = 2;
- break;
- case VIDEO_EFFECT_GRADIENT:
- i = 3;
- break;
- default:
- i = 0;
- break;
- }
- glUseProgram(mProgram[i]);
- CHECK_GL_ERROR;
-
- mPositionHandle = glGetAttribLocation(mProgram[i], "vPosition");
- mTexPosHandle = glGetAttribLocation(mProgram[i], "vTexPos");
- mTexMatrixHandle = glGetUniformLocation(mProgram[i], "texMatrix");
- CHECK_GL_ERROR;
-}
-
-void NativeWindowRenderer::calculatePositionCoordinates(
- M4xVSS_MediaRendering renderingMode, int srcWidth, int srcHeight) {
- float x, y;
- switch (renderingMode) {
- case M4xVSS_kResizing:
- default:
- x = 1;
- y = 1;
- break;
- case M4xVSS_kCropping:
- x = float(srcWidth) / mDstWidth;
- y = float(srcHeight) / mDstHeight;
- // Make the smaller side 1
- if (x > y) {
- x /= y;
- y = 1;
- } else {
- y /= x;
- x = 1;
- }
- break;
- case M4xVSS_kBlackBorders:
- x = float(srcWidth) / mDstWidth;
- y = float(srcHeight) / mDstHeight;
- // Make the larger side 1
- if (x > y) {
- y /= x;
- x = 1;
- } else {
- x /= y;
- y = 1;
- }
- break;
- }
-
- mPositionCoordinates[0] = -x;
- mPositionCoordinates[1] = y;
- mPositionCoordinates[2] = -x;
- mPositionCoordinates[3] = -y;
- mPositionCoordinates[4] = x;
- mPositionCoordinates[5] = -y;
- mPositionCoordinates[6] = x;
- mPositionCoordinates[7] = y;
-}
-
-//
-// The functions below run in other threads.
-//
-
-void NativeWindowRenderer::startRequest(int cmd) {
- mLock.lock();
- while (mThreadCmd != CMD_IDLE) {
- mCond.wait(mLock);
- }
- mThreadCmd = cmd;
-}
-
-void NativeWindowRenderer::sendRequest() {
- mCond.broadcast();
- while (mThreadCmd != CMD_IDLE) {
- mCond.wait(mLock);
- }
- mLock.unlock();
-}
-
-RenderInput* NativeWindowRenderer::createRenderInput() {
- ALOGD("new render input %d", mNextTextureId);
- RenderInput* input = new RenderInput(this, mNextTextureId);
-
- startRequest(CMD_RESERVE_TEXTURE);
- mThreadTextureId = mNextTextureId;
- sendRequest();
-
- mNextTextureId++;
- mActiveInputs++;
- return input;
-}
-
-void NativeWindowRenderer::destroyRenderInput(RenderInput* input) {
- ALOGD("destroy render input %d", input->mTextureId);
- GLuint textureId = input->mTextureId;
- delete input;
-
- startRequest(CMD_DELETE_TEXTURE);
- mThreadTextureId = textureId;
- sendRequest();
-
- mActiveInputs--;
-}
-
-//
-// RenderInput
-//
-
-RenderInput::RenderInput(NativeWindowRenderer* renderer, GLuint textureId)
- : mRenderer(renderer)
- , mTextureId(textureId) {
- sp<BufferQueue> bq = new BufferQueue();
- mST = new GLConsumer(bq, mTextureId);
- mSTC = new Surface(bq);
- native_window_connect(mSTC.get(), NATIVE_WINDOW_API_MEDIA);
-}
-
-RenderInput::~RenderInput() {
-}
-
-ANativeWindow* RenderInput::getTargetWindow() {
- return mSTC.get();
-}
-
-void RenderInput::updateVideoSize(sp<MetaData> meta) {
- CHECK(meta->findInt32(kKeyWidth, &mWidth));
- CHECK(meta->findInt32(kKeyHeight, &mHeight));
-
- int left, top, right, bottom;
- if (meta->findRect(kKeyCropRect, &left, &top, &right, &bottom)) {
- mWidth = right - left + 1;
- mHeight = bottom - top + 1;
- }
-
- // If rotation degrees is 90 or 270, swap width and height
- // (mWidth and mHeight are the _rotated_ source rectangle).
- int32_t rotationDegrees;
- if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
- rotationDegrees = 0;
- }
-
- if (rotationDegrees == 90 || rotationDegrees == 270) {
- int tmp = mWidth;
- mWidth = mHeight;
- mHeight = tmp;
- }
-}
-
-void RenderInput::render(MediaBuffer* buffer, uint32_t videoEffect,
- M4xVSS_MediaRendering renderingMode, bool isExternalBuffer) {
- mVideoEffect = videoEffect;
- mRenderingMode = renderingMode;
- mIsExternalBuffer = isExternalBuffer;
- mBuffer = buffer;
-
- mRenderer->startRequest(NativeWindowRenderer::CMD_RENDER_INPUT);
- mRenderer->mThreadRenderInput = this;
- mRenderer->sendRequest();
-}
-
-} // namespace android