Loading media/java/android/media/MediaPlayer2Impl.java +123 −102 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -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); } } }); Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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; } } Loading Loading @@ -707,34 +705,29 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } boolean hasNextDSD; synchronized (mSrcLock) { hasNextDSD = (mNextDSDs != null && !mNextDSDs.isEmpty()); } int state = getState(); synchronized (mSrcLock) { hasNextDSD = !mNextSourceInfos.isEmpty(); 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) { 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(); } } Loading @@ -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) { Loading @@ -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(); } } Loading Loading @@ -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) { Loading Loading @@ -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 { final SourceInfo sourceInfo = getSourceInfoById(srcId); if (sourceInfo == null) { return; } } final DataSourceDesc dsd = sourceInfo.mDSD; switch(msg.what) { case MEDIA_PREPARED: Loading @@ -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(); } } Loading Loading @@ -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) { Loading @@ -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(); Loading Loading @@ -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; } Loading Loading @@ -1751,7 +1727,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { }); if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) { if (isCurrentSrcId) { if (isCurrentSource(srcId)) { prepareNextDataSource(); } } Loading Loading @@ -1854,6 +1830,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } } } } /* Loading Loading @@ -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); } }); Loading Loading @@ -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) { Loading Loading @@ -2817,7 +2794,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override public void notify(DrmEventCallback callback) { callback.onDrmPrepared( mediaPlayer, mCurrentDSD, status); mediaPlayer, getCurrentDataSource(), status); } }); Loading Loading @@ -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) { Loading Loading @@ -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; } } Loading
media/java/android/media/MediaPlayer2Impl.java +123 −102 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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 Loading Loading @@ -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); } } }); Loading @@ -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(); } Loading @@ -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(); } Loading @@ -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; } } Loading Loading @@ -707,34 +705,29 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } boolean hasNextDSD; synchronized (mSrcLock) { hasNextDSD = (mNextDSDs != null && !mNextDSDs.isEmpty()); } int state = getState(); synchronized (mSrcLock) { hasNextDSD = !mNextSourceInfos.isEmpty(); 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) { 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(); } } Loading @@ -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) { Loading @@ -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(); } } Loading Loading @@ -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) { Loading Loading @@ -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 { final SourceInfo sourceInfo = getSourceInfoById(srcId); if (sourceInfo == null) { return; } } final DataSourceDesc dsd = sourceInfo.mDSD; switch(msg.what) { case MEDIA_PREPARED: Loading @@ -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(); } } Loading Loading @@ -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) { Loading @@ -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(); Loading Loading @@ -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; } Loading Loading @@ -1751,7 +1727,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { }); if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) { if (isCurrentSrcId) { if (isCurrentSource(srcId)) { prepareNextDataSource(); } } Loading Loading @@ -1854,6 +1830,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { } } } } /* Loading Loading @@ -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); } }); Loading Loading @@ -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) { Loading Loading @@ -2817,7 +2794,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { @Override public void notify(DrmEventCallback callback) { callback.onDrmPrepared( mediaPlayer, mCurrentDSD, status); mediaPlayer, getCurrentDataSource(), status); } }); Loading Loading @@ -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) { Loading Loading @@ -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; } }