1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef NATIVE_WINDOW_RENDERER_H_
18#define NATIVE_WINDOW_RENDERER_H_
19
20#include <EGL/egl.h>
21#include <GLES2/gl2.h>
22#include <media/stagefright/MediaBuffer.h>
23#include <media/stagefright/MetaData.h>
24#include <utils/RefBase.h>
25#include <utils/threads.h>
26
27#include "M4xVSS_API.h"
28
29// The NativeWindowRenderer draws video frames stored in MediaBuffers to
30// an ANativeWindow.  It can apply "rendering mode" and color effects to
31// the frames. "Rendering mode" is the option to do resizing, cropping,
32// or black-bordering when the source and destination aspect ratio are
33// different. Color effects include sepia, negative, and gradient.
34//
35// The input to NativeWindowRenderer is provided by the RenderInput class,
36// and there can be multiple active RenderInput at the same time. Although
37// we only expect that happens briefly when one clip is about to finish
38// and the next clip is about to start.
39//
40// We allocate a SurfaceTexture for each RenderInput and the user can use
41// the getTargetWindow() function to get the corresponding ANativeWindow
42// for that SurfaceTexture. The intention is that the user can pass that
43// ANativeWindow to OMXCodec::Create() so the codec can decode directly
44// to buffers provided by the texture.
45
46namespace android {
47
48class SurfaceTexture;
49class SurfaceTextureClient;
50class RenderInput;
51
52class NativeWindowRenderer {
53public:
54    NativeWindowRenderer(sp<ANativeWindow> nativeWindow, int width, int height);
55    ~NativeWindowRenderer();
56
57    RenderInput* createRenderInput();
58    void destroyRenderInput(RenderInput* input);
59
60private:
61    // No copy constructor and assignment
62    NativeWindowRenderer(const NativeWindowRenderer &);
63    NativeWindowRenderer &operator=(const NativeWindowRenderer &);
64
65    // Initialization and finialization
66    void initializeEGL();
67    void terminateEGL();
68    void createPrograms();
69    void createProgram(
70            GLuint vertexShader, GLuint fragmentShader, GLuint* outPgm);
71    void loadShader(
72            GLenum shaderType, const char* pSource, GLuint* outShader);
73
74    // These functions are executed every frame.
75    void render(RenderInput* input);
76    void queueInternalBuffer(ANativeWindow* anw, MediaBuffer* buffer);
77    void queueExternalBuffer(ANativeWindow* anw, MediaBuffer* buffer,
78            int width, int height);
79    void copyI420Buffer(MediaBuffer* src, uint8_t* dst,
80            int srcWidth, int srcHeight, int stride);
81    void updateProgramAndHandle(uint32_t videoEffect);
82    void calculatePositionCoordinates(M4xVSS_MediaRendering renderingMode,
83            int srcWidth, int srcHeight);
84
85    // These variables are initialized once and doesn't change afterwards.
86    sp<ANativeWindow> mNativeWindow;
87    int mDstWidth, mDstHeight;
88    EGLDisplay mEglDisplay;
89    EGLSurface mEglSurface;
90    EGLContext mEglContext;
91    enum {
92        EFFECT_NORMAL,
93        EFFECT_SEPIA,
94        EFFECT_NEGATIVE,
95        EFFECT_GRADIENT,
96        NUMBER_OF_EFFECTS
97    };
98    GLuint mProgram[NUMBER_OF_EFFECTS];
99
100    // We use one shader program for each effect. mLastVideoEffect remembers
101    // the program used for the last frame. when the effect used changes,
102    // we change the program used and update the handles.
103    uint32_t mLastVideoEffect;
104    GLint mPositionHandle;
105    GLint mTexPosHandle;
106    GLint mTexMatrixHandle;
107
108    // This is the vertex coordinates used for the frame texture.
109    // It's calculated according the the rendering mode and the source and
110    // destination aspect ratio.
111    GLfloat mPositionCoordinates[8];
112
113    // We use a different GL id for each SurfaceTexture.
114    GLuint mNextTextureId;
115
116    // Number of existing RenderInputs, just for debugging.
117    int mActiveInputs;
118
119    // The GL thread functions
120    static int threadStart(void* self);
121    void glThread();
122
123    // These variables are used to communicate between the GL thread and
124    // other threads.
125    Mutex mLock;
126    Condition mCond;
127    enum {
128        CMD_IDLE,
129        CMD_RENDER_INPUT,
130        CMD_RESERVE_TEXTURE,
131        CMD_DELETE_TEXTURE,
132        CMD_QUIT,
133    };
134    int mThreadCmd;
135    RenderInput* mThreadRenderInput;
136    GLuint mThreadTextureId;
137
138    // These functions are used to send commands to the GL thread.
139    // sendRequest() also waits for the GL thread acknowledges the
140    // command is finished.
141    void startRequest(int cmd);
142    void sendRequest();
143
144    friend class RenderInput;
145};
146
147class RenderInput {
148public:
149    // Returns the ANativeWindow corresponds to the SurfaceTexture.
150    ANativeWindow* getTargetWindow();
151
152    // Updates video frame size from the MediaSource's metadata. Specifically
153    // we look for kKeyWidth, kKeyHeight, and (optionally) kKeyCropRect.
154    void updateVideoSize(sp<MetaData> meta);
155
156    // Renders the buffer with the given video effect and rending mode.
157    // The video effets are defined in VideoEditorTools.h
158    // Set isExternalBuffer to true only when the buffer given is not
159    // provided by the SurfaceTexture.
160    void render(MediaBuffer *buffer, uint32_t videoEffect,
161        M4xVSS_MediaRendering renderingMode, bool isExternalBuffer);
162private:
163    RenderInput(NativeWindowRenderer* renderer, GLuint textureId);
164    ~RenderInput();
165    NativeWindowRenderer* mRenderer;
166    GLuint mTextureId;
167    sp<SurfaceTexture> mST;
168    sp<SurfaceTextureClient> mSTC;
169    int mWidth, mHeight;
170
171    // These are only valid during render() calls
172    uint32_t mVideoEffect;
173    M4xVSS_MediaRendering mRenderingMode;
174    bool mIsExternalBuffer;
175    MediaBuffer* mBuffer;
176
177    friend class NativeWindowRenderer;
178};
179
180}  // namespace android
181
182#endif  // NATIVE_WINDOW_RENDERER_H_
183