/*
 * Copyright (C) 2008 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.
 */

package android.media;

import java.io.InputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

import android.annotation.UnsupportedAppUsage;
import android.media.MediaCodec.BufferInfo;
import android.util.Log;


/**
 * DO NOT USE
 * @hide
 */
public final class AmrInputStream extends InputStream {
    private final static String TAG = "AmrInputStream";

    // frame is 20 msec at 8.000 khz
    private final static int SAMPLES_PER_FRAME = 8000 * 20 / 1000;

    MediaCodec mCodec;
    BufferInfo mInfo;
    boolean mSawOutputEOS;
    boolean mSawInputEOS;

    // pcm input stream
    private InputStream mInputStream;

    // result amr stream
    private final byte[] mBuf = new byte[SAMPLES_PER_FRAME * 2];
    private int mBufIn = 0;
    private int mBufOut = 0;

    // helper for bytewise read()
    private byte[] mOneByte = new byte[1];

    /**
     * DO NOT USE - use MediaCodec instead
     */
    @UnsupportedAppUsage
    public AmrInputStream(InputStream inputStream) {
        Log.w(TAG, "@@@@ AmrInputStream is not a public API @@@@");
        mInputStream = inputStream;

        MediaFormat format  = new MediaFormat();
        format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AMR_NB);
        format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 8000);
        format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
        format.setInteger(MediaFormat.KEY_BIT_RATE, 12200);

        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
        String name = mcl.findEncoderForFormat(format);
        if (name != null) {
            try {
                mCodec = MediaCodec.createByCodecName(name);
                mCodec.configure(format,
                        null /* surface */,
                        null /* crypto */,
                        MediaCodec.CONFIGURE_FLAG_ENCODE);
                mCodec.start();
            } catch (IOException e) {
                if (mCodec != null) {
                    mCodec.release();
                }
                mCodec = null;
            }
        }
        mInfo = new BufferInfo();
    }

    /**
     * DO NOT USE
     */
    @Override
    public int read() throws IOException {
        int rtn = read(mOneByte, 0, 1);
        return rtn == 1 ? (0xff & mOneByte[0]) : -1;
    }

    /**
     * DO NOT USE
     */
    @Override
    public int read(byte[] b) throws IOException {
        return read(b, 0, b.length);
    }

    /**
     * DO NOT USE
     */
    @Override
    public int read(byte[] b, int offset, int length) throws IOException {
        if (mCodec == null) {
            throw new IllegalStateException("not open");
        }

        if (mBufOut >= mBufIn && !mSawOutputEOS) {
            // no data left in buffer, refill it
            mBufOut = 0;
            mBufIn = 0;

            // first push as much data into the encoder as possible
            while (!mSawInputEOS) {
                int index = mCodec.dequeueInputBuffer(0);
                if (index < 0) {
                    // no input buffer currently available
                    break;
                } else {
                    int numRead;
                    for (numRead = 0; numRead < SAMPLES_PER_FRAME * 2; ) {
                        int n = mInputStream.read(mBuf, numRead, SAMPLES_PER_FRAME * 2 - numRead);
                        if (n == -1) {
                            mSawInputEOS = true;
                            break;
                        }
                        numRead += n;
                    }
                    ByteBuffer buf = mCodec.getInputBuffer(index);
                    buf.put(mBuf, 0, numRead);
                    mCodec.queueInputBuffer(index,
                            0 /* offset */,
                            numRead,
                            0 /* presentationTimeUs */,
                            mSawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0 /* flags */);
                }
            }

            // now read encoded data from the encoder
            int index = mCodec.dequeueOutputBuffer(mInfo, 0);
            if (index >= 0) {
                mBufIn = mInfo.size;
                ByteBuffer out = mCodec.getOutputBuffer(index);
                out.get(mBuf, 0 /* offset */, mBufIn /* length */);
                mCodec.releaseOutputBuffer(index,  false /* render */);
                if ((mInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                    mSawOutputEOS = true;
                }
            }
        }

        if (mBufOut < mBufIn) {
            // there is data in the buffer
            if (length > mBufIn - mBufOut) {
                length = mBufIn - mBufOut;
            }
            System.arraycopy(mBuf, mBufOut, b, offset, length);
            mBufOut += length;
            return length;
        }

        if (mSawInputEOS && mSawOutputEOS) {
            // no more data available in buffer, codec or input stream
            return -1;
        }

        // caller should try again
        return 0;
    }

    @Override
    public void close() throws IOException {
        try {
            if (mInputStream != null) {
                mInputStream.close();
            }
        } finally {
            mInputStream = null;
            try {
                if (mCodec != null) {
                    mCodec.release();
                }
            } finally {
                mCodec = null;
            }
        }
    }

    @Override
    protected void finalize() throws Throwable {
        if (mCodec != null) {
            Log.w(TAG, "AmrInputStream wasn't closed");
            mCodec.release();
        }
    }
}
