/*
**
** Copyright 2007, 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.
*/

#define LOG_TAG "AmrInputStream"
#include "utils/Log.h"

#include <media/mediarecorder.h>
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <utils/threads.h>

#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include "gsmamr_encoder_wrapper.h"


// ----------------------------------------------------------------------------

using namespace android;

// Corresponds to max bit rate of 12.2 kbps.
static const int aMaxOutputBufferSize = 32;

static const int SAMPLES_PER_FRAME = 8000 * 20 / 1000;


//
// helper function to throw an exception
//
static void throwException(JNIEnv *env, const char* ex, const char* fmt, int data) {
    if (jclass cls = env->FindClass(ex)) {
        char msg[1000];
        sprintf(msg, fmt, data);
        env->ThrowNew(cls, msg);
        env->DeleteLocalRef(cls);
    }
}

static jint android_media_AmrInputStream_GsmAmrEncoderNew
        (JNIEnv *env, jclass clazz) {
    CPvGsmAmrEncoder* gae = new CPvGsmAmrEncoder();
    if (gae == NULL) {
        throwException(env, "java/lang/IllegalStateException",
                "new CPvGsmAmrEncoder() failed", 0);
    }
    return (jint)gae;
}

static void android_media_AmrInputStream_GsmAmrEncoderInitialize
        (JNIEnv *env, jclass clazz, jint gae) {
    // set input parameters
    TEncodeProperties encodeProps;
    encodeProps.iInBitsPerSample = 16;
    encodeProps.iInSamplingRate = 8000;
    encodeProps.iInClockRate = 1000;
    encodeProps.iInNumChannels = 1;
    encodeProps.iInInterleaveMode = TEncodeProperties::EINTERLEAVE_LR;
    encodeProps.iMode = CPvGsmAmrEncoder::GSM_AMR_12_2;
    encodeProps.iBitStreamFormat = false;
    encodeProps.iAudioObjectType = 0;
    encodeProps.iOutSamplingRate = encodeProps.iInSamplingRate;
    encodeProps.iOutNumChannels = encodeProps.iInNumChannels;
    encodeProps.iOutClockRate = encodeProps.iInClockRate;

    if (int rtn = ((CPvGsmAmrEncoder*)gae)->
            InitializeEncoder(aMaxOutputBufferSize, &encodeProps)) {
        throwException(env, "java/lang/IllegalArgumentException",
                "CPvGsmAmrEncoder::InitializeEncoder failed %d", rtn);
    }
}

static jint android_media_AmrInputStream_GsmAmrEncoderEncode
        (JNIEnv *env, jclass clazz,
         jint gae, jbyteArray pcm, jint pcmOffset, jbyteArray amr, jint amrOffset) {

    // set up input stream
    jbyte inBuf[SAMPLES_PER_FRAME*2];
    TInputAudioStream in;
    in.iSampleBuffer = (uint8*)inBuf;
    env->GetByteArrayRegion(pcm, pcmOffset, sizeof(inBuf), inBuf);
    in.iSampleLength = sizeof(inBuf);
    in.iMode = CPvGsmAmrEncoder::GSM_AMR_12_2;
    in.iStartTime = 0;
    in.iStopTime = 0;

    // set up output stream
    jbyte outBuf[aMaxOutputBufferSize];
    int32 sampleFrameSize[1] = { 0 };
    TOutputAudioStream out;
    out.iBitStreamBuffer = (uint8*)outBuf;
    out.iNumSampleFrames = 0;
    out.iSampleFrameSize = sampleFrameSize;
    out.iStartTime = 0;
    out.iStopTime = 0;

    // encode
    if (int rtn = ((CPvGsmAmrEncoder*)gae)->Encode(in, out)) {
        throwException(env, "java/io/IOException", "CPvGsmAmrEncoder::Encode failed %d", rtn);
        return -1;
    }

    // validate one-frame assumption
    if (out.iNumSampleFrames != 1) {
        throwException(env, "java/io/IOException",
                "CPvGsmAmrEncoder::Encode more than one frame returned %d", out.iNumSampleFrames);
        return 0;
    }

    // copy result
    int length = out.iSampleFrameSize[0];

    // The 1st byte of PV AMR frames are WMF (Wireless Multimedia Forum)
    // bitpacked, i.e.;
    //    [P(4) + FT(4)]. Q=1 for good frame, P=padding bit, 0
    // Here we are converting the header to be as specified in Section 5.3 of
    // RFC 3267 (AMR storage format) i.e.
    //    [P(1) + FT(4) + Q(1) + P(2)].
    if (length > 0) {
      outBuf[0] = (outBuf[0] << 3) | 0x4;
    }

    env->SetByteArrayRegion(amr, amrOffset, length, outBuf);

    return length;
}

static void android_media_AmrInputStream_GsmAmrEncoderCleanup
        (JNIEnv *env, jclass clazz, jint gae) {
    if (int rtn = ((CPvGsmAmrEncoder*)gae)->CleanupEncoder()) {
        throwException(env, "java/lang/IllegalStateException",
                "CPvGsmAmrEncoder::CleanupEncoder failed %d", rtn);
    }
}

static void android_media_AmrInputStream_GsmAmrEncoderDelete
        (JNIEnv *env, jclass clazz, jint gae) {
    delete (CPvGsmAmrEncoder*)gae;
}

// ----------------------------------------------------------------------------

static JNINativeMethod gMethods[] = {
    {"GsmAmrEncoderNew",        "()I",        (void*)android_media_AmrInputStream_GsmAmrEncoderNew},
    {"GsmAmrEncoderInitialize", "(I)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderInitialize},
    {"GsmAmrEncoderEncode",     "(I[BI[BI)I", (void*)android_media_AmrInputStream_GsmAmrEncoderEncode},
    {"GsmAmrEncoderCleanup",    "(I)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderCleanup},
    {"GsmAmrEncoderDelete",     "(I)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderDelete},
};


int register_android_media_AmrInputStream(JNIEnv *env)
{
    const char* const kClassPathName = "android/media/AmrInputStream";

    return AndroidRuntime::registerNativeMethods(env,
            kClassPathName, gMethods, NELEM(gMethods));
}


