Use GL to render preview.
To speed up the preview, we direct the decoder output to a
SurfaceTexture, then draw the texture to a surface. The media
rendering parameters (crop, black-border) are implemented
using different vertex coordinates. The color effects are
implemented using fragment shaders. Currently only three color
effects are implemented, but that's all the appplication uses.
Change-Id: If84439fee572ed37ea077749ef9f2bd4f78703e1
diff --git a/libvideoeditor/lvpp/NativeWindowRenderer.h b/libvideoeditor/lvpp/NativeWindowRenderer.h
new file mode 100755
index 0000000..2af19a3
--- /dev/null
+++ b/libvideoeditor/lvpp/NativeWindowRenderer.h
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+#ifndef NATIVE_WINDOW_RENDERER_H_
+#define NATIVE_WINDOW_RENDERER_H_
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+#include <stagefright/MediaBuffer.h>
+#include <stagefright/MetaData.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+#include "M4xVSS_API.h"
+
+// The NativeWindowRenderer draws video frames stored in MediaBuffers to
+// an ANativeWindow. It can apply "rendering mode" and color effects to
+// the frames. "Rendering mode" is the option to do resizing, cropping,
+// or black-bordering when the source and destination aspect ratio are
+// different. Color effects include sepia, negative, and gradient.
+//
+// The input to NativeWindowRenderer is provided by the RenderInput class,
+// and there can be multiple active RenderInput at the same time. Although
+// we only expect that happens briefly when one clip is about to finish
+// and the next clip is about to start.
+//
+// We allocate a SurfaceTexture for each RenderInput and the user can use
+// the getTargetWindow() function to get the corresponding ANativeWindow
+// for that SurfaceTexture. The intention is that the user can pass that
+// ANativeWindow to OMXCodec::Create() so the codec can decode directly
+// to buffers provided by the texture.
+
+namespace android {
+
+class SurfaceTexture;
+class SurfaceTextureClient;
+class RenderInput;
+
+class NativeWindowRenderer {
+public:
+ NativeWindowRenderer(sp<ANativeWindow> nativeWindow, int width, int height);
+ ~NativeWindowRenderer();
+
+ RenderInput* createRenderInput();
+ void destroyRenderInput(RenderInput* input);
+
+private:
+ // No copy constructor and assignment
+ NativeWindowRenderer(const NativeWindowRenderer &);
+ NativeWindowRenderer &operator=(const NativeWindowRenderer &);
+
+ // Initialization and finialization
+ void initializeEGL();
+ void terminateEGL();
+ void createPrograms();
+ void createProgram(
+ GLuint vertexShader, GLuint fragmentShader, GLuint* outPgm);
+ void loadShader(
+ GLenum shaderType, const char* pSource, GLuint* outShader);
+
+ // These functions are executed every frame.
+ void render(RenderInput* input);
+ void queueInternalBuffer(ANativeWindow* anw, MediaBuffer* buffer);
+ void queueExternalBuffer(ANativeWindow* anw, MediaBuffer* buffer,
+ int width, int height);
+ void copyYV12Buffer(MediaBuffer* src, uint8_t* dst,
+ int srcWidth, int srcHeight, int stride);
+ void updateProgramAndHandle(uint32_t videoEffect);
+ void calculatePositionCoordinates(M4xVSS_MediaRendering renderingMode,
+ int srcWidth, int srcHeight);
+
+ // These variables are initialized once and doesn't change afterwards.
+ sp<ANativeWindow> mNativeWindow;
+ int mDstWidth, mDstHeight;
+ EGLDisplay mEglDisplay;
+ EGLSurface mEglSurface;
+ EGLContext mEglContext;
+ enum {
+ EFFECT_NORMAL,
+ EFFECT_SEPIA,
+ EFFECT_NEGATIVE,
+ EFFECT_GRADIENT,
+ NUMBER_OF_EFFECTS
+ };
+ GLuint mProgram[NUMBER_OF_EFFECTS];
+
+ // We use one shader program for each effect. mLastVideoEffect remembers
+ // the program used for the last frame. when the effect used changes,
+ // we change the program used and update the handles.
+ uint32_t mLastVideoEffect;
+ GLint mPositionHandle;
+ GLint mTexPosHandle;
+ GLint mTexMatrixHandle;
+
+ // This is the vertex coordinates used for the frame texture.
+ // It's calculated according the the rendering mode and the source and
+ // destination aspect ratio.
+ GLfloat mPositionCoordinates[8];
+
+ // We use a different GL id for each SurfaceTexture.
+ GLuint mNextTextureId;
+
+ // Number of existing RenderInputs, just for debugging.
+ int mActiveInputs;
+
+ // The GL thread functions
+ static int threadStart(void* self);
+ void glThread();
+
+ // These variables are used to communicate between the GL thread and
+ // other threads.
+ Mutex mLock;
+ Condition mCond;
+ enum {
+ CMD_IDLE,
+ CMD_RENDER_INPUT,
+ CMD_RESERVE_TEXTURE,
+ CMD_DELETE_TEXTURE,
+ CMD_QUIT,
+ };
+ int mThreadCmd;
+ RenderInput* mThreadRenderInput;
+ GLuint mThreadTextureId;
+
+ // These functions are used to send commands to the GL thread.
+ // sendRequest() also waits for the GL thread acknowledges the
+ // command is finished.
+ void startRequest(int cmd);
+ void sendRequest();
+
+ friend class RenderInput;
+};
+
+class RenderInput {
+public:
+ // Returns the ANativeWindow corresponds to the SurfaceTexture.
+ ANativeWindow* getTargetWindow();
+
+ // Updates video frame size from the MediaSource's metadata. Specifically
+ // we look for kKeyWidth, kKeyHeight, and (optionally) kKeyCropRect.
+ void updateVideoSize(sp<MetaData> meta);
+
+ // Renders the buffer with the given video effect and rending mode.
+ // The video effets are defined in VideoEditorTools.h
+ // Set isExternalBuffer to true only when the buffer given is not
+ // provided by the SurfaceTexture.
+ void render(MediaBuffer *buffer, uint32_t videoEffect,
+ M4xVSS_MediaRendering renderingMode, bool isExternalBuffer);
+private:
+ RenderInput(NativeWindowRenderer* renderer, GLuint textureId);
+ ~RenderInput();
+ NativeWindowRenderer* mRenderer;
+ GLuint mTextureId;
+ sp<SurfaceTexture> mST;
+ sp<SurfaceTextureClient> mSTC;
+ int mWidth, mHeight;
+
+ // These are only valid during render() calls
+ uint32_t mVideoEffect;
+ M4xVSS_MediaRendering mRenderingMode;
+ bool mIsExternalBuffer;
+ MediaBuffer* mBuffer;
+
+ friend class NativeWindowRenderer;
+};
+
+} // namespace android
+
+#endif // NATIVE_WINDOW_RENDERER_H_