/*
 * 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 android.compat.annotation.UnsupportedAppUsage;
import android.media.MediaCodec.BufferInfo;
import android.util.Log;

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


/**
 * 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();
        }
    }
}
