/*
 * 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 <media/stagefright/MediaBuffer.h>
#include <media/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 copyI420Buffer(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_
