/*
 * Copyright (C) 2015 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.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.media.AudioTrack;
import android.media.PlaybackParams;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Surface;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit;
import java.util.LinkedList;
import java.util.List;

/**
 * MediaSync class can be used to synchronously play audio and video streams.
 * It can be used to play audio-only or video-only stream, too.
 *
 * <p>MediaSync is generally used like this:
 * <pre>
 * MediaSync sync = new MediaSync();
 * sync.setSurface(surface);
 * Surface inputSurface = sync.createInputSurface();
 * ...
 * // MediaCodec videoDecoder = ...;
 * videoDecoder.configure(format, inputSurface, ...);
 * ...
 * sync.setAudioTrack(audioTrack);
 * sync.setCallback(new MediaSync.Callback() {
 *     {@literal @Override}
 *     public void onAudioBufferConsumed(MediaSync sync, ByteBuffer audioBuffer, int bufferId) {
 *         ...
 *     }
 * }, null);
 * // This needs to be done since sync is paused on creation.
 * sync.setPlaybackParams(new PlaybackParams().setSpeed(1.f));
 *
 * for (;;) {
 *   ...
 *   // send video frames to surface for rendering, e.g., call
 *   // videoDecoder.releaseOutputBuffer(videoOutputBufferIx, videoPresentationTimeNs);
 *   // More details are available as below.
 *   ...
 *   sync.queueAudio(audioByteBuffer, bufferId, audioPresentationTimeUs); // non-blocking.
 *   // The audioByteBuffer and bufferId will be returned via callback.
 *   // More details are available as below.
 *   ...
 *     ...
 * }
 * sync.setPlaybackParams(new PlaybackParams().setSpeed(0.f));
 * sync.release();
 * sync = null;
 *
 * // The following code snippet illustrates how video/audio raw frames are created by
 * // MediaCodec's, how they are fed to MediaSync and how they are returned by MediaSync.
 * // This is the callback from MediaCodec.
 * onOutputBufferAvailable(MediaCodec codec, int bufferId, BufferInfo info) {
 *     // ...
 *     if (codec == videoDecoder) {
 *         // surface timestamp must contain media presentation time in nanoseconds.
 *         codec.releaseOutputBuffer(bufferId, 1000 * info.presentationTime);
 *     } else {
 *         ByteBuffer audioByteBuffer = codec.getOutputBuffer(bufferId);
 *         sync.queueAudio(audioByteBuffer, bufferId, info.presentationTime);
 *     }
 *     // ...
 * }
 *
 * // This is the callback from MediaSync.
 * onAudioBufferConsumed(MediaSync sync, ByteBuffer buffer, int bufferId) {
 *     // ...
 *     audioDecoder.releaseBuffer(bufferId, false);
 *     // ...
 * }
 *
 * </pre>
 *
 * The client needs to configure corresponding sink by setting the Surface and/or AudioTrack
 * based on the stream type it will play.
 * <p>
 * For video, the client needs to call {@link #createInputSurface} to obtain a surface on
 * which it will render video frames.
 * <p>
 * For audio, the client needs to set up audio track correctly, e.g., using {@link
 * AudioTrack#MODE_STREAM}. The audio buffers are sent to MediaSync directly via {@link
 * #queueAudio}, and are returned to the client via {@link Callback#onAudioBufferConsumed}
 * asynchronously. The client should not modify an audio buffer till it's returned.
 * <p>
 * The client can optionally pre-fill audio/video buffers by setting playback rate to 0.0,
 * and then feed audio/video buffers to corresponding components. This can reduce possible
 * initial underrun.
 * <p>
 */
public final class MediaSync {
    /**
     * MediaSync callback interface. Used to notify the user asynchronously
     * of various MediaSync events.
     */
    public static abstract class Callback {
        /**
         * Called when returning an audio buffer which has been consumed.
         *
         * @param sync The MediaSync object.
         * @param audioBuffer The returned audio buffer.
         * @param bufferId The ID associated with audioBuffer as passed into
         *     {@link MediaSync#queueAudio}.
         */
        public abstract void onAudioBufferConsumed(
                @NonNull MediaSync sync, @NonNull ByteBuffer audioBuffer, int bufferId);
    }

    /** Audio track failed.
     * @see android.media.MediaSync.OnErrorListener
     */
    public static final int MEDIASYNC_ERROR_AUDIOTRACK_FAIL = 1;

    /** The surface failed to handle video buffers.
     * @see android.media.MediaSync.OnErrorListener
     */
    public static final int MEDIASYNC_ERROR_SURFACE_FAIL = 2;

    /**
     * Interface definition of a callback to be invoked when there
     * has been an error during an asynchronous operation (other errors
     * will throw exceptions at method call time).
     */
    public interface OnErrorListener {
        /**
         * Called to indicate an error.
         *
         * @param sync The MediaSync the error pertains to
         * @param what The type of error that has occurred:
         * <ul>
         * <li>{@link #MEDIASYNC_ERROR_AUDIOTRACK_FAIL}
         * <li>{@link #MEDIASYNC_ERROR_SURFACE_FAIL}
         * </ul>
         * @param extra an extra code, specific to the error. Typically
         * implementation dependent.
         */
        void onError(@NonNull MediaSync sync, int what, int extra);
    }

    private static final String TAG = "MediaSync";

    private static final int EVENT_CALLBACK = 1;
    private static final int EVENT_SET_CALLBACK = 2;

    private static final int CB_RETURN_AUDIO_BUFFER = 1;

    private static class AudioBuffer {
        public ByteBuffer mByteBuffer;
        public int mBufferIndex;
        long mPresentationTimeUs;

        public AudioBuffer(@NonNull ByteBuffer byteBuffer, int bufferId,
                           long presentationTimeUs) {
            mByteBuffer = byteBuffer;
            mBufferIndex = bufferId;
            mPresentationTimeUs = presentationTimeUs;
        }
    }

    private final Object mCallbackLock = new Object();
    private Handler mCallbackHandler = null;
    private MediaSync.Callback mCallback = null;

    private final Object mOnErrorListenerLock = new Object();
    private Handler mOnErrorListenerHandler = null;
    private MediaSync.OnErrorListener mOnErrorListener = null;

    private Thread mAudioThread = null;
    // Created on mAudioThread when mAudioThread is started. When used on user thread, they should
    // be guarded by checking mAudioThread.
    private Handler mAudioHandler = null;
    private Looper mAudioLooper = null;

    private final Object mAudioLock = new Object();
    private AudioTrack mAudioTrack = null;
    private List<AudioBuffer> mAudioBuffers = new LinkedList<AudioBuffer>();
    // this is only used for paused/running decisions, so it is not affected by clock drift
    private float mPlaybackRate = 0.0f;

    private long mNativeContext;

    /**
     * Class constructor. On creation, MediaSync is paused, i.e., playback rate is 0.0f.
     */
    public MediaSync() {
        native_setup();
    }

    private native final void native_setup();

    @Override
    protected void finalize() {
        native_finalize();
    }

    private native final void native_finalize();

    /**
     * Make sure you call this when you're done to free up any opened
     * component instance instead of relying on the garbage collector
     * to do this for you at some point in the future.
     */
    public final void release() {
        returnAudioBuffers();
        if (mAudioThread != null) {
            if (mAudioLooper != null) {
                mAudioLooper.quit();
            }
        }
        setCallback(null, null);
        native_release();
    }

    private native final void native_release();

    /**
     * Sets an asynchronous callback for actionable MediaSync events.
     * <p>
     * This method can be called multiple times to update a previously set callback. If the
     * handler is changed, undelivered notifications scheduled for the old handler may be dropped.
     * <p>
     * <b>Do not call this inside callback.</b>
     *
     * @param cb The callback that will run. Use {@code null} to stop receiving callbacks.
     * @param handler The Handler that will run the callback. Use {@code null} to use MediaSync's
     *     internal handler if it exists.
     */
    public void setCallback(@Nullable /* MediaSync. */ Callback cb, @Nullable Handler handler) {
        synchronized(mCallbackLock) {
            if (handler != null) {
                mCallbackHandler = handler;
            } else {
                Looper looper;
                if ((looper = Looper.myLooper()) == null) {
                    looper = Looper.getMainLooper();
                }
                if (looper == null) {
                    mCallbackHandler = null;
                } else {
                    mCallbackHandler = new Handler(looper);
                }
            }

            mCallback = cb;
        }
    }

    /**
     * Sets an asynchronous callback for error events.
     * <p>
     * This method can be called multiple times to update a previously set listener. If the
     * handler is changed, undelivered notifications scheduled for the old handler may be dropped.
     * <p>
     * <b>Do not call this inside callback.</b>
     *
     * @param listener The callback that will run. Use {@code null} to stop receiving callbacks.
     * @param handler The Handler that will run the callback. Use {@code null} to use MediaSync's
     *     internal handler if it exists.
     */
    public void setOnErrorListener(@Nullable /* MediaSync. */ OnErrorListener listener,
            @Nullable Handler handler) {
        synchronized(mOnErrorListenerLock) {
            if (handler != null) {
                mOnErrorListenerHandler = handler;
            } else {
                Looper looper;
                if ((looper = Looper.myLooper()) == null) {
                    looper = Looper.getMainLooper();
                }
                if (looper == null) {
                    mOnErrorListenerHandler = null;
                } else {
                    mOnErrorListenerHandler = new Handler(looper);
                }
            }

            mOnErrorListener = listener;
        }
    }

    /**
     * Sets the output surface for MediaSync.
     * <p>
     * Currently, this is only supported in the Initialized state.
     *
     * @param surface Specify a surface on which to render the video data.
     * @throws IllegalArgumentException if the surface has been released, is invalid,
     *     or can not be connected.
     * @throws IllegalStateException if setting the surface is not supported, e.g.
     *     not in the Initialized state, or another surface has already been set.
     */
    public void setSurface(@Nullable Surface surface) {
        native_setSurface(surface);
    }

    private native final void native_setSurface(@Nullable Surface surface);

    /**
     * Sets the audio track for MediaSync.
     * <p>
     * Currently, this is only supported in the Initialized state.
     *
     * @param audioTrack Specify an AudioTrack through which to render the audio data.
     * @throws IllegalArgumentException if the audioTrack has been released, or is invalid.
     * @throws IllegalStateException if setting the audio track is not supported, e.g.
     *     not in the Initialized state, or another audio track has already been set.
     */
    public void setAudioTrack(@Nullable AudioTrack audioTrack) {
        native_setAudioTrack(audioTrack);
        mAudioTrack = audioTrack;
        if (audioTrack != null && mAudioThread == null) {
            createAudioThread();
        }
    }

    private native final void native_setAudioTrack(@Nullable AudioTrack audioTrack);

    /**
     * Requests a Surface to use as the input. This may only be called after
     * {@link #setSurface}.
     * <p>
     * The application is responsible for calling release() on the Surface when
     * done.
     * @throws IllegalStateException if not set, or another input surface has
     *     already been created.
     */
    @NonNull
    public native final Surface createInputSurface();

    /**
     * Sets playback rate using {@link PlaybackParams}.
     * <p>
     * When using MediaSync with {@link AudioTrack}, set playback params using this
     * call instead of calling it directly on the track, so that the sync is aware of
     * the params change.
     * <p>
     * This call also works if there is no audio track.
     *
     * @param params the playback params to use. {@link PlaybackParams#getSpeed
     *     Speed} is the ratio between desired playback rate and normal one. 1.0 means
     *     normal playback speed. 0.0 means pause. Value larger than 1.0 means faster playback,
     *     while value between 0.0 and 1.0 for slower playback. <b>Note:</b> the normal rate
     *     does not change as a result of this call. To restore the original rate at any time,
     *     use speed of 1.0.
     *
     * @throws IllegalStateException if the internal sync engine or the audio track has not
     *     been initialized.
     * @throws IllegalArgumentException if the params are not supported.
     */
    public void setPlaybackParams(@NonNull PlaybackParams params) {
        synchronized(mAudioLock) {
            mPlaybackRate = native_setPlaybackParams(params);;
        }
        if (mPlaybackRate != 0.0 && mAudioThread != null) {
            postRenderAudio(0);
        }
    }

    /**
     * Gets the playback rate using {@link PlaybackParams}.
     *
     * @return the playback rate being used.
     *
     * @throws IllegalStateException if the internal sync engine or the audio track has not
     *     been initialized.
     */
    @NonNull
    public native PlaybackParams getPlaybackParams();

    private native float native_setPlaybackParams(@NonNull PlaybackParams params);

    /**
     * Sets A/V sync mode.
     *
     * @param params the A/V sync params to apply
     *
     * @throws IllegalStateException if the internal player engine has not been
     * initialized.
     * @throws IllegalArgumentException if params are not supported.
     */
    public void setSyncParams(@NonNull SyncParams params) {
        synchronized(mAudioLock) {
            mPlaybackRate = native_setSyncParams(params);;
        }
        if (mPlaybackRate != 0.0 && mAudioThread != null) {
            postRenderAudio(0);
        }
    }

    private native float native_setSyncParams(@NonNull SyncParams params);

    /**
     * Gets the A/V sync mode.
     *
     * @return the A/V sync params
     *
     * @throws IllegalStateException if the internal player engine has not been
     * initialized.
     */
    @NonNull
    public native SyncParams getSyncParams();

    /**
     * Flushes all buffers from the sync object.
     * <p>
     * All pending unprocessed audio and video buffers are discarded. If an audio track was
     * configured, it is flushed and stopped. If a video output surface was configured, the
     * last frame queued to it is left on the frame. Queue a blank video frame to clear the
     * surface,
     * <p>
     * No callbacks are received for the flushed buffers.
     *
     * @throws IllegalStateException if the internal player engine has not been
     * initialized.
     */
    public void flush() {
        synchronized(mAudioLock) {
            mAudioBuffers.clear();
            mCallbackHandler.removeCallbacksAndMessages(null);
        }
        if (mAudioTrack != null) {
            mAudioTrack.pause();
            mAudioTrack.flush();
            // Call stop() to signal to the AudioSink to completely fill the
            // internal buffer before resuming playback.
            mAudioTrack.stop();
        }
        native_flush();
    }

    private native final void native_flush();

    /**
     * Get current playback position.
     * <p>
     * The MediaTimestamp represents how the media time correlates to the system time in
     * a linear fashion using an anchor and a clock rate. During regular playback, the media
     * time moves fairly constantly (though the anchor frame may be rebased to a current
     * system time, the linear correlation stays steady). Therefore, this method does not
     * need to be called often.
     * <p>
     * To help users get current playback position, this method always anchors the timestamp
     * to the current {@link System#nanoTime system time}, so
     * {@link MediaTimestamp#getAnchorMediaTimeUs} can be used as current playback position.
     *
     * @return a MediaTimestamp object if a timestamp is available, or {@code null} if no timestamp
     *         is available, e.g. because the media player has not been initialized.
     *
     * @see MediaTimestamp
     */
    @Nullable
    public MediaTimestamp getTimestamp()
    {
        try {
            // TODO: create the timestamp in native
            MediaTimestamp timestamp = new MediaTimestamp();
            if (native_getTimestamp(timestamp)) {
                return timestamp;
            } else {
                return null;
            }
        } catch (IllegalStateException e) {
            return null;
        }
    }

    private native final boolean native_getTimestamp(@NonNull MediaTimestamp timestamp);

    /**
     * Queues the audio data asynchronously for playback (AudioTrack must be in streaming mode).
     * If the audio track was flushed as a result of {@link #flush}, it will be restarted.
     * @param audioData the buffer that holds the data to play. This buffer will be returned
     *     to the client via registered callback.
     * @param bufferId an integer used to identify audioData. It will be returned to
     *     the client along with audioData. This helps applications to keep track of audioData,
     *     e.g., it can be used to store the output buffer index used by the audio codec.
     * @param presentationTimeUs the presentation timestamp in microseconds for the first frame
     *     in the buffer.
     * @throws IllegalStateException if audio track is not set or internal configureation
     *     has not been done correctly.
     */
    public void queueAudio(
            @NonNull ByteBuffer audioData, int bufferId, long presentationTimeUs) {
        if (mAudioTrack == null || mAudioThread == null) {
            throw new IllegalStateException(
                    "AudioTrack is NOT set or audio thread is not created");
        }

        synchronized(mAudioLock) {
            mAudioBuffers.add(new AudioBuffer(audioData, bufferId, presentationTimeUs));
        }

        if (mPlaybackRate != 0.0) {
            postRenderAudio(0);
        }
    }

    // When called on user thread, make sure to check mAudioThread != null.
    private void postRenderAudio(long delayMillis) {
        mAudioHandler.postDelayed(new Runnable() {
            public void run() {
                synchronized(mAudioLock) {
                    if (mPlaybackRate == 0.0) {
                        return;
                    }

                    if (mAudioBuffers.isEmpty()) {
                        return;
                    }

                    AudioBuffer audioBuffer = mAudioBuffers.get(0);
                    int size = audioBuffer.mByteBuffer.remaining();
                    // restart audio track after flush
                    if (size > 0 && mAudioTrack.getPlayState() != AudioTrack.PLAYSTATE_PLAYING) {
                        try {
                            mAudioTrack.play();
                        } catch (IllegalStateException e) {
                            Log.w(TAG, "could not start audio track");
                        }
                    }
                    int sizeWritten = mAudioTrack.write(
                            audioBuffer.mByteBuffer,
                            size,
                            AudioTrack.WRITE_NON_BLOCKING);
                    if (sizeWritten > 0) {
                        if (audioBuffer.mPresentationTimeUs != -1) {
                            native_updateQueuedAudioData(
                                    size, audioBuffer.mPresentationTimeUs);
                            audioBuffer.mPresentationTimeUs = -1;
                        }

                        if (sizeWritten == size) {
                            postReturnByteBuffer(audioBuffer);
                            mAudioBuffers.remove(0);
                            if (!mAudioBuffers.isEmpty()) {
                                postRenderAudio(0);
                            }
                            return;
                        }
                    }
                    long pendingTimeMs = TimeUnit.MICROSECONDS.toMillis(
                            native_getPlayTimeForPendingAudioFrames());
                    postRenderAudio(pendingTimeMs / 2);
                }
            }
        }, delayMillis);
    }

    private native final void native_updateQueuedAudioData(
            int sizeInBytes, long presentationTimeUs);

    private native final long native_getPlayTimeForPendingAudioFrames();

    private final void postReturnByteBuffer(@NonNull final AudioBuffer audioBuffer) {
        synchronized(mCallbackLock) {
            if (mCallbackHandler != null) {
                final MediaSync sync = this;
                mCallbackHandler.post(new Runnable() {
                    public void run() {
                        Callback callback;
                        synchronized(mCallbackLock) {
                            callback = mCallback;
                            if (mCallbackHandler == null
                                    || mCallbackHandler.getLooper().getThread()
                                            != Thread.currentThread()) {
                                // callback handler has been changed.
                                return;
                            }
                        }
                        if (callback != null) {
                            callback.onAudioBufferConsumed(sync, audioBuffer.mByteBuffer,
                                    audioBuffer.mBufferIndex);
                        }
                    }
                });
            }
        }
    }

    private final void returnAudioBuffers() {
        synchronized(mAudioLock) {
            for (AudioBuffer audioBuffer: mAudioBuffers) {
                postReturnByteBuffer(audioBuffer);
            }
            mAudioBuffers.clear();
        }
    }

    private void createAudioThread() {
        mAudioThread = new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                synchronized(mAudioLock) {
                    mAudioLooper = Looper.myLooper();
                    mAudioHandler = new Handler();
                    mAudioLock.notify();
                }
                Looper.loop();
            }
        };
        mAudioThread.start();

        synchronized(mAudioLock) {
            try {
                mAudioLock.wait();
            } catch(InterruptedException e) {
            }
        }
    }

    static {
        System.loadLibrary("media_jni");
        native_init();
    }

    private static native final void native_init();
}
