Use extension rather than composition for track selection

It doesn't look like TrackSelectionPolicy is going to be
useful other than with DefaultTrackSelector, and it's kinda
confusing dealing with both "selector" and "policy"
terminology. This change does the following:

DefaultTrackSelector -> selector.MappingTrackSelector
DefaultTrackSelectionPolicy -> selector.DefaultTrackSelector
TrackSelectionPolicy -> [deleted]
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=127196326
This commit is contained in:
olly 2016-07-12 07:12:28 -07:00 committed by Oliver Woodman
parent 67be677ddf
commit d4d1640808
40 changed files with 157 additions and 551 deletions

View File

@ -16,19 +16,19 @@
package com.google.android.exoplayer2.demo;
import com.google.android.exoplayer2.CodecCounters;
import com.google.android.exoplayer2.DefaultTrackSelector;
import com.google.android.exoplayer2.DefaultTrackSelector.TrackInfo;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.drm.StreamingDrmSessionManager;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.TrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DataSpec;
import android.os.SystemClock;
@ -43,7 +43,7 @@ import java.util.Locale;
*/
public class EventLogger implements ExoPlayer.EventListener, SimpleExoPlayer.DebugListener,
AdaptiveMediaSourceEventListener, ExtractorMediaSource.EventListener,
StreamingDrmSessionManager.EventListener, DefaultTrackSelector.EventListener {
StreamingDrmSessionManager.EventListener, MappingTrackSelector.EventListener {
private static final String TAG = "EventLogger";
private static final NumberFormat TIME_FORMAT;
@ -92,7 +92,7 @@ public class EventLogger implements ExoPlayer.EventListener, SimpleExoPlayer.Deb
Log.e(TAG, "playerFailed [" + getSessionTimeString() + "]", e);
}
// DefaultTrackSelector.EventListener
// MappingTrackSelector.EventListener
@Override
public void onTracksChanged(TrackInfo trackInfo) {

View File

@ -17,9 +17,6 @@ package com.google.android.exoplayer2.demo;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultTrackSelectionPolicy;
import com.google.android.exoplayer2.DefaultTrackSelector;
import com.google.android.exoplayer2.DefaultTrackSelector.TrackInfo;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
@ -46,6 +43,9 @@ import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingMedia
import com.google.android.exoplayer2.text.CaptionStyleCompat;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.SubtitleLayout;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.TrackInfo;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.PlayerControl;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
@ -92,7 +92,7 @@ import java.util.UUID;
*/
public class PlayerActivity extends Activity implements SurfaceHolder.Callback, OnClickListener,
ExoPlayer.EventListener, SimpleExoPlayer.VideoListener, SimpleExoPlayer.CaptionListener,
SimpleExoPlayer.Id3MetadataListener, DefaultTrackSelector.EventListener {
SimpleExoPlayer.Id3MetadataListener, MappingTrackSelector.EventListener {
public static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid";
public static final String DRM_CONTENT_ID_EXTRA = "drm_content_id";
@ -130,7 +130,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
private DataSourceFactory dataSourceFactory;
private SimpleExoPlayer player;
private DefaultTrackSelector trackSelector;
private MappingTrackSelector trackSelector;
private TrackSelectionHelper trackSelectionHelper;
private DebugTextViewHelper debugViewHelper;
private BandwidthMeter bandwidthMeter;
@ -272,7 +272,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
}
eventLogger = new EventLogger();
eventLogger.startSession();
trackSelector = new DefaultTrackSelector(new DefaultTrackSelectionPolicy(), mainHandler);
trackSelector = new DefaultTrackSelector(mainHandler);
trackSelector.addListener(this);
trackSelector.addListener(eventLogger);
trackSelectionHelper = new TrackSelectionHelper(trackSelector);
@ -490,7 +490,7 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
shutterView.setVisibility(View.GONE);
}
// DefaultTrackSelector.EventListener implementation
// MappingTrackSelector.EventListener implementation
@Override
public void onTracksChanged(TrackInfo trackInfo) {

View File

@ -15,13 +15,13 @@
*/
package com.google.android.exoplayer2.demo;
import com.google.android.exoplayer2.DefaultTrackSelector;
import com.google.android.exoplayer2.DefaultTrackSelector.TrackInfo;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.TrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.util.MimeTypes;
import android.annotation.SuppressLint;
@ -44,7 +44,7 @@ import java.util.Locale;
/* package */ final class TrackSelectionHelper implements View.OnClickListener,
DialogInterface.OnClickListener {
private final DefaultTrackSelector selector;
private final MappingTrackSelector selector;
private TrackInfo trackInfo;
private int rendererIndex;
@ -60,7 +60,7 @@ import java.util.Locale;
/**
* @param selector The track selector.
*/
public TrackSelectionHelper(DefaultTrackSelector selector) {
public TrackSelectionHelper(MappingTrackSelector selector) {
this.selector = selector;
}

View File

@ -62,7 +62,7 @@ public final class FfmpegAudioRenderer extends AudioDecoderRenderer {
}
@Override
protected int supportsFormat(Format format) {
public int supportsFormat(Format format) {
if (!FfmpegDecoder.IS_AVAILABLE) {
return FORMAT_UNSUPPORTED_TYPE;
}

View File

@ -15,14 +15,13 @@
*/
package com.google.android.exoplayer2.ext.flac;
import com.google.android.exoplayer2.DefaultTrackSelectionPolicy;
import com.google.android.exoplayer2.DefaultTrackSelector;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import android.content.Context;
@ -72,8 +71,7 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
public void run() {
Looper.prepare();
LibflacAudioRenderer audioRenderer = new LibflacAudioRenderer();
DefaultTrackSelector trackSelector = new DefaultTrackSelector(
new DefaultTrackSelectionPolicy(), null);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(null);
player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector);
player.addListener(this);
ExtractorMediaSource mediaSource = new ExtractorMediaSource(

View File

@ -65,7 +65,7 @@ public class LibflacAudioRenderer extends AudioDecoderRenderer {
}
@Override
protected int supportsFormat(Format format) {
public int supportsFormat(Format format) {
return isLibflacAvailable() && MimeTypes.AUDIO_FLAC.equalsIgnoreCase(format.sampleMimeType)
? FORMAT_HANDLED : FORMAT_UNSUPPORTED_TYPE;
}

View File

@ -15,14 +15,13 @@
*/
package com.google.android.exoplayer2.ext.opus;
import com.google.android.exoplayer2.DefaultTrackSelectionPolicy;
import com.google.android.exoplayer2.DefaultTrackSelector;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import android.content.Context;
@ -72,8 +71,7 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
public void run() {
Looper.prepare();
LibopusAudioRenderer audioRenderer = new LibopusAudioRenderer();
DefaultTrackSelector trackSelector = new DefaultTrackSelector(
new DefaultTrackSelectionPolicy(), null);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(null);
player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector);
player.addListener(this);
ExtractorMediaSource mediaSource = new ExtractorMediaSource(

View File

@ -73,7 +73,7 @@ public final class LibopusAudioRenderer extends AudioDecoderRenderer {
}
@Override
protected int supportsFormat(Format format) {
public int supportsFormat(Format format) {
return isLibopusAvailable() && MimeTypes.AUDIO_OPUS.equalsIgnoreCase(format.sampleMimeType)
? FORMAT_HANDLED : FORMAT_UNSUPPORTED_TYPE;
}

View File

@ -15,14 +15,13 @@
*/
package com.google.android.exoplayer2.ext.vp9;
import com.google.android.exoplayer2.DefaultTrackSelectionPolicy;
import com.google.android.exoplayer2.DefaultTrackSelector;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import android.content.Context;
@ -88,8 +87,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
public void run() {
Looper.prepare();
LibvpxVideoRenderer videoRenderer = new LibvpxVideoRenderer(true, 0);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(
new DefaultTrackSelectionPolicy(), null);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(null);
player = ExoPlayerFactory.newInstance(new Renderer[] {videoRenderer}, trackSelector);
player.addListener(this);
ExtractorMediaSource mediaSource = new ExtractorMediaSource(

View File

@ -137,7 +137,7 @@ public final class LibvpxVideoRenderer extends Renderer {
}
@Override
protected int supportsFormat(Format format) {
public int supportsFormat(Format format) {
return isLibvpxAvailable() && MimeTypes.VIDEO_VP9.equalsIgnoreCase(format.sampleMimeType)
? (FORMAT_HANDLED | ADAPTIVE_SEAMLESS) : FORMAT_UNSUPPORTED_TYPE;
}

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.util.Util;

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2;
import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import android.content.Context;
import android.os.Looper;

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2;
import com.google.android.exoplayer2.ExoPlayerImplInternal.PlaybackInfo;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.util.Assertions;
import android.annotation.SuppressLint;

View File

@ -16,11 +16,14 @@
package com.google.android.exoplayer2;
import com.google.android.exoplayer2.ExoPlayer.ExoPlayerMessage;
import com.google.android.exoplayer2.TrackSelector.InvalidationListener;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelector.InvalidationListener;
import com.google.android.exoplayer2.util.PriorityHandlerThread;
import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.util.Util;

View File

@ -17,6 +17,8 @@ package com.google.android.exoplayer2;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.Allocator;
/**

View File

@ -222,12 +222,12 @@ public abstract class MediaCodecRenderer extends Renderer {
}
@Override
protected final int supportsMixedMimeTypeAdaptation() throws ExoPlaybackException {
public final int supportsMixedMimeTypeAdaptation() throws ExoPlaybackException {
return ADAPTIVE_NOT_SEAMLESS;
}
@Override
protected final int supportsFormat(Format format) throws ExoPlaybackException {
public final int supportsFormat(Format format) throws ExoPlaybackException {
try {
return supportsFormat(mediaCodecSelector, format);
} catch (DecoderQueryException e) {

View File

@ -165,7 +165,7 @@ public abstract class Renderer implements ExoPlayerComponent {
* {@link #ADAPTIVE_NOT_SUPPORTED}.
* @throws ExoPlaybackException If an error occurs.
*/
protected int supportsMixedMimeTypeAdaptation() throws ExoPlaybackException {
public int supportsMixedMimeTypeAdaptation() throws ExoPlaybackException {
return ADAPTIVE_NOT_SUPPORTED;
}
@ -408,7 +408,7 @@ public abstract class Renderer implements ExoPlayerComponent {
* @return The extent to which the renderer is capable of supporting the given format.
* @throws ExoPlaybackException If an error occurs.
*/
protected abstract int supportsFormat(Format format) throws ExoPlaybackException;
public abstract int supportsFormat(Format format) throws ExoPlaybackException;
/**
* Incrementally renders the {@link SampleStream}.

View File

@ -23,6 +23,7 @@ import com.google.android.exoplayer2.metadata.id3.Id3Parser;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextRenderer;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;

View File

@ -1,70 +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;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
/**
* Defines a policy for selecting the track rendered by each {@link Renderer}.
*/
public abstract class TrackSelectionPolicy {
/**
* Notified when selection parameters have changed.
*/
/* package */ interface InvalidationListener {
/**
* Invoked by a {@link TrackSelectionPolicy} when previous selections are invalidated.
*/
void invalidatePolicySelections();
}
private InvalidationListener listener;
/* package */ final void init(InvalidationListener listener) {
this.listener = listener;
}
/**
* Must be invoked by subclasses when a selection parameter has changed, invalidating previous
* selections.
*/
protected void invalidate() {
if (listener != null) {
listener.invalidatePolicySelections();
}
}
/**
* Given an array of {@link Renderer}s and a set of {@link TrackGroup}s assigned to each of
* them, provides a {@link TrackSelection} per renderer.
*
* @param renderers The available {@link Renderer}s.
* @param rendererTrackGroupArrays An array of {@link TrackGroupArray}s where each entry
* corresponds to the {@link Renderer} of equal index in {@code renderers}.
* @param rendererFormatSupports Maps every available track to a specific level of support as
* defined by the {@link Renderer} {@code FORMAT_*} constants.
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
*/
protected abstract TrackSelection[] selectTracks(Renderer[] renderers,
TrackGroupArray[] rendererTrackGroupArrays, int[][][] rendererFormatSupports)
throws ExoPlaybackException;
}

View File

@ -279,7 +279,6 @@ public final class VideoFrameReleaseTimeHelper {
}
}
private void createChoreographerInstanceInternal() {
choreographer = Choreographer.getInstance();
}
@ -299,7 +298,6 @@ public final class VideoFrameReleaseTimeHelper {
}
}
}
}

View File

@ -1,345 +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.chunk;
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.extractor.DefaultTrackOutput;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SequenceableLoader;
import com.google.android.exoplayer2.source.chunk.BaseMediaChunk;
import com.google.android.exoplayer2.source.chunk.Chunk;
import com.google.android.exoplayer2.source.chunk.ChunkHolder;
import com.google.android.exoplayer2.source.chunk.ChunkSource;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* A {@link SampleStream} that loads media in {@link Chunk}s, obtained from a {@link ChunkSource}.
*/
public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, SequenceableLoader,
Loader.Callback<Chunk> {
private final int trackType;
private final T chunkSource;
private final SequenceableLoader.Callback<ChunkSampleStream<T>> callback;
private final EventDispatcher eventDispatcher;
private final int minLoadableRetryCount;
private final LinkedList<BaseMediaChunk> mediaChunks;
private final List<BaseMediaChunk> readOnlyMediaChunks;
private final DefaultTrackOutput sampleQueue;
private final ChunkHolder nextChunkHolder;
private final Loader loader;
private Format downstreamFormat;
private long lastSeekPositionUs;
private long pendingResetPositionUs;
private boolean loadingFinished;
/**
* @param trackType The type of the track. One of the {@link C} {@code TRACK_TYPE_*} constants.
* @param chunkSource A {@link ChunkSource} from which chunks to load are obtained.
* @param callback An {@link Callback} for the stream.
* @param allocator An {@link Allocator} from which allocations can be obtained.
* @param positionUs The position from which to start loading media.
* @param minLoadableRetryCount The minimum number of times that the source should retry a load
* before propagating an error.
* @param eventDispatcher A dispatcher to notify of events.
*/
public ChunkSampleStream(int trackType, T chunkSource,
SequenceableLoader.Callback<ChunkSampleStream<T>> callback, Allocator allocator,
long positionUs, int minLoadableRetryCount, EventDispatcher eventDispatcher) {
this.trackType = trackType;
this.chunkSource = chunkSource;
this.callback = callback;
this.eventDispatcher = eventDispatcher;
this.minLoadableRetryCount = minLoadableRetryCount;
loader = new Loader("Loader:ChunkSampleStream");
nextChunkHolder = new ChunkHolder();
mediaChunks = new LinkedList<>();
readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks);
sampleQueue = new DefaultTrackOutput(allocator);
pendingResetPositionUs = C.UNSET_TIME_US;
lastSeekPositionUs = positionUs;
pendingResetPositionUs = positionUs;
}
/**
* Returns the {@link ChunkSource} used by this stream.
*
* @return The {@link ChunkSource}.
*/
public T getChunkSource() {
return chunkSource;
}
/**
* Returns an estimate of the position up to which data is buffered.
*
* @return An estimate of the absolute position in microseconds up to which data is buffered, or
* {@link C#END_OF_SOURCE_US} if the track is fully buffered.
*/
public long getBufferedPositionUs() {
if (loadingFinished) {
return C.END_OF_SOURCE_US;
} else if (isPendingReset()) {
return pendingResetPositionUs;
} else {
long bufferedPositionUs = lastSeekPositionUs;
BaseMediaChunk lastMediaChunk = mediaChunks.getLast();
BaseMediaChunk lastCompletedMediaChunk = lastMediaChunk.isLoadCompleted() ? lastMediaChunk
: mediaChunks.size() > 1 ? mediaChunks.get(mediaChunks.size() - 2) : null;
if (lastCompletedMediaChunk != null) {
bufferedPositionUs = Math.max(bufferedPositionUs, lastCompletedMediaChunk.endTimeUs);
}
return Math.max(bufferedPositionUs, sampleQueue.getLargestQueuedTimestampUs());
}
}
/**
* Seeks to the specified position in microseconds.
*
* @param positionUs The seek position in microseconds.
*/
public void seekToUs(long positionUs) {
lastSeekPositionUs = positionUs;
// If we're not pending a reset, see if we can seek within the sample queue.
boolean seekInsideBuffer = !isPendingReset() && sampleQueue.skipToKeyframeBefore(positionUs);
if (seekInsideBuffer) {
// We succeeded. All we need to do is discard any chunks that we've moved past.
while (mediaChunks.size() > 1
&& mediaChunks.get(1).getFirstSampleIndex() <= sampleQueue.getReadIndex()) {
mediaChunks.removeFirst();
}
} else {
// We failed, and need to restart.
pendingResetPositionUs = positionUs;
loadingFinished = false;
mediaChunks.clear();
if (loader.isLoading()) {
loader.cancelLoading();
} else {
sampleQueue.reset(true);
}
}
}
/**
* Releases the stream.
* <p>
* This method should be called when the stream is no longer required.
*/
public void release() {
chunkSource.release();
sampleQueue.disable();
loader.release();
}
// SampleStream implementation.
@Override
public boolean isReady() {
return loadingFinished || (!isPendingReset() && !sampleQueue.isEmpty());
}
@Override
public void maybeThrowError() throws IOException {
loader.maybeThrowError();
if (!loader.isLoading()) {
chunkSource.maybeThrowError();
}
}
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
if (isPendingReset()) {
return C.RESULT_NOTHING_READ;
}
while (mediaChunks.size() > 1
&& mediaChunks.get(1).getFirstSampleIndex() <= sampleQueue.getReadIndex()) {
mediaChunks.removeFirst();
}
BaseMediaChunk currentChunk = mediaChunks.getFirst();
Format format = currentChunk.format;
if (!format.equals(downstreamFormat)) {
eventDispatcher.downstreamFormatChanged(trackType, format,
currentChunk.formatEvaluatorTrigger, currentChunk.formatEvaluatorData,
currentChunk.startTimeUs);
}
downstreamFormat = format;
return sampleQueue.readData(formatHolder, buffer, loadingFinished, lastSeekPositionUs);
}
// Loader.Callback implementation.
@Override
public void onLoadCompleted(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs) {
chunkSource.onChunkLoadCompleted(loadable);
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, trackType, loadable.format,
loadable.formatEvaluatorTrigger, loadable.formatEvaluatorData, loadable.startTimeUs,
loadable.endTimeUs, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded());
callback.onContinueLoadingRequested(this);
}
@Override
public void onLoadCanceled(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs,
boolean released) {
eventDispatcher.loadCanceled(loadable.dataSpec, loadable.type, trackType, loadable.format,
loadable.formatEvaluatorTrigger, loadable.formatEvaluatorData, loadable.startTimeUs,
loadable.endTimeUs, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded());
if (!released) {
sampleQueue.reset(true);
callback.onContinueLoadingRequested(this);
}
}
@Override
public int onLoadError(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs,
IOException error) {
long bytesLoaded = loadable.bytesLoaded();
boolean isMediaChunk = isMediaChunk(loadable);
boolean cancelable = !isMediaChunk || bytesLoaded == 0 || mediaChunks.size() > 1;
boolean canceled = false;
if (chunkSource.onChunkLoadError(loadable, cancelable, error)) {
canceled = true;
if (isMediaChunk) {
BaseMediaChunk removed = mediaChunks.removeLast();
Assertions.checkState(removed == loadable);
sampleQueue.discardUpstreamSamples(removed.getFirstSampleIndex());
if (mediaChunks.isEmpty()) {
pendingResetPositionUs = lastSeekPositionUs;
}
}
}
eventDispatcher.loadError(loadable.dataSpec, loadable.type, trackType, loadable.format,
loadable.formatEvaluatorTrigger, loadable.formatEvaluatorData, loadable.startTimeUs,
loadable.endTimeUs, elapsedRealtimeMs, loadDurationMs, bytesLoaded, error,
canceled);
if (canceled) {
callback.onContinueLoadingRequested(this);
return Loader.DONT_RETRY;
} else {
return Loader.RETRY;
}
}
// SequenceableLoader implementation
@Override
public boolean continueLoading(long positionUs) {
if (loader.isLoading()) {
return false;
}
chunkSource.getNextChunk(mediaChunks.isEmpty() ? null : mediaChunks.getLast(),
pendingResetPositionUs != C.UNSET_TIME_US ? pendingResetPositionUs : positionUs,
nextChunkHolder);
boolean endOfStream = nextChunkHolder.endOfStream;
Chunk loadable = nextChunkHolder.chunk;
nextChunkHolder.clear();
if (endOfStream) {
loadingFinished = true;
return true;
}
if (loadable == null) {
return false;
}
if (isMediaChunk(loadable)) {
pendingResetPositionUs = C.UNSET_TIME_US;
BaseMediaChunk mediaChunk = (BaseMediaChunk) loadable;
mediaChunk.init(sampleQueue);
mediaChunks.add(mediaChunk);
}
long elapsedRealtimeMs = loader.startLoading(loadable, this, minLoadableRetryCount);
eventDispatcher.loadStarted(loadable.dataSpec, loadable.type, trackType, loadable.format,
loadable.formatEvaluatorTrigger, loadable.formatEvaluatorData, loadable.startTimeUs,
loadable.endTimeUs, elapsedRealtimeMs);
return true;
}
@Override
public long getNextLoadPositionUs() {
if (isPendingReset()) {
return pendingResetPositionUs;
} else {
return loadingFinished ? C.END_OF_SOURCE_US : mediaChunks.getLast().endTimeUs;
}
}
// Internal methods
// TODO[REFACTOR]: Call maybeDiscardUpstream for DASH and SmoothStreaming.
/**
* Discards media chunks from the back of the buffer if conditions have changed such that it's
* preferable to re-buffer the media at a different quality.
*
* @param positionUs The current playback position in microseconds.
*/
private void maybeDiscardUpstream(long positionUs) {
int queueSize = chunkSource.getPreferredQueueSize(positionUs, readOnlyMediaChunks);
discardUpstreamMediaChunks(Math.max(1, queueSize));
}
private boolean isMediaChunk(Chunk chunk) {
return chunk instanceof BaseMediaChunk;
}
private boolean isPendingReset() {
return pendingResetPositionUs != C.UNSET_TIME_US;
}
/**
* Discard upstream media chunks until the queue length is equal to the length specified.
*
* @param queueLength The desired length of the queue.
* @return True if chunks were discarded. False otherwise.
*/
private boolean discardUpstreamMediaChunks(int queueLength) {
if (mediaChunks.size() <= queueLength) {
return false;
}
long startTimeUs = 0;
long endTimeUs = mediaChunks.getLast().endTimeUs;
BaseMediaChunk removed = null;
while (mediaChunks.size() > queueLength) {
removed = mediaChunks.removeLast();
startTimeUs = removed.startTimeUs;
loadingFinished = false;
}
sampleQueue.discardUpstreamSamples(removed.getFirstSampleIndex());
eventDispatcher.upstreamDiscarded(trackType, startTimeUs, endTimeUs);
return true;
}
}

View File

@ -89,7 +89,7 @@ public final class MetadataRenderer<T> extends Renderer implements Callback {
}
@Override
protected int supportsFormat(Format format) {
public int supportsFormat(Format format) {
return metadataParser.canParse(format.sampleMimeType) ? Renderer.FORMAT_HANDLED
: Renderer.FORMAT_UNSUPPORTED_TYPE;
}

View File

@ -20,7 +20,6 @@ import com.google.android.exoplayer2.DecoderInputBuffer;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.DefaultTrackOutput;
@ -32,6 +31,7 @@ import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DataSource;

View File

@ -16,7 +16,7 @@
package com.google.android.exoplayer2.source;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import java.io.IOException;

View File

@ -16,7 +16,7 @@
package com.google.android.exoplayer2.source;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import android.util.Pair;

View File

@ -19,7 +19,7 @@ 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.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSourceFactory;

View File

@ -18,8 +18,6 @@ package com.google.android.exoplayer2.source.dash;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.chunk.ChunkSampleStream;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.CompositeSequenceableLoader;
@ -29,6 +27,7 @@ import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SequenceableLoader;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.chunk.ChunkSampleStream;
import com.google.android.exoplayer2.source.chunk.FormatEvaluator;
import com.google.android.exoplayer2.source.chunk.FormatEvaluator.AdaptiveEvaluator;
import com.google.android.exoplayer2.source.dash.mpd.AdaptationSet;
@ -37,6 +36,7 @@ import com.google.android.exoplayer2.source.dash.mpd.MediaPresentationDescriptio
import com.google.android.exoplayer2.source.dash.mpd.Period;
import com.google.android.exoplayer2.source.dash.mpd.Representation;
import com.google.android.exoplayer2.source.dash.mpd.UtcTimingElement;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DataSource;

View File

@ -18,7 +18,6 @@ package com.google.android.exoplayer2.source.hls;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.CompositeSequenceableLoader;
@ -33,6 +32,7 @@ import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist;
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylist;
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser;
import com.google.android.exoplayer2.source.hls.playlist.Variant;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DataSource;

View File

@ -19,7 +19,6 @@ 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.TrackSelection;
import com.google.android.exoplayer2.extractor.DefaultTrackOutput;
import com.google.android.exoplayer2.extractor.DefaultTrackOutput.UpstreamFormatChangedListener;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
@ -31,6 +30,7 @@ import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.chunk.Chunk;
import com.google.android.exoplayer2.source.chunk.ChunkHolder;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.util.Assertions;

View File

@ -18,8 +18,6 @@ package com.google.android.exoplayer2.source.smoothstreaming;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.chunk.ChunkSampleStream;
import com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
@ -30,10 +28,12 @@ import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SequenceableLoader;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.chunk.ChunkSampleStream;
import com.google.android.exoplayer2.source.chunk.FormatEvaluator;
import com.google.android.exoplayer2.source.chunk.FormatEvaluator.AdaptiveEvaluator;
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingManifest.ProtectionElement;
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingManifest.StreamElement;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DataSource;

View File

@ -108,7 +108,7 @@ public final class TextRenderer extends Renderer implements Callback {
}
@Override
protected int supportsFormat(Format format) {
public int supportsFormat(Format format) {
return parserFactory.supportsFormat(format) ? Renderer.FORMAT_HANDLED
: (MimeTypes.isText(format.sampleMimeType) ? FORMAT_UNSUPPORTED_SUBTYPE
: FORMAT_UNSUPPORTED_TYPE);

View File

@ -13,18 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2;
package com.google.android.exoplayer2.trackselection;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.util.Util;
import android.os.Handler;
import java.util.Locale;
/**
* A {@link TrackSelectionPolicy} that allows configuration of common parameters.
* A {@link MappingTrackSelector} that allows configuration of common parameters.
*/
public class DefaultTrackSelectionPolicy extends TrackSelectionPolicy {
public class DefaultTrackSelector extends MappingTrackSelector {
private static final int[] NO_TRACKS = new int[0];
@ -35,7 +41,8 @@ public class DefaultTrackSelectionPolicy extends TrackSelectionPolicy {
private int maxVideoHeight;
private boolean exceedVideoConstraintsIfNecessary;
public DefaultTrackSelectionPolicy() {
public DefaultTrackSelector(Handler eventHandler) {
super(eventHandler);
allowNonSeamlessAdaptiveness = true;
exceedVideoConstraintsIfNecessary = true;
maxVideoWidth = Integer.MAX_VALUE;
@ -124,7 +131,7 @@ public class DefaultTrackSelectionPolicy extends TrackSelectionPolicy {
// TrackSelectionPolicy implementation.
@Override
public TrackSelection[] selectTracks(Renderer[] renderers,
protected TrackSelection[] selectTracks(Renderer[] renderers,
TrackGroupArray[] rendererTrackGroupArrays, int[][][] rendererFormatSupports)
throws ExoPlaybackException {
// Make a track selection for each renderer.

View File

@ -13,8 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2;
package com.google.android.exoplayer2.trackselection;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.util.Assertions;
@ -31,13 +34,14 @@ import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* A {@link TrackSelector} suitable for a wide range of use cases.
* Base class for {@link TrackSelector}s that first establish a mapping between {@link TrackGroup}s
* and {@link Renderer}s, and then from the mapping create {@link TrackSelection}s for each of the
* {@link Renderer}s.
*/
public final class DefaultTrackSelector extends TrackSelector implements
TrackSelectionPolicy.InvalidationListener{
public abstract class MappingTrackSelector extends TrackSelector {
/**
* Interface definition for a callback to be notified of {@link DefaultTrackSelector} events.
* Interface definition for a callback to be notified of {@link MappingTrackSelector} events.
*/
public interface EventListener {
@ -54,22 +58,18 @@ public final class DefaultTrackSelector extends TrackSelector implements
private final CopyOnWriteArraySet<EventListener> listeners;
private final SparseArray<Map<TrackGroupArray, TrackSelection>> trackSelectionOverrides;
private final SparseBooleanArray rendererDisabledFlags;
private final TrackSelectionPolicy trackSelectionPolicy;
private TrackInfo activeTrackInfo;
/**
* @param trackSelectionPolicy Defines the policy for track selection.
* @param eventHandler A handler to use when delivering events to listeners added via
* {@link #addListener(EventListener)}.
*/
public DefaultTrackSelector(TrackSelectionPolicy trackSelectionPolicy, Handler eventHandler) {
this.trackSelectionPolicy = Assertions.checkNotNull(trackSelectionPolicy);
public MappingTrackSelector(Handler eventHandler) {
this.eventHandler = eventHandler;
this.listeners = new CopyOnWriteArraySet<>();
trackSelectionOverrides = new SparseArray<>();
rendererDisabledFlags = new SparseBooleanArray();
trackSelectionPolicy.init(this);
}
/**
@ -78,7 +78,7 @@ public final class DefaultTrackSelector extends TrackSelector implements
*
* @param listener The listener to register.
*/
public void addListener(EventListener listener) {
public final void addListener(EventListener listener) {
Assertions.checkState(eventHandler != null);
listeners.add(listener);
}
@ -88,7 +88,7 @@ public final class DefaultTrackSelector extends TrackSelector implements
*
* @param listener The listener to unregister.
*/
public void removeListener(EventListener listener) {
public final void removeListener(EventListener listener) {
listeners.remove(listener);
}
@ -97,7 +97,7 @@ public final class DefaultTrackSelector extends TrackSelector implements
*
* @return Contains the current tracks and track selection information.
*/
public TrackInfo getTrackInfo() {
public final TrackInfo getTrackInfo() {
return activeTrackInfo;
}
@ -107,7 +107,7 @@ public final class DefaultTrackSelector extends TrackSelector implements
* @param rendererIndex The renderer index.
* @param disabled True if the renderer is disabled. False otherwise.
*/
public void setRendererDisabled(int rendererIndex, boolean disabled) {
public final void setRendererDisabled(int rendererIndex, boolean disabled) {
if (rendererDisabledFlags.get(rendererIndex) == disabled) {
// The disabled flag is unchanged.
return;
@ -122,7 +122,7 @@ public final class DefaultTrackSelector extends TrackSelector implements
* @param rendererIndex The renderer index.
* @return True if the renderer is disabled. False otherwise.
*/
public boolean getRendererDisabled(int rendererIndex) {
public final boolean getRendererDisabled(int rendererIndex) {
return rendererDisabledFlags.get(rendererIndex);
}
@ -144,7 +144,7 @@ public final class DefaultTrackSelector extends TrackSelector implements
*/
// TODO - Don't allow overrides that select unsupported tracks, unless some flag has been
// explicitly set by the user to indicate that they want this.
public void setSelectionOverride(int rendererIndex, TrackGroupArray groups,
public final void setSelectionOverride(int rendererIndex, TrackGroupArray groups,
TrackSelection override) {
Map<TrackGroupArray, TrackSelection> overrides = trackSelectionOverrides.get(rendererIndex);
if (overrides == null) {
@ -166,7 +166,7 @@ public final class DefaultTrackSelector extends TrackSelector implements
* @param groups The {@link TrackGroupArray}.
* @return True if there is an override. False otherwise.
*/
public boolean hasSelectionOverride(int rendererIndex, TrackGroupArray groups) {
public final boolean hasSelectionOverride(int rendererIndex, TrackGroupArray groups) {
Map<TrackGroupArray, TrackSelection> overrides = trackSelectionOverrides.get(rendererIndex);
return overrides != null && overrides.containsKey(groups);
}
@ -177,7 +177,7 @@ public final class DefaultTrackSelector extends TrackSelector implements
* @param rendererIndex The renderer index.
* @param groups The {@link TrackGroupArray} for which the override should be cleared.
*/
public void clearSelectionOverride(int rendererIndex, TrackGroupArray groups) {
public final void clearSelectionOverride(int rendererIndex, TrackGroupArray groups) {
Map<TrackGroupArray, TrackSelection> overrides = trackSelectionOverrides.get(rendererIndex);
if (overrides == null || !overrides.containsKey(groups)) {
// Nothing to clear.
@ -195,7 +195,7 @@ public final class DefaultTrackSelector extends TrackSelector implements
*
* @param rendererIndex The renderer index.
*/
public void clearSelectionOverrides(int rendererIndex) {
public final void clearSelectionOverrides(int rendererIndex) {
Map<TrackGroupArray, TrackSelection> overrides = trackSelectionOverrides.get(rendererIndex);
if (overrides == null || overrides.isEmpty()) {
// Nothing to clear.
@ -208,7 +208,7 @@ public final class DefaultTrackSelector extends TrackSelector implements
/**
* Clears all track selection overrides.
*/
public void clearSelectionOverrides() {
public final void clearSelectionOverrides() {
if (trackSelectionOverrides.size() == 0) {
// Nothing to clear.
return;
@ -217,24 +217,16 @@ public final class DefaultTrackSelector extends TrackSelector implements
invalidate();
}
/**
* Invoked when the {@link TrackSelectionPolicy} has changed.
*/
@Override
public void invalidatePolicySelections() {
invalidate();
}
// TrackSelector implementation.
@Override
protected void onSelectionActivated(Object selectionInfo) {
public final void onSelectionActivated(Object selectionInfo) {
activeTrackInfo = (TrackInfo) selectionInfo;
notifyTrackInfoChanged(activeTrackInfo);
}
@Override
protected Pair<TrackSelectionArray, Object> selectTracks(Renderer[] renderers,
public final Pair<TrackSelectionArray, Object> selectTracks(Renderer[] renderers,
TrackGroupArray trackGroups) throws ExoPlaybackException {
// Structures into which data will be written during the selection. The extra item at the end
// of each array is to store data associated with track groups that cannot be associated with
@ -280,8 +272,8 @@ public final class DefaultTrackSelector extends TrackSelector implements
TrackGroupArray unassociatedTrackGroupArray = new TrackGroupArray(
Arrays.copyOf(rendererTrackGroups[renderers.length], unassociatedTrackGroupCount));
TrackSelection[] rendererTrackSelections = trackSelectionPolicy.selectTracks(renderers,
rendererTrackGroupArrays, rendererFormatSupports);
TrackSelection[] rendererTrackSelections = selectTracks(renderers, rendererTrackGroupArrays,
rendererFormatSupports);
// Apply track disabling and overriding.
for (int i = 0; i < renderers.length; i++) {
@ -317,6 +309,21 @@ public final class DefaultTrackSelector extends TrackSelector implements
return Pair.<TrackSelectionArray, Object>create(trackSelectionArray, trackInfo);
}
/**
* Given an array of {@link Renderer}s and a set of {@link TrackGroup}s mapped to each of
* them, provides a {@link TrackSelection} per renderer.
*
* @param renderers The available {@link Renderer}s.
* @param rendererTrackGroupArrays An array of {@link TrackGroupArray}s where each entry
* corresponds to the {@link Renderer} of equal index in {@code renderers}.
* @param rendererFormatSupports Maps every available track to a specific level of support as
* defined by the {@link Renderer} {@code FORMAT_*} constants.
* @throws ExoPlaybackException If an error occurs while selecting the tracks.
*/
protected abstract TrackSelection[] selectTracks(Renderer[] renderers,
TrackGroupArray[] rendererTrackGroupArrays, int[][][] rendererFormatSupports)
throws ExoPlaybackException;
/**
* Finds the renderer to which the provided {@link TrackGroup} should be associated.
* <p>

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2;
package com.google.android.exoplayer2.trackselection;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.util.Assertions;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2;
package com.google.android.exoplayer2.trackselection;
import java.util.Arrays;

View File

@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2;
package com.google.android.exoplayer2.trackselection;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.source.TrackGroupArray;
import android.util.Pair;
@ -27,7 +29,7 @@ public abstract class TrackSelector {
/**
* Notified when previous selections by a {@link TrackSelector} are no longer valid.
*/
/* package */ interface InvalidationListener {
public interface InvalidationListener {
/**
* Invoked by a {@link TrackSelector} when previous selections are no longer valid.
@ -38,17 +40,13 @@ public abstract class TrackSelector {
private InvalidationListener listener;
/* package */ void init(InvalidationListener listener) {
this.listener = listener;
}
/**
* Invalidates all previously generated track selections.
* Initializes the selector.
*
* @param listener A listener for the selector.
*/
protected final void invalidate() {
if (listener != null) {
listener.onTrackSelectionsInvalidated();
}
public final void init(InvalidationListener listener) {
this.listener = listener;
}
/**
@ -65,7 +63,7 @@ public abstract class TrackSelector {
* if the selection is activated.
* @throws ExoPlaybackException If an error occurs selecting tracks.
*/
protected abstract Pair<TrackSelectionArray, Object> selectTracks(Renderer[] renderers,
public abstract Pair<TrackSelectionArray, Object> selectTracks(Renderer[] renderers,
TrackGroupArray trackGroups) throws ExoPlaybackException;
/**
@ -74,6 +72,15 @@ public abstract class TrackSelector {
*
* @param selectionInfo The opaque object associated with the selection.
*/
protected abstract void onSelectionActivated(Object selectionInfo);
public abstract void onSelectionActivated(Object selectionInfo);
/**
* Invalidates all previously generated track selections.
*/
protected final void invalidate() {
if (listener != null) {
listener.onTrackSelectionsInvalidated();
}
}
}

View File

@ -23,8 +23,6 @@ import com.google.android.exoplayer2.MediaCodecDecoderInfo;
import com.google.android.exoplayer2.MediaCodecUtil;
import com.google.android.exoplayer2.MediaCodecUtil.DecoderQueryException;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.TrackSelectionPolicy;
import com.google.android.exoplayer2.playbacktests.util.ActionSchedule;
import com.google.android.exoplayer2.playbacktests.util.CodecCountersUtil;
import com.google.android.exoplayer2.playbacktests.util.ExoHostedTest;
@ -34,6 +32,8 @@ import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.dash.DashMediaSource;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DataSourceFactory;
import com.google.android.exoplayer2.util.Assertions;
@ -381,7 +381,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
private final Uri manifestUri;
private final MetricsLogger metricsLogger;
private final boolean fullPlaybackNoSeeking;
private final DashTestTrackSelectionPolicy trackSelectionPolicy;
private final DashTestTrackSelector trackSelector;
private boolean needsCddLimitedRetry;
@ -406,7 +406,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
this.manifestUri = manifestUri;
this.metricsLogger = metricsLogger;
this.fullPlaybackNoSeeking = fullPlaybackNoSeeking;
trackSelectionPolicy = new DashTestTrackSelectionPolicy(new String[] {audioFormat},
trackSelector = new DashTestTrackSelector(new String[] {audioFormat},
videoFormats, canIncludeAdditionalVideoFormats);
if (actionSchedule != null) {
setSchedule(actionSchedule);
@ -414,8 +414,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
@Override
protected TrackSelectionPolicy buildTrackSelectionPolicy(HostActivity host) {
return trackSelectionPolicy;
protected MappingTrackSelector buildTrackSelector(HostActivity host) {
return trackSelector;
}
@Override
@ -463,7 +463,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
CodecCountersUtil.assertConsecutiveDroppedOutputBufferLimit(VIDEO_TAG, videoCounters,
MAX_CONSECUTIVE_DROPPED_VIDEO_FRAMES);
} catch (AssertionFailedError e) {
if (trackSelectionPolicy.includedAdditionalVideoFormats) {
if (trackSelector.includedAdditionalVideoFormats) {
// Retry limiting to CDD mandated formats (b/28220076).
Log.e(TAG, "Too many dropped or consecutive dropped frames.", e);
needsCddLimitedRetry = true;
@ -475,7 +475,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
private static final class DashTestTrackSelectionPolicy extends TrackSelectionPolicy {
private static final class DashTestTrackSelector extends MappingTrackSelector {
private final String[] audioFormatIds;
private final String[] videoFormatIds;
@ -483,8 +483,9 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
public boolean includedAdditionalVideoFormats;
private DashTestTrackSelectionPolicy(String[] audioFormatIds, String[] videoFormatIds,
private DashTestTrackSelector(String[] audioFormatIds, String[] videoFormatIds,
boolean canIncludeAdditionalVideoFormats) {
super(null);
this.audioFormatIds = audioFormatIds;
this.videoFormatIds = videoFormatIds;
this.canIncludeAdditionalVideoFormats = canIncludeAdditionalVideoFormats;

View File

@ -15,8 +15,8 @@
*/
package com.google.android.exoplayer2.playbacktests.util;
import com.google.android.exoplayer2.DefaultTrackSelector;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import android.util.Log;
@ -43,18 +43,18 @@ public abstract class Action {
* @param player The player to which the action should be applied.
* @param trackSelector The track selector to which the action should be applied.
*/
public final void doAction(ExoPlayer player, DefaultTrackSelector trackSelector) {
public final void doAction(ExoPlayer player, MappingTrackSelector trackSelector) {
Log.i(tag, description);
doActionImpl(player, trackSelector);
}
/**
* Called by {@link #doAction(ExoPlayer, DefaultTrackSelector)} do actually perform the action.
* Called by {@link #doAction(ExoPlayer, MappingTrackSelector)} do actually perform the action.
*
* @param player The player to which the action should be applied.
* @param trackSelector The track selector to which the action should be applied.
*/
protected abstract void doActionImpl(ExoPlayer player, DefaultTrackSelector trackSelector);
protected abstract void doActionImpl(ExoPlayer player, MappingTrackSelector trackSelector);
/**
* Calls {@link ExoPlayer#seekTo(long)}.
@ -73,7 +73,7 @@ public abstract class Action {
}
@Override
protected void doActionImpl(ExoPlayer player, DefaultTrackSelector trackSelector) {
protected void doActionImpl(ExoPlayer player, MappingTrackSelector trackSelector) {
player.seekTo(positionMs);
}
@ -92,7 +92,7 @@ public abstract class Action {
}
@Override
protected void doActionImpl(ExoPlayer player, DefaultTrackSelector trackSelector) {
protected void doActionImpl(ExoPlayer player, MappingTrackSelector trackSelector) {
player.stop();
}
@ -115,14 +115,14 @@ public abstract class Action {
}
@Override
protected void doActionImpl(ExoPlayer player, DefaultTrackSelector trackSelector) {
protected void doActionImpl(ExoPlayer player, MappingTrackSelector trackSelector) {
player.setPlayWhenReady(playWhenReady);
}
}
/**
* Calls {@link DefaultTrackSelector#setRendererDisabled(int, boolean)}.
* Calls {@link MappingTrackSelector#setRendererDisabled(int, boolean)}.
*/
public static final class SetRendererDisabled extends Action {
@ -141,7 +141,7 @@ public abstract class Action {
}
@Override
protected void doActionImpl(ExoPlayer player, DefaultTrackSelector trackSelector) {
protected void doActionImpl(ExoPlayer player, MappingTrackSelector trackSelector) {
trackSelector.setRendererDisabled(rendererIndex, disabled);
}

View File

@ -15,12 +15,12 @@
*/
package com.google.android.exoplayer2.playbacktests.util;
import com.google.android.exoplayer2.DefaultTrackSelector;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.playbacktests.util.Action.Seek;
import com.google.android.exoplayer2.playbacktests.util.Action.SetPlayWhenReady;
import com.google.android.exoplayer2.playbacktests.util.Action.SetRendererDisabled;
import com.google.android.exoplayer2.playbacktests.util.Action.Stop;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import android.os.Handler;
@ -45,7 +45,7 @@ public final class ActionSchedule {
* @param trackSelector The track selector to which actions should be applied.
* @param mainHandler A handler associated with the main thread of the host activity.
*/
/* package */ void start(ExoPlayer player, DefaultTrackSelector trackSelector,
/* package */ void start(ExoPlayer player, MappingTrackSelector trackSelector,
Handler mainHandler) {
rootNode.schedule(player, trackSelector, mainHandler);
}
@ -167,7 +167,7 @@ public final class ActionSchedule {
private ActionNode next;
private ExoPlayer player;
private DefaultTrackSelector trackSelector;
private MappingTrackSelector trackSelector;
private Handler mainHandler;
/**
@ -196,7 +196,7 @@ public final class ActionSchedule {
* @param trackSelector The track selector to which actions should be applied.
* @param mainHandler A handler associated with the main thread of the host activity.
*/
public void schedule(ExoPlayer player, DefaultTrackSelector trackSelector,
public void schedule(ExoPlayer player, MappingTrackSelector trackSelector,
Handler mainHandler) {
this.player = player;
this.trackSelector = trackSelector;
@ -224,7 +224,7 @@ public final class ActionSchedule {
}
@Override
protected void doActionImpl(ExoPlayer player, DefaultTrackSelector trackSelector) {
protected void doActionImpl(ExoPlayer player, MappingTrackSelector trackSelector) {
// Do nothing.
}

View File

@ -16,17 +16,16 @@
package com.google.android.exoplayer2.playbacktests.util;
import com.google.android.exoplayer2.CodecCounters;
import com.google.android.exoplayer2.DefaultTrackSelectionPolicy;
import com.google.android.exoplayer2.DefaultTrackSelector;
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.SimpleExoPlayer;
import com.google.android.exoplayer2.TrackSelectionPolicy;
import com.google.android.exoplayer2.audio.AudioTrack;
import com.google.android.exoplayer2.playbacktests.util.HostActivity.HostedTest;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
import com.google.android.exoplayer2.upstream.DataSourceFactory;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
@ -64,7 +63,7 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
private ActionSchedule pendingSchedule;
private Handler actionHandler;
private DefaultTrackSelector trackSelector;
private MappingTrackSelector trackSelector;
private SimpleExoPlayer player;
private ExoPlaybackException playerError;
private boolean playerWasPrepared;
@ -124,8 +123,7 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
@Override
public final void onStart(HostActivity host, Surface surface) {
// Build the player.
TrackSelectionPolicy trackSelectionPolicy = buildTrackSelectionPolicy(host);
trackSelector = new DefaultTrackSelector(trackSelectionPolicy, null);
trackSelector = buildTrackSelector(host);
player = buildExoPlayer(host, surface, trackSelector);
DataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(host, Util
.getUserAgent(host, "ExoPlayerPlaybackTests"));
@ -275,13 +273,13 @@ public abstract class ExoHostedTest implements HostedTest, ExoPlayer.EventListen
// Internal logic
@SuppressWarnings("unused")
protected TrackSelectionPolicy buildTrackSelectionPolicy(HostActivity host) {
return new DefaultTrackSelectionPolicy();
protected MappingTrackSelector buildTrackSelector(HostActivity host) {
return new DefaultTrackSelector(null);
}
@SuppressWarnings("unused")
protected SimpleExoPlayer buildExoPlayer(HostActivity host, Surface surface,
DefaultTrackSelector trackSelector) {
MappingTrackSelector trackSelector) {
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(host, trackSelector);
player.setSurface(surface);
return player;