diff options
| -rw-r--r-- | media/java/android/media/MediaPlayer2Impl.java | 225 |
1 files changed, 123 insertions, 102 deletions
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java index 35346369ed8e..4ac0188581e8 100644 --- a/media/java/android/media/MediaPlayer2Impl.java +++ b/media/java/android/media/MediaPlayer2Impl.java @@ -56,15 +56,20 @@ import java.net.URL; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Queue; import java.util.UUID; +import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; /** * @hide @@ -94,17 +99,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { private final Object mSrcLock = new Object(); //--- guarded by |mSrcLock| start - private long mSrcIdGenerator = 0; - private DataSourceDesc mCurrentDSD; - private long mCurrentSrcId = mSrcIdGenerator++; - private List<DataSourceDesc> mNextDSDs; - private long mNextSrcId = mSrcIdGenerator++; - private int mNextSourceState = NEXT_SOURCE_STATE_INIT; - private boolean mNextSourcePlayPending = false; + private SourceInfo mCurrentSourceInfo; + private final Queue<SourceInfo> mNextSourceInfos = new ConcurrentLinkedQueue<>(); //--- guarded by |mSrcLock| end + private final AtomicLong mSrcIdGenerator = new AtomicLong(0); - private AtomicInteger mBufferedPercentageCurrent = new AtomicInteger(0); - private AtomicInteger mBufferedPercentageNext = new AtomicInteger(0); private volatile float mVolume = 1.0f; private VideoSize mVideoSize = new VideoSize(0, 0); @@ -227,7 +226,15 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override public long getBufferedPosition() { // Use cached buffered percent for now. - return getDuration() * mBufferedPercentageCurrent.get() / 100; + int bufferedPercentage; + synchronized (mSrcLock) { + if (mCurrentSourceInfo == null) { + bufferedPercentage = 0; + } else { + bufferedPercentage = mCurrentSourceInfo.mBufferedPercentage.get(); + } + } + return getDuration() * bufferedPercentage / 100; } @Override @@ -268,9 +275,8 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } synchronized (mSrcLock) { - mCurrentDSD = dsd; - mCurrentSrcId = mSrcIdGenerator++; - handleDataSource(true /* isCurrent */, dsd, mCurrentSrcId); + mCurrentSourceInfo = new SourceInfo(dsd); + handleDataSource(true /* isCurrent */, dsd, mCurrentSourceInfo.mId); } } }); @@ -283,10 +289,8 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { void process() { checkArgument(dsd != null, "the DataSourceDesc cannot be null"); synchronized (mSrcLock) { - mNextDSDs = new ArrayList<DataSourceDesc>(1); - mNextDSDs.add(dsd); - mNextSrcId = mSrcIdGenerator++; - mNextSourceState = NEXT_SOURCE_STATE_INIT; + mNextSourceInfos.clear(); + mNextSourceInfos.add(new SourceInfo(dsd)); } prepareNextDataSource(); } @@ -309,9 +313,10 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } synchronized (mSrcLock) { - mNextDSDs = new ArrayList(dsds); - mNextSrcId = mSrcIdGenerator++; - mNextSourceState = NEXT_SOURCE_STATE_INIT; + mNextSourceInfos.clear(); + for (DataSourceDesc dsd : dsds) { + mNextSourceInfos.add(new SourceInfo(dsd)); + } } prepareNextDataSource(); } @@ -323,22 +328,15 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { return addTask(new Task(CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES, false) { @Override void process() { - synchronized (mSrcLock) { - if (mNextDSDs != null) { - mNextDSDs.clear(); - mNextDSDs = null; - } - mNextSrcId = mSrcIdGenerator++; - mNextSourceState = NEXT_SOURCE_STATE_INIT; - } + mNextSourceInfos.clear(); } }); } @Override - public @NonNull DataSourceDesc getCurrentDataSource() { + public DataSourceDesc getCurrentDataSource() { synchronized (mSrcLock) { - return mCurrentDSD; + return mCurrentSourceInfo == null ? null : mCurrentSourceInfo.mDSD; } } @@ -707,34 +705,29 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } 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 hasNextDSD; - } - synchronized (mSrcLock) { - if (!hasNextDSD || mNextSourceState != NEXT_SOURCE_STATE_INIT) { + hasNextDSD = !mNextSourceInfos.isEmpty(); + if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) { + // Current source has not been prepared yet. + return hasNextDSD; + } + + SourceInfo nextSource = mNextSourceInfos.peek(); + if (!hasNextDSD || nextSource.mStateAsNextSource != NEXT_SOURCE_STATE_INIT) { // There is no next source or it's in preparing or prepared state. return hasNextDSD; } try { - mNextSourceState = NEXT_SOURCE_STATE_PREPARING; - handleDataSource(false /* isCurrent */, mNextDSDs.get(0), mNextSrcId); + nextSource.mStateAsNextSource = NEXT_SOURCE_STATE_PREPARING; + handleDataSource(false /* isCurrent */, nextSource.mDSD, nextSource.mId); } catch (Exception e) { Message msg = mTaskHandler.obtainMessage( MEDIA_ERROR, MEDIA_ERROR_IO, MEDIA_ERROR_UNKNOWN, null); - mTaskHandler.handleMessage(msg, mNextSrcId); + mTaskHandler.handleMessage(msg, nextSource.mId); - mNextDSDs.remove(0); - // make a new SrcId to obsolete notification for previous one. - mNextSrcId = mSrcIdGenerator++; - mNextSourceState = NEXT_SOURCE_STATE_INIT; + mNextSourceInfos.poll(); return prepareNextDataSource(); } } @@ -749,19 +742,14 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { boolean hasNextDSD = false; synchronized (mSrcLock) { - if (mNextDSDs != null && !mNextDSDs.isEmpty()) { + if (!mNextSourceInfos.isEmpty()) { hasNextDSD = true; - if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) { + SourceInfo nextSourceInfo = mNextSourceInfos.peek(); + if (nextSourceInfo.mStateAsNextSource == 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; + mCurrentSourceInfo = mNextSourceInfos.poll(); + + long srcId = mCurrentSourceInfo.mId; try { nativePlayNextDataSource(srcId); } catch (Exception e) { @@ -776,9 +764,8 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { // 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) { + } else if (nextSourceInfo.mStateAsNextSource == NEXT_SOURCE_STATE_INIT) { hasNextDSD = prepareNextDataSource(); } } @@ -1073,12 +1060,8 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { mDrmEventCallbackRecords.clear(); } synchronized (mSrcLock) { - if (mNextDSDs != null) { - mNextDSDs.clear(); - mNextDSDs = null; - } - mNextSrcId = mSrcIdGenerator++; - mNextSourceState = NEXT_SOURCE_STATE_INIT; + mCurrentSourceInfo = null; + mNextSourceInfos.clear(); } synchronized (mTaskLock) { @@ -1532,20 +1515,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { final int what = msg.arg1; final int extra = msg.arg2; - final DataSourceDesc dsd; - boolean isCurrentSrcId = false; - boolean isNextSrcId = false; - synchronized (mSrcLock) { - if (srcId == mCurrentSrcId) { - dsd = mCurrentDSD; - isCurrentSrcId = true; - } else if (mNextDSDs != null && !mNextDSDs.isEmpty() && srcId == mNextSrcId) { - dsd = mNextDSDs.get(0); - isNextSrcId = true; - } else { - return; - } + final SourceInfo sourceInfo = getSourceInfoById(srcId); + if (sourceInfo == null) { + return; } + final DataSourceDesc dsd = sourceInfo.mDSD; switch(msg.what) { case MEDIA_PREPARED: @@ -1561,14 +1535,16 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } synchronized (mSrcLock) { + SourceInfo nextSourceInfo = mNextSourceInfos.peek(); Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId - + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId); + + ", curSrc=" + mCurrentSourceInfo + + ", nextSrc=" + nextSourceInfo); - if (isCurrentSrcId) { + if (isCurrentSource(srcId)) { prepareNextDataSource(); - } else if (isNextSrcId) { - mNextSourceState = NEXT_SOURCE_STATE_PREPARED; - if (mNextSourcePlayPending) { + } else if (isNextSource(srcId)) { + nextSourceInfo.mStateAsNextSource = NEXT_SOURCE_STATE_PREPARED; + if (nextSourceInfo.mPlayPendingAsNextSource) { playNextDataSource(); } } @@ -1621,7 +1597,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { case MEDIA_PLAYBACK_COMPLETE: { - if (isCurrentSrcId) { + if (isCurrentSource(srcId)) { sendEvent(new EventNotifier() { @Override public void notify(EventCallback callback) { @@ -1632,11 +1608,13 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { stayAwake(false); synchronized (mSrcLock) { - mNextSourcePlayPending = true; - + SourceInfo nextSourceInfo = mNextSourceInfos.peek(); + if (nextSourceInfo != null) { + nextSourceInfo.mPlayPendingAsNextSource = true; + } Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId - + ", currentSrcId=" + mCurrentSrcId - + ", nextSrcId=" + mNextSrcId); + + ", curSrc=" + mCurrentSourceInfo + + ", nextSrc=" + nextSourceInfo); } playNextDataSource(); @@ -1667,13 +1645,11 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } }); - synchronized (mSrcLock) { - if (isCurrentSrcId) { - mBufferedPercentageCurrent.set(percent); - } else if (isNextSrcId) { - mBufferedPercentageNext.set(percent); - } + SourceInfo src = getSourceInfoById(srcId); + if (src != null) { + src.mBufferedPercentage.set(percent); } + return; } @@ -1751,7 +1727,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { }); if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) { - if (isCurrentSrcId) { + if (isCurrentSource(srcId)) { prepareNextDataSource(); } } @@ -1854,6 +1830,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } } } + } /* @@ -2130,7 +2107,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override public void notify(DrmEventCallback callback) { callback.onDrmPrepared( - MediaPlayer2Impl.this, mCurrentDSD, prepareDrmStatus); + MediaPlayer2Impl.this, getCurrentDataSource(), prepareDrmStatus); } }); @@ -2196,7 +2173,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { // call the callback outside the lock if (mOnDrmConfigHelper != null) { - mOnDrmConfigHelper.onDrmConfig(this, mCurrentDSD); + mOnDrmConfigHelper.onDrmConfig(this, getCurrentDataSource()); } synchronized (mDrmLock) { @@ -2817,7 +2794,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override public void notify(DrmEventCallback callback) { callback.onDrmPrepared( - mediaPlayer, mCurrentDSD, status); + mediaPlayer, getCurrentDataSource(), status); } }); @@ -3084,9 +3061,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } catch (Exception e) { status = CALL_STATUS_ERROR_UNKNOWN; } - synchronized (mSrcLock) { - mDSD = mCurrentDSD; - } + mDSD = getCurrentDataSource(); if (mMediaCallType != CALL_COMPLETED_SEEK_TO) { synchronized (mTaskLock) { @@ -3129,4 +3104,50 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { super(detailMessage); } }; + + private final class SourceInfo { + final DataSourceDesc mDSD; + final long mId = mSrcIdGenerator.getAndIncrement(); + AtomicInteger mBufferedPercentage = new AtomicInteger(0); + + // m*AsNextSource (below) only applies to pending data sources in the playlist; + // the meanings of mCurrentSourceInfo.{mStateAsNextSource,mPlayPendingAsNextSource} + // are undefined. + int mStateAsNextSource = NEXT_SOURCE_STATE_INIT; + boolean mPlayPendingAsNextSource = false; + + SourceInfo(DataSourceDesc dsd) { + this.mDSD = dsd; + } + + @Override + public String toString() { + return String.format("%s(%d)", SourceInfo.class.getName(), mId); + } + + } + + private SourceInfo getSourceInfoById(long srcId) { + synchronized (mSrcLock) { + if (isCurrentSource(srcId)) { + return mCurrentSourceInfo; + } + if (isNextSource(srcId)) { + return mNextSourceInfos.peek(); + } + } + return null; + } + + private boolean isCurrentSource(long srcId) { + synchronized (mSrcLock) { + return mCurrentSourceInfo != null && mCurrentSourceInfo.mId == srcId; + } + } + + private boolean isNextSource(long srcId) { + SourceInfo nextSourceInfo = mNextSourceInfos.peek(); + return nextSourceInfo != null && nextSourceInfo.mId == srcId; + } + } |