Loading media/java/android/media/MediaPlayer2.java +10 −10 Original line number Diff line number Diff line Loading @@ -1794,18 +1794,17 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener public @interface MediaError {} /* Do not change these values without updating their counterparts * in include/media/mediaplayer2.h! * in include/media/MediaPlayer2Types.h! */ /** Unspecified media player info. * @see android.media.MediaPlayer2.EventCallback#onInfo */ public static final int MEDIA_INFO_UNKNOWN = 1; /** The player switched to this datas source because it is the * next-to-be-played in the playlist. /** The player just started the playback of this datas source. * @see android.media.MediaPlayer2.EventCallback#onInfo */ public static final int MEDIA_INFO_STARTED_AS_NEXT = 2; public static final int MEDIA_INFO_DATA_SOURCE_START = 2; /** The player just pushed the very first video frame for rendering. * @see android.media.MediaPlayer2.EventCallback#onInfo Loading @@ -1820,12 +1819,13 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener /** The player just completed the playback of this data source. * @see android.media.MediaPlayer2.EventCallback#onInfo */ public static final int MEDIA_INFO_PLAYBACK_COMPLETE = 5; public static final int MEDIA_INFO_DATA_SOURCE_END = 5; /** The player just completed the playback of the full playlist. /** The player just completed the playback of all data sources set by {@link #setDataSource}, * {@link #setNextDataSource} and {@link #setNextDataSources}. * @see android.media.MediaPlayer2.EventCallback#onInfo */ public static final int MEDIA_INFO_PLAYLIST_END = 6; public static final int MEDIA_INFO_DATA_SOURCE_LIST_END = 6; /** The player just prepared a data source. * @see android.media.MediaPlayer2.EventCallback#onInfo Loading Loading @@ -1927,11 +1927,11 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener */ @IntDef(flag = false, prefix = "MEDIA_INFO", value = { MEDIA_INFO_UNKNOWN, MEDIA_INFO_STARTED_AS_NEXT, MEDIA_INFO_DATA_SOURCE_START, MEDIA_INFO_VIDEO_RENDERING_START, MEDIA_INFO_AUDIO_RENDERING_START, MEDIA_INFO_PLAYBACK_COMPLETE, MEDIA_INFO_PLAYLIST_END, MEDIA_INFO_DATA_SOURCE_END, MEDIA_INFO_DATA_SOURCE_LIST_END, MEDIA_INFO_PREPARED, MEDIA_INFO_VIDEO_TRACK_LAGGING, MEDIA_INFO_BUFFERING_START, Loading media/java/android/media/MediaPlayer2Impl.java +93 −58 Original line number Diff line number Diff line Loading @@ -210,6 +210,22 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override void process() { stayAwake(true); // TODO: remove this block when native code sends MEDIA_INFO_DATA_SOURCE_START // when pipeline is created. if (getState() == PLAYER_STATE_PREPARED) { final DataSourceDesc dsd; synchronized (mSrcLock) { dsd = mCurrentDSD; } synchronized (mEventCbLock) { for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { cb.first.execute(() -> cb.second.onInfo( MediaPlayer2Impl.this, dsd, MEDIA_INFO_DATA_SOURCE_START, 0)); } } } _start(); } }); Loading Loading @@ -246,6 +262,22 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override void process() { stayAwake(false); // TODO: remove this block when native code allows prepared -> pause // and sends MEDIA_INFO_DATA_SOURCE_START when pipeline is created. if (getState() == PLAYER_STATE_PREPARED) { final DataSourceDesc dsd; synchronized (mSrcLock) { dsd = mCurrentDSD; } synchronized (mEventCbLock) { for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { cb.first.execute(() -> cb.second.onInfo( MediaPlayer2Impl.this, dsd, MEDIA_INFO_DATA_SOURCE_START, 0)); } } } _pause(); } }); Loading Loading @@ -888,23 +920,30 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { private native void nativeHandleDataSourceCallback( boolean isCurrent, long srcId, Media2DataSource dataSource); /** * @return true if there is a next data source, false otherwise. */ // This function should be always called on |mHandlerThread|. private void prepareNextDataSource() { private boolean prepareNextDataSource() { if (Looper.myLooper() != mHandlerThread.getLooper()) { Log.e(TAG, "prepareNextDataSource: called on wrong looper"); } boolean hasNextDSD; synchronized (mSrcLock) { hasNextDSD = (mNextDSDs != null && !mNextDSDs.isEmpty()); } int state = getState(); if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) { // Current source has not been prepared yet. return; return hasNextDSD; } synchronized (mSrcLock) { if (mNextDSDs == null || mNextDSDs.isEmpty() || mNextSourceState != NEXT_SOURCE_STATE_INIT) { if (!hasNextDSD || mNextSourceState != NEXT_SOURCE_STATE_INIT) { // There is no next source or it's in preparing or prepared state. return; return hasNextDSD; } try { Loading @@ -919,9 +958,10 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { // make a new SrcId to obsolete notification for previous one. mNextSrcId = mSrcIdGenerator++; mNextSourceState = NEXT_SOURCE_STATE_INIT; prepareNextDataSource(); return prepareNextDataSource(); } } return hasNextDSD; } // This function should be always called on |mHandlerThread|. Loading @@ -930,11 +970,10 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { Log.e(TAG, "playNextDataSource: called on wrong looper"); } boolean hasNextDSD = false; synchronized (mSrcLock) { if (mNextDSDs == null || mNextDSDs.isEmpty()) { return; } if (mNextDSDs != null && !mNextDSDs.isEmpty()) { hasNextDSD = true; if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) { // Switch to next source only when it has been prepared. mCurrentDSD = mNextDSDs.get(0); Loading @@ -953,17 +992,26 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null); mTaskHandler.handleMessage(msg2, srcId); // Keep |mNextSourcePlayPending| prepareNextDataSource(); return; hasNextDSD = prepareNextDataSource(); } if (hasNextDSD) { stayAwake(true); // Now a new current src is playing. // Wait for MEDIA2_INFO_STARTED_AS_NEXT to prepare next source. // Wait for MEDIA_INFO_DATA_SOURCE_START to prepare next source. mNextSourcePlayPending = false; } else { if (mNextSourceState == NEXT_SOURCE_STATE_INIT) { prepareNextDataSource(); } } else if (mNextSourceState == NEXT_SOURCE_STATE_INIT) { hasNextDSD = prepareNextDataSource(); } } } if (!hasNextDSD) { synchronized (mEventCbLock) { for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { cb.first.execute(() -> cb.second.onInfo( MediaPlayer2Impl.this, null, MEDIA_INFO_DATA_SOURCE_LIST_END, 0)); } } } Loading Loading @@ -2767,7 +2815,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { synchronized (mEventCbLock) { for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { cb.first.execute(() -> cb.second.onInfo( mMediaPlayer, dsd, MEDIA_INFO_PLAYBACK_COMPLETE, 0)); mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0)); } } stayAwake(false); Loading Loading @@ -2869,7 +2917,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { cb.first.execute(() -> cb.second.onError( mMediaPlayer, dsd, what, extra)); cb.first.execute(() -> cb.second.onInfo( mMediaPlayer, dsd, MEDIA_INFO_PLAYBACK_COMPLETE, 0)); mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0)); } } stayAwake(false); Loading @@ -2878,8 +2926,15 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { case MEDIA_INFO: { synchronized (mEventCbLock) { for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { cb.first.execute(() -> cb.second.onInfo( mMediaPlayer, dsd, what, extra)); } } switch (msg.arg1) { case MEDIA_INFO_STARTED_AS_NEXT: case MEDIA_INFO_DATA_SOURCE_START: if (isCurrentSrcId) { prepareNextDataSource(); } Loading Loading @@ -2916,13 +2971,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } break; } synchronized (mEventCbLock) { for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { cb.first.execute(() -> cb.second.onInfo( mMediaPlayer, dsd, what, extra)); } } // No real default action so far. return; } Loading Loading @@ -3034,19 +3082,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } switch (what) { case MEDIA_INFO: if (arg1 == MEDIA_INFO_STARTED_AS_NEXT) { new Thread(new Runnable() { @Override public void run() { // this acquires the wakelock if needed, and sets the client side state mp.play(); } }).start(); Thread.yield(); } break; case MEDIA_DRM_INFO: // We need to derive mDrmInfoImpl before prepare() returns so processing it here // before the notification is sent to TaskHandler below. TaskHandler runs in the Loading Loading
media/java/android/media/MediaPlayer2.java +10 −10 Original line number Diff line number Diff line Loading @@ -1794,18 +1794,17 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener public @interface MediaError {} /* Do not change these values without updating their counterparts * in include/media/mediaplayer2.h! * in include/media/MediaPlayer2Types.h! */ /** Unspecified media player info. * @see android.media.MediaPlayer2.EventCallback#onInfo */ public static final int MEDIA_INFO_UNKNOWN = 1; /** The player switched to this datas source because it is the * next-to-be-played in the playlist. /** The player just started the playback of this datas source. * @see android.media.MediaPlayer2.EventCallback#onInfo */ public static final int MEDIA_INFO_STARTED_AS_NEXT = 2; public static final int MEDIA_INFO_DATA_SOURCE_START = 2; /** The player just pushed the very first video frame for rendering. * @see android.media.MediaPlayer2.EventCallback#onInfo Loading @@ -1820,12 +1819,13 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener /** The player just completed the playback of this data source. * @see android.media.MediaPlayer2.EventCallback#onInfo */ public static final int MEDIA_INFO_PLAYBACK_COMPLETE = 5; public static final int MEDIA_INFO_DATA_SOURCE_END = 5; /** The player just completed the playback of the full playlist. /** The player just completed the playback of all data sources set by {@link #setDataSource}, * {@link #setNextDataSource} and {@link #setNextDataSources}. * @see android.media.MediaPlayer2.EventCallback#onInfo */ public static final int MEDIA_INFO_PLAYLIST_END = 6; public static final int MEDIA_INFO_DATA_SOURCE_LIST_END = 6; /** The player just prepared a data source. * @see android.media.MediaPlayer2.EventCallback#onInfo Loading Loading @@ -1927,11 +1927,11 @@ public abstract class MediaPlayer2 implements SubtitleController.Listener */ @IntDef(flag = false, prefix = "MEDIA_INFO", value = { MEDIA_INFO_UNKNOWN, MEDIA_INFO_STARTED_AS_NEXT, MEDIA_INFO_DATA_SOURCE_START, MEDIA_INFO_VIDEO_RENDERING_START, MEDIA_INFO_AUDIO_RENDERING_START, MEDIA_INFO_PLAYBACK_COMPLETE, MEDIA_INFO_PLAYLIST_END, MEDIA_INFO_DATA_SOURCE_END, MEDIA_INFO_DATA_SOURCE_LIST_END, MEDIA_INFO_PREPARED, MEDIA_INFO_VIDEO_TRACK_LAGGING, MEDIA_INFO_BUFFERING_START, Loading
media/java/android/media/MediaPlayer2Impl.java +93 −58 Original line number Diff line number Diff line Loading @@ -210,6 +210,22 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override void process() { stayAwake(true); // TODO: remove this block when native code sends MEDIA_INFO_DATA_SOURCE_START // when pipeline is created. if (getState() == PLAYER_STATE_PREPARED) { final DataSourceDesc dsd; synchronized (mSrcLock) { dsd = mCurrentDSD; } synchronized (mEventCbLock) { for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { cb.first.execute(() -> cb.second.onInfo( MediaPlayer2Impl.this, dsd, MEDIA_INFO_DATA_SOURCE_START, 0)); } } } _start(); } }); Loading Loading @@ -246,6 +262,22 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override void process() { stayAwake(false); // TODO: remove this block when native code allows prepared -> pause // and sends MEDIA_INFO_DATA_SOURCE_START when pipeline is created. if (getState() == PLAYER_STATE_PREPARED) { final DataSourceDesc dsd; synchronized (mSrcLock) { dsd = mCurrentDSD; } synchronized (mEventCbLock) { for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { cb.first.execute(() -> cb.second.onInfo( MediaPlayer2Impl.this, dsd, MEDIA_INFO_DATA_SOURCE_START, 0)); } } } _pause(); } }); Loading Loading @@ -888,23 +920,30 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { private native void nativeHandleDataSourceCallback( boolean isCurrent, long srcId, Media2DataSource dataSource); /** * @return true if there is a next data source, false otherwise. */ // This function should be always called on |mHandlerThread|. private void prepareNextDataSource() { private boolean prepareNextDataSource() { if (Looper.myLooper() != mHandlerThread.getLooper()) { Log.e(TAG, "prepareNextDataSource: called on wrong looper"); } boolean hasNextDSD; synchronized (mSrcLock) { hasNextDSD = (mNextDSDs != null && !mNextDSDs.isEmpty()); } int state = getState(); if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) { // Current source has not been prepared yet. return; return hasNextDSD; } synchronized (mSrcLock) { if (mNextDSDs == null || mNextDSDs.isEmpty() || mNextSourceState != NEXT_SOURCE_STATE_INIT) { if (!hasNextDSD || mNextSourceState != NEXT_SOURCE_STATE_INIT) { // There is no next source or it's in preparing or prepared state. return; return hasNextDSD; } try { Loading @@ -919,9 +958,10 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { // make a new SrcId to obsolete notification for previous one. mNextSrcId = mSrcIdGenerator++; mNextSourceState = NEXT_SOURCE_STATE_INIT; prepareNextDataSource(); return prepareNextDataSource(); } } return hasNextDSD; } // This function should be always called on |mHandlerThread|. Loading @@ -930,11 +970,10 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { Log.e(TAG, "playNextDataSource: called on wrong looper"); } boolean hasNextDSD = false; synchronized (mSrcLock) { if (mNextDSDs == null || mNextDSDs.isEmpty()) { return; } if (mNextDSDs != null && !mNextDSDs.isEmpty()) { hasNextDSD = true; if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) { // Switch to next source only when it has been prepared. mCurrentDSD = mNextDSDs.get(0); Loading @@ -953,17 +992,26 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null); mTaskHandler.handleMessage(msg2, srcId); // Keep |mNextSourcePlayPending| prepareNextDataSource(); return; hasNextDSD = prepareNextDataSource(); } if (hasNextDSD) { stayAwake(true); // Now a new current src is playing. // Wait for MEDIA2_INFO_STARTED_AS_NEXT to prepare next source. // Wait for MEDIA_INFO_DATA_SOURCE_START to prepare next source. mNextSourcePlayPending = false; } else { if (mNextSourceState == NEXT_SOURCE_STATE_INIT) { prepareNextDataSource(); } } else if (mNextSourceState == NEXT_SOURCE_STATE_INIT) { hasNextDSD = prepareNextDataSource(); } } } if (!hasNextDSD) { synchronized (mEventCbLock) { for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { cb.first.execute(() -> cb.second.onInfo( MediaPlayer2Impl.this, null, MEDIA_INFO_DATA_SOURCE_LIST_END, 0)); } } } Loading Loading @@ -2767,7 +2815,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { synchronized (mEventCbLock) { for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { cb.first.execute(() -> cb.second.onInfo( mMediaPlayer, dsd, MEDIA_INFO_PLAYBACK_COMPLETE, 0)); mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0)); } } stayAwake(false); Loading Loading @@ -2869,7 +2917,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { cb.first.execute(() -> cb.second.onError( mMediaPlayer, dsd, what, extra)); cb.first.execute(() -> cb.second.onInfo( mMediaPlayer, dsd, MEDIA_INFO_PLAYBACK_COMPLETE, 0)); mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0)); } } stayAwake(false); Loading @@ -2878,8 +2926,15 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { case MEDIA_INFO: { synchronized (mEventCbLock) { for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { cb.first.execute(() -> cb.second.onInfo( mMediaPlayer, dsd, what, extra)); } } switch (msg.arg1) { case MEDIA_INFO_STARTED_AS_NEXT: case MEDIA_INFO_DATA_SOURCE_START: if (isCurrentSrcId) { prepareNextDataSource(); } Loading Loading @@ -2916,13 +2971,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } break; } synchronized (mEventCbLock) { for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) { cb.first.execute(() -> cb.second.onInfo( mMediaPlayer, dsd, what, extra)); } } // No real default action so far. return; } Loading Loading @@ -3034,19 +3082,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } switch (what) { case MEDIA_INFO: if (arg1 == MEDIA_INFO_STARTED_AS_NEXT) { new Thread(new Runnable() { @Override public void run() { // this acquires the wakelock if needed, and sets the client side state mp.play(); } }).start(); Thread.yield(); } break; case MEDIA_DRM_INFO: // We need to derive mDrmInfoImpl before prepare() returns so processing it here // before the notification is sent to TaskHandler below. TaskHandler runs in the Loading