mirror of
https://github.com/samsonjs/media.git
synced 2026-04-25 14:47:40 +00:00
Finalize class naming
SampleSourceProvider -> MediaSource SampleSource -> MediaPeriod ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=126914964
This commit is contained in:
parent
c9ec7beb92
commit
8e0354c0a6
32 changed files with 635 additions and 666 deletions
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.demo;
|
||||
|
||||
import com.google.android.exoplayer2.AdaptiveSourceEventListener;
|
||||
import com.google.android.exoplayer2.AdaptiveMediaSourceEventListener;
|
||||
import com.google.android.exoplayer2.CodecCounters;
|
||||
import com.google.android.exoplayer2.DefaultTrackSelector;
|
||||
import com.google.android.exoplayer2.DefaultTrackSelector.TrackInfo;
|
||||
|
|
@ -28,7 +28,7 @@ import com.google.android.exoplayer2.TrackGroupArray;
|
|||
import com.google.android.exoplayer2.TrackRenderer;
|
||||
import com.google.android.exoplayer2.TrackSelection;
|
||||
import com.google.android.exoplayer2.drm.StreamingDrmSessionManager;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorSampleSource;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorMediaSource;
|
||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||
|
||||
import android.os.SystemClock;
|
||||
|
|
@ -42,7 +42,7 @@ import java.util.Locale;
|
|||
* Logs player events using {@link Log}.
|
||||
*/
|
||||
public class EventLogger implements ExoPlayer.EventListener, SimpleExoPlayer.DebugListener,
|
||||
AdaptiveSourceEventListener, ExtractorSampleSource.EventListener,
|
||||
AdaptiveMediaSourceEventListener, ExtractorMediaSource.EventListener,
|
||||
StreamingDrmSessionManager.EventListener, DefaultTrackSelector.EventListener {
|
||||
|
||||
private static final String TAG = "EventLogger";
|
||||
|
|
@ -78,8 +78,8 @@ public class EventLogger implements ExoPlayer.EventListener, SimpleExoPlayer.Deb
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity(int sourceIndex, long positionMs) {
|
||||
Log.d(TAG, "discontinuity [" + sourceIndex + ", " + positionMs + "]");
|
||||
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
||||
Log.d(TAG, "discontinuity [" + periodIndex + ", " + positionMs + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -211,14 +211,14 @@ public class EventLogger implements ExoPlayer.EventListener, SimpleExoPlayer.Deb
|
|||
Log.d(TAG, "drmKeysLoaded [" + getSessionTimeString() + "]");
|
||||
}
|
||||
|
||||
// ExtractorSampleSource.EventListener
|
||||
// ExtractorMediaSource.EventListener
|
||||
|
||||
@Override
|
||||
public void onLoadError(IOException error) {
|
||||
printInternalError("loadError", error);
|
||||
}
|
||||
|
||||
// AdaptiveSourceEventListener
|
||||
// AdaptiveMediaSourceEventListener
|
||||
|
||||
@Override
|
||||
public void onLoadStarted(DataSpec dataSpec, int dataType, int trackType, Format format,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ package com.google.android.exoplayer2.demo;
|
|||
|
||||
import com.google.android.exoplayer2.AspectRatioFrameLayout;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.ConcatenatingSampleSourceProvider;
|
||||
import com.google.android.exoplayer2.ConcatenatingMediaSource;
|
||||
import com.google.android.exoplayer2.DefaultLoadControl;
|
||||
import com.google.android.exoplayer2.DefaultTrackSelectionPolicy;
|
||||
import com.google.android.exoplayer2.DefaultTrackSelector;
|
||||
|
|
@ -27,23 +27,23 @@ import com.google.android.exoplayer2.ExoPlayer;
|
|||
import com.google.android.exoplayer2.ExoPlayerFactory;
|
||||
import com.google.android.exoplayer2.MediaCodecTrackRenderer.DecoderInitializationException;
|
||||
import com.google.android.exoplayer2.MediaCodecUtil.DecoderQueryException;
|
||||
import com.google.android.exoplayer2.SampleSourceProvider;
|
||||
import com.google.android.exoplayer2.MediaSource;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.TrackGroupArray;
|
||||
import com.google.android.exoplayer2.dash.DashSampleSource;
|
||||
import com.google.android.exoplayer2.dash.DashMediaSource;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||
import com.google.android.exoplayer2.drm.StreamingDrmSessionManager;
|
||||
import com.google.android.exoplayer2.drm.UnsupportedDrmException;
|
||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorSampleSource;
|
||||
import com.google.android.exoplayer2.hls.HlsSampleSource;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorMediaSource;
|
||||
import com.google.android.exoplayer2.hls.HlsMediaSource;
|
||||
import com.google.android.exoplayer2.metadata.id3.ApicFrame;
|
||||
import com.google.android.exoplayer2.metadata.id3.GeobFrame;
|
||||
import com.google.android.exoplayer2.metadata.id3.Id3Frame;
|
||||
import com.google.android.exoplayer2.metadata.id3.PrivFrame;
|
||||
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
|
||||
import com.google.android.exoplayer2.metadata.id3.TxxxFrame;
|
||||
import com.google.android.exoplayer2.smoothstreaming.SmoothStreamingSampleSource;
|
||||
import com.google.android.exoplayer2.smoothstreaming.SmoothStreamingMediaSource;
|
||||
import com.google.android.exoplayer2.text.CaptionStyleCompat;
|
||||
import com.google.android.exoplayer2.text.Cue;
|
||||
import com.google.android.exoplayer2.text.SubtitleLayout;
|
||||
|
|
@ -320,34 +320,33 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||
return;
|
||||
}
|
||||
|
||||
SampleSourceProvider[] providers = new SampleSourceProvider[uris.length];
|
||||
MediaSource[] mediaSources = new MediaSource[uris.length];
|
||||
for (int i = 0; i < uris.length; i++) {
|
||||
providers[i] = getSampleSourceProvider(uris[i], extensions[i]);
|
||||
mediaSources[i] = getMediaSource(uris[i], extensions[i]);
|
||||
}
|
||||
SampleSourceProvider sourceProvider = providers.length == 1 ? providers[0]
|
||||
: new ConcatenatingSampleSourceProvider(providers);
|
||||
player.setSourceProvider(sourceProvider);
|
||||
MediaSource mediaSource = mediaSources.length == 1 ? mediaSources[0]
|
||||
: new ConcatenatingMediaSource(mediaSources);
|
||||
player.setMediaSource(mediaSource);
|
||||
playerNeedsSource = false;
|
||||
updateButtonVisibilities();
|
||||
}
|
||||
}
|
||||
|
||||
private SampleSourceProvider getSampleSourceProvider(Uri uri, String overrideExtension) {
|
||||
private MediaSource getMediaSource(Uri uri, String overrideExtension) {
|
||||
String lastPathSegment = !TextUtils.isEmpty(overrideExtension) ? "." + overrideExtension
|
||||
: uri.getLastPathSegment();
|
||||
int type = Util.inferContentType(lastPathSegment);
|
||||
switch (type) {
|
||||
case Util.TYPE_SS:
|
||||
return new SmoothStreamingSampleSource(uri, dataSourceFactory, bandwidthMeter, mainHandler,
|
||||
return new SmoothStreamingMediaSource(uri, dataSourceFactory, bandwidthMeter, mainHandler,
|
||||
eventLogger);
|
||||
case Util.TYPE_DASH:
|
||||
return new DashSampleSource(uri, dataSourceFactory, bandwidthMeter, mainHandler,
|
||||
return new DashMediaSource(uri, dataSourceFactory, bandwidthMeter, mainHandler,
|
||||
eventLogger);
|
||||
case Util.TYPE_HLS:
|
||||
return new HlsSampleSource(uri, dataSourceFactory, bandwidthMeter, mainHandler,
|
||||
eventLogger);
|
||||
return new HlsMediaSource(uri, dataSourceFactory, bandwidthMeter, mainHandler, eventLogger);
|
||||
case Util.TYPE_OTHER:
|
||||
return new ExtractorSampleSource(uri, dataSourceFactory, bandwidthMeter,
|
||||
return new ExtractorMediaSource(uri, dataSourceFactory, bandwidthMeter,
|
||||
new DefaultExtractorsFactory(), mainHandler, eventLogger);
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported type: " + type);
|
||||
|
|
@ -437,7 +436,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity(int sourceIndex, long positionMs) {
|
||||
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
||||
if (mediaController.isShowing()) {
|
||||
// The MediaController is visible, so force it to show the updated position immediately.
|
||||
mediaController.show();
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import com.google.android.exoplayer2.ExoPlaybackException;
|
|||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.ExoPlayerFactory;
|
||||
import com.google.android.exoplayer2.TrackRenderer;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorSampleSource;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorMediaSource;
|
||||
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
|
||||
|
|
@ -76,14 +76,14 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
|
|||
new DefaultTrackSelectionPolicy(), null);
|
||||
player = ExoPlayerFactory.newInstance(new TrackRenderer[] {audioRenderer}, trackSelector);
|
||||
player.addListener(this);
|
||||
ExtractorSampleSource sampleSource = new ExtractorSampleSource(
|
||||
ExtractorMediaSource mediaSource = new ExtractorMediaSource(
|
||||
uri,
|
||||
new DefaultDataSourceFactory(context, "ExoPlayerExtFlacTest"),
|
||||
null,
|
||||
new MatroskaExtractor.Factory(),
|
||||
null,
|
||||
null);
|
||||
player.setSourceProvider(sampleSource);
|
||||
player.setMediaSource(mediaSource);
|
||||
player.setPlayWhenReady(true);
|
||||
Looper.loop();
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity(int sourceIndex, long positionMs) {
|
||||
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import com.google.android.exoplayer2.ExoPlaybackException;
|
|||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.ExoPlayerFactory;
|
||||
import com.google.android.exoplayer2.TrackRenderer;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorSampleSource;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorMediaSource;
|
||||
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
|
||||
|
|
@ -76,14 +76,14 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
|
|||
new DefaultTrackSelectionPolicy(), null);
|
||||
player = ExoPlayerFactory.newInstance(new TrackRenderer[] {audioRenderer}, trackSelector);
|
||||
player.addListener(this);
|
||||
ExtractorSampleSource sampleSource = new ExtractorSampleSource(
|
||||
ExtractorMediaSource mediaSource = new ExtractorMediaSource(
|
||||
uri,
|
||||
new DefaultDataSourceFactory(context, "ExoPlayerExtOpusTest"),
|
||||
null,
|
||||
new MatroskaExtractor.Factory(),
|
||||
null,
|
||||
null);
|
||||
player.setSourceProvider(sampleSource);
|
||||
player.setMediaSource(mediaSource);
|
||||
player.setPlayWhenReady(true);
|
||||
Looper.loop();
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity(int sourceIndex, long positionMs) {
|
||||
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
||||
|
|
@ -21,7 +21,7 @@ import com.google.android.exoplayer2.ExoPlaybackException;
|
|||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.ExoPlayerFactory;
|
||||
import com.google.android.exoplayer2.TrackRenderer;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorSampleSource;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorMediaSource;
|
||||
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
|
|||
new DefaultTrackSelectionPolicy(), null);
|
||||
player = ExoPlayerFactory.newInstance(new TrackRenderer[] {videoRenderer}, trackSelector);
|
||||
player.addListener(this);
|
||||
ExtractorSampleSource sampleSource = new ExtractorSampleSource(
|
||||
ExtractorMediaSource mediaSource = new ExtractorMediaSource(
|
||||
uri,
|
||||
new DefaultDataSourceFactory(context, "ExoPlayerExtVp9Test"),
|
||||
null,
|
||||
|
|
@ -102,7 +102,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
|
|||
player.sendMessages(new ExoPlayer.ExoPlayerMessage(videoRenderer,
|
||||
LibvpxVideoTrackRenderer.MSG_SET_OUTPUT_BUFFER_RENDERER,
|
||||
new VpxVideoSurfaceView(context)));
|
||||
player.setSourceProvider(sampleSource);
|
||||
player.setMediaSource(mediaSource);
|
||||
player.setPlayWhenReady(true);
|
||||
Looper.loop();
|
||||
}
|
||||
|
|
@ -118,7 +118,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity(int sourceIndex, long positionMs) {
|
||||
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
||||
|
|
@ -25,9 +25,9 @@ import android.os.SystemClock;
|
|||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Interface for callbacks to be notified about events during adaptive playbacks.
|
||||
* Interface for callbacks to be notified of adaptive {@link MediaSource} events.
|
||||
*/
|
||||
public interface AdaptiveSourceEventListener {
|
||||
public interface AdaptiveMediaSourceEventListener {
|
||||
|
||||
/**
|
||||
* Invoked when a load begins.
|
||||
|
|
@ -171,14 +171,14 @@ public interface AdaptiveSourceEventListener {
|
|||
Object formatEvaluatorData, long mediaTimeMs);
|
||||
|
||||
/**
|
||||
* Dispatches events to a {@link AdaptiveSourceEventListener}.
|
||||
* Dispatches events to a {@link AdaptiveMediaSourceEventListener}.
|
||||
*/
|
||||
final class EventDispatcher {
|
||||
|
||||
private final Handler handler;
|
||||
private final AdaptiveSourceEventListener listener;
|
||||
private final AdaptiveMediaSourceEventListener listener;
|
||||
|
||||
public EventDispatcher(Handler handler, AdaptiveSourceEventListener listener) {
|
||||
public EventDispatcher(Handler handler, AdaptiveMediaSourceEventListener listener) {
|
||||
this.handler = listener != null ? Assertions.checkNotNull(handler) : null;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2;
|
||||
|
||||
/**
|
||||
* A {@link MediaSource} that concatenates multiple {@link MediaSource}s.
|
||||
*/
|
||||
public final class ConcatenatingMediaSource implements MediaSource {
|
||||
|
||||
private final MediaSource[] mediaSources;
|
||||
|
||||
/**
|
||||
* @param mediaSources The {@link MediaSource}s to concatenate.
|
||||
*/
|
||||
public ConcatenatingMediaSource(MediaSource... mediaSources) {
|
||||
this.mediaSources = mediaSources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPeriodCount() {
|
||||
int sourceCount = 0;
|
||||
for (MediaSource mediaSource : mediaSources) {
|
||||
int count = mediaSource.getPeriodCount();
|
||||
if (count == MediaSource.UNKNOWN_PERIOD_COUNT) {
|
||||
return UNKNOWN_PERIOD_COUNT;
|
||||
}
|
||||
sourceCount += count;
|
||||
}
|
||||
return sourceCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaPeriod createPeriod(int index) {
|
||||
int sourceCount = 0;
|
||||
for (MediaSource mediaSource : mediaSources) {
|
||||
int count = mediaSource.getPeriodCount();
|
||||
if (count == MediaSource.UNKNOWN_PERIOD_COUNT || index < sourceCount + count) {
|
||||
return mediaSource.createPeriod(index - sourceCount);
|
||||
}
|
||||
sourceCount += count;
|
||||
}
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2;
|
||||
|
||||
/**
|
||||
* A {@link SampleSourceProvider} that concatenates multiple {@link SampleSourceProvider}s.
|
||||
*/
|
||||
public final class ConcatenatingSampleSourceProvider implements SampleSourceProvider {
|
||||
|
||||
private final SampleSourceProvider[] sampleSourceProviders;
|
||||
|
||||
/**
|
||||
* @param sampleSourcePoviders The {@link SampleSourceProvider}s to concatenate.
|
||||
*/
|
||||
public ConcatenatingSampleSourceProvider(SampleSourceProvider... sampleSourcePoviders) {
|
||||
this.sampleSourceProviders = sampleSourcePoviders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSourceCount() {
|
||||
int sourceCount = 0;
|
||||
for (SampleSourceProvider sampleSourceProvider : sampleSourceProviders) {
|
||||
int count = sampleSourceProvider.getSourceCount();
|
||||
if (count == SampleSourceProvider.UNKNOWN_SOURCE_COUNT) {
|
||||
return UNKNOWN_SOURCE_COUNT;
|
||||
}
|
||||
sourceCount += count;
|
||||
}
|
||||
return sourceCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleSource createSource(int index) {
|
||||
int sourceCount = 0;
|
||||
for (SampleSourceProvider sampleSourceProvider : sampleSourceProviders) {
|
||||
int count = sampleSourceProvider.getSourceCount();
|
||||
if (count == SampleSourceProvider.UNKNOWN_SOURCE_COUNT || index < sourceCount + count) {
|
||||
return sampleSourceProvider.createSource(index - sourceCount);
|
||||
}
|
||||
sourceCount += count;
|
||||
}
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ import java.io.IOException;
|
|||
public final class ExoPlaybackException extends Exception {
|
||||
|
||||
/**
|
||||
* The error occurred loading data from a {@link SampleSource}.
|
||||
* The error occurred loading data from a {@link MediaSource}.
|
||||
* <p>
|
||||
* Call {@link #getSourceException()} to retrieve the underlying cause.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -38,11 +38,11 @@ package com.google.android.exoplayer2;
|
|||
*
|
||||
* <p>{@link MediaCodecAudioTrackRenderer} and {@link MediaCodecVideoTrackRenderer} can be used for
|
||||
* the common cases of rendering audio and video. These components in turn require an
|
||||
* <i>upstream</i> {@link SampleSource} to be injected through their constructors, where upstream
|
||||
* <i>upstream</i> {@link MediaPeriod} to be injected through their constructors, where upstream
|
||||
* is defined to denote a component that is closer to the source of the media. This pattern of
|
||||
* upstream dependency injection is actively encouraged, since it means that the functionality of
|
||||
* the player is built up through the composition of components that can easily be exchanged for
|
||||
* alternate implementations. For example a {@link SampleSource} implementation may require a
|
||||
* alternate implementations. For example a {@link MediaPeriod} implementation may require a
|
||||
* further upstream data loading component to be injected through its constructor, with different
|
||||
* implementations enabling the loading of data from various sources.
|
||||
*
|
||||
|
|
@ -84,8 +84,7 @@ package com.google.android.exoplayer2;
|
|||
*
|
||||
* <p>The possible playback state transitions are shown below. Transitions can be triggered either
|
||||
* by changes in the state of the {@link TrackRenderer}s being used, or as a result of
|
||||
* {@link #setSource(SampleSource)}, {@link #setSourceProvider(SampleSourceProvider)},
|
||||
* {@link #stop()} or {@link #release()} being invoked.</p>
|
||||
* {@link #setMediaSource(MediaSource)}, {@link #stop()} or {@link #release()} being invoked.</p>
|
||||
* <p align="center"><img src="../../../../../images/exoplayer_playbackstate.png"
|
||||
* alt="ExoPlayer playback state transitions"
|
||||
* border="0"/></p>
|
||||
|
|
@ -128,12 +127,12 @@ public interface ExoPlayer {
|
|||
// TODO[playlists]: Should source-initiated resets also cause this to be invoked?
|
||||
/**
|
||||
* Invoked when the player's position changes due to a discontinuity (seeking or playback
|
||||
* transitioning to the next source).
|
||||
* transitioning to the next period).
|
||||
*
|
||||
* @param sourceIndex The index of the source being played.
|
||||
* @param positionMs The playback position in that source, in milliseconds.
|
||||
* @param periodIndex The index of the period being played.
|
||||
* @param positionMs The playback position in that period, in milliseconds.
|
||||
*/
|
||||
void onPositionDiscontinuity(int sourceIndex, long positionMs);
|
||||
void onPositionDiscontinuity(int periodIndex, long positionMs);
|
||||
|
||||
/**
|
||||
* Invoked when an error occurs. The playback state will transition to
|
||||
|
|
@ -189,7 +188,7 @@ public interface ExoPlayer {
|
|||
}
|
||||
|
||||
/**
|
||||
* The player does not have a source to load, so it is neither buffering nor ready to play.
|
||||
* The player does not have a source to play, so it is neither buffering nor ready to play.
|
||||
*/
|
||||
int STATE_IDLE = 1;
|
||||
/**
|
||||
|
|
@ -236,17 +235,18 @@ public interface ExoPlayer {
|
|||
int getPlaybackState();
|
||||
|
||||
/**
|
||||
* Sets the player's source provider. The player's position will be reset to the start of the
|
||||
* first source and the player will transition to {@link #STATE_BUFFERING} until it is ready to
|
||||
* play it.
|
||||
* Sets the {@link MediaSource} to play.
|
||||
* <p>
|
||||
* The player's position will be reset to the start of the source.
|
||||
*
|
||||
* @param sourceProvider The provider of {@link SampleSource}s to play.
|
||||
* @param mediaSource The {@link MediaSource} to play.
|
||||
*/
|
||||
void setSourceProvider(SampleSourceProvider sourceProvider);
|
||||
void setMediaSource(MediaSource mediaSource);
|
||||
|
||||
/**
|
||||
* Sets whether playback should proceed when {@link #getPlaybackState()} == {@link #STATE_READY}.
|
||||
* If the player is already in this state, then this method can be used to pause and resume
|
||||
* <p>
|
||||
* If the player is already in the ready state then this method can be used to pause and resume
|
||||
* playback.
|
||||
*
|
||||
* @param playWhenReady Whether playback should proceed when ready.
|
||||
|
|
@ -276,19 +276,19 @@ public interface ExoPlayer {
|
|||
boolean isLoading();
|
||||
|
||||
/**
|
||||
* Seeks to a position specified in milliseconds in the current source.
|
||||
* Seeks to a position specified in milliseconds in the current period.
|
||||
*
|
||||
* @param positionMs The seek position.
|
||||
*/
|
||||
void seekTo(long positionMs);
|
||||
|
||||
/**
|
||||
* Seeks to a position specified in milliseconds in the specified source.
|
||||
* Seeks to a position specified in milliseconds in the specified period.
|
||||
*
|
||||
* @param sourceIndex The index of the source to seek to.
|
||||
* @param positionMs The seek position relative to the start of the specified source.
|
||||
* @param periodIndex The index of the period to seek to.
|
||||
* @param positionMs The seek position relative to the start of the specified period.
|
||||
*/
|
||||
void seekTo(int sourceIndex, long positionMs);
|
||||
void seekTo(int periodIndex, long positionMs);
|
||||
|
||||
/**
|
||||
* Stops playback. Use {@code setPlayWhenReady(false)} rather than this method if the intention
|
||||
|
|
@ -298,9 +298,7 @@ public interface ExoPlayer {
|
|||
* {@link ExoPlayer#STATE_IDLE}. The player instance can still be used, and
|
||||
* {@link ExoPlayer#release()} must still be called on the player if it's no longer required.
|
||||
* <p>
|
||||
* Calling this method does not reset the playback position. If this player instance will be used
|
||||
* to play another video from its start, then {@code seekTo(0)} should be called after stopping
|
||||
* the player and before setting the next source.
|
||||
* Calling this method does not reset the playback position.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
|
|
@ -337,18 +335,18 @@ public interface ExoPlayer {
|
|||
long getDuration();
|
||||
|
||||
/**
|
||||
* Gets the playback position in the current source, in milliseconds.
|
||||
* Gets the playback position in the current period, in milliseconds.
|
||||
*
|
||||
* @return The playback position in the current source, in milliseconds.
|
||||
* @return The playback position in the current period, in milliseconds.
|
||||
*/
|
||||
long getCurrentPosition();
|
||||
|
||||
/**
|
||||
* Gets the index of the current source.
|
||||
* Gets the index of the current period.
|
||||
*
|
||||
* @return The index of the current source.
|
||||
* @return The index of the current period.
|
||||
*/
|
||||
int getCurrentSourceIndex();
|
||||
int getCurrentPeriodIndex();
|
||||
|
||||
/**
|
||||
* Gets an estimate of the absolute position in milliseconds up to which data is buffered.
|
||||
|
|
|
|||
|
|
@ -40,14 +40,14 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
private boolean playWhenReady;
|
||||
private int playbackState;
|
||||
private int pendingPlayWhenReadyAcks;
|
||||
private int pendingSetSourceProviderAndSeekAcks;
|
||||
private int pendingSetMediaSourceAndSeekAcks;
|
||||
private boolean isLoading;
|
||||
|
||||
// Playback information when there is no pending seek/set source operation.
|
||||
private PlaybackInfo playbackInfo;
|
||||
|
||||
// Playback information when there is a pending seek/set source operation.
|
||||
private int maskingSourceIndex;
|
||||
private int maskingPeriodIndex;
|
||||
private long maskingPositionMs;
|
||||
private long maskingDurationMs;
|
||||
|
||||
|
|
@ -94,13 +94,13 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setSourceProvider(SampleSourceProvider sourceProvider) {
|
||||
maskingSourceIndex = 0;
|
||||
public void setMediaSource(MediaSource mediaSource) {
|
||||
maskingPeriodIndex = 0;
|
||||
maskingPositionMs = 0;
|
||||
maskingDurationMs = ExoPlayer.UNKNOWN_TIME;
|
||||
|
||||
pendingSetSourceProviderAndSeekAcks++;
|
||||
internalPlayer.setSourceProvider(sourceProvider);
|
||||
pendingSetMediaSourceAndSeekAcks++;
|
||||
internalPlayer.setMediaSource(mediaSource);
|
||||
for (EventListener listener : listeners) {
|
||||
listener.onPositionDiscontinuity(0, 0);
|
||||
}
|
||||
|
|
@ -135,20 +135,20 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
|
||||
@Override
|
||||
public void seekTo(long positionMs) {
|
||||
seekTo(getCurrentSourceIndex(), positionMs);
|
||||
seekTo(getCurrentPeriodIndex(), positionMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void seekTo(int sourceIndex, long positionMs) {
|
||||
boolean sourceChanging = sourceIndex != getCurrentSourceIndex();
|
||||
maskingSourceIndex = sourceIndex;
|
||||
public void seekTo(int periodIndex, long positionMs) {
|
||||
boolean periodChanging = periodIndex != getCurrentPeriodIndex();
|
||||
maskingPeriodIndex = periodIndex;
|
||||
maskingPositionMs = positionMs;
|
||||
maskingDurationMs = sourceChanging ? ExoPlayer.UNKNOWN_TIME : getDuration();
|
||||
maskingDurationMs = periodChanging ? ExoPlayer.UNKNOWN_TIME : getDuration();
|
||||
|
||||
pendingSetSourceProviderAndSeekAcks++;
|
||||
internalPlayer.seekTo(sourceIndex, positionMs * 1000);
|
||||
pendingSetMediaSourceAndSeekAcks++;
|
||||
internalPlayer.seekTo(periodIndex, positionMs * 1000);
|
||||
for (EventListener listener : listeners) {
|
||||
listener.onPositionDiscontinuity(sourceIndex, positionMs);
|
||||
listener.onPositionDiscontinuity(periodIndex, positionMs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
|
||||
@Override
|
||||
public long getDuration() {
|
||||
if (pendingSetSourceProviderAndSeekAcks == 0) {
|
||||
if (pendingSetMediaSourceAndSeekAcks == 0) {
|
||||
long durationUs = playbackInfo.durationUs;
|
||||
return durationUs == C.UNSET_TIME_US ? ExoPlayer.UNKNOWN_TIME : durationUs / 1000;
|
||||
} else {
|
||||
|
|
@ -185,18 +185,18 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
|
||||
@Override
|
||||
public long getCurrentPosition() {
|
||||
return pendingSetSourceProviderAndSeekAcks == 0 ? playbackInfo.positionUs / 1000
|
||||
return pendingSetMediaSourceAndSeekAcks == 0 ? playbackInfo.positionUs / 1000
|
||||
: maskingPositionMs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentSourceIndex() {
|
||||
return pendingSetSourceProviderAndSeekAcks == 0 ? playbackInfo.sourceIndex : maskingSourceIndex;
|
||||
public int getCurrentPeriodIndex() {
|
||||
return pendingSetMediaSourceAndSeekAcks == 0 ? playbackInfo.periodIndex : maskingPeriodIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBufferedPosition() {
|
||||
if (pendingSetSourceProviderAndSeekAcks == 0) {
|
||||
if (pendingSetMediaSourceAndSeekAcks == 0) {
|
||||
long bufferedPositionUs = playbackInfo.bufferedPositionUs;
|
||||
return bufferedPositionUs == C.END_OF_SOURCE_US ? getDuration() : bufferedPositionUs / 1000;
|
||||
} else {
|
||||
|
|
@ -238,16 +238,16 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
}
|
||||
break;
|
||||
}
|
||||
case ExoPlayerImplInternal.MSG_SET_SOURCE_PROVIDER_ACK: // Fall through.
|
||||
case ExoPlayerImplInternal.MSG_SET_MEDIA_SOURCE_ACK: // Fall through.
|
||||
case ExoPlayerImplInternal.MSG_SEEK_ACK: {
|
||||
pendingSetSourceProviderAndSeekAcks--;
|
||||
pendingSetMediaSourceAndSeekAcks--;
|
||||
break;
|
||||
}
|
||||
case ExoPlayerImplInternal.MSG_SOURCE_CHANGED: {
|
||||
case ExoPlayerImplInternal.MSG_PERIOD_CHANGED: {
|
||||
playbackInfo = (ExoPlayerImplInternal.PlaybackInfo) msg.obj;
|
||||
if (pendingSetSourceProviderAndSeekAcks == 0) {
|
||||
if (pendingSetMediaSourceAndSeekAcks == 0) {
|
||||
for (EventListener listener : listeners) {
|
||||
listener.onPositionDiscontinuity(playbackInfo.sourceIndex, 0);
|
||||
listener.onPositionDiscontinuity(playbackInfo.periodIndex, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ import java.util.ArrayList;
|
|||
/**
|
||||
* Implements the internal behavior of {@link ExoPlayerImpl}.
|
||||
*/
|
||||
/* package */ final class ExoPlayerImplInternal implements Handler.Callback, SampleSource.Callback,
|
||||
/* package */ final class ExoPlayerImplInternal implements Handler.Callback, MediaPeriod.Callback,
|
||||
InvalidationListener {
|
||||
|
||||
/**
|
||||
|
|
@ -44,14 +44,14 @@ import java.util.ArrayList;
|
|||
*/
|
||||
public static final class PlaybackInfo {
|
||||
|
||||
public final int sourceIndex;
|
||||
public final int periodIndex;
|
||||
|
||||
public volatile long positionUs;
|
||||
public volatile long bufferedPositionUs;
|
||||
public volatile long durationUs;
|
||||
|
||||
public PlaybackInfo(int sourceIndex) {
|
||||
this.sourceIndex = sourceIndex;
|
||||
public PlaybackInfo(int periodIndex) {
|
||||
this.periodIndex = periodIndex;
|
||||
durationUs = C.UNSET_TIME_US;
|
||||
}
|
||||
|
||||
|
|
@ -63,19 +63,19 @@ import java.util.ArrayList;
|
|||
public static final int MSG_STATE_CHANGED = 1;
|
||||
public static final int MSG_LOADING_CHANGED = 2;
|
||||
public static final int MSG_SET_PLAY_WHEN_READY_ACK = 3;
|
||||
public static final int MSG_SET_SOURCE_PROVIDER_ACK = 4;
|
||||
public static final int MSG_SET_MEDIA_SOURCE_ACK = 4;
|
||||
public static final int MSG_SEEK_ACK = 5;
|
||||
public static final int MSG_SOURCE_CHANGED = 6;
|
||||
public static final int MSG_PERIOD_CHANGED = 6;
|
||||
public static final int MSG_ERROR = 7;
|
||||
|
||||
// Internal messages
|
||||
private static final int MSG_SET_SOURCE_PROVIDER = 0;
|
||||
private static final int MSG_SET_MEDIA_SOURCE = 0;
|
||||
private static final int MSG_SET_PLAY_WHEN_READY = 1;
|
||||
private static final int MSG_DO_SOME_WORK = 2;
|
||||
private static final int MSG_SEEK_TO = 3;
|
||||
private static final int MSG_STOP = 4;
|
||||
private static final int MSG_RELEASE = 5;
|
||||
private static final int MSG_SOURCE_PREPARED = 6;
|
||||
private static final int MSG_PERIOD_PREPARED = 6;
|
||||
private static final int MSG_SOURCE_CONTINUE_LOADING_REQUESTED = 7;
|
||||
private static final int MSG_TRACK_SELECTION_INVALIDATED = 8;
|
||||
private static final int MSG_CUSTOM = 9;
|
||||
|
|
@ -102,7 +102,7 @@ import java.util.ArrayList;
|
|||
private PlaybackInfo playbackInfo;
|
||||
private TrackRenderer rendererMediaClockSource;
|
||||
private MediaClock rendererMediaClock;
|
||||
private SampleSourceProvider sampleSourceProvider;
|
||||
private MediaSource mediaSource;
|
||||
private TrackRenderer[] enabledRenderers;
|
||||
private boolean released;
|
||||
private boolean playWhenReady;
|
||||
|
|
@ -142,16 +142,16 @@ import java.util.ArrayList;
|
|||
handler = new Handler(internalPlaybackThread.getLooper(), this);
|
||||
}
|
||||
|
||||
public void setSourceProvider(SampleSourceProvider sourceProvider) {
|
||||
handler.obtainMessage(MSG_SET_SOURCE_PROVIDER, sourceProvider).sendToTarget();
|
||||
public void setMediaSource(MediaSource mediaSource) {
|
||||
handler.obtainMessage(MSG_SET_MEDIA_SOURCE, mediaSource).sendToTarget();
|
||||
}
|
||||
|
||||
public void setPlayWhenReady(boolean playWhenReady) {
|
||||
handler.obtainMessage(MSG_SET_PLAY_WHEN_READY, playWhenReady ? 1 : 0, 0).sendToTarget();
|
||||
}
|
||||
|
||||
public void seekTo(int sourceIndex, long positionUs) {
|
||||
handler.obtainMessage(MSG_SEEK_TO, sourceIndex, -1, positionUs).sendToTarget();
|
||||
public void seekTo(int periodIndex, long positionUs) {
|
||||
handler.obtainMessage(MSG_SEEK_TO, periodIndex, -1, positionUs).sendToTarget();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
|
|
@ -205,15 +205,15 @@ import java.util.ArrayList;
|
|||
handler.sendEmptyMessage(MSG_TRACK_SELECTION_INVALIDATED);
|
||||
}
|
||||
|
||||
// SampleSource.Callback implementation.
|
||||
// MediaPeriod.Callback implementation.
|
||||
|
||||
@Override
|
||||
public void onSourcePrepared(SampleSource source) {
|
||||
handler.obtainMessage(MSG_SOURCE_PREPARED, source).sendToTarget();
|
||||
public void onPeriodPrepared(MediaPeriod source) {
|
||||
handler.obtainMessage(MSG_PERIOD_PREPARED, source).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(SampleSource source) {
|
||||
public void onContinueLoadingRequested(MediaPeriod source) {
|
||||
handler.obtainMessage(MSG_SOURCE_CONTINUE_LOADING_REQUESTED, source).sendToTarget();
|
||||
}
|
||||
|
||||
|
|
@ -223,8 +223,8 @@ import java.util.ArrayList;
|
|||
public boolean handleMessage(Message msg) {
|
||||
try {
|
||||
switch (msg.what) {
|
||||
case MSG_SET_SOURCE_PROVIDER: {
|
||||
setSourceProviderInternal((SampleSourceProvider) msg.obj);
|
||||
case MSG_SET_MEDIA_SOURCE: {
|
||||
setMediaSourceInternal((MediaSource) msg.obj);
|
||||
return true;
|
||||
}
|
||||
case MSG_SET_PLAY_WHEN_READY: {
|
||||
|
|
@ -247,12 +247,12 @@ import java.util.ArrayList;
|
|||
releaseInternal();
|
||||
return true;
|
||||
}
|
||||
case MSG_SOURCE_PREPARED: {
|
||||
timeline.handleSourcePrepared((SampleSource) msg.obj);
|
||||
case MSG_PERIOD_PREPARED: {
|
||||
timeline.handlePeriodPrepared((MediaPeriod) msg.obj);
|
||||
return true;
|
||||
}
|
||||
case MSG_SOURCE_CONTINUE_LOADING_REQUESTED: {
|
||||
timeline.handleContinueLoadingRequested((SampleSource) msg.obj);
|
||||
timeline.handleContinueLoadingRequested((MediaPeriod) msg.obj);
|
||||
return true;
|
||||
}
|
||||
case MSG_TRACK_SELECTION_INVALIDATED: {
|
||||
|
|
@ -301,14 +301,14 @@ import java.util.ArrayList;
|
|||
}
|
||||
}
|
||||
|
||||
private void setSourceProviderInternal(SampleSourceProvider sourceProvider) {
|
||||
private void setMediaSourceInternal(MediaSource mediaSource) {
|
||||
try {
|
||||
resetInternal();
|
||||
sampleSourceProvider = sourceProvider;
|
||||
this.mediaSource = mediaSource;
|
||||
setState(ExoPlayer.STATE_BUFFERING);
|
||||
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
||||
} finally {
|
||||
eventHandler.sendEmptyMessage(MSG_SET_SOURCE_PROVIDER_ACK);
|
||||
eventHandler.sendEmptyMessage(MSG_SET_MEDIA_SOURCE_ACK);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -348,18 +348,18 @@ import java.util.ArrayList;
|
|||
}
|
||||
|
||||
private void updatePlaybackPositions() throws ExoPlaybackException {
|
||||
SampleSource sampleSource = timeline.getSampleSource();
|
||||
if (sampleSource == null) {
|
||||
MediaPeriod mediaPeriod = timeline.getPeriod();
|
||||
if (mediaPeriod == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the duration.
|
||||
if (playbackInfo.durationUs == C.UNSET_TIME_US) {
|
||||
playbackInfo.durationUs = sampleSource.getDurationUs();
|
||||
playbackInfo.durationUs = mediaPeriod.getDurationUs();
|
||||
}
|
||||
|
||||
// Update the playback position.
|
||||
long positionUs = sampleSource.readDiscontinuity();
|
||||
long positionUs = mediaPeriod.readDiscontinuity();
|
||||
if (positionUs != C.UNSET_TIME_US) {
|
||||
resetInternalPosition(positionUs);
|
||||
} else {
|
||||
|
|
@ -369,7 +369,7 @@ import java.util.ArrayList;
|
|||
} else {
|
||||
internalPositionUs = standaloneMediaClock.getPositionUs();
|
||||
}
|
||||
positionUs = internalPositionUs - timeline.playingSource.offsetUs;
|
||||
positionUs = internalPositionUs - timeline.playingPeriod.offsetUs;
|
||||
}
|
||||
playbackInfo.positionUs = positionUs;
|
||||
elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
|
||||
|
|
@ -379,7 +379,7 @@ import java.util.ArrayList;
|
|||
if (enabledRenderers.length == 0) {
|
||||
bufferedPositionUs = C.END_OF_SOURCE_US;
|
||||
} else {
|
||||
bufferedPositionUs = sampleSource.getBufferedPositionUs();
|
||||
bufferedPositionUs = mediaPeriod.getBufferedPositionUs();
|
||||
}
|
||||
playbackInfo.bufferedPositionUs = bufferedPositionUs;
|
||||
}
|
||||
|
|
@ -387,10 +387,10 @@ import java.util.ArrayList;
|
|||
private void doSomeWork() throws ExoPlaybackException, IOException {
|
||||
long operationStartTimeMs = SystemClock.elapsedRealtime();
|
||||
|
||||
timeline.updateSources();
|
||||
if (timeline.getSampleSource() == null) {
|
||||
timeline.updatePeriods();
|
||||
if (timeline.getPeriod() == null) {
|
||||
// We're still waiting for the first source to be prepared.
|
||||
timeline.maybeThrowSourcePrepareError();
|
||||
timeline.maybeThrowPeriodPrepareError();
|
||||
scheduleNextOperation(MSG_DO_SOME_WORK, operationStartTimeMs, PREPARING_SOURCE_INTERVAL_MS);
|
||||
return;
|
||||
}
|
||||
|
|
@ -416,7 +416,7 @@ import java.util.ArrayList;
|
|||
}
|
||||
|
||||
if (!allRenderersReadyOrEnded) {
|
||||
timeline.maybeThrowSourcePrepareError();
|
||||
timeline.maybeThrowPeriodPrepareError();
|
||||
}
|
||||
|
||||
if (allRenderersEnded && (playbackInfo.durationUs == C.UNSET_TIME_US
|
||||
|
|
@ -460,9 +460,9 @@ import java.util.ArrayList;
|
|||
}
|
||||
}
|
||||
|
||||
private void seekToInternal(int sourceIndex, long seekPositionUs) throws ExoPlaybackException {
|
||||
private void seekToInternal(int periodIndex, long seekPositionUs) throws ExoPlaybackException {
|
||||
try {
|
||||
if (sourceIndex == playbackInfo.sourceIndex
|
||||
if (periodIndex == playbackInfo.periodIndex
|
||||
&& (seekPositionUs / 1000) == (playbackInfo.positionUs / 1000)) {
|
||||
// Seek position equals the current position to the nearest millisecond. Do nothing.
|
||||
return;
|
||||
|
|
@ -471,17 +471,17 @@ import java.util.ArrayList;
|
|||
stopRenderers();
|
||||
rebuffering = false;
|
||||
|
||||
seekPositionUs = timeline.seekTo(sourceIndex, seekPositionUs);
|
||||
if (sourceIndex != playbackInfo.sourceIndex) {
|
||||
playbackInfo = new PlaybackInfo(sourceIndex);
|
||||
seekPositionUs = timeline.seekTo(periodIndex, seekPositionUs);
|
||||
if (periodIndex != playbackInfo.periodIndex) {
|
||||
playbackInfo = new PlaybackInfo(periodIndex);
|
||||
playbackInfo.positionUs = seekPositionUs;
|
||||
eventHandler.obtainMessage(MSG_SOURCE_CHANGED, playbackInfo).sendToTarget();
|
||||
eventHandler.obtainMessage(MSG_PERIOD_CHANGED, playbackInfo).sendToTarget();
|
||||
} else {
|
||||
playbackInfo.positionUs = seekPositionUs;
|
||||
}
|
||||
|
||||
updatePlaybackPositions();
|
||||
if (sampleSourceProvider != null) {
|
||||
if (mediaSource != null) {
|
||||
setState(ExoPlayer.STATE_BUFFERING);
|
||||
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
||||
}
|
||||
|
|
@ -490,9 +490,9 @@ import java.util.ArrayList;
|
|||
}
|
||||
}
|
||||
|
||||
private void resetInternalPosition(long sourcePositionUs) throws ExoPlaybackException {
|
||||
long sourceOffsetUs = timeline.playingSource == null ? 0 : timeline.playingSource.offsetUs;
|
||||
internalPositionUs = sourceOffsetUs + sourcePositionUs;
|
||||
private void resetInternalPosition(long periodPositionUs) throws ExoPlaybackException {
|
||||
long sourceOffsetUs = timeline.playingPeriod == null ? 0 : timeline.playingPeriod.offsetUs;
|
||||
internalPositionUs = sourceOffsetUs + periodPositionUs;
|
||||
standaloneMediaClock.setPositionUs(internalPositionUs);
|
||||
for (TrackRenderer renderer : enabledRenderers) {
|
||||
renderer.reset(internalPositionUs);
|
||||
|
|
@ -529,7 +529,7 @@ import java.util.ArrayList;
|
|||
}
|
||||
}
|
||||
enabledRenderers = new TrackRenderer[0];
|
||||
sampleSourceProvider = null;
|
||||
mediaSource = null;
|
||||
timeline.reset();
|
||||
loadControl.reset();
|
||||
setIsLoading(false);
|
||||
|
|
@ -540,7 +540,7 @@ import java.util.ArrayList;
|
|||
for (ExoPlayerMessage message : messages) {
|
||||
message.target.handleMessage(message.messageType, message.message);
|
||||
}
|
||||
if (sampleSourceProvider != null) {
|
||||
if (mediaSource != null) {
|
||||
// The message may have caused something to change that now requires us to do work.
|
||||
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
||||
}
|
||||
|
|
@ -559,7 +559,7 @@ import java.util.ArrayList;
|
|||
}
|
||||
|
||||
private void reselectTracksInternal() throws ExoPlaybackException {
|
||||
if (timeline.getSampleSource() == null) {
|
||||
if (timeline.getPeriod() == null) {
|
||||
// We don't have tracks yet, so we don't care.
|
||||
return;
|
||||
}
|
||||
|
|
@ -569,7 +569,7 @@ import java.util.ArrayList;
|
|||
}
|
||||
|
||||
/**
|
||||
* Keeps track of the {@link Source}s of media being played in the timeline.
|
||||
* Keeps track of the {@link Period}s of media being played in the timeline.
|
||||
*/
|
||||
private final class Timeline {
|
||||
|
||||
|
|
@ -578,107 +578,107 @@ import java.util.ArrayList;
|
|||
public boolean isReady;
|
||||
public boolean isEnded;
|
||||
|
||||
private Source playingSource;
|
||||
private Source readingSource;
|
||||
private Source loadingSource;
|
||||
private Period playingPeriod;
|
||||
private Period readingPeriod;
|
||||
private Period loadingPeriod;
|
||||
|
||||
private int pendingSourceIndex;
|
||||
private long playingSourceEndPositionUs;
|
||||
private int pendingPeriodIndex;
|
||||
private long playingPeriodEndPositionUs;
|
||||
|
||||
public Timeline(TrackRenderer[] renderers) {
|
||||
this.renderers = renderers;
|
||||
playingSourceEndPositionUs = C.UNSET_TIME_US;
|
||||
playingPeriodEndPositionUs = C.UNSET_TIME_US;
|
||||
}
|
||||
|
||||
public SampleSource getSampleSource() throws ExoPlaybackException {
|
||||
return playingSource == null ? null : playingSource.sampleSource;
|
||||
public MediaPeriod getPeriod() throws ExoPlaybackException {
|
||||
return playingPeriod == null ? null : playingPeriod.mediaPeriod;
|
||||
}
|
||||
|
||||
public boolean haveSufficientBuffer(boolean rebuffering) {
|
||||
if (loadingSource == null) {
|
||||
if (loadingPeriod == null) {
|
||||
return false;
|
||||
}
|
||||
long positionUs = internalPositionUs - loadingSource.offsetUs;
|
||||
long bufferedPositionUs = !loadingSource.prepared ? 0
|
||||
: loadingSource.sampleSource.getBufferedPositionUs();
|
||||
long positionUs = internalPositionUs - loadingPeriod.offsetUs;
|
||||
long bufferedPositionUs = !loadingPeriod.prepared ? 0
|
||||
: loadingPeriod.mediaPeriod.getBufferedPositionUs();
|
||||
if (bufferedPositionUs == C.END_OF_SOURCE_US) {
|
||||
int sourceCount = sampleSourceProvider.getSourceCount();
|
||||
if (sourceCount != SampleSourceProvider.UNKNOWN_SOURCE_COUNT
|
||||
&& loadingSource.index == sourceCount - 1) {
|
||||
int periodCount = mediaSource.getPeriodCount();
|
||||
if (periodCount != MediaSource.UNKNOWN_PERIOD_COUNT
|
||||
&& loadingPeriod.index == periodCount - 1) {
|
||||
return true;
|
||||
}
|
||||
bufferedPositionUs = loadingSource.sampleSource.getDurationUs();
|
||||
bufferedPositionUs = loadingPeriod.mediaPeriod.getDurationUs();
|
||||
}
|
||||
return loadControl.shouldStartPlayback(bufferedPositionUs - positionUs, rebuffering);
|
||||
}
|
||||
|
||||
public void maybeThrowSourcePrepareError() throws IOException {
|
||||
if (loadingSource != null && !loadingSource.prepared
|
||||
&& (readingSource == null || readingSource.nextSource == loadingSource)) {
|
||||
public void maybeThrowPeriodPrepareError() throws IOException {
|
||||
if (loadingPeriod != null && !loadingPeriod.prepared
|
||||
&& (readingPeriod == null || readingPeriod.nextPeriod == loadingPeriod)) {
|
||||
for (TrackRenderer renderer : enabledRenderers) {
|
||||
if (!renderer.hasReadStreamToEnd()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
loadingSource.sampleSource.maybeThrowPrepareError();
|
||||
loadingPeriod.mediaPeriod.maybeThrowPrepareError();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSources() throws ExoPlaybackException, IOException {
|
||||
// TODO[playlists]: Let sample source providers invalidate sources that are already loaded.
|
||||
public void updatePeriods() throws ExoPlaybackException, IOException {
|
||||
// TODO[playlists]: Let MediaSource invalidate periods that are already loaded.
|
||||
|
||||
// Update the loading source.
|
||||
int sourceCount = sampleSourceProvider.getSourceCount();
|
||||
if (loadingSource == null
|
||||
|| (loadingSource.isFullyBuffered() && loadingSource.index
|
||||
- (playingSource != null ? playingSource.index : 0) < MAXIMUM_BUFFER_AHEAD_SOURCES)) {
|
||||
// Try and obtain the next source to start loading.
|
||||
int sourceIndex = loadingSource == null ? pendingSourceIndex : loadingSource.index + 1;
|
||||
if (sourceCount == SampleSourceProvider.UNKNOWN_SOURCE_COUNT || sourceIndex < sourceCount) {
|
||||
// Attempt to create the next source.
|
||||
SampleSource sampleSource = sampleSourceProvider.createSource(sourceIndex);
|
||||
if (sampleSource != null) {
|
||||
Source newSource = new Source(renderers, trackSelector, sampleSource, sourceIndex);
|
||||
if (loadingSource != null) {
|
||||
loadingSource.setNextSource(newSource);
|
||||
// Update the loading period.
|
||||
int periodCount = mediaSource.getPeriodCount();
|
||||
if (loadingPeriod == null
|
||||
|| (loadingPeriod.isFullyBuffered() && loadingPeriod.index
|
||||
- (playingPeriod != null ? playingPeriod.index : 0) < MAXIMUM_BUFFER_AHEAD_SOURCES)) {
|
||||
// Try and obtain the next period to start loading.
|
||||
int periodIndex = loadingPeriod == null ? pendingPeriodIndex : loadingPeriod.index + 1;
|
||||
if (periodCount == MediaSource.UNKNOWN_PERIOD_COUNT || periodIndex < periodCount) {
|
||||
// Attempt to create the next period.
|
||||
MediaPeriod mediaPeriod = mediaSource.createPeriod(periodIndex);
|
||||
if (mediaPeriod != null) {
|
||||
Period newPeriod = new Period(renderers, trackSelector, mediaPeriod, periodIndex);
|
||||
if (loadingPeriod != null) {
|
||||
loadingPeriod.setNextPeriod(newPeriod);
|
||||
}
|
||||
loadingSource = newSource;
|
||||
long startPositionUs = playingSource == null ? playbackInfo.positionUs : 0;
|
||||
loadingPeriod = newPeriod;
|
||||
long startPositionUs = playingPeriod == null ? playbackInfo.positionUs : 0;
|
||||
setIsLoading(true);
|
||||
loadingSource.sampleSource.prepare(ExoPlayerImplInternal.this,
|
||||
loadingPeriod.mediaPeriod.prepare(ExoPlayerImplInternal.this,
|
||||
loadControl.getAllocator(), startPositionUs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loadingSource == null || loadingSource.isFullyBuffered()) {
|
||||
if (loadingPeriod == null || loadingPeriod.isFullyBuffered()) {
|
||||
setIsLoading(false);
|
||||
} else if (loadingSource != null && loadingSource.needsContinueLoading) {
|
||||
} else if (loadingPeriod != null && loadingPeriod.needsContinueLoading) {
|
||||
maybeContinueLoading();
|
||||
}
|
||||
|
||||
if (playingSource == null) {
|
||||
// We're waiting for the first source to be prepared.
|
||||
if (playingPeriod == null) {
|
||||
// We're waiting for the first period to be prepared.
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the playing and reading sources.
|
||||
if (playingSourceEndPositionUs == C.UNSET_TIME_US && playingSource.isFullyBuffered()) {
|
||||
playingSourceEndPositionUs = playingSource.offsetUs
|
||||
+ playingSource.sampleSource.getDurationUs();
|
||||
// Update the playing and reading periods.
|
||||
if (playingPeriodEndPositionUs == C.UNSET_TIME_US && playingPeriod.isFullyBuffered()) {
|
||||
playingPeriodEndPositionUs = playingPeriod.offsetUs
|
||||
+ playingPeriod.mediaPeriod.getDurationUs();
|
||||
}
|
||||
while (playingSource != readingSource && playingSource.nextSource != null
|
||||
&& internalPositionUs >= playingSource.nextSource.offsetUs) {
|
||||
while (playingPeriod != readingPeriod && playingPeriod.nextPeriod != null
|
||||
&& internalPositionUs >= playingPeriod.nextPeriod.offsetUs) {
|
||||
// All enabled renderers' streams have been read to the end, and the playback position
|
||||
// reached the end of the playing source, so advance playback to the next source.
|
||||
playingSource.release();
|
||||
setPlayingSource(playingSource.nextSource);
|
||||
playbackInfo = new PlaybackInfo(playingSource.index);
|
||||
// reached the end of the playing period, so advance playback to the next period.
|
||||
playingPeriod.release();
|
||||
setPlayingPeriod(playingPeriod.nextPeriod);
|
||||
playbackInfo = new PlaybackInfo(playingPeriod.index);
|
||||
updatePlaybackPositions();
|
||||
eventHandler.obtainMessage(MSG_SOURCE_CHANGED, playbackInfo).sendToTarget();
|
||||
eventHandler.obtainMessage(MSG_PERIOD_CHANGED, playbackInfo).sendToTarget();
|
||||
}
|
||||
updateTimelineState();
|
||||
if (readingSource == null) {
|
||||
if (readingPeriod == null) {
|
||||
// The renderers have their final TrackStreams.
|
||||
return;
|
||||
}
|
||||
|
|
@ -687,104 +687,104 @@ import java.util.ArrayList;
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (readingSource.nextSource != null && readingSource.nextSource.prepared) {
|
||||
TrackSelectionArray oldTrackSelections = readingSource.trackSelections;
|
||||
readingSource = readingSource.nextSource;
|
||||
TrackSelectionArray newTrackSelections = readingSource.trackSelections;
|
||||
TrackGroupArray groups = readingSource.sampleSource.getTrackGroups();
|
||||
if (readingPeriod.nextPeriod != null && readingPeriod.nextPeriod.prepared) {
|
||||
TrackSelectionArray oldTrackSelections = readingPeriod.trackSelections;
|
||||
readingPeriod = readingPeriod.nextPeriod;
|
||||
TrackSelectionArray newTrackSelections = readingPeriod.trackSelections;
|
||||
TrackGroupArray groups = readingPeriod.mediaPeriod.getTrackGroups();
|
||||
for (int i = 0; i < renderers.length; i++) {
|
||||
TrackRenderer renderer = renderers[i];
|
||||
TrackSelection oldSelection = oldTrackSelections.get(i);
|
||||
TrackSelection newSelection = newTrackSelections.get(i);
|
||||
if (oldSelection != null) {
|
||||
if (newSelection != null) {
|
||||
// Replace the renderer's TrackStream so the transition to playing the next source can
|
||||
// Replace the renderer's TrackStream so the transition to playing the next period can
|
||||
// be seamless.
|
||||
Format[] formats = new Format[newSelection.length];
|
||||
for (int j = 0; j < formats.length; j++) {
|
||||
formats[j] = groups.get(newSelection.group).getFormat(newSelection.getTrack(j));
|
||||
}
|
||||
renderer.replaceTrackStream(formats, readingSource.trackStreams[i],
|
||||
readingSource.offsetUs);
|
||||
renderer.replaceTrackStream(formats, readingPeriod.trackStreams[i],
|
||||
readingPeriod.offsetUs);
|
||||
} else {
|
||||
// The renderer will be disabled when transitioning to playing the next source. Mark
|
||||
// The renderer will be disabled when transitioning to playing the next period. Mark
|
||||
// the TrackStream as final to play out any remaining data.
|
||||
renderer.setCurrentTrackStreamIsFinal();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (sourceCount != SampleSourceProvider.UNKNOWN_SOURCE_COUNT
|
||||
&& readingSource.index == sourceCount - 1) {
|
||||
readingSource = null;
|
||||
// This is the last source, so signal the renderers to read the end of the stream.
|
||||
} else if (periodCount != MediaSource.UNKNOWN_PERIOD_COUNT
|
||||
&& readingPeriod.index == periodCount - 1) {
|
||||
readingPeriod = null;
|
||||
// This is the last period, so signal the renderers to read the end of the stream.
|
||||
for (TrackRenderer renderer : enabledRenderers) {
|
||||
renderer.setCurrentTrackStreamIsFinal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleSourcePrepared(SampleSource source) throws ExoPlaybackException {
|
||||
if (loadingSource == null || loadingSource.sampleSource != source) {
|
||||
public void handlePeriodPrepared(MediaPeriod period) throws ExoPlaybackException {
|
||||
if (loadingPeriod == null || loadingPeriod.mediaPeriod != period) {
|
||||
// Stale event.
|
||||
return;
|
||||
}
|
||||
long startPositionUs = playingSource == null ? playbackInfo.positionUs : 0;
|
||||
loadingSource.handlePrepared(startPositionUs, loadControl);
|
||||
if (playingSource == null) {
|
||||
// This is the first prepared source, so start playing it.
|
||||
readingSource = loadingSource;
|
||||
setPlayingSource(readingSource);
|
||||
long startPositionUs = playingPeriod == null ? playbackInfo.positionUs : 0;
|
||||
loadingPeriod.handlePrepared(startPositionUs, loadControl);
|
||||
if (playingPeriod == null) {
|
||||
// This is the first prepared period, so start playing it.
|
||||
readingPeriod = loadingPeriod;
|
||||
setPlayingPeriod(readingPeriod);
|
||||
updateTimelineState();
|
||||
}
|
||||
maybeContinueLoading();
|
||||
}
|
||||
|
||||
public void handleContinueLoadingRequested(SampleSource source) {
|
||||
if (loadingSource == null || loadingSource.sampleSource != source) {
|
||||
public void handleContinueLoadingRequested(MediaPeriod period) {
|
||||
if (loadingPeriod == null || loadingPeriod.mediaPeriod != period) {
|
||||
return;
|
||||
}
|
||||
maybeContinueLoading();
|
||||
}
|
||||
|
||||
private void maybeContinueLoading() {
|
||||
long nextLoadPositionUs = loadingSource.sampleSource.getNextLoadPositionUs();
|
||||
long nextLoadPositionUs = loadingPeriod.mediaPeriod.getNextLoadPositionUs();
|
||||
if (nextLoadPositionUs != C.END_OF_SOURCE_US) {
|
||||
long positionUs = internalPositionUs - loadingSource.offsetUs;
|
||||
long positionUs = internalPositionUs - loadingPeriod.offsetUs;
|
||||
long bufferedDurationUs = nextLoadPositionUs - positionUs;
|
||||
boolean continueLoading = loadControl.shouldContinueLoading(bufferedDurationUs);
|
||||
setIsLoading(continueLoading);
|
||||
if (continueLoading) {
|
||||
loadingSource.needsContinueLoading = false;
|
||||
loadingSource.sampleSource.continueLoading(positionUs);
|
||||
loadingPeriod.needsContinueLoading = false;
|
||||
loadingPeriod.mediaPeriod.continueLoading(positionUs);
|
||||
} else {
|
||||
loadingSource.needsContinueLoading = true;
|
||||
loadingPeriod.needsContinueLoading = true;
|
||||
}
|
||||
} else {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
public long seekTo(int sourceIndex, long seekPositionUs) throws ExoPlaybackException {
|
||||
// Clear the timeline, but keep the requested source if it is already prepared.
|
||||
Source source = playingSource;
|
||||
Source newPlayingSource = null;
|
||||
while (source != null) {
|
||||
if (source.index == sourceIndex && source.prepared) {
|
||||
newPlayingSource = source;
|
||||
public long seekTo(int periodIndex, long seekPositionUs) throws ExoPlaybackException {
|
||||
// Clear the timeline, but keep the requested period if it is already prepared.
|
||||
Period period = playingPeriod;
|
||||
Period newPlayingPeriod = null;
|
||||
while (period != null) {
|
||||
if (period.index == periodIndex && period.prepared) {
|
||||
newPlayingPeriod = period;
|
||||
} else {
|
||||
source.release();
|
||||
period.release();
|
||||
}
|
||||
source = source.nextSource;
|
||||
period = period.nextPeriod;
|
||||
}
|
||||
|
||||
if (newPlayingSource != null) {
|
||||
newPlayingSource.nextSource = null;
|
||||
setPlayingSource(newPlayingSource);
|
||||
if (newPlayingPeriod != null) {
|
||||
newPlayingPeriod.nextPeriod = null;
|
||||
setPlayingPeriod(newPlayingPeriod);
|
||||
updateTimelineState();
|
||||
readingSource = playingSource;
|
||||
loadingSource = playingSource;
|
||||
if (playingSource.hasEnabledTracks) {
|
||||
seekPositionUs = playingSource.sampleSource.seekToUs(seekPositionUs);
|
||||
readingPeriod = playingPeriod;
|
||||
loadingPeriod = playingPeriod;
|
||||
if (playingPeriod.hasEnabledTracks) {
|
||||
seekPositionUs = playingPeriod.mediaPeriod.seekToUs(seekPositionUs);
|
||||
}
|
||||
resetInternalPosition(seekPositionUs);
|
||||
maybeContinueLoading();
|
||||
|
|
@ -794,51 +794,51 @@ import java.util.ArrayList;
|
|||
renderer.disable();
|
||||
}
|
||||
enabledRenderers = new TrackRenderer[0];
|
||||
playingSource = null;
|
||||
readingSource = null;
|
||||
loadingSource = null;
|
||||
pendingSourceIndex = sourceIndex;
|
||||
playingPeriod = null;
|
||||
readingPeriod = null;
|
||||
loadingPeriod = null;
|
||||
pendingPeriodIndex = periodIndex;
|
||||
resetInternalPosition(seekPositionUs);
|
||||
}
|
||||
return seekPositionUs;
|
||||
}
|
||||
|
||||
public void reselectTracks() throws ExoPlaybackException {
|
||||
// Reselect tracks on each source in turn, until the selection changes.
|
||||
Source source = playingSource;
|
||||
boolean selectionsChangedForReadSource = true;
|
||||
// Reselect tracks on each period in turn, until the selection changes.
|
||||
Period period = playingPeriod;
|
||||
boolean selectionsChangedForReadPeriod = true;
|
||||
while (true) {
|
||||
if (source == null || !source.prepared) {
|
||||
// The reselection did not change any prepared sources.
|
||||
if (period == null || !period.prepared) {
|
||||
// The reselection did not change any prepared periods.
|
||||
return;
|
||||
}
|
||||
if (source.selectTracks()) {
|
||||
if (period.selectTracks()) {
|
||||
break;
|
||||
}
|
||||
if (source == readingSource) {
|
||||
// The track reselection didn't affect any source that has been read.
|
||||
selectionsChangedForReadSource = false;
|
||||
if (period == readingPeriod) {
|
||||
// The track reselection didn't affect any period that has been read.
|
||||
selectionsChangedForReadPeriod = false;
|
||||
}
|
||||
source = source.nextSource;
|
||||
period = period.nextPeriod;
|
||||
}
|
||||
|
||||
if (selectionsChangedForReadSource) {
|
||||
// Release everything after the playing source because a renderer may have read data from a
|
||||
if (selectionsChangedForReadPeriod) {
|
||||
// Release everything after the playing period because a renderer may have read data from a
|
||||
// track whose selection has now changed.
|
||||
source = playingSource.nextSource;
|
||||
while (source != null) {
|
||||
source.release();
|
||||
source = source.nextSource;
|
||||
period = playingPeriod.nextPeriod;
|
||||
while (period != null) {
|
||||
period.release();
|
||||
period = period.nextPeriod;
|
||||
}
|
||||
playingSource.nextSource = null;
|
||||
readingSource = playingSource;
|
||||
loadingSource = playingSource;
|
||||
playingSourceEndPositionUs = C.UNSET_TIME_US;
|
||||
playingPeriod.nextPeriod = null;
|
||||
readingPeriod = playingPeriod;
|
||||
loadingPeriod = playingPeriod;
|
||||
playingPeriodEndPositionUs = C.UNSET_TIME_US;
|
||||
|
||||
// Update streams for the new selection, recreating all streams if reading ahead.
|
||||
boolean recreateStreams = readingSource != playingSource;
|
||||
TrackSelectionArray playingSourceOldTrackSelections = playingSource.sourceTrackSelections;
|
||||
playingSource.updateSourceTrackSelection(playbackInfo.positionUs, loadControl,
|
||||
boolean recreateStreams = readingPeriod != playingPeriod;
|
||||
TrackSelectionArray playingPeriodOldTrackSelections = playingPeriod.periodTrackSelections;
|
||||
playingPeriod.updatePeriodTrackSelection(playbackInfo.positionUs, loadControl,
|
||||
recreateStreams);
|
||||
|
||||
int enabledRendererCount = 0;
|
||||
|
|
@ -846,8 +846,8 @@ import java.util.ArrayList;
|
|||
for (int i = 0; i < renderers.length; i++) {
|
||||
TrackRenderer renderer = renderers[i];
|
||||
rendererWasEnabledFlags[i] = renderer.getState() != TrackRenderer.STATE_DISABLED;
|
||||
TrackSelection oldSelection = playingSourceOldTrackSelections.get(i);
|
||||
TrackSelection newSelection = playingSource.trackSelections.get(i);
|
||||
TrackSelection oldSelection = playingPeriodOldTrackSelections.get(i);
|
||||
TrackSelection newSelection = playingPeriod.trackSelections.get(i);
|
||||
if (newSelection != null) {
|
||||
enabledRendererCount++;
|
||||
}
|
||||
|
|
@ -868,52 +868,52 @@ import java.util.ArrayList;
|
|||
renderer.disable();
|
||||
}
|
||||
}
|
||||
trackSelector.onSelectionActivated(playingSource.trackSelectionData);
|
||||
trackSelector.onSelectionActivated(playingPeriod.trackSelectionData);
|
||||
enableRenderers(rendererWasEnabledFlags, enabledRendererCount);
|
||||
} else {
|
||||
// Release and re-prepare/buffer sources after the one whose selection changed.
|
||||
loadingSource = source;
|
||||
source = loadingSource.nextSource;
|
||||
while (source != null) {
|
||||
source.release();
|
||||
source = source.nextSource;
|
||||
// Release and re-prepare/buffer periods after the one whose selection changed.
|
||||
loadingPeriod = period;
|
||||
period = loadingPeriod.nextPeriod;
|
||||
while (period != null) {
|
||||
period.release();
|
||||
period = period.nextPeriod;
|
||||
}
|
||||
loadingSource.nextSource = null;
|
||||
long positionUs = Math.max(0, internalPositionUs - loadingSource.offsetUs);
|
||||
loadingSource.updateSourceTrackSelection(positionUs, loadControl, false);
|
||||
loadingPeriod.nextPeriod = null;
|
||||
long positionUs = Math.max(0, internalPositionUs - loadingPeriod.offsetUs);
|
||||
loadingPeriod.updatePeriodTrackSelection(positionUs, loadControl, false);
|
||||
}
|
||||
maybeContinueLoading();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
Source source = playingSource != null ? playingSource : loadingSource;
|
||||
while (source != null) {
|
||||
source.release();
|
||||
source = source.nextSource;
|
||||
Period period = playingPeriod != null ? playingPeriod : loadingPeriod;
|
||||
while (period != null) {
|
||||
period.release();
|
||||
period = period.nextPeriod;
|
||||
}
|
||||
isReady = false;
|
||||
isEnded = false;
|
||||
playingSource = null;
|
||||
readingSource = null;
|
||||
loadingSource = null;
|
||||
playingSourceEndPositionUs = C.UNSET_TIME_US;
|
||||
pendingSourceIndex = 0;
|
||||
playingPeriod = null;
|
||||
readingPeriod = null;
|
||||
loadingPeriod = null;
|
||||
playingPeriodEndPositionUs = C.UNSET_TIME_US;
|
||||
pendingPeriodIndex = 0;
|
||||
playbackInfo = new PlaybackInfo(0);
|
||||
eventHandler.obtainMessage(MSG_SOURCE_CHANGED, playbackInfo).sendToTarget();
|
||||
eventHandler.obtainMessage(MSG_PERIOD_CHANGED, playbackInfo).sendToTarget();
|
||||
}
|
||||
|
||||
private void setPlayingSource(Source source) throws ExoPlaybackException {
|
||||
private void setPlayingPeriod(Period period) throws ExoPlaybackException {
|
||||
int enabledRendererCount = 0;
|
||||
boolean[] rendererWasEnabledFlags = new boolean[renderers.length];
|
||||
for (int i = 0; i < renderers.length; i++) {
|
||||
TrackRenderer renderer = renderers[i];
|
||||
rendererWasEnabledFlags[i] = renderer.getState() != TrackRenderer.STATE_DISABLED;
|
||||
TrackSelection newSelection = source.trackSelections.get(i);
|
||||
TrackSelection newSelection = period.trackSelections.get(i);
|
||||
if (newSelection != null) {
|
||||
// The renderer should be enabled when playing the new source.
|
||||
// The renderer should be enabled when playing the new period.
|
||||
enabledRendererCount++;
|
||||
} else if (rendererWasEnabledFlags[i]) {
|
||||
// The renderer should be disabled when playing the new source.
|
||||
// The renderer should be disabled when playing the new period.
|
||||
if (renderer == rendererMediaClockSource) {
|
||||
// Sync standaloneMediaClock so that it can take over timing responsibilities.
|
||||
standaloneMediaClock.setPositionUs(rendererMediaClock.getPositionUs());
|
||||
|
|
@ -925,29 +925,29 @@ import java.util.ArrayList;
|
|||
}
|
||||
}
|
||||
|
||||
trackSelector.onSelectionActivated(source.trackSelectionData);
|
||||
playingSource = source;
|
||||
playingSourceEndPositionUs = C.UNSET_TIME_US;
|
||||
trackSelector.onSelectionActivated(period.trackSelectionData);
|
||||
playingPeriod = period;
|
||||
playingPeriodEndPositionUs = C.UNSET_TIME_US;
|
||||
enableRenderers(rendererWasEnabledFlags, enabledRendererCount);
|
||||
}
|
||||
|
||||
private void updateTimelineState() {
|
||||
isReady = playingSourceEndPositionUs == C.UNSET_TIME_US
|
||||
|| internalPositionUs < playingSourceEndPositionUs
|
||||
|| (playingSource.nextSource != null && playingSource.nextSource.prepared);
|
||||
int sourceCount = sampleSourceProvider.getSourceCount();
|
||||
isEnded = sourceCount != SampleSourceProvider.UNKNOWN_SOURCE_COUNT
|
||||
&& playingSource.index == sourceCount - 1;
|
||||
isReady = playingPeriodEndPositionUs == C.UNSET_TIME_US
|
||||
|| internalPositionUs < playingPeriodEndPositionUs
|
||||
|| (playingPeriod.nextPeriod != null && playingPeriod.nextPeriod.prepared);
|
||||
int periodCount = mediaSource.getPeriodCount();
|
||||
isEnded = periodCount != MediaSource.UNKNOWN_PERIOD_COUNT
|
||||
&& playingPeriod.index == periodCount - 1;
|
||||
}
|
||||
|
||||
private void enableRenderers(boolean[] rendererWasEnabledFlags, int enabledRendererCount)
|
||||
throws ExoPlaybackException {
|
||||
enabledRenderers = new TrackRenderer[enabledRendererCount];
|
||||
enabledRendererCount = 0;
|
||||
TrackGroupArray trackGroups = playingSource.sampleSource.getTrackGroups();
|
||||
TrackGroupArray trackGroups = playingPeriod.mediaPeriod.getTrackGroups();
|
||||
for (int i = 0; i < renderers.length; i++) {
|
||||
TrackRenderer renderer = renderers[i];
|
||||
TrackSelection newSelection = playingSource.trackSelections.get(i);
|
||||
TrackSelection newSelection = playingPeriod.trackSelections.get(i);
|
||||
if (newSelection != null) {
|
||||
enabledRenderers[enabledRendererCount++] = renderer;
|
||||
if (renderer.getState() == TrackRenderer.STATE_DISABLED) {
|
||||
|
|
@ -961,8 +961,8 @@ import java.util.ArrayList;
|
|||
formats[j] = trackGroups.get(newSelection.group).getFormat(newSelection.getTrack(j));
|
||||
}
|
||||
// Enable the renderer.
|
||||
renderer.enable(formats, playingSource.trackStreams[i], internalPositionUs, joining,
|
||||
playingSource.offsetUs);
|
||||
renderer.enable(formats, playingPeriod.trackStreams[i], internalPositionUs, joining,
|
||||
playingPeriod.offsetUs);
|
||||
MediaClock mediaClock = renderer.getMediaClock();
|
||||
if (mediaClock != null) {
|
||||
if (rendererMediaClock != null) {
|
||||
|
|
@ -984,58 +984,58 @@ import java.util.ArrayList;
|
|||
}
|
||||
|
||||
/**
|
||||
* Represents a {@link SampleSource} with information required to play it as part of a timeline.
|
||||
* Represents a {@link MediaPeriod} with information required to play it as part of a timeline.
|
||||
*/
|
||||
private static final class Source {
|
||||
private static final class Period {
|
||||
|
||||
private final TrackRenderer[] renderers;
|
||||
private final TrackSelector trackSelector;
|
||||
|
||||
public final SampleSource sampleSource;
|
||||
public final MediaPeriod mediaPeriod;
|
||||
public final int index;
|
||||
public final TrackStream[] trackStreams;
|
||||
|
||||
public boolean prepared;
|
||||
public boolean hasEnabledTracks;
|
||||
public long offsetUs;
|
||||
public Source nextSource;
|
||||
public Period nextPeriod;
|
||||
public boolean needsContinueLoading;
|
||||
|
||||
private Object trackSelectionData;
|
||||
private TrackSelectionArray trackSelections;
|
||||
private TrackSelectionArray sourceTrackSelections;
|
||||
private TrackSelectionArray periodTrackSelections;
|
||||
|
||||
public Source(TrackRenderer[] renderers, TrackSelector trackSelector, SampleSource sampleSource,
|
||||
public Period(TrackRenderer[] renderers, TrackSelector trackSelector, MediaPeriod mediaPeriod,
|
||||
int index) {
|
||||
this.renderers = renderers;
|
||||
this.trackSelector = trackSelector;
|
||||
this.sampleSource = sampleSource;
|
||||
this.mediaPeriod = mediaPeriod;
|
||||
this.index = index;
|
||||
trackStreams = new TrackStream[renderers.length];
|
||||
}
|
||||
|
||||
public void setNextSource(Source nextSource) {
|
||||
this.nextSource = nextSource;
|
||||
nextSource.offsetUs = offsetUs + sampleSource.getDurationUs();
|
||||
public void setNextPeriod(Period nextPeriod) {
|
||||
this.nextPeriod = nextPeriod;
|
||||
nextPeriod.offsetUs = offsetUs + mediaPeriod.getDurationUs();
|
||||
}
|
||||
|
||||
public boolean isFullyBuffered() {
|
||||
return prepared && (!hasEnabledTracks
|
||||
|| sampleSource.getBufferedPositionUs() == C.END_OF_SOURCE_US);
|
||||
|| mediaPeriod.getBufferedPositionUs() == C.END_OF_SOURCE_US);
|
||||
}
|
||||
|
||||
public void handlePrepared(long positionUs, LoadControl loadControl)
|
||||
throws ExoPlaybackException {
|
||||
prepared = true;
|
||||
selectTracks();
|
||||
updateSourceTrackSelection(positionUs, loadControl, false);
|
||||
updatePeriodTrackSelection(positionUs, loadControl, false);
|
||||
}
|
||||
|
||||
public boolean selectTracks() throws ExoPlaybackException {
|
||||
Pair<TrackSelectionArray, Object> result =
|
||||
trackSelector.selectTracks(renderers, sampleSource.getTrackGroups());
|
||||
trackSelector.selectTracks(renderers, mediaPeriod.getTrackGroups());
|
||||
TrackSelectionArray newTrackSelections = result.first;
|
||||
if (newTrackSelections.equals(sourceTrackSelections)) {
|
||||
if (newTrackSelections.equals(periodTrackSelections)) {
|
||||
return false;
|
||||
}
|
||||
trackSelections = newTrackSelections;
|
||||
|
|
@ -1043,14 +1043,14 @@ import java.util.ArrayList;
|
|||
return true;
|
||||
}
|
||||
|
||||
public void updateSourceTrackSelection(long positionUs, LoadControl loadControl,
|
||||
public void updatePeriodTrackSelection(long positionUs, LoadControl loadControl,
|
||||
boolean forceRecreateStreams) throws ExoPlaybackException {
|
||||
// Populate lists of streams that are being disabled/newly enabled.
|
||||
ArrayList<TrackStream> oldStreams = new ArrayList<>();
|
||||
ArrayList<TrackSelection> newSelections = new ArrayList<>();
|
||||
for (int i = 0; i < trackSelections.length; i++) {
|
||||
TrackSelection oldSelection =
|
||||
sourceTrackSelections == null ? null : sourceTrackSelections.get(i);
|
||||
periodTrackSelections == null ? null : periodTrackSelections.get(i);
|
||||
TrackSelection newSelection = trackSelections.get(i);
|
||||
if (forceRecreateStreams || !Util.areEqual(oldSelection, newSelection)) {
|
||||
if (oldSelection != null) {
|
||||
|
|
@ -1062,9 +1062,9 @@ import java.util.ArrayList;
|
|||
}
|
||||
}
|
||||
|
||||
// Disable streams on the source and get new streams for updated/newly-enabled tracks.
|
||||
TrackStream[] newStreams = sampleSource.selectTracks(oldStreams, newSelections, positionUs);
|
||||
sourceTrackSelections = trackSelections;
|
||||
// Disable streams on the period and get new streams for updated/newly-enabled tracks.
|
||||
TrackStream[] newStreams = mediaPeriod.selectTracks(oldStreams, newSelections, positionUs);
|
||||
periodTrackSelections = trackSelections;
|
||||
hasEnabledTracks = false;
|
||||
for (int i = 0; i < trackSelections.length; i++) {
|
||||
TrackSelection selection = trackSelections.get(i);
|
||||
|
|
@ -1082,15 +1082,15 @@ import java.util.ArrayList;
|
|||
}
|
||||
|
||||
// The track selection has changed.
|
||||
loadControl.onTrackSelections(renderers, sampleSource.getTrackGroups(), trackSelections);
|
||||
loadControl.onTrackSelections(renderers, mediaPeriod.getTrackGroups(), trackSelections);
|
||||
}
|
||||
|
||||
public void release() {
|
||||
try {
|
||||
sampleSource.release();
|
||||
mediaPeriod.release();
|
||||
} catch (RuntimeException e) {
|
||||
// There's nothing we can do.
|
||||
Log.e(TAG, "Source release failed.", e);
|
||||
Log.e(TAG, "Period release failed.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -652,7 +652,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Invoked when a new format is read from the upstream {@link SampleSource}.
|
||||
* Invoked when a new format is read from the upstream {@link MediaPeriod}.
|
||||
*
|
||||
* @param newFormat The new format.
|
||||
* @throws ExoPlaybackException If an error occurs reinitializing the {@link MediaCodec}.
|
||||
|
|
|
|||
|
|
@ -21,67 +21,67 @@ import java.io.IOException;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A source of media.
|
||||
* A source of a single period of media.
|
||||
*/
|
||||
public interface SampleSource extends SequenceableLoader {
|
||||
public interface MediaPeriod extends SequenceableLoader {
|
||||
|
||||
/**
|
||||
* A callback to be notified of {@link SampleSource} events.
|
||||
* A callback to be notified of {@link MediaPeriod} events.
|
||||
*/
|
||||
interface Callback extends SequenceableLoader.Callback<SampleSource> {
|
||||
interface Callback extends SequenceableLoader.Callback<MediaPeriod> {
|
||||
|
||||
/**
|
||||
* Invoked by the source when preparation completes.
|
||||
* Invoked when preparation completes.
|
||||
* <p>
|
||||
* May be called from any thread. After invoking this method, the source can expect
|
||||
* {@link #selectTracks(List, List, long)} to be invoked when the initial track selection.
|
||||
* May be called from any thread. After invoking this method, the {@link MediaPeriod} can expect
|
||||
* for {@link #selectTracks(List, List, long)} to be invoked with the initial track selection.
|
||||
*
|
||||
* @param source The prepared source.
|
||||
* @param mediaPeriod The prepared {@link MediaPeriod}.
|
||||
*/
|
||||
void onSourcePrepared(SampleSource source);
|
||||
void onPeriodPrepared(MediaPeriod mediaPeriod);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts preparation of the source.
|
||||
* Starts preparation of the period.
|
||||
* <p>
|
||||
* {@link Callback#onSourcePrepared(SampleSource)} is invoked when preparation completes. If
|
||||
* {@link Callback#onPeriodPrepared(MediaPeriod)} is invoked when preparation completes. If
|
||||
* preparation fails, {@link #maybeThrowPrepareError()} will throw an {@link IOException} if
|
||||
* invoked.
|
||||
*
|
||||
* @param callback A callback to receive updates from the source.
|
||||
* @param callback A callback to receive updates from the period.
|
||||
* @param allocator An {@link Allocator} from which to obtain media buffer allocations.
|
||||
* @param positionUs The player's current playback position.
|
||||
*/
|
||||
void prepare(Callback callback, Allocator allocator, long positionUs);
|
||||
|
||||
/**
|
||||
* Throws an error that's preventing the source from becoming prepared. Does nothing if no such
|
||||
* Throws an error that's preventing the period from becoming prepared. Does nothing if no such
|
||||
* error exists.
|
||||
* <p>
|
||||
* This method should only be called before the source has completed preparation.
|
||||
* This method should only be called before the period has completed preparation.
|
||||
*
|
||||
* @throws IOException The underlying error.
|
||||
*/
|
||||
void maybeThrowPrepareError() throws IOException;
|
||||
|
||||
/**
|
||||
* Returns the duration of the source in microseconds, or {@link C#UNSET_TIME_US} if not known.
|
||||
* Returns the duration of the period in microseconds, or {@link C#UNSET_TIME_US} if not known.
|
||||
* <p>
|
||||
* If {@link #getBufferedPositionUs()} returns {@link C#END_OF_SOURCE_US}, the duration is
|
||||
* guaranteed to be known.
|
||||
* <p>
|
||||
* This method should only be called after the source has been prepared.
|
||||
* This method should only be called after the period has been prepared.
|
||||
*
|
||||
* @return The duration of the source in microseconds, or {@link C#UNSET_TIME_US} if the duration
|
||||
* @return The duration of the period in microseconds, or {@link C#UNSET_TIME_US} if the duration
|
||||
* is not known.
|
||||
*/
|
||||
long getDurationUs();
|
||||
|
||||
/**
|
||||
* Returns the {@link TrackGroup}s exposed by the source.
|
||||
* Returns the {@link TrackGroup}s exposed by the period.
|
||||
* <p>
|
||||
* This method should only be called after the source has been prepared.
|
||||
* This method should only be called after the period has been prepared.
|
||||
*
|
||||
* @return The {@link TrackGroup}s.
|
||||
*/
|
||||
|
|
@ -95,7 +95,7 @@ public interface SampleSource extends SequenceableLoader {
|
|||
* must have a {@link TrackSelection#group} index distinct from those of currently enabled tracks,
|
||||
* except for those being unselected.
|
||||
* <p>
|
||||
* This method should only be called after the source has been prepared.
|
||||
* This method should only be called after the period has been prepared.
|
||||
*
|
||||
* @param oldStreams {@link TrackStream}s corresponding to tracks being unselected. May be empty
|
||||
* but must not be null.
|
||||
|
|
@ -111,7 +111,7 @@ public interface SampleSource extends SequenceableLoader {
|
|||
* Attempts to read a discontinuity.
|
||||
* <p>
|
||||
* After this method has returned a value other than {@link C#UNSET_TIME_US}, all
|
||||
* {@link TrackStream}s provided by the source are guaranteed to start from a key frame.
|
||||
* {@link TrackStream}s provided by the period are guaranteed to start from a key frame.
|
||||
*
|
||||
* @return If a discontinuity was read then the playback position in microseconds after the
|
||||
* discontinuity. Else {@link C#UNSET_TIME_US}.
|
||||
|
|
@ -131,20 +131,20 @@ public interface SampleSource extends SequenceableLoader {
|
|||
/**
|
||||
* Attempts to seek to the specified position in microseconds.
|
||||
* <p>
|
||||
* After this method has been called, all {@link TrackStream}s provided by the source are
|
||||
* After this method has been called, all {@link TrackStream}s provided by the period are
|
||||
* guaranteed to start from a key frame.
|
||||
* <p>
|
||||
* This method should only be called when at least one track is selected.
|
||||
*
|
||||
* @param positionUs The seek position in microseconds.
|
||||
* @return The actual position to which the source was seeked, in microseconds.
|
||||
* @return The actual position to which the period was seeked, in microseconds.
|
||||
*/
|
||||
long seekToUs(long positionUs);
|
||||
|
||||
/**
|
||||
* Releases the source.
|
||||
* Releases the period.
|
||||
* <p>
|
||||
* This method should be called when the source is no longer required. It may be called in any
|
||||
* This method should be called when the period is no longer required. It may be called in any
|
||||
* state.
|
||||
*/
|
||||
void release();
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2;
|
||||
|
||||
/**
|
||||
* A source of media consisting of one or more {@link MediaPeriod}s.
|
||||
*/
|
||||
public interface MediaSource {
|
||||
|
||||
/**
|
||||
* Returned by {@link #getPeriodCount()} if the number of periods is not known.
|
||||
*/
|
||||
int UNKNOWN_PERIOD_COUNT = -1;
|
||||
|
||||
/**
|
||||
* Returns the number of periods in the source, or {@link #UNKNOWN_PERIOD_COUNT} if the number
|
||||
* of periods is not yet known.
|
||||
*/
|
||||
int getPeriodCount();
|
||||
|
||||
/**
|
||||
* Returns a {@link MediaPeriod} corresponding to the period at the specified index, or
|
||||
* {@code null} if the period at the specified index is not yet available.
|
||||
*
|
||||
* @param index The index of the period. Must be less than {@link #getPeriodCount()} unless the
|
||||
* period count is {@link #UNKNOWN_PERIOD_COUNT}.
|
||||
* @return A {@link MediaPeriod}, or {@code null} if the source at the specified index is not yet
|
||||
* available.
|
||||
*/
|
||||
MediaPeriod createPeriod(int index);
|
||||
|
||||
}
|
||||
|
|
@ -24,13 +24,14 @@ import java.util.ArrayList;
|
|||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
|
||||
// TODO: Make this a MediaSource
|
||||
/**
|
||||
* Combines multiple {@link SampleSource} instances.
|
||||
* Merges multiple {@link MediaPeriod} instances.
|
||||
*/
|
||||
public final class MultiSampleSource implements SampleSource, SampleSource.Callback {
|
||||
public final class MultiMediaPeriod implements MediaPeriod, MediaPeriod.Callback {
|
||||
|
||||
private final SampleSource[] sources;
|
||||
private final IdentityHashMap<TrackStream, SampleSource> trackStreamSources;
|
||||
private final MediaPeriod[] periods;
|
||||
private final IdentityHashMap<TrackStream, MediaPeriod> trackStreamPeriods;
|
||||
private final int[] selectedTrackCounts;
|
||||
|
||||
private Callback callback;
|
||||
|
|
@ -39,28 +40,28 @@ public final class MultiSampleSource implements SampleSource, SampleSource.Callb
|
|||
private TrackGroupArray trackGroups;
|
||||
|
||||
private boolean seenFirstTrackSelection;
|
||||
private SampleSource[] enabledSources;
|
||||
private MediaPeriod[] enabledPeriods;
|
||||
private SequenceableLoader sequenceableLoader;
|
||||
|
||||
public MultiSampleSource(SampleSource... sources) {
|
||||
this.sources = sources;
|
||||
pendingChildPrepareCount = sources.length;
|
||||
trackStreamSources = new IdentityHashMap<>();
|
||||
selectedTrackCounts = new int[sources.length];
|
||||
public MultiMediaPeriod(MediaPeriod... periods) {
|
||||
this.periods = periods;
|
||||
pendingChildPrepareCount = periods.length;
|
||||
trackStreamPeriods = new IdentityHashMap<>();
|
||||
selectedTrackCounts = new int[periods.length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||
this.callback = callback;
|
||||
for (SampleSource source : sources) {
|
||||
source.prepare(this, allocator, positionUs);
|
||||
for (MediaPeriod period : periods) {
|
||||
period.prepare(this, allocator, positionUs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void maybeThrowPrepareError() throws IOException {
|
||||
for (SampleSource source : sources) {
|
||||
source.maybeThrowPrepareError();
|
||||
for (MediaPeriod period : periods) {
|
||||
period.maybeThrowPrepareError();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -78,25 +79,25 @@ public final class MultiSampleSource implements SampleSource, SampleSource.Callb
|
|||
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
|
||||
List<TrackSelection> newSelections, long positionUs) {
|
||||
TrackStream[] newStreams = new TrackStream[newSelections.size()];
|
||||
// Select tracks for each source.
|
||||
int enabledSourceCount = 0;
|
||||
for (int i = 0; i < sources.length; i++) {
|
||||
selectedTrackCounts[i] += selectTracks(sources[i], oldStreams, newSelections, positionUs,
|
||||
// Select tracks for each period.
|
||||
int enabledPeriodCount = 0;
|
||||
for (int i = 0; i < periods.length; i++) {
|
||||
selectedTrackCounts[i] += selectTracks(periods[i], oldStreams, newSelections, positionUs,
|
||||
newStreams, seenFirstTrackSelection);
|
||||
if (selectedTrackCounts[i] > 0) {
|
||||
enabledSourceCount++;
|
||||
enabledPeriodCount++;
|
||||
}
|
||||
}
|
||||
seenFirstTrackSelection = true;
|
||||
// Update the enabled sources.
|
||||
enabledSources = new SampleSource[enabledSourceCount];
|
||||
enabledSourceCount = 0;
|
||||
for (int i = 0; i < sources.length; i++) {
|
||||
// Update the enabled periods.
|
||||
enabledPeriods = new MediaPeriod[enabledPeriodCount];
|
||||
enabledPeriodCount = 0;
|
||||
for (int i = 0; i < periods.length; i++) {
|
||||
if (selectedTrackCounts[i] > 0) {
|
||||
enabledSources[enabledSourceCount++] = sources[i];
|
||||
enabledPeriods[enabledPeriodCount++] = periods[i];
|
||||
}
|
||||
}
|
||||
sequenceableLoader = new CompositeSequenceableLoader(enabledSources);
|
||||
sequenceableLoader = new CompositeSequenceableLoader(enabledPeriods);
|
||||
return newStreams;
|
||||
}
|
||||
|
||||
|
|
@ -112,18 +113,18 @@ public final class MultiSampleSource implements SampleSource, SampleSource.Callb
|
|||
|
||||
@Override
|
||||
public long readDiscontinuity() {
|
||||
long positionUs = enabledSources[0].readDiscontinuity();
|
||||
long positionUs = enabledPeriods[0].readDiscontinuity();
|
||||
if (positionUs != C.UNSET_TIME_US) {
|
||||
// It must be possible to seek additional sources to the new position.
|
||||
for (int i = 1; i < enabledSources.length; i++) {
|
||||
if (enabledSources[i].seekToUs(positionUs) != positionUs) {
|
||||
// It must be possible to seek additional periods to the new position.
|
||||
for (int i = 1; i < enabledPeriods.length; i++) {
|
||||
if (enabledPeriods[i].seekToUs(positionUs) != positionUs) {
|
||||
throw new IllegalStateException("Children seeked to different positions");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Additional sources are not allowed to report discontinuities.
|
||||
for (int i = 1; i < enabledSources.length; i++) {
|
||||
if (enabledSources[i].readDiscontinuity() != C.UNSET_TIME_US) {
|
||||
// Additional periods are not allowed to report discontinuities.
|
||||
for (int i = 1; i < enabledPeriods.length; i++) {
|
||||
if (enabledPeriods[i].readDiscontinuity() != C.UNSET_TIME_US) {
|
||||
throw new IllegalStateException("Child reported discontinuity");
|
||||
}
|
||||
}
|
||||
|
|
@ -133,8 +134,8 @@ public final class MultiSampleSource implements SampleSource, SampleSource.Callb
|
|||
@Override
|
||||
public long getBufferedPositionUs() {
|
||||
long bufferedPositionUs = Long.MAX_VALUE;
|
||||
for (SampleSource source : enabledSources) {
|
||||
long rendererBufferedPositionUs = source.getBufferedPositionUs();
|
||||
for (MediaPeriod period : enabledPeriods) {
|
||||
long rendererBufferedPositionUs = period.getBufferedPositionUs();
|
||||
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
|
||||
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
|
||||
}
|
||||
|
|
@ -144,10 +145,10 @@ public final class MultiSampleSource implements SampleSource, SampleSource.Callb
|
|||
|
||||
@Override
|
||||
public long seekToUs(long positionUs) {
|
||||
positionUs = enabledSources[0].seekToUs(positionUs);
|
||||
// Additional sources must seek to the same position.
|
||||
for (int i = 1; i < enabledSources.length; i++) {
|
||||
if (enabledSources[i].seekToUs(positionUs) != positionUs) {
|
||||
positionUs = enabledPeriods[0].seekToUs(positionUs);
|
||||
// Additional periods must seek to the same position.
|
||||
for (int i = 1; i < enabledPeriods.length; i++) {
|
||||
if (enabledPeriods[i].seekToUs(positionUs) != positionUs) {
|
||||
throw new IllegalStateException("Children seeked to different positions");
|
||||
}
|
||||
}
|
||||
|
|
@ -156,42 +157,42 @@ public final class MultiSampleSource implements SampleSource, SampleSource.Callb
|
|||
|
||||
@Override
|
||||
public void release() {
|
||||
for (SampleSource source : sources) {
|
||||
source.release();
|
||||
for (MediaPeriod period : periods) {
|
||||
period.release();
|
||||
}
|
||||
}
|
||||
|
||||
// SampleSource.Callback implementation
|
||||
// MediaPeriod.Callback implementation
|
||||
|
||||
@Override
|
||||
public void onSourcePrepared(SampleSource ignored) {
|
||||
public void onPeriodPrepared(MediaPeriod ignored) {
|
||||
if (--pendingChildPrepareCount > 0) {
|
||||
return;
|
||||
}
|
||||
durationUs = 0;
|
||||
int totalTrackGroupCount = 0;
|
||||
for (SampleSource source : sources) {
|
||||
totalTrackGroupCount += source.getTrackGroups().length;
|
||||
for (MediaPeriod period : periods) {
|
||||
totalTrackGroupCount += period.getTrackGroups().length;
|
||||
if (durationUs != C.UNSET_TIME_US) {
|
||||
long sourceDurationUs = source.getDurationUs();
|
||||
durationUs = sourceDurationUs == C.UNSET_TIME_US
|
||||
? C.UNSET_TIME_US : Math.max(durationUs, sourceDurationUs);
|
||||
long periodDurationUs = period.getDurationUs();
|
||||
durationUs = periodDurationUs == C.UNSET_TIME_US
|
||||
? C.UNSET_TIME_US : Math.max(durationUs, periodDurationUs);
|
||||
}
|
||||
}
|
||||
TrackGroup[] trackGroupArray = new TrackGroup[totalTrackGroupCount];
|
||||
int trackGroupIndex = 0;
|
||||
for (SampleSource source : sources) {
|
||||
int sourceTrackGroupCount = source.getTrackGroups().length;
|
||||
for (int j = 0; j < sourceTrackGroupCount; j++) {
|
||||
trackGroupArray[trackGroupIndex++] = source.getTrackGroups().get(j);
|
||||
for (MediaPeriod period : periods) {
|
||||
int periodTrackGroupCount = period.getTrackGroups().length;
|
||||
for (int j = 0; j < periodTrackGroupCount; j++) {
|
||||
trackGroupArray[trackGroupIndex++] = period.getTrackGroups().get(j);
|
||||
}
|
||||
}
|
||||
trackGroups = new TrackGroupArray(trackGroupArray);
|
||||
callback.onSourcePrepared(this);
|
||||
callback.onPeriodPrepared(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContinueLoadingRequested(SampleSource ignored) {
|
||||
public void onContinueLoadingRequested(MediaPeriod ignored) {
|
||||
if (trackGroups == null) {
|
||||
// Still preparing.
|
||||
return;
|
||||
|
|
@ -201,27 +202,27 @@ public final class MultiSampleSource implements SampleSource, SampleSource.Callb
|
|||
|
||||
// Internal methods.
|
||||
|
||||
private int selectTracks(SampleSource source, List<TrackStream> allOldStreams,
|
||||
private int selectTracks(MediaPeriod period, List<TrackStream> allOldStreams,
|
||||
List<TrackSelection> allNewSelections, long positionUs, TrackStream[] allNewStreams,
|
||||
boolean seenFirstTrackSelection) {
|
||||
// Get the subset of the old streams for the source.
|
||||
// Get the subset of the old streams for the period.
|
||||
ArrayList<TrackStream> oldStreams = new ArrayList<>();
|
||||
for (int i = 0; i < allOldStreams.size(); i++) {
|
||||
TrackStream stream = allOldStreams.get(i);
|
||||
if (trackStreamSources.get(stream) == source) {
|
||||
trackStreamSources.remove(stream);
|
||||
if (trackStreamPeriods.get(stream) == period) {
|
||||
trackStreamPeriods.remove(stream);
|
||||
oldStreams.add(stream);
|
||||
}
|
||||
}
|
||||
// Get the subset of the new selections for the source.
|
||||
// Get the subset of the new selections for the period.
|
||||
ArrayList<TrackSelection> newSelections = new ArrayList<>();
|
||||
int[] newSelectionOriginalIndices = new int[allNewSelections.size()];
|
||||
for (int i = 0; i < allNewSelections.size(); i++) {
|
||||
TrackSelection selection = allNewSelections.get(i);
|
||||
Pair<SampleSource, Integer> sourceAndGroup = getSourceAndGroup(selection.group);
|
||||
if (sourceAndGroup.first == source) {
|
||||
Pair<MediaPeriod, Integer> periodAndGroup = getPeriodAndGroup(selection.group);
|
||||
if (periodAndGroup.first == period) {
|
||||
newSelectionOriginalIndices[newSelections.size()] = i;
|
||||
newSelections.add(new TrackSelection(sourceAndGroup.second, selection.getTracks()));
|
||||
newSelections.add(new TrackSelection(periodAndGroup.second, selection.getTracks()));
|
||||
}
|
||||
}
|
||||
// Do nothing if nothing has changed, except during the first selection.
|
||||
|
|
@ -229,22 +230,22 @@ public final class MultiSampleSource implements SampleSource, SampleSource.Callb
|
|||
return 0;
|
||||
}
|
||||
// Perform the selection.
|
||||
TrackStream[] newStreams = source.selectTracks(oldStreams, newSelections, positionUs);
|
||||
TrackStream[] newStreams = period.selectTracks(oldStreams, newSelections, positionUs);
|
||||
for (int j = 0; j < newStreams.length; j++) {
|
||||
allNewStreams[newSelectionOriginalIndices[j]] = newStreams[j];
|
||||
trackStreamSources.put(newStreams[j], source);
|
||||
trackStreamPeriods.put(newStreams[j], period);
|
||||
}
|
||||
return newSelections.size() - oldStreams.size();
|
||||
}
|
||||
|
||||
private Pair<SampleSource, Integer> getSourceAndGroup(int group) {
|
||||
private Pair<MediaPeriod, Integer> getPeriodAndGroup(int group) {
|
||||
int totalTrackGroupCount = 0;
|
||||
for (SampleSource source : sources) {
|
||||
int sourceTrackGroupCount = source.getTrackGroups().length;
|
||||
if (group < totalTrackGroupCount + sourceTrackGroupCount) {
|
||||
return Pair.create(source, group - totalTrackGroupCount);
|
||||
for (MediaPeriod period : periods) {
|
||||
int periodTrackGroupCount = period.getTrackGroups().length;
|
||||
if (group < totalTrackGroupCount + periodTrackGroupCount) {
|
||||
return Pair.create(period, group - totalTrackGroupCount);
|
||||
}
|
||||
totalTrackGroupCount += sourceTrackGroupCount;
|
||||
totalTrackGroupCount += periodTrackGroupCount;
|
||||
}
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2;
|
||||
|
||||
// TODO[playlists]: Rename this and maybe change the interface once we support multi-period DASH.
|
||||
/**
|
||||
* Provides a sequence of {@link SampleSource}s to play back.
|
||||
*/
|
||||
public interface SampleSourceProvider {
|
||||
|
||||
/**
|
||||
* Returned by {@link #getSourceCount()} if the number of sources is not known.
|
||||
*/
|
||||
int UNKNOWN_SOURCE_COUNT = -1;
|
||||
|
||||
/**
|
||||
* Returns the number of sources in the sequence, or {@link #UNKNOWN_SOURCE_COUNT} if the number
|
||||
* of sources is not yet known.
|
||||
*/
|
||||
int getSourceCount();
|
||||
|
||||
/**
|
||||
* Returns a new {@link SampleSource} providing media at the specified index in the sequence, or
|
||||
* {@code null} if the source at the specified index is not yet available.
|
||||
*
|
||||
* @param index The index of the source to create, which must be less than the count returned by
|
||||
* {@link #getSourceCount()}.
|
||||
* @return A new {@link SampleSource}, or {@code null} if the source at the specified index is not
|
||||
* yet available.
|
||||
*/
|
||||
SampleSource createSource(int index);
|
||||
|
||||
}
|
||||
|
|
@ -314,8 +314,8 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setSourceProvider(SampleSourceProvider sourceProvider) {
|
||||
player.setSourceProvider(sourceProvider);
|
||||
public void setMediaSource(MediaSource mediaSource) {
|
||||
player.setMediaSource(mediaSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -344,8 +344,8 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void seekTo(int sourceIndex, long positionMs) {
|
||||
player.seekTo(sourceIndex, positionMs);
|
||||
public void seekTo(int periodIndex, long positionMs) {
|
||||
player.seekTo(periodIndex, positionMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -379,8 +379,8 @@ public final class SimpleExoPlayer implements ExoPlayer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentSourceIndex() {
|
||||
return player.getCurrentSourceIndex();
|
||||
public int getCurrentPeriodIndex() {
|
||||
return player.getCurrentPeriodIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -31,21 +31,20 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link SampleSource} that loads the data at a given {@link Uri} as a single sample. Also acts
|
||||
* as a {@link SampleSourceProvider} providing {@link SingleSampleSource} instances.
|
||||
* Loads data at a given {@link Uri} as a single sample belonging to a single {@link MediaPeriod}.
|
||||
*/
|
||||
public final class SingleSampleSource implements SampleSource, SampleSourceProvider, TrackStream,
|
||||
Loader.Callback<SingleSampleSource.SourceLoadable> {
|
||||
public final class SingleSampleMediaSource implements MediaPeriod, MediaSource, TrackStream,
|
||||
Loader.Callback<SingleSampleMediaSource.SourceLoadable> {
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be notified of {@link SingleSampleSource} events.
|
||||
* Interface definition for a callback to be notified of {@link SingleSampleMediaSource} events.
|
||||
*/
|
||||
public interface EventListener {
|
||||
|
||||
/**
|
||||
* Invoked when an error occurs loading media data.
|
||||
*
|
||||
* @param sourceId The id of the reporting {@link SampleSource}.
|
||||
* @param sourceId The id of the reporting {@link SingleSampleMediaSource}.
|
||||
* @param e The cause of the failure.
|
||||
*/
|
||||
void onLoadError(int sourceId, IOException e);
|
||||
|
|
@ -83,17 +82,17 @@ public final class SingleSampleSource implements SampleSource, SampleSourceProvi
|
|||
private byte[] sampleData;
|
||||
private int sampleSize;
|
||||
|
||||
public SingleSampleSource(Uri uri, DataSourceFactory dataSourceFactory, Format format,
|
||||
public SingleSampleMediaSource(Uri uri, DataSourceFactory dataSourceFactory, Format format,
|
||||
long durationUs) {
|
||||
this(uri, dataSourceFactory, format, durationUs, DEFAULT_MIN_LOADABLE_RETRY_COUNT);
|
||||
}
|
||||
|
||||
public SingleSampleSource(Uri uri, DataSourceFactory dataSourceFactory, Format format,
|
||||
public SingleSampleMediaSource(Uri uri, DataSourceFactory dataSourceFactory, Format format,
|
||||
long durationUs, int minLoadableRetryCount) {
|
||||
this(uri, dataSourceFactory, format, durationUs, minLoadableRetryCount, null, null, 0);
|
||||
}
|
||||
|
||||
public SingleSampleSource(Uri uri, DataSourceFactory dataSourceFactory, Format format,
|
||||
public SingleSampleMediaSource(Uri uri, DataSourceFactory dataSourceFactory, Format format,
|
||||
long durationUs, int minLoadableRetryCount, Handler eventHandler, EventListener eventListener,
|
||||
int eventSourceId) {
|
||||
this.uri = uri;
|
||||
|
|
@ -109,25 +108,25 @@ public final class SingleSampleSource implements SampleSource, SampleSourceProvi
|
|||
streamState = STREAM_STATE_SEND_FORMAT;
|
||||
}
|
||||
|
||||
// SampleSourceProvider implementation.
|
||||
// MediaSource implementation.
|
||||
|
||||
@Override
|
||||
public int getSourceCount() {
|
||||
public int getPeriodCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleSource createSource(int index) {
|
||||
public MediaPeriod createPeriod(int index) {
|
||||
Assertions.checkArgument(index == 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
// SampleSource implementation.
|
||||
// MediaPeriod implementation.
|
||||
|
||||
@Override
|
||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||
loader = new Loader("Loader:SingleSampleSource");
|
||||
callback.onSourcePrepared(this);
|
||||
loader = new Loader("Loader:SingleSampleMediaSource");
|
||||
callback.onPeriodPrepared(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -20,9 +20,9 @@ import com.google.android.exoplayer2.util.Assertions;
|
|||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Defines a group of tracks exposed by a {@link SampleSource}.
|
||||
* Defines a group of tracks exposed by a {@link MediaPeriod}.
|
||||
* <p>
|
||||
* A {@link SampleSource} is only able to provide one {@link TrackStream} corresponding to a group
|
||||
* A {@link MediaPeriod} is only able to provide one {@link TrackStream} corresponding to a group
|
||||
* at any given time. If {@link #adaptive} is true this {@link TrackStream} can adapt between
|
||||
* multiple tracks within the group. If {@link #adaptive} is false then it's only possible to
|
||||
* consume one track from the group at a given time.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ package com.google.android.exoplayer2;
|
|||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* An array of {@link TrackGroup}s exposed by a {@link SampleSource}.
|
||||
* An array of {@link TrackGroup}s exposed by a {@link MediaPeriod}.
|
||||
*/
|
||||
public final class TrackGroupArray {
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.chunk;
|
||||
|
||||
import com.google.android.exoplayer2.AdaptiveSourceEventListener.EventDispatcher;
|
||||
import com.google.android.exoplayer2.AdaptiveMediaSourceEventListener.EventDispatcher;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.DecoderInputBuffer;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.dash;
|
||||
|
||||
import com.google.android.exoplayer2.AdaptiveSourceEventListener;
|
||||
import com.google.android.exoplayer2.AdaptiveSourceEventListener.EventDispatcher;
|
||||
import com.google.android.exoplayer2.AdaptiveMediaSourceEventListener;
|
||||
import com.google.android.exoplayer2.AdaptiveMediaSourceEventListener.EventDispatcher;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.CompositeSequenceableLoader;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.MediaPeriod;
|
||||
import com.google.android.exoplayer2.MediaSource;
|
||||
import com.google.android.exoplayer2.ParserException;
|
||||
import com.google.android.exoplayer2.SampleSource;
|
||||
import com.google.android.exoplayer2.SampleSourceProvider;
|
||||
import com.google.android.exoplayer2.SequenceableLoader;
|
||||
import com.google.android.exoplayer2.TrackGroup;
|
||||
import com.google.android.exoplayer2.TrackGroupArray;
|
||||
|
|
@ -63,10 +63,9 @@ import java.util.Locale;
|
|||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* A {@link SampleSource} for DASH media. Also acts as a {@link SampleSourceProvider} providing
|
||||
* {@link DashSampleSource} instances.
|
||||
* A DASH {@link MediaSource}.
|
||||
*/
|
||||
public final class DashSampleSource implements SampleSource, SampleSourceProvider,
|
||||
public final class DashMediaSource implements MediaPeriod, MediaSource,
|
||||
SequenceableLoader.Callback<ChunkTrackStream<DashChunkSource>> {
|
||||
|
||||
/**
|
||||
|
|
@ -74,7 +73,7 @@ public final class DashSampleSource implements SampleSource, SampleSourceProvide
|
|||
*/
|
||||
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3;
|
||||
|
||||
private static final String TAG = "DashSampleSource";
|
||||
private static final String TAG = "DashMediaSource";
|
||||
|
||||
private final DataSourceFactory dataSourceFactory;
|
||||
private final BandwidthMeter bandwidthMeter;
|
||||
|
|
@ -102,16 +101,16 @@ public final class DashSampleSource implements SampleSource, SampleSourceProvide
|
|||
private TrackGroupArray trackGroups;
|
||||
private int[] trackGroupAdaptationSetIndices;
|
||||
|
||||
public DashSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
public DashMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, Handler eventHandler,
|
||||
AdaptiveSourceEventListener eventListener) {
|
||||
AdaptiveMediaSourceEventListener eventListener) {
|
||||
this(manifestUri, dataSourceFactory, bandwidthMeter, DEFAULT_MIN_LOADABLE_RETRY_COUNT,
|
||||
eventHandler, eventListener);
|
||||
}
|
||||
|
||||
public DashSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
public DashMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, int minLoadableRetryCount, Handler eventHandler,
|
||||
AdaptiveSourceEventListener eventListener) {
|
||||
AdaptiveMediaSourceEventListener eventListener) {
|
||||
this.manifestUri = manifestUri;
|
||||
this.dataSourceFactory = dataSourceFactory;
|
||||
this.bandwidthMeter = bandwidthMeter;
|
||||
|
|
@ -121,20 +120,20 @@ public final class DashSampleSource implements SampleSource, SampleSourceProvide
|
|||
manifestCallback = new ManifestCallback();
|
||||
}
|
||||
|
||||
// SampleSourceProvider implementation.
|
||||
// MediaSource implementation.
|
||||
|
||||
@Override
|
||||
public int getSourceCount() {
|
||||
public int getPeriodCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleSource createSource(int index) {
|
||||
public MediaPeriod createPeriod(int index) {
|
||||
Assertions.checkArgument(index == 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
// SampleSource implementation.
|
||||
// MediaPeriod implementation.
|
||||
|
||||
@Override
|
||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||
|
|
@ -143,7 +142,7 @@ public final class DashSampleSource implements SampleSource, SampleSourceProvide
|
|||
trackStreams = newTrackStreamArray(0);
|
||||
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
|
||||
dataSource = dataSourceFactory.createDataSource();
|
||||
loader = new Loader("Loader:DashSampleSource");
|
||||
loader = new Loader("Loader:DashMediaSource");
|
||||
manifestRefreshHandler = new Handler();
|
||||
startLoadingManifest();
|
||||
}
|
||||
|
|
@ -373,7 +372,7 @@ public final class DashSampleSource implements SampleSource, SampleSourceProvide
|
|||
|
||||
private void finishPrepare() {
|
||||
prepared = true;
|
||||
callback.onSourcePrepared(this);
|
||||
callback.onPeriodPrepared(this);
|
||||
scheduleManifestRefresh();
|
||||
}
|
||||
|
||||
|
|
@ -467,7 +466,7 @@ public final class DashSampleSource implements SampleSource, SampleSourceProvide
|
|||
@Override
|
||||
public void onLoadCanceled(ParsingLoadable<MediaPresentationDescription> loadable,
|
||||
long elapsedRealtimeMs, long loadDurationMs, boolean released) {
|
||||
DashSampleSource.this.onLoadCanceled(loadable, elapsedRealtimeMs, loadDurationMs);
|
||||
DashMediaSource.this.onLoadCanceled(loadable, elapsedRealtimeMs, loadDurationMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -489,7 +488,7 @@ public final class DashSampleSource implements SampleSource, SampleSourceProvide
|
|||
@Override
|
||||
public void onLoadCanceled(ParsingLoadable<Long> loadable, long elapsedRealtimeMs,
|
||||
long loadDurationMs, boolean released) {
|
||||
DashSampleSource.this.onLoadCanceled(loadable, elapsedRealtimeMs, loadDurationMs);
|
||||
DashMediaSource.this.onLoadCanceled(loadable, elapsedRealtimeMs, loadDurationMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -19,9 +19,9 @@ import com.google.android.exoplayer2.C;
|
|||
import com.google.android.exoplayer2.DecoderInputBuffer;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.FormatHolder;
|
||||
import com.google.android.exoplayer2.MediaPeriod;
|
||||
import com.google.android.exoplayer2.MediaSource;
|
||||
import com.google.android.exoplayer2.ParserException;
|
||||
import com.google.android.exoplayer2.SampleSource;
|
||||
import com.google.android.exoplayer2.SampleSourceProvider;
|
||||
import com.google.android.exoplayer2.SequenceableLoader;
|
||||
import com.google.android.exoplayer2.TrackGroup;
|
||||
import com.google.android.exoplayer2.TrackGroupArray;
|
||||
|
|
@ -48,10 +48,10 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link SampleSource} that extracts sample data using an {@link Extractor}. Also acts as a
|
||||
* {@link SampleSourceProvider} providing {@link ExtractorSampleSource} instances.
|
||||
*
|
||||
* <p>If the possible input stream container formats are known, pass a factory that instantiates
|
||||
* Provides a single {@link MediaPeriod} whose data is loaded from a {@link Uri} and extracted using
|
||||
* an {@link Extractor}.
|
||||
* <p>
|
||||
* If the possible input stream container formats are known, pass a factory that instantiates
|
||||
* extractors for them to the constructor. Otherwise, pass a {@link DefaultExtractorsFactory} to
|
||||
* use the default extractors. When reading a new stream, the first {@link Extractor} in the array
|
||||
* of extractors created by the factory that returns {@code true} from
|
||||
|
|
@ -59,12 +59,12 @@ import java.util.List;
|
|||
*
|
||||
* <p>Note that the built-in extractors for AAC, MPEG TS and FLV streams do not support seeking.
|
||||
*/
|
||||
public final class ExtractorSampleSource implements SampleSource, SampleSourceProvider,
|
||||
ExtractorOutput, Loader.Callback<ExtractorSampleSource.ExtractingLoadable>,
|
||||
public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
|
||||
ExtractorOutput, Loader.Callback<ExtractorMediaSource.ExtractingLoadable>,
|
||||
UpstreamFormatChangedListener {
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be notified of {@link ExtractorSampleSource} events.
|
||||
* Interface definition for a callback to be notified of {@link ExtractorMediaSource} events.
|
||||
*/
|
||||
public interface EventListener {
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourcePr
|
|||
* Otherwise, pass a {@link DefaultExtractorsFactory} to use default extractors.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
*/
|
||||
public ExtractorSampleSource(Uri uri, DataSourceFactory dataSourceFactory,
|
||||
public ExtractorMediaSource(Uri uri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, ExtractorsFactory extractorsFactory, Handler eventHandler,
|
||||
EventListener eventListener) {
|
||||
this(uri, dataSourceFactory, bandwidthMeter, extractorsFactory,
|
||||
|
|
@ -168,7 +168,7 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourcePr
|
|||
* if a loading error occurs.
|
||||
* @param eventListener A listener of events. May be null if delivery of events is not required.
|
||||
*/
|
||||
public ExtractorSampleSource(Uri uri, DataSourceFactory dataSourceFactory,
|
||||
public ExtractorMediaSource(Uri uri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, ExtractorsFactory extractorsFactory, int minLoadableRetryCount,
|
||||
Handler eventHandler, EventListener eventListener) {
|
||||
this.uri = uri;
|
||||
|
|
@ -180,20 +180,20 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourcePr
|
|||
this.eventListener = eventListener;
|
||||
}
|
||||
|
||||
// SampleSourceProvider implementation.
|
||||
// MediaSource implementation.
|
||||
|
||||
@Override
|
||||
public int getSourceCount() {
|
||||
public int getPeriodCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleSource createSource(int index) {
|
||||
public MediaPeriod createPeriod(int index) {
|
||||
Assertions.checkArgument(index == 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
// SampleSource implementation.
|
||||
// MediaPeriod implementation.
|
||||
|
||||
@Override
|
||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||
|
|
@ -202,7 +202,7 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourcePr
|
|||
|
||||
dataSource = dataSourceFactory.createDataSource(bandwidthMeter);
|
||||
extractorHolder = new ExtractorHolder(extractorsFactory.createExtractors(), this);
|
||||
loader = new Loader("Loader:ExtractorSampleSource", extractorHolder);
|
||||
loader = new Loader("Loader:ExtractorMediaSource", extractorHolder);
|
||||
loadCondition = new ConditionVariable();
|
||||
pendingResetPositionUs = C.UNSET_TIME_US;
|
||||
sampleQueues = new DefaultTrackOutput[0];
|
||||
|
|
@ -483,7 +483,7 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourcePr
|
|||
}
|
||||
tracks = new TrackGroupArray(trackArray);
|
||||
prepared = true;
|
||||
callback.onSourcePrepared(this);
|
||||
callback.onPeriodPrepared(this);
|
||||
}
|
||||
|
||||
private void copyLengthFromLoader(ExtractingLoadable loadable) {
|
||||
|
|
@ -584,17 +584,17 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourcePr
|
|||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return ExtractorSampleSource.this.isReady(track);
|
||||
return ExtractorMediaSource.this.isReady(track);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void maybeThrowError() throws IOException {
|
||||
ExtractorSampleSource.this.maybeThrowError();
|
||||
ExtractorMediaSource.this.maybeThrowError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
||||
return ExtractorSampleSource.this.readData(track, formatHolder, buffer);
|
||||
return ExtractorMediaSource.this.readData(track, formatHolder, buffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -670,7 +670,7 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourcePr
|
|||
if (input.getPosition() > position + CONTINUE_LOADING_CHECK_INTERVAL_BYTES) {
|
||||
position = input.getPosition();
|
||||
loadCondition.close();
|
||||
callback.onContinueLoadingRequested(ExtractorSampleSource.this);
|
||||
callback.onContinueLoadingRequested(ExtractorMediaSource.this);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
|
@ -15,14 +15,14 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.hls;
|
||||
|
||||
import com.google.android.exoplayer2.AdaptiveSourceEventListener;
|
||||
import com.google.android.exoplayer2.AdaptiveSourceEventListener.EventDispatcher;
|
||||
import com.google.android.exoplayer2.AdaptiveMediaSourceEventListener;
|
||||
import com.google.android.exoplayer2.AdaptiveMediaSourceEventListener.EventDispatcher;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.CompositeSequenceableLoader;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.MediaPeriod;
|
||||
import com.google.android.exoplayer2.MediaSource;
|
||||
import com.google.android.exoplayer2.ParserException;
|
||||
import com.google.android.exoplayer2.SampleSource;
|
||||
import com.google.android.exoplayer2.SampleSourceProvider;
|
||||
import com.google.android.exoplayer2.TrackGroup;
|
||||
import com.google.android.exoplayer2.TrackGroupArray;
|
||||
import com.google.android.exoplayer2.TrackSelection;
|
||||
|
|
@ -53,10 +53,9 @@ import java.util.IdentityHashMap;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link SampleSource} for HLS streams. Also acts as a {@link SampleSourceProvider} providing
|
||||
* {@link HlsSampleSource} instances.
|
||||
* An HLS {@link MediaSource}.
|
||||
*/
|
||||
public final class HlsSampleSource implements SampleSource, SampleSourceProvider,
|
||||
public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||
Loader.Callback<ParsingLoadable<HlsPlaylist>>, HlsTrackStreamWrapper.Callback {
|
||||
|
||||
/**
|
||||
|
|
@ -90,16 +89,16 @@ public final class HlsSampleSource implements SampleSource, SampleSourceProvider
|
|||
private HlsTrackStreamWrapper[] enabledTrackStreamWrappers;
|
||||
private CompositeSequenceableLoader sequenceableLoader;
|
||||
|
||||
public HlsSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
public HlsMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, Handler eventHandler,
|
||||
AdaptiveSourceEventListener eventListener) {
|
||||
AdaptiveMediaSourceEventListener eventListener) {
|
||||
this(manifestUri, dataSourceFactory, bandwidthMeter, DEFAULT_MIN_LOADABLE_RETRY_COUNT,
|
||||
eventHandler, eventListener);
|
||||
}
|
||||
|
||||
public HlsSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
public HlsMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, int minLoadableRetryCount, Handler eventHandler,
|
||||
AdaptiveSourceEventListener eventListener) {
|
||||
AdaptiveMediaSourceEventListener eventListener) {
|
||||
this.manifestUri = manifestUri;
|
||||
this.dataSourceFactory = dataSourceFactory;
|
||||
this.bandwidthMeter = bandwidthMeter;
|
||||
|
|
@ -111,20 +110,20 @@ public final class HlsSampleSource implements SampleSource, SampleSourceProvider
|
|||
manifestParser = new HlsPlaylistParser();
|
||||
}
|
||||
|
||||
// SampleSourceProvider implementation.
|
||||
// MediaSource implementation.
|
||||
|
||||
@Override
|
||||
public int getSourceCount() {
|
||||
public int getPeriodCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleSource createSource(int index) {
|
||||
public MediaPeriod createPeriod(int index) {
|
||||
Assertions.checkArgument(index == 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
// SampleSource implementation.
|
||||
// MediaPeriod implementation.
|
||||
|
||||
@Override
|
||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||
|
|
@ -314,7 +313,7 @@ public final class HlsSampleSource implements SampleSource, SampleSourceProvider
|
|||
}
|
||||
}
|
||||
trackGroups = new TrackGroupArray(trackGroupArray);
|
||||
callback.onSourcePrepared(this);
|
||||
callback.onPeriodPrepared(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.hls;
|
||||
|
||||
import com.google.android.exoplayer2.AdaptiveSourceEventListener.EventDispatcher;
|
||||
import com.google.android.exoplayer2.AdaptiveMediaSourceEventListener.EventDispatcher;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.DecoderInputBuffer;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.smoothstreaming;
|
||||
|
||||
import com.google.android.exoplayer2.AdaptiveSourceEventListener;
|
||||
import com.google.android.exoplayer2.AdaptiveSourceEventListener.EventDispatcher;
|
||||
import com.google.android.exoplayer2.AdaptiveMediaSourceEventListener;
|
||||
import com.google.android.exoplayer2.AdaptiveMediaSourceEventListener.EventDispatcher;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.CompositeSequenceableLoader;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.MediaPeriod;
|
||||
import com.google.android.exoplayer2.MediaSource;
|
||||
import com.google.android.exoplayer2.ParserException;
|
||||
import com.google.android.exoplayer2.SampleSource;
|
||||
import com.google.android.exoplayer2.SampleSourceProvider;
|
||||
import com.google.android.exoplayer2.SequenceableLoader;
|
||||
import com.google.android.exoplayer2.TrackGroup;
|
||||
import com.google.android.exoplayer2.TrackGroupArray;
|
||||
|
|
@ -53,10 +53,9 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A {@link SampleSource} for SmoothStreaming media. Also acts as a {@link SampleSourceProvider}
|
||||
* providing {@link SmoothStreamingSampleSource} instances.
|
||||
* A SmoothStreaming {@link MediaSource}.
|
||||
*/
|
||||
public final class SmoothStreamingSampleSource implements SampleSource, SampleSourceProvider,
|
||||
public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSource,
|
||||
SequenceableLoader.Callback<ChunkTrackStream<SmoothStreamingChunkSource>>,
|
||||
Loader.Callback<ParsingLoadable<SmoothStreamingManifest>> {
|
||||
|
||||
|
|
@ -92,16 +91,16 @@ public final class SmoothStreamingSampleSource implements SampleSource, SampleSo
|
|||
private TrackGroupArray trackGroups;
|
||||
private int[] trackGroupElementIndices;
|
||||
|
||||
public SmoothStreamingSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
public SmoothStreamingMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, Handler eventHandler,
|
||||
AdaptiveSourceEventListener eventListener) {
|
||||
AdaptiveMediaSourceEventListener eventListener) {
|
||||
this(manifestUri, dataSourceFactory, bandwidthMeter, DEFAULT_MIN_LOADABLE_RETRY_COUNT,
|
||||
eventHandler, eventListener);
|
||||
}
|
||||
|
||||
public SmoothStreamingSampleSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
public SmoothStreamingMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter, int minLoadableRetryCount, Handler eventHandler,
|
||||
AdaptiveSourceEventListener eventListener) {
|
||||
AdaptiveMediaSourceEventListener eventListener) {
|
||||
this.manifestUri = Util.toLowerInvariant(manifestUri.getLastPathSegment()).equals("manifest")
|
||||
? manifestUri : Uri.withAppendedPath(manifestUri, "Manifest");
|
||||
this.dataSourceFactory = dataSourceFactory;
|
||||
|
|
@ -111,20 +110,20 @@ public final class SmoothStreamingSampleSource implements SampleSource, SampleSo
|
|||
manifestParser = new SmoothStreamingManifestParser();
|
||||
}
|
||||
|
||||
// SampleSourceProvider implementation.
|
||||
// MediaSource implementation.
|
||||
|
||||
@Override
|
||||
public int getSourceCount() {
|
||||
public int getPeriodCount() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleSource createSource(int index) {
|
||||
public MediaPeriod createPeriod(int index) {
|
||||
Assertions.checkArgument(index == 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
// SampleSource implementation.
|
||||
// MediaPeriod implementation.
|
||||
|
||||
@Override
|
||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||
|
|
@ -273,7 +272,7 @@ public final class SmoothStreamingSampleSource implements SampleSource, SampleSo
|
|||
new TrackEncryptionBox(true, INITIALIZATION_VECTOR_SIZE, keyId)};
|
||||
}
|
||||
prepared = true;
|
||||
callback.onSourcePrepared(this);
|
||||
callback.onPeriodPrepared(this);
|
||||
} else {
|
||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
||||
trackStream.getChunkSource().updateManifest(manifest);
|
||||
|
|
@ -81,7 +81,7 @@ public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListe
|
|||
}
|
||||
|
||||
private void updateTextView() {
|
||||
textView.setText(getPlayerStateString() + getPlayerSourceIndexString() + getBandwidthString()
|
||||
textView.setText(getPlayerStateString() + getPlayerPeriodIndexString() + getBandwidthString()
|
||||
+ getVideoString() + getAudioString());
|
||||
}
|
||||
|
||||
|
|
@ -107,8 +107,8 @@ public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListe
|
|||
return text;
|
||||
}
|
||||
|
||||
private String getPlayerSourceIndexString() {
|
||||
return " source:" + player.getCurrentSourceIndex();
|
||||
private String getPlayerPeriodIndexString() {
|
||||
return " period:" + player.getCurrentPeriodIndex();
|
||||
}
|
||||
|
||||
private String getBandwidthString() {
|
||||
|
|
@ -169,7 +169,7 @@ public final class DebugTextViewHelper implements Runnable, ExoPlayer.EventListe
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPositionDiscontinuity(int sourceIndex, long positionMs) {
|
||||
public void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
||||
updateTextView();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ import com.google.android.exoplayer2.ExoPlaybackException;
|
|||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.MediaCodecUtil;
|
||||
import com.google.android.exoplayer2.MediaCodecUtil.DecoderQueryException;
|
||||
import com.google.android.exoplayer2.SampleSourceProvider;
|
||||
import com.google.android.exoplayer2.MediaSource;
|
||||
import com.google.android.exoplayer2.TrackGroup;
|
||||
import com.google.android.exoplayer2.TrackGroupArray;
|
||||
import com.google.android.exoplayer2.TrackRenderer;
|
||||
import com.google.android.exoplayer2.TrackSelection;
|
||||
import com.google.android.exoplayer2.TrackSelectionPolicy;
|
||||
import com.google.android.exoplayer2.dash.DashSampleSource;
|
||||
import com.google.android.exoplayer2.dash.DashMediaSource;
|
||||
import com.google.android.exoplayer2.playbacktests.util.ActionSchedule;
|
||||
import com.google.android.exoplayer2.playbacktests.util.CodecCountersUtil;
|
||||
import com.google.android.exoplayer2.playbacktests.util.ExoHostedTest;
|
||||
|
|
@ -418,9 +418,9 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
|
|||
}
|
||||
|
||||
@Override
|
||||
public SampleSourceProvider buildSource(HostActivity host, DataSourceFactory dataSourceFactory,
|
||||
public MediaSource buildSource(HostActivity host, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter) {
|
||||
return new DashSampleSource(manifestUri, dataSourceFactory, bandwidthMeter,
|
||||
return new DashMediaSource(manifestUri, dataSourceFactory, bandwidthMeter,
|
||||
MIN_LOADABLE_RETRY_COUNT, null, null);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import com.google.android.exoplayer2.ExoPlaybackException;
|
|||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.ExoPlayerFactory;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.SampleSourceProvider;
|
||||
import com.google.android.exoplayer2.MediaSource;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.TrackSelectionPolicy;
|
||||
import com.google.android.exoplayer2.audio.AudioTrack;
|
||||
|
|
@ -128,7 +128,7 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
|
|||
player = buildExoPlayer(host, surface, trackSelector);
|
||||
DataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(host, Util
|
||||
.getUserAgent(host, "ExoPlayerPlaybackTests"));
|
||||
player.setSourceProvider(buildSource(host, dataSourceFactory, player.getBandwidthMeter()));
|
||||
player.setMediaSource(buildSource(host, dataSourceFactory, player.getBandwidthMeter()));
|
||||
player.addListener(this);
|
||||
player.setDebugListener(this);
|
||||
player.setPlayWhenReady(true);
|
||||
|
|
@ -210,7 +210,7 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
|
|||
}
|
||||
|
||||
@Override
|
||||
public final void onPositionDiscontinuity(int sourceIndex, long positionMs) {
|
||||
public final void onPositionDiscontinuity(int periodIndex, long positionMs) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
|
|
@ -287,8 +287,8 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
|
|||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected abstract SampleSourceProvider buildSource(HostActivity host,
|
||||
DataSourceFactory dataSourceFactory, BandwidthMeter bandwidthMeter);
|
||||
protected abstract MediaSource buildSource(HostActivity host, DataSourceFactory dataSourceFactory,
|
||||
BandwidthMeter bandwidthMeter);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected void onPlayerErrorInternal(ExoPlaybackException error) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue