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_