/*
 * Copyright 2012, 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 _ANDROID_MEDIA_MEDIACODEC_H_
#define _ANDROID_MEDIA_MEDIACODEC_H_

#include "jni.h"

#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AHandler.h>
#include <utils/Errors.h>

namespace android {

struct ABuffer;
struct ALooper;
struct AMessage;
struct AString;
struct ICrypto;
struct IGraphicBufferProducer;
struct MediaCodec;
struct PersistentSurface;
class Surface;

struct JMediaCodec : public AHandler {
    JMediaCodec(
            JNIEnv *env, jobject thiz,
            const char *name, bool nameIsType, bool encoder);

    status_t initCheck() const;

    void registerSelf();
    void release();

    status_t enableOnFrameRenderedListener(jboolean enable);

    status_t setCallback(jobject cb);

    status_t configure(
            const sp<AMessage> &format,
            const sp<IGraphicBufferProducer> &bufferProducer,
            const sp<ICrypto> &crypto,
            int flags);

    status_t setSurface(
            const sp<IGraphicBufferProducer> &surface);

    status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer);
    status_t setInputSurface(const sp<PersistentSurface> &surface);

    status_t start();
    status_t stop();
    status_t reset();

    status_t flush();

    status_t queueInputBuffer(
            size_t index,
            size_t offset, size_t size, int64_t timeUs, uint32_t flags,
            AString *errorDetailMsg);

    status_t queueSecureInputBuffer(
            size_t index,
            size_t offset,
            const CryptoPlugin::SubSample *subSamples,
            size_t numSubSamples,
            const uint8_t key[16],
            const uint8_t iv[16],
            CryptoPlugin::Mode mode,
            const CryptoPlugin::Pattern &pattern,
            int64_t presentationTimeUs,
            uint32_t flags,
            AString *errorDetailMsg);

    status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs);

    status_t dequeueOutputBuffer(
            JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs);

    status_t releaseOutputBuffer(
            size_t index, bool render, bool updatePTS, int64_t timestampNs);

    status_t signalEndOfInputStream();

    status_t getFormat(JNIEnv *env, bool input, jobject *format) const;

    status_t getOutputFormat(JNIEnv *env, size_t index, jobject *format) const;

    status_t getBuffers(
            JNIEnv *env, bool input, jobjectArray *bufArray) const;

    status_t getBuffer(
            JNIEnv *env, bool input, size_t index, jobject *buf) const;

    status_t getImage(
            JNIEnv *env, bool input, size_t index, jobject *image) const;

    status_t getName(JNIEnv *env, jstring *name) const;

    status_t setParameters(const sp<AMessage> &params);

    void setVideoScalingMode(int mode);

protected:
    virtual ~JMediaCodec();

    virtual void onMessageReceived(const sp<AMessage> &msg);

private:
    enum {
        kWhatCallbackNotify,
        kWhatFrameRendered,
    };

    jclass mClass;
    jweak mObject;
    sp<Surface> mSurfaceTextureClient;

    // java objects cached
    jclass mByteBufferClass;
    jobject mNativeByteOrderObj;
    jmethodID mByteBufferOrderMethodID;
    jmethodID mByteBufferPositionMethodID;
    jmethodID mByteBufferLimitMethodID;
    jmethodID mByteBufferAsReadOnlyBufferMethodID;

    sp<ALooper> mLooper;
    sp<MediaCodec> mCodec;

    sp<AMessage> mCallbackNotification;
    sp<AMessage> mOnFrameRenderedNotification;

    status_t mInitStatus;

    status_t createByteBufferFromABuffer(
            JNIEnv *env, bool readOnly, bool clearBuffer, const sp<ABuffer> &buffer,
            jobject *buf) const;

    void cacheJavaObjects(JNIEnv *env);
    void deleteJavaObjects(JNIEnv *env);
    void handleCallback(const sp<AMessage> &msg);
    void handleFrameRenderedNotification(const sp<AMessage> &msg);

    DISALLOW_EVIL_CONSTRUCTORS(JMediaCodec);
};

}  // namespace android

#endif  // _ANDROID_MEDIA_MEDIACODEC_H_
