diff options
Diffstat (limited to 'libvideoeditor/lvpp/NativeWindowRenderer.cpp')
-rwxr-xr-x | libvideoeditor/lvpp/NativeWindowRenderer.cpp | 620 |
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 |