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:
parent
67be677ddf
commit
d4d1640808
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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) {
|
||||
|
@ -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}.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -279,7 +279,6 @@ public final class VideoFrameReleaseTimeHelper {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void createChoreographerInstanceInternal() {
|
||||
choreographer = Choreographer.getInstance();
|
||||
}
|
||||
@ -299,7 +298,6 @@ public final class VideoFrameReleaseTimeHelper {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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.
|
@ -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>
|
@ -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;
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user