diff options
| -rw-r--r-- | media/java/android/media/MediaPlayer2.java | 20 | ||||
| -rw-r--r-- | media/java/android/media/MediaPlayer2Impl.java | 151 |
2 files changed, 103 insertions, 68 deletions
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java index 61c412dac185..bcff5bfa8428 100644 --- a/media/java/android/media/MediaPlayer2.java +++ b/media/java/android/media/MediaPlayer2.java @@ -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 @@ -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 @@ -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, diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java index d5dd46caca7b..95ba00fa617b 100644 --- a/media/java/android/media/MediaPlayer2Impl.java +++ b/media/java/android/media/MediaPlayer2Impl.java @@ -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(); } }); @@ -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(); } }); @@ -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 { @@ -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|. @@ -930,40 +970,48 @@ 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); + mCurrentSrcId = mNextSrcId; + mBufferedPercentageCurrent.set(mBufferedPercentageNext.get()); + mNextDSDs.remove(0); + mNextSrcId = mSrcIdGenerator++; // make it different from |mCurrentSrcId| + mBufferedPercentageNext.set(0); + mNextSourceState = NEXT_SOURCE_STATE_INIT; - if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) { - // Switch to next source only when it has been prepared. - mCurrentDSD = mNextDSDs.get(0); - mCurrentSrcId = mNextSrcId; - mBufferedPercentageCurrent.set(mBufferedPercentageNext.get()); - mNextDSDs.remove(0); - mNextSrcId = mSrcIdGenerator++; // make it different from |mCurrentSrcId| - mBufferedPercentageNext.set(0); - mNextSourceState = NEXT_SOURCE_STATE_INIT; + long srcId = mCurrentSrcId; + try { + nativePlayNextDataSource(srcId); + } catch (Exception e) { + Message msg2 = mTaskHandler.obtainMessage( + MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null); + mTaskHandler.handleMessage(msg2, srcId); + // Keep |mNextSourcePlayPending| + hasNextDSD = prepareNextDataSource(); + } + if (hasNextDSD) { + stayAwake(true); - long srcId = mCurrentSrcId; - try { - nativePlayNextDataSource(srcId); - } catch (Exception e) { - Message msg2 = mTaskHandler.obtainMessage( - MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null); - mTaskHandler.handleMessage(msg2, srcId); - // Keep |mNextSourcePlayPending| - prepareNextDataSource(); - return; + // Now a new current src is playing. + // Wait for MEDIA_INFO_DATA_SOURCE_START to prepare next source. + mNextSourcePlayPending = false; + } + } else if (mNextSourceState == NEXT_SOURCE_STATE_INIT) { + hasNextDSD = prepareNextDataSource(); } - stayAwake(true); + } + } - // Now a new current src is playing. - // Wait for MEDIA2_INFO_STARTED_AS_NEXT to prepare next source. - mNextSourcePlayPending = false; - } else { - if (mNextSourceState == NEXT_SOURCE_STATE_INIT) { - 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)); } } } @@ -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); @@ -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); @@ -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(); } @@ -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; } @@ -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 |