Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52ac301e authored by Gil Dobjanschi's avatar Gil Dobjanschi
Browse files

Added audio track playback API

Change-Id: I9884ab5d3a7d8d8310f4b4426e50b0496cbbd295
parent c0ed31d7
Loading
Loading
Loading
Loading
+173 −1
Original line number Diff line number Diff line
@@ -18,12 +18,17 @@ package android.media.videoeditor;

import java.io.IOException;

import android.util.Log;

/**
 * This class allows to handle an audio track. This audio file is mixed with the
 * audio samples of the MediaItems.
 * {@hide}
 */
public class AudioTrack {
    // Logging
    private static final String TAG = "AudioTrack";

    // Instance variables
    private final String mUniqueId;
    private final String mFilename;
@@ -47,6 +52,129 @@ public class AudioTrack {

    // The audio waveform filename
    private String mAudioWaveformFilename;
    private PlaybackThread mPlaybackThread;

    /**
     * This listener interface is used by the AudioTrack to emit playback
     * progress notifications.
     */
    public interface PlaybackProgressListener {
        /**
         * This method notifies the listener of the current time position while
         * playing an audio track
         *
         * @param audioTrack The audio track
         * @param timeMs The current playback position (expressed in milliseconds
         *            since the beginning of the audio track).
         * @param end true if the end of the audio track was reached
         */
        public void onProgress(AudioTrack audioTrack, long timeMs, boolean end);
    }

    /**
     * The playback thread
     */
    private class PlaybackThread extends Thread {
        // Instance variables
        private final PlaybackProgressListener mListener;
        private final long mFromMs, mToMs;
        private boolean mRun;
        private final boolean mLoop;
        private long mPositionMs;

        /**
         * Constructor
         *
         * @param fromMs The time (relative to the beginning of the audio track)
         *            at which the playback will start
         * @param toMs The time (relative to the beginning of the audio track) at
         *            which the playback will stop. Use -1 to play to the end of
         *            the audio track
         * @param loop true if the playback should be looped once it reaches the
         *            end
         * @param listener The listener which will be notified of the playback
         *            progress
         */
        public PlaybackThread(long fromMs, long toMs, boolean loop,
                PlaybackProgressListener listener) {
            mPositionMs = mFromMs = fromMs;
            if (toMs < 0) {
                mToMs = mDurationMs;
            } else {
                mToMs = toMs;
            }
            mLoop = loop;
            mListener = listener;
            mRun = true;
        }

        /*
         * {@inheritDoc}
         */
        @Override
        public void run() {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "===> PlaybackThread.run enter");
            }

            while (mRun) {
                try {
                    sleep(100);
                } catch (InterruptedException ex) {
                    break;
                }

                mPositionMs += 100;

                if (mPositionMs >= mToMs) {
                    if (!mLoop) {
                        if (mListener != null) {
                            mListener.onProgress(AudioTrack.this, mPositionMs, true);
                        }
                        if (Log.isLoggable(TAG, Log.DEBUG)) {
                            Log.d(TAG, "PlaybackThread.run playback complete");
                        }
                        break;
                    } else {
                        // Fire a notification for the end of the clip
                        if (mListener != null) {
                            mListener.onProgress(AudioTrack.this, mToMs, false);
                        }

                        // Rewind
                        mPositionMs = mFromMs;
                        if (mListener != null) {
                            mListener.onProgress(AudioTrack.this, mPositionMs, false);
                        }
                        if (Log.isLoggable(TAG, Log.DEBUG)) {
                            Log.d(TAG, "PlaybackThread.run playback complete");
                        }
                    }
                } else {
                    if (mListener != null) {
                        mListener.onProgress(AudioTrack.this, mPositionMs, false);
                    }
                }
            }
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "===> PlaybackThread.run exit");
            }
        }

        /**
         * Stop the playback
         *
         * @return The stop position
         */
        public long stopPlayback() {
            mRun = false;
            try {
                join();
            } catch (InterruptedException ex) {
            }
            return mPositionMs;
        }
    };

    /**
     * An object of this type cannot be instantiated by using the default
@@ -99,7 +227,7 @@ public class AudioTrack {
    }

    /**
     * @return The id of the media item
     * @return The id of the audio track
     */
    public String getId() {
        return mUniqueId;
@@ -311,6 +439,50 @@ public class AudioTrack {
        return mDuckingLowVolume;
    }

    /**
     * Start the playback of this audio track. This method does not block (does
     * not wait for the playback to complete).
     *
     * @param fromMs The time (relative to the beginning of the audio track) at
     *            which the playback will start
     * @param toMs The time (relative to the beginning of the audio track) at
     *            which the playback will stop. Use -1 to play to the end of the
     *            audio track
     * @param loop true if the playback should be looped once it reaches the end
     * @param listener The listener which will be notified of the playback
     *            progress
     * @throws IllegalArgumentException if fromMs or toMs is beyond the playback
     *             duration
     * @throws IllegalStateException if a playback, preview or an export is
     *             already in progress
     */
    public void startPlayback(long fromMs, long toMs, boolean loop,
            PlaybackProgressListener listener) {
        if (fromMs >= mDurationMs) {
            return;
        }
        mPlaybackThread = new PlaybackThread(fromMs, toMs, loop, listener);
        mPlaybackThread.start();
    }

    /**
     * Stop the audio track playback. This method blocks until the ongoing
     * playback is stopped.
     *
     * @return The accurate current time when stop is effective expressed in
     *         milliseconds
     */
    public long stopPlayback() {
        final long stopTimeMs;
        if (mPlaybackThread != null) {
            stopTimeMs = mPlaybackThread.stopPlayback();
            mPlaybackThread = null;
        } else {
            stopTimeMs = 0;
        }
        return stopTimeMs;
    }

    /**
     * This API allows to generate a file containing the sample volume levels of
     * this audio track object. This function may take significant time and is
+5 −8
Original line number Diff line number Diff line
@@ -537,16 +537,13 @@ public class VideoEditorTestImpl implements VideoEditor {
     * {@inheritDoc}
     */
    public AudioTrack getAudioTrack(String audioTrackId) {
        if (mPreviewThread != null) {
            throw new IllegalStateException("Previewing is in progress");
        for (AudioTrack at : mAudioTracks) {
            if (at.getId().equals(audioTrackId)) {
                return at;
            }

        final AudioTrack audioTrack = getAudioTrack(audioTrackId);
        if (audioTrack != null) {
            mAudioTracks.remove(audioTrack);
        }

        return audioTrack;
        return null;
    }

    /*