Merge "Added audio track playback API"
This commit is contained in:
committed by
Android (Google) Code Review
commit
e799720dd4
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user