Loading media/java/android/media/MediaPlayer2Impl.java +66 −15 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package android.media; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityThread; Loading @@ -26,7 +25,6 @@ import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; Loading @@ -48,17 +46,8 @@ import android.view.Surface; import android.view.SurfaceHolder; import android.widget.VideoView; import android.graphics.SurfaceTexture; import android.media.AudioManager; import android.media.MediaDrm; import android.media.MediaFormat; import android.media.MediaPlayer2; import android.media.MediaTimeProvider; import android.media.PlaybackParams; import android.media.SubtitleController; import android.media.SubtitleController.Anchor; import android.media.SubtitleData; import android.media.SubtitleTrack.RenderingWidget; import android.media.SyncParams; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; Loading @@ -74,16 +63,12 @@ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.AutoCloseable; import java.lang.Runnable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.net.CookieHandler; import java.net.CookieManager; import java.net.HttpCookie; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.URL; import java.nio.ByteOrder; import java.util.ArrayList; Loading Loading @@ -2190,6 +2175,13 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { private native final void native_setup(Object mediaplayer2_this); private native final void native_finalize(); private static native final void native_stream_event_onTearDown( long nativeCallbackPtr, long userDataPtr); private static native final void native_stream_event_onStreamPresentationEnd( long nativeCallbackPtr, long userDataPtr); private static native final void native_stream_event_onStreamDataRequest( long jAudioTrackPtr, long nativeCallbackPtr, long userDataPtr); /** * Class for MediaPlayer2 to return each audio/video/subtitle track's metadata. * Loading Loading @@ -4228,6 +4220,65 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } // Called from the native side @SuppressWarnings("unused") private static boolean setAudioOutputDeviceById(AudioTrack track, int deviceId) { if (track == null) { return false; } if (deviceId == 0) { // Use default routing. track.setPreferredDevice(null); return true; } // TODO: Unhide AudioManager.getDevicesStatic. AudioDeviceInfo[] outputDevices = AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS); boolean success = false; for (AudioDeviceInfo device : outputDevices) { if (device.getId() == deviceId) { track.setPreferredDevice(device); success = true; break; } } return success; } // Instantiated from the native side @SuppressWarnings("unused") private static class StreamEventCallback extends AudioTrack.StreamEventCallback { public long mJAudioTrackPtr; public long mNativeCallbackPtr; public long mUserDataPtr; public StreamEventCallback(long jAudioTrackPtr, long nativeCallbackPtr, long userDataPtr) { super(); mJAudioTrackPtr = jAudioTrackPtr; mNativeCallbackPtr = nativeCallbackPtr; mUserDataPtr = userDataPtr; } @Override public void onTearDown(AudioTrack track) { native_stream_event_onTearDown(mNativeCallbackPtr, mUserDataPtr); } @Override public void onStreamPresentationEnd(AudioTrack track) { native_stream_event_onStreamPresentationEnd(mNativeCallbackPtr, mUserDataPtr); } @Override public void onStreamDataRequest(AudioTrack track) { native_stream_event_onStreamDataRequest( mJAudioTrackPtr, mNativeCallbackPtr, mUserDataPtr); } } private class ProvisioningThread extends Thread { public static final int TIMEOUT_MS = 60000; Loading media/jni/android_media_MediaPlayer2.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include <media/NdkWrapper.h> #include <media/stagefright/Utils.h> #include <media/stagefright/foundation/ByteUtils.h> // for FOURCC definition #include <mediaplayer2/JAudioTrack.h> #include <mediaplayer2/mediaplayer2.h> #include <stdio.h> #include <assert.h> Loading Loading @@ -1387,6 +1388,65 @@ static void android_media_MediaPlayer2_enableDeviceCallback( // AudioRouting end // ---------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////////////// // AudioTrack.StreamEventCallback begin static void android_media_MediaPlayer2_native_on_tear_down(JNIEnv *env __unused, jobject thiz __unused, jlong callbackPtr, jlong userDataPtr) { JAudioTrack::callback_t callback = (JAudioTrack::callback_t) callbackPtr; if (callback != NULL) { callback(JAudioTrack::EVENT_NEW_IAUDIOTRACK, (void *) userDataPtr, NULL); } } static void android_media_MediaPlayer2_native_on_stream_presentation_end(JNIEnv *env __unused, jobject thiz __unused, jlong callbackPtr, jlong userDataPtr) { JAudioTrack::callback_t callback = (JAudioTrack::callback_t) callbackPtr; if (callback != NULL) { callback(JAudioTrack::EVENT_STREAM_END, (void *) userDataPtr, NULL); } } static void android_media_MediaPlayer2_native_on_stream_data_request(JNIEnv *env __unused, jobject thiz __unused, jlong jAudioTrackPtr, jlong callbackPtr, jlong userDataPtr) { JAudioTrack::callback_t callback = (JAudioTrack::callback_t) callbackPtr; JAudioTrack* track = (JAudioTrack *) jAudioTrackPtr; if (callback != NULL && track != NULL) { JAudioTrack::Buffer* buffer = new JAudioTrack::Buffer(); size_t bufferSizeInFrames = track->frameCount(); audio_format_t format = track->format(); size_t bufferSizeInBytes; if (audio_has_proportional_frames(format)) { bufferSizeInBytes = bufferSizeInFrames * audio_bytes_per_sample(format) * track->channelCount(); } else { // See Javadoc of AudioTrack::getBufferSizeInFrames(). bufferSizeInBytes = bufferSizeInFrames; } uint8_t* byteBuffer = new uint8_t[bufferSizeInBytes]; buffer->mSize = bufferSizeInBytes; buffer->mData = (void *) byteBuffer; callback(JAudioTrack::EVENT_MORE_DATA, (void *) userDataPtr, buffer); if (buffer->mSize > 0 && buffer->mData == byteBuffer) { track->write(buffer->mData, buffer->mSize, true /* Blocking */); } delete[] byteBuffer; delete buffer; } } // AudioTrack.StreamEventCallback end // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { { "nativeSetDataSource", Loading Loading @@ -1443,6 +1503,11 @@ static const JNINativeMethod gMethods[] = { {"native_setOutputDevice", "(I)Z", (void *)android_media_MediaPlayer2_setOutputDevice}, {"native_getRoutedDeviceId", "()I", (void *)android_media_MediaPlayer2_getRoutedDeviceId}, {"native_enableDeviceCallback", "(Z)V", (void *)android_media_MediaPlayer2_enableDeviceCallback}, // StreamEventCallback for JAudioTrack {"native_stream_event_onTearDown", "(JJ)V", (void *)android_media_MediaPlayer2_native_on_tear_down}, {"native_stream_event_onStreamPresentationEnd", "(JJ)V", (void *)android_media_MediaPlayer2_native_on_stream_presentation_end}, {"native_stream_event_onStreamDataRequest", "(JJJ)V", (void *)android_media_MediaPlayer2_native_on_stream_data_request}, }; // This function only registers the native methods Loading Loading
media/java/android/media/MediaPlayer2Impl.java +66 −15 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package android.media; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityThread; Loading @@ -26,7 +25,6 @@ import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; Loading @@ -48,17 +46,8 @@ import android.view.Surface; import android.view.SurfaceHolder; import android.widget.VideoView; import android.graphics.SurfaceTexture; import android.media.AudioManager; import android.media.MediaDrm; import android.media.MediaFormat; import android.media.MediaPlayer2; import android.media.MediaTimeProvider; import android.media.PlaybackParams; import android.media.SubtitleController; import android.media.SubtitleController.Anchor; import android.media.SubtitleData; import android.media.SubtitleTrack.RenderingWidget; import android.media.SyncParams; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; Loading @@ -74,16 +63,12 @@ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.AutoCloseable; import java.lang.Runnable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.net.CookieHandler; import java.net.CookieManager; import java.net.HttpCookie; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.URL; import java.nio.ByteOrder; import java.util.ArrayList; Loading Loading @@ -2190,6 +2175,13 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { private native final void native_setup(Object mediaplayer2_this); private native final void native_finalize(); private static native final void native_stream_event_onTearDown( long nativeCallbackPtr, long userDataPtr); private static native final void native_stream_event_onStreamPresentationEnd( long nativeCallbackPtr, long userDataPtr); private static native final void native_stream_event_onStreamDataRequest( long jAudioTrackPtr, long nativeCallbackPtr, long userDataPtr); /** * Class for MediaPlayer2 to return each audio/video/subtitle track's metadata. * Loading Loading @@ -4228,6 +4220,65 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } // Called from the native side @SuppressWarnings("unused") private static boolean setAudioOutputDeviceById(AudioTrack track, int deviceId) { if (track == null) { return false; } if (deviceId == 0) { // Use default routing. track.setPreferredDevice(null); return true; } // TODO: Unhide AudioManager.getDevicesStatic. AudioDeviceInfo[] outputDevices = AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS); boolean success = false; for (AudioDeviceInfo device : outputDevices) { if (device.getId() == deviceId) { track.setPreferredDevice(device); success = true; break; } } return success; } // Instantiated from the native side @SuppressWarnings("unused") private static class StreamEventCallback extends AudioTrack.StreamEventCallback { public long mJAudioTrackPtr; public long mNativeCallbackPtr; public long mUserDataPtr; public StreamEventCallback(long jAudioTrackPtr, long nativeCallbackPtr, long userDataPtr) { super(); mJAudioTrackPtr = jAudioTrackPtr; mNativeCallbackPtr = nativeCallbackPtr; mUserDataPtr = userDataPtr; } @Override public void onTearDown(AudioTrack track) { native_stream_event_onTearDown(mNativeCallbackPtr, mUserDataPtr); } @Override public void onStreamPresentationEnd(AudioTrack track) { native_stream_event_onStreamPresentationEnd(mNativeCallbackPtr, mUserDataPtr); } @Override public void onStreamDataRequest(AudioTrack track) { native_stream_event_onStreamDataRequest( mJAudioTrackPtr, mNativeCallbackPtr, mUserDataPtr); } } private class ProvisioningThread extends Thread { public static final int TIMEOUT_MS = 60000; Loading
media/jni/android_media_MediaPlayer2.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include <media/NdkWrapper.h> #include <media/stagefright/Utils.h> #include <media/stagefright/foundation/ByteUtils.h> // for FOURCC definition #include <mediaplayer2/JAudioTrack.h> #include <mediaplayer2/mediaplayer2.h> #include <stdio.h> #include <assert.h> Loading Loading @@ -1387,6 +1388,65 @@ static void android_media_MediaPlayer2_enableDeviceCallback( // AudioRouting end // ---------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////////////// // AudioTrack.StreamEventCallback begin static void android_media_MediaPlayer2_native_on_tear_down(JNIEnv *env __unused, jobject thiz __unused, jlong callbackPtr, jlong userDataPtr) { JAudioTrack::callback_t callback = (JAudioTrack::callback_t) callbackPtr; if (callback != NULL) { callback(JAudioTrack::EVENT_NEW_IAUDIOTRACK, (void *) userDataPtr, NULL); } } static void android_media_MediaPlayer2_native_on_stream_presentation_end(JNIEnv *env __unused, jobject thiz __unused, jlong callbackPtr, jlong userDataPtr) { JAudioTrack::callback_t callback = (JAudioTrack::callback_t) callbackPtr; if (callback != NULL) { callback(JAudioTrack::EVENT_STREAM_END, (void *) userDataPtr, NULL); } } static void android_media_MediaPlayer2_native_on_stream_data_request(JNIEnv *env __unused, jobject thiz __unused, jlong jAudioTrackPtr, jlong callbackPtr, jlong userDataPtr) { JAudioTrack::callback_t callback = (JAudioTrack::callback_t) callbackPtr; JAudioTrack* track = (JAudioTrack *) jAudioTrackPtr; if (callback != NULL && track != NULL) { JAudioTrack::Buffer* buffer = new JAudioTrack::Buffer(); size_t bufferSizeInFrames = track->frameCount(); audio_format_t format = track->format(); size_t bufferSizeInBytes; if (audio_has_proportional_frames(format)) { bufferSizeInBytes = bufferSizeInFrames * audio_bytes_per_sample(format) * track->channelCount(); } else { // See Javadoc of AudioTrack::getBufferSizeInFrames(). bufferSizeInBytes = bufferSizeInFrames; } uint8_t* byteBuffer = new uint8_t[bufferSizeInBytes]; buffer->mSize = bufferSizeInBytes; buffer->mData = (void *) byteBuffer; callback(JAudioTrack::EVENT_MORE_DATA, (void *) userDataPtr, buffer); if (buffer->mSize > 0 && buffer->mData == byteBuffer) { track->write(buffer->mData, buffer->mSize, true /* Blocking */); } delete[] byteBuffer; delete buffer; } } // AudioTrack.StreamEventCallback end // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { { "nativeSetDataSource", Loading Loading @@ -1443,6 +1503,11 @@ static const JNINativeMethod gMethods[] = { {"native_setOutputDevice", "(I)Z", (void *)android_media_MediaPlayer2_setOutputDevice}, {"native_getRoutedDeviceId", "()I", (void *)android_media_MediaPlayer2_getRoutedDeviceId}, {"native_enableDeviceCallback", "(Z)V", (void *)android_media_MediaPlayer2_enableDeviceCallback}, // StreamEventCallback for JAudioTrack {"native_stream_event_onTearDown", "(JJ)V", (void *)android_media_MediaPlayer2_native_on_tear_down}, {"native_stream_event_onStreamPresentationEnd", "(JJ)V", (void *)android_media_MediaPlayer2_native_on_stream_presentation_end}, {"native_stream_event_onStreamDataRequest", "(JJJ)V", (void *)android_media_MediaPlayer2_native_on_stream_data_request}, }; // This function only registers the native methods Loading