Commit eaf82188 by olly Committed by Oliver Woodman

Fix shutter open/close behavior

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=134389619
parent d74166cd
...@@ -38,9 +38,10 @@ import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener; ...@@ -38,9 +38,10 @@ import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
import com.google.android.exoplayer2.source.ExtractorMediaSource; import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.TrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelections;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.video.VideoRendererEventListener; import com.google.android.exoplayer2.video.VideoRendererEventListener;
import java.io.IOException; import java.io.IOException;
...@@ -54,7 +55,7 @@ import java.util.Locale; ...@@ -54,7 +55,7 @@ import java.util.Locale;
/* package */ final class EventLogger implements ExoPlayer.EventListener, /* package */ final class EventLogger implements ExoPlayer.EventListener,
AudioRendererEventListener, VideoRendererEventListener, AdaptiveMediaSourceEventListener, AudioRendererEventListener, VideoRendererEventListener, AdaptiveMediaSourceEventListener,
ExtractorMediaSource.EventListener, StreamingDrmSessionManager.EventListener, ExtractorMediaSource.EventListener, StreamingDrmSessionManager.EventListener,
MappingTrackSelector.EventListener, MetadataRenderer.Output<List<Id3Frame>> { TrackSelector.EventListener<MappedTrackInfo>, MetadataRenderer.Output<List<Id3Frame>> {
private static final String TAG = "EventLogger"; private static final String TAG = "EventLogger";
private static final int MAX_TIMELINE_ITEM_LINES = 3; private static final int MAX_TIMELINE_ITEM_LINES = 3;
...@@ -125,23 +126,24 @@ import java.util.Locale; ...@@ -125,23 +126,24 @@ import java.util.Locale;
// MappingTrackSelector.EventListener // MappingTrackSelector.EventListener
@Override @Override
public void onTracksChanged(TrackInfo trackInfo) { public void onTrackSelectionsChanged(TrackSelections<? extends MappedTrackInfo> trackSelections) {
Log.d(TAG, "Tracks ["); Log.d(TAG, "Tracks [");
// Log tracks associated to renderers. // Log tracks associated to renderers.
for (int rendererIndex = 0; rendererIndex < trackInfo.rendererCount; rendererIndex++) { MappedTrackInfo info = trackSelections.info;
TrackGroupArray trackGroups = trackInfo.getTrackGroups(rendererIndex); for (int rendererIndex = 0; rendererIndex < trackSelections.length; rendererIndex++) {
TrackSelection trackSelection = trackInfo.getTrackSelection(rendererIndex); TrackGroupArray trackGroups = info.getTrackGroups(rendererIndex);
TrackSelection trackSelection = trackSelections.get(rendererIndex);
if (trackGroups.length > 0) { if (trackGroups.length > 0) {
Log.d(TAG, " Renderer:" + rendererIndex + " ["); Log.d(TAG, " Renderer:" + rendererIndex + " [");
for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) {
TrackGroup trackGroup = trackGroups.get(groupIndex); TrackGroup trackGroup = trackGroups.get(groupIndex);
String adaptiveSupport = getAdaptiveSupportString( String adaptiveSupport = getAdaptiveSupportString(
trackGroup.length, trackInfo.getAdaptiveSupport(rendererIndex, groupIndex, false)); trackGroup.length, info.getAdaptiveSupport(rendererIndex, groupIndex, false));
Log.d(TAG, " Group:" + groupIndex + ", adaptive_supported=" + adaptiveSupport + " ["); Log.d(TAG, " Group:" + groupIndex + ", adaptive_supported=" + adaptiveSupport + " [");
for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) { for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) {
String status = getTrackStatusString(trackSelection, trackGroup, trackIndex); String status = getTrackStatusString(trackSelection, trackGroup, trackIndex);
String formatSupport = getFormatSupportString( String formatSupport = getFormatSupportString(
trackInfo.getTrackFormatSupport(rendererIndex, groupIndex, trackIndex)); info.getTrackFormatSupport(rendererIndex, groupIndex, trackIndex));
Log.d(TAG, " " + status + " Track:" + trackIndex + ", " Log.d(TAG, " " + status + " Track:" + trackIndex + ", "
+ getFormatString(trackGroup.getFormat(trackIndex)) + getFormatString(trackGroup.getFormat(trackIndex))
+ ", supported=" + formatSupport); + ", supported=" + formatSupport);
...@@ -152,7 +154,7 @@ import java.util.Locale; ...@@ -152,7 +154,7 @@ import java.util.Locale;
} }
} }
// Log tracks not associated with a renderer. // Log tracks not associated with a renderer.
TrackGroupArray trackGroups = trackInfo.getUnassociatedTrackGroups(); TrackGroupArray trackGroups = info.getUnassociatedTrackGroups();
if (trackGroups.length > 0) { if (trackGroups.length > 0) {
Log.d(TAG, " Renderer:None ["); Log.d(TAG, " Renderer:None [");
for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) {
......
...@@ -36,6 +36,7 @@ import com.google.android.exoplayer2.ExoPlayerFactory; ...@@ -36,6 +36,7 @@ import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.drm.FrameworkMediaDrm; import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
import com.google.android.exoplayer2.drm.HttpMediaDrmCallback; import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
import com.google.android.exoplayer2.drm.StreamingDrmSessionManager; import com.google.android.exoplayer2.drm.StreamingDrmSessionManager;
...@@ -55,8 +56,10 @@ import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource; ...@@ -55,8 +56,10 @@ import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.trackselection.AdaptiveVideoTrackSelection; import com.google.android.exoplayer2.trackselection.AdaptiveVideoTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.TrackInfo; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelections;
import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.ui.DebugTextViewHelper; import com.google.android.exoplayer2.ui.DebugTextViewHelper;
import com.google.android.exoplayer2.ui.PlaybackControlView; import com.google.android.exoplayer2.ui.PlaybackControlView;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView; import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
...@@ -77,7 +80,7 @@ import java.util.UUID; ...@@ -77,7 +80,7 @@ import java.util.UUID;
* An activity that plays media using {@link SimpleExoPlayer}. * An activity that plays media using {@link SimpleExoPlayer}.
*/ */
public class PlayerActivity extends Activity implements OnClickListener, ExoPlayer.EventListener, public class PlayerActivity extends Activity implements OnClickListener, ExoPlayer.EventListener,
MappingTrackSelector.EventListener, PlaybackControlView.VisibilityListener { TrackSelector.EventListener<MappedTrackInfo>, PlaybackControlView.VisibilityListener {
public static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid"; public static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid";
public static final String DRM_LICENSE_URL = "drm_license_url"; public static final String DRM_LICENSE_URL = "drm_license_url";
...@@ -203,7 +206,7 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay ...@@ -203,7 +206,7 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
initializePlayer(); initializePlayer();
} else if (view.getParent() == debugRootView) { } else if (view.getParent() == debugRootView) {
trackSelectionHelper.showSelectionDialog(this, ((Button) view).getText(), trackSelectionHelper.showSelectionDialog(this, ((Button) view).getText(),
trackSelector.getTrackInfo(), (int) view.getTag()); trackSelector.getCurrentSelections().info, (int) view.getTag());
} }
} }
...@@ -222,7 +225,7 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay ...@@ -222,7 +225,7 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
boolean preferExtensionDecoders = intent.getBooleanExtra(PREFER_EXTENSION_DECODERS, false); boolean preferExtensionDecoders = intent.getBooleanExtra(PREFER_EXTENSION_DECODERS, false);
UUID drmSchemeUuid = intent.hasExtra(DRM_SCHEME_UUID_EXTRA) UUID drmSchemeUuid = intent.hasExtra(DRM_SCHEME_UUID_EXTRA)
? UUID.fromString(intent.getStringExtra(DRM_SCHEME_UUID_EXTRA)) : null; ? UUID.fromString(intent.getStringExtra(DRM_SCHEME_UUID_EXTRA)) : null;
DrmSessionManager drmSessionManager = null; DrmSessionManager<FrameworkMediaCrypto> drmSessionManager = null;
if (drmSchemeUuid != null) { if (drmSchemeUuid != null) {
String drmLicenseUrl = intent.getStringExtra(DRM_LICENSE_URL); String drmLicenseUrl = intent.getStringExtra(DRM_LICENSE_URL);
String[] keyRequestPropertiesArray = intent.getStringArrayExtra(DRM_KEY_REQUEST_PROPERTIES); String[] keyRequestPropertiesArray = intent.getStringArrayExtra(DRM_KEY_REQUEST_PROPERTIES);
...@@ -333,9 +336,8 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay ...@@ -333,9 +336,8 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
} }
} }
private DrmSessionManager buildDrmSessionManager(UUID uuid, String licenseUrl, private DrmSessionManager<FrameworkMediaCrypto> buildDrmSessionManager(UUID uuid,
Map<String, String> keyRequestProperties) String licenseUrl, Map<String, String> keyRequestProperties) throws UnsupportedDrmException {
throws UnsupportedDrmException {
if (Util.SDK_INT < 18) { if (Util.SDK_INT < 18) {
return null; return null;
} }
...@@ -452,8 +454,9 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay ...@@ -452,8 +454,9 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
// MappingTrackSelector.EventListener implementation // MappingTrackSelector.EventListener implementation
@Override @Override
public void onTracksChanged(TrackInfo trackInfo) { public void onTrackSelectionsChanged(TrackSelections<? extends MappedTrackInfo> trackSelections) {
updateButtonVisibilities(); updateButtonVisibilities();
MappedTrackInfo trackInfo = trackSelections.info;
if (trackInfo.hasOnlyUnplayableTracks(C.TRACK_TYPE_VIDEO)) { if (trackInfo.hasOnlyUnplayableTracks(C.TRACK_TYPE_VIDEO)) {
showToast(R.string.error_unsupported_video); showToast(R.string.error_unsupported_video);
} }
...@@ -474,14 +477,14 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay ...@@ -474,14 +477,14 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
return; return;
} }
TrackInfo trackInfo = trackSelector.getTrackInfo(); TrackSelections<MappedTrackInfo> trackSelections = trackSelector.getCurrentSelections();
if (trackInfo == null) { if (trackSelections == null) {
return; return;
} }
int rendererCount = trackInfo.rendererCount; int rendererCount = trackSelections.length;
for (int i = 0; i < rendererCount; i++) { for (int i = 0; i < rendererCount; i++) {
TrackGroupArray trackGroups = trackInfo.getTrackGroups(i); TrackGroupArray trackGroups = trackSelections.info.getTrackGroups(i);
if (trackGroups.length != 0) { if (trackGroups.length != 0) {
Button button = new Button(this); Button button = new Button(this);
int label; int label;
......
...@@ -31,8 +31,8 @@ import com.google.android.exoplayer2.source.TrackGroup; ...@@ -31,8 +31,8 @@ import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.FixedTrackSelection; import com.google.android.exoplayer2.trackselection.FixedTrackSelection;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.SelectionOverride; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.TrackInfo;
import com.google.android.exoplayer2.trackselection.RandomTrackSelection; import com.google.android.exoplayer2.trackselection.RandomTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
...@@ -51,7 +51,7 @@ import java.util.Locale; ...@@ -51,7 +51,7 @@ import java.util.Locale;
private final MappingTrackSelector selector; private final MappingTrackSelector selector;
private final TrackSelection.Factory adaptiveVideoTrackSelectionFactory; private final TrackSelection.Factory adaptiveVideoTrackSelectionFactory;
private TrackInfo trackInfo; private MappedTrackInfo trackInfo;
private int rendererIndex; private int rendererIndex;
private TrackGroupArray trackGroups; private TrackGroupArray trackGroups;
private boolean[] trackGroupsAdaptive; private boolean[] trackGroupsAdaptive;
...@@ -82,7 +82,7 @@ import java.util.Locale; ...@@ -82,7 +82,7 @@ import java.util.Locale;
* @param trackInfo The current track information. * @param trackInfo The current track information.
* @param rendererIndex The index of the renderer. * @param rendererIndex The index of the renderer.
*/ */
public void showSelectionDialog(Activity activity, CharSequence title, TrackInfo trackInfo, public void showSelectionDialog(Activity activity, CharSequence title, MappedTrackInfo trackInfo,
int rendererIndex) { int rendererIndex) {
this.trackInfo = trackInfo; this.trackInfo = trackInfo;
this.rendererIndex = rendererIndex; this.rendererIndex = rendererIndex;
......
...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.ext.flac; ...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.ext.flac;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.test.InstrumentationTestCase; import android.test.InstrumentationTestCase;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
...@@ -71,7 +72,7 @@ public class FlacPlaybackTest extends InstrumentationTestCase { ...@@ -71,7 +72,7 @@ public class FlacPlaybackTest extends InstrumentationTestCase {
public void run() { public void run() {
Looper.prepare(); Looper.prepare();
LibflacAudioRenderer audioRenderer = new LibflacAudioRenderer(); LibflacAudioRenderer audioRenderer = new LibflacAudioRenderer();
DefaultTrackSelector trackSelector = new DefaultTrackSelector(null); DefaultTrackSelector trackSelector = new DefaultTrackSelector(new Handler());
player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector); player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector);
player.addListener(this); player.addListener(this);
ExtractorMediaSource mediaSource = new ExtractorMediaSource( ExtractorMediaSource mediaSource = new ExtractorMediaSource(
......
...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.ext.opus; ...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.ext.opus;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.test.InstrumentationTestCase; import android.test.InstrumentationTestCase;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
...@@ -71,7 +72,7 @@ public class OpusPlaybackTest extends InstrumentationTestCase { ...@@ -71,7 +72,7 @@ public class OpusPlaybackTest extends InstrumentationTestCase {
public void run() { public void run() {
Looper.prepare(); Looper.prepare();
LibopusAudioRenderer audioRenderer = new LibopusAudioRenderer(); LibopusAudioRenderer audioRenderer = new LibopusAudioRenderer();
DefaultTrackSelector trackSelector = new DefaultTrackSelector(null); DefaultTrackSelector trackSelector = new DefaultTrackSelector(new Handler());
player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector); player = ExoPlayerFactory.newInstance(new Renderer[] {audioRenderer}, trackSelector);
player.addListener(this); player.addListener(this);
ExtractorMediaSource mediaSource = new ExtractorMediaSource( ExtractorMediaSource mediaSource = new ExtractorMediaSource(
......
...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.ext.vp9; ...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.ext.vp9;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.test.InstrumentationTestCase; import android.test.InstrumentationTestCase;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
...@@ -87,7 +88,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase { ...@@ -87,7 +88,7 @@ public class VpxPlaybackTest extends InstrumentationTestCase {
public void run() { public void run() {
Looper.prepare(); Looper.prepare();
LibvpxVideoRenderer videoRenderer = new LibvpxVideoRenderer(true, 0); LibvpxVideoRenderer videoRenderer = new LibvpxVideoRenderer(true, 0);
DefaultTrackSelector trackSelector = new DefaultTrackSelector(null); DefaultTrackSelector trackSelector = new DefaultTrackSelector(new Handler());
player = ExoPlayerFactory.newInstance(new Renderer[] {videoRenderer}, trackSelector); player = ExoPlayerFactory.newInstance(new Renderer[] {videoRenderer}, trackSelector);
player.addListener(this); player.addListener(this);
ExtractorMediaSource mediaSource = new ExtractorMediaSource( ExtractorMediaSource mediaSource = new ExtractorMediaSource(
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
package com.google.android.exoplayer2; package com.google.android.exoplayer2;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.trackselection.TrackSelections;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DefaultAllocator; import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
...@@ -106,7 +106,7 @@ public final class DefaultLoadControl implements LoadControl { ...@@ -106,7 +106,7 @@ public final class DefaultLoadControl implements LoadControl {
@Override @Override
public void onTracksSelected(Renderer[] renderers, TrackGroupArray trackGroups, public void onTracksSelected(Renderer[] renderers, TrackGroupArray trackGroups,
TrackSelectionArray trackSelections) { TrackSelections<?> trackSelections) {
targetBufferSize = 0; targetBufferSize = 0;
for (int i = 0; i < renderers.length; i++) { for (int i = 0; i < renderers.length; i++) {
if (trackSelections.get(i) != null) { if (trackSelections.get(i) != null) {
......
...@@ -27,7 +27,7 @@ import com.google.android.exoplayer2.source.MediaPeriod; ...@@ -27,7 +27,7 @@ import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.trackselection.TrackSelections;
import com.google.android.exoplayer2.trackselection.TrackSelector; import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MediaClock; import com.google.android.exoplayer2.util.MediaClock;
...@@ -40,8 +40,8 @@ import java.io.IOException; ...@@ -40,8 +40,8 @@ import java.io.IOException;
/** /**
* Implements the internal behavior of {@link ExoPlayerImpl}. * Implements the internal behavior of {@link ExoPlayerImpl}.
*/ */
/* package */ final class ExoPlayerImplInternal implements Handler.Callback, MediaPeriod.Callback, /* package */ final class ExoPlayerImplInternal<T> implements Handler.Callback,
TrackSelector.InvalidationListener, MediaSource.Listener { MediaPeriod.Callback, TrackSelector.InvalidationListener, MediaSource.Listener {
/** /**
* Playback position information which is read on the application's thread by * Playback position information which is read on the application's thread by
...@@ -100,7 +100,7 @@ import java.io.IOException; ...@@ -100,7 +100,7 @@ import java.io.IOException;
private final Renderer[] renderers; private final Renderer[] renderers;
private final RendererCapabilities[] rendererCapabilities; private final RendererCapabilities[] rendererCapabilities;
private final TrackSelector trackSelector; private final TrackSelector<T> trackSelector;
private final LoadControl loadControl; private final LoadControl loadControl;
private final StandaloneMediaClock standaloneMediaClock; private final StandaloneMediaClock standaloneMediaClock;
private final Handler handler; private final Handler handler;
...@@ -128,13 +128,13 @@ import java.io.IOException; ...@@ -128,13 +128,13 @@ import java.io.IOException;
private boolean isTimelineReady; private boolean isTimelineReady;
private boolean isTimelineEnded; private boolean isTimelineEnded;
private int bufferAheadPeriodCount; private int bufferAheadPeriodCount;
private MediaPeriodHolder playingPeriodHolder; private MediaPeriodHolder<T> playingPeriodHolder;
private MediaPeriodHolder readingPeriodHolder; private MediaPeriodHolder<T> readingPeriodHolder;
private MediaPeriodHolder loadingPeriodHolder; private MediaPeriodHolder<T> loadingPeriodHolder;
private Timeline timeline; private Timeline timeline;
public ExoPlayerImplInternal(Renderer[] renderers, TrackSelector trackSelector, public ExoPlayerImplInternal(Renderer[] renderers, TrackSelector<T> trackSelector,
LoadControl loadControl, boolean playWhenReady, Handler eventHandler, LoadControl loadControl, boolean playWhenReady, Handler eventHandler,
PlaybackInfo playbackInfo) { PlaybackInfo playbackInfo) {
this.renderers = renderers; this.renderers = renderers;
...@@ -538,8 +538,8 @@ import java.io.IOException; ...@@ -538,8 +538,8 @@ import java.io.IOException;
} }
// Clear the timeline, but keep the requested period if it is already prepared. // Clear the timeline, but keep the requested period if it is already prepared.
MediaPeriodHolder periodHolder = playingPeriodHolder; MediaPeriodHolder<T> periodHolder = playingPeriodHolder;
MediaPeriodHolder newPlayingPeriodHolder = null; MediaPeriodHolder<T> newPlayingPeriodHolder = null;
while (periodHolder != null) { while (periodHolder != null) {
if (periodHolder.index == periodIndex && periodHolder.prepared) { if (periodHolder.index == periodIndex && periodHolder.prepared) {
newPlayingPeriodHolder = periodHolder; newPlayingPeriodHolder = periodHolder;
...@@ -671,7 +671,7 @@ import java.io.IOException; ...@@ -671,7 +671,7 @@ import java.io.IOException;
return; return;
} }
// Reselect tracks on each period in turn, until the selection changes. // Reselect tracks on each period in turn, until the selection changes.
MediaPeriodHolder periodHolder = playingPeriodHolder; MediaPeriodHolder<T> periodHolder = playingPeriodHolder;
boolean selectionsChangedForReadPeriod = true; boolean selectionsChangedForReadPeriod = true;
while (true) { while (true) {
if (periodHolder == null || !periodHolder.prepared) { if (periodHolder == null || !periodHolder.prepared) {
...@@ -738,7 +738,7 @@ import java.io.IOException; ...@@ -738,7 +738,7 @@ import java.io.IOException;
} }
} }
} }
trackSelector.onSelectionActivated(playingPeriodHolder.trackSelectionData); trackSelector.onSelectionActivated(playingPeriodHolder.trackSelections);
enableRenderers(rendererWasEnabledFlags, enabledRendererCount); enableRenderers(rendererWasEnabledFlags, enabledRendererCount);
} else { } else {
// Release and re-prepare/buffer periods after the one whose selection changed. // Release and re-prepare/buffer periods after the one whose selection changed.
...@@ -810,11 +810,11 @@ import java.io.IOException; ...@@ -810,11 +810,11 @@ import java.io.IOException;
playingPeriodHolder.setIndex(timeline, timeline.getWindow(period.windowIndex, window), playingPeriodHolder.setIndex(timeline, timeline.getWindow(period.windowIndex, window),
index); index);
MediaPeriodHolder previousPeriod = playingPeriodHolder; MediaPeriodHolder<T> previousPeriod = playingPeriodHolder;
boolean seenReadingPeriod = false; boolean seenReadingPeriod = false;
bufferAheadPeriodCount = 0; bufferAheadPeriodCount = 0;
while (previousPeriod.next != null) { while (previousPeriod.next != null) {
MediaPeriodHolder periodHolder = previousPeriod.next; MediaPeriodHolder<T> periodHolder = previousPeriod.next;
index++; index++;
timeline.getPeriod(index, period, true); timeline.getPeriod(index, period, true);
if (!periodHolder.uid.equals(period.uid)) { if (!periodHolder.uid.equals(period.uid)) {
...@@ -954,8 +954,9 @@ import java.io.IOException; ...@@ -954,8 +954,9 @@ import java.io.IOException;
Object newPeriodUid = timeline.getPeriod(newLoadingPeriodIndex, period, true).uid; Object newPeriodUid = timeline.getPeriod(newLoadingPeriodIndex, period, true).uid;
MediaPeriod newMediaPeriod = mediaSource.createPeriod(newLoadingPeriodIndex, this, MediaPeriod newMediaPeriod = mediaSource.createPeriod(newLoadingPeriodIndex, this,
loadControl.getAllocator(), periodStartPositionUs); loadControl.getAllocator(), periodStartPositionUs);
MediaPeriodHolder newPeriodHolder = new MediaPeriodHolder(renderers, rendererCapabilities, MediaPeriodHolder<T> newPeriodHolder = new MediaPeriodHolder<>(renderers,
trackSelector, mediaSource, newMediaPeriod, newPeriodUid, periodStartPositionUs); rendererCapabilities, trackSelector, mediaSource, newMediaPeriod, newPeriodUid,
periodStartPositionUs);
timeline.getWindow(windowIndex, window); timeline.getWindow(windowIndex, window);
newPeriodHolder.setIndex(timeline, window, newLoadingPeriodIndex); newPeriodHolder.setIndex(timeline, window, newLoadingPeriodIndex);
if (loadingPeriodHolder != null) { if (loadingPeriodHolder != null) {
...@@ -1012,9 +1013,9 @@ import java.io.IOException; ...@@ -1012,9 +1013,9 @@ import java.io.IOException;
} }
} }
if (readingPeriodHolder.next != null && readingPeriodHolder.next.prepared) { if (readingPeriodHolder.next != null && readingPeriodHolder.next.prepared) {
TrackSelectionArray oldTrackSelections = readingPeriodHolder.trackSelections; TrackSelections<T> oldTrackSelections = readingPeriodHolder.trackSelections;
readingPeriodHolder = readingPeriodHolder.next; readingPeriodHolder = readingPeriodHolder.next;
TrackSelectionArray newTrackSelections = readingPeriodHolder.trackSelections; TrackSelections<T> newTrackSelections = readingPeriodHolder.trackSelections;
for (int i = 0; i < renderers.length; i++) { for (int i = 0; i < renderers.length; i++) {
Renderer renderer = renderers[i]; Renderer renderer = renderers[i];
TrackSelection oldSelection = oldTrackSelections.get(i); TrackSelection oldSelection = oldTrackSelections.get(i);
...@@ -1088,14 +1089,15 @@ import java.io.IOException; ...@@ -1088,14 +1089,15 @@ import java.io.IOException;
} }
} }
private void releasePeriodHoldersFrom(MediaPeriodHolder periodHolder) { private void releasePeriodHoldersFrom(MediaPeriodHolder<T> periodHolder) {
while (periodHolder != null) { while (periodHolder != null) {
periodHolder.release(); periodHolder.release();
periodHolder = periodHolder.next; periodHolder = periodHolder.next;
} }
} }
private void setPlayingPeriodHolder(MediaPeriodHolder periodHolder) throws ExoPlaybackException { private void setPlayingPeriodHolder(MediaPeriodHolder<T> periodHolder)
throws ExoPlaybackException {
int enabledRendererCount = 0; int enabledRendererCount = 0;
boolean[] rendererWasEnabledFlags = new boolean[renderers.length]; boolean[] rendererWasEnabledFlags = new boolean[renderers.length];
for (int i = 0; i < renderers.length; i++) { for (int i = 0; i < renderers.length; i++) {
...@@ -1118,7 +1120,7 @@ import java.io.IOException; ...@@ -1118,7 +1120,7 @@ import java.io.IOException;
} }
} }
trackSelector.onSelectionActivated(periodHolder.trackSelectionData); trackSelector.onSelectionActivated(periodHolder.trackSelections);
playingPeriodHolder = periodHolder; playingPeriodHolder = periodHolder;
enableRenderers(rendererWasEnabledFlags, enabledRendererCount); enableRenderers(rendererWasEnabledFlags, enabledRendererCount);
} }
...@@ -1175,7 +1177,7 @@ import java.io.IOException; ...@@ -1175,7 +1177,7 @@ import java.io.IOException;
/** /**
* Holds a {@link MediaPeriod} with information required to play it as part of a timeline. * Holds a {@link MediaPeriod} with information required to play it as part of a timeline.
*/ */
private static final class MediaPeriodHolder { private static final class MediaPeriodHolder<T> {
public final MediaPeriod mediaPeriod; public final MediaPeriod mediaPeriod;
public final Object uid; public final Object uid;
...@@ -1189,21 +1191,20 @@ import java.io.IOException; ...@@ -1189,21 +1191,20 @@ import java.io.IOException;
public boolean prepared; public boolean prepared;
public boolean hasEnabledTracks; public boolean hasEnabledTracks;
public long rendererPositionOffsetUs; public long rendererPositionOffsetUs;
public MediaPeriodHolder next; public MediaPeriodHolder<T> next;
public boolean needsContinueLoading; public boolean needsContinueLoading;
private final Renderer[] renderers; private final Renderer[] renderers;
private final RendererCapabilities[] rendererCapabilities; private final RendererCapabilities[] rendererCapabilities;
private final TrackSelector trackSelector; private final TrackSelector<T> trackSelector;
private final MediaSource mediaSource; private final MediaSource mediaSource;
private Object trackSelectionData; private TrackSelections<T> trackSelections;
private TrackSelectionArray trackSelections; private TrackSelections<T> periodTrackSelections;
private TrackSelectionArray periodTrackSelections;
public MediaPeriodHolder(Renderer[] renderers, RendererCapabilities[] rendererCapabilities, public MediaPeriodHolder(Renderer[] renderers, RendererCapabilities[] rendererCapabilities,
TrackSelector trackSelector, MediaSource mediaSource, MediaPeriod mediaPeriod, Object uid, TrackSelector<T> trackSelector, MediaSource mediaSource, MediaPeriod mediaPeriod,
long positionUs) { Object uid, long positionUs) {
this.renderers = renderers; this.renderers = renderers;
this.rendererCapabilities = rendererCapabilities; this.rendererCapabilities = rendererCapabilities;
this.trackSelector = trackSelector; this.trackSelector = trackSelector;
...@@ -1215,7 +1216,7 @@ import java.io.IOException; ...@@ -1215,7 +1216,7 @@ import java.io.IOException;
startPositionUs = positionUs; startPositionUs = positionUs;
} }
public void setNext(MediaPeriodHolder next) { public void setNext(MediaPeriodHolder<T> next) {
this.next = next; this.next = next;
} }
...@@ -1237,14 +1238,12 @@ import java.io.IOException; ...@@ -1237,14 +1238,12 @@ import java.io.IOException;
} }
public boolean selectTracks() throws ExoPlaybackException { public boolean selectTracks() throws ExoPlaybackException {
Pair<TrackSelectionArray, Object> result = TrackSelections<T> newTrackSelections = trackSelector.selectTracks(rendererCapabilities,
trackSelector.selectTracks(rendererCapabilities, mediaPeriod.getTrackGroups()); mediaPeriod.getTrackGroups());
TrackSelectionArray newTrackSelections = result.first;
if (newTrackSelections.equals(periodTrackSelections)) { if (newTrackSelections.equals(periodTrackSelections)) {
return false; return false;
} }
trackSelections = newTrackSelections; trackSelections = newTrackSelections;
trackSelectionData = result.second;
return true; return true;
} }
......
...@@ -17,8 +17,7 @@ package com.google.android.exoplayer2; ...@@ -17,8 +17,7 @@ package com.google.android.exoplayer2;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelections;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
/** /**
...@@ -31,10 +30,10 @@ public interface LoadControl { ...@@ -31,10 +30,10 @@ public interface LoadControl {
* *
* @param renderers The renderers. * @param renderers The renderers.
* @param trackGroups The {@link TrackGroup}s from which the selection was made. * @param trackGroups The {@link TrackGroup}s from which the selection was made.
* @param trackSelections The {@link TrackSelection}s that were made. * @param trackSelections The track selections that were made.
*/ */
void onTracksSelected(Renderer[] renderers, TrackGroupArray trackGroups, void onTracksSelected(Renderer[] renderers, TrackGroupArray trackGroups,
TrackSelectionArray trackSelections); TrackSelections<?> trackSelections);
/** /**
* Called by the player when all tracks are disabled. * Called by the player when all tracks are disabled.
......
...@@ -33,6 +33,7 @@ import com.google.android.exoplayer2.audio.AudioTrack; ...@@ -33,6 +33,7 @@ import com.google.android.exoplayer2.audio.AudioTrack;
import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer; import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer;
import com.google.android.exoplayer2.decoder.DecoderCounters; import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.drm.DrmSessionManager; import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector; import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
import com.google.android.exoplayer2.metadata.MetadataRenderer; import com.google.android.exoplayer2.metadata.MetadataRenderer;
import com.google.android.exoplayer2.metadata.id3.Id3Decoder; import com.google.android.exoplayer2.metadata.id3.Id3Decoder;
...@@ -40,6 +41,7 @@ import com.google.android.exoplayer2.metadata.id3.Id3Frame; ...@@ -40,6 +41,7 @@ import com.google.android.exoplayer2.metadata.id3.Id3Frame;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextRenderer; import com.google.android.exoplayer2.text.TextRenderer;
import com.google.android.exoplayer2.trackselection.TrackSelections;
import com.google.android.exoplayer2.trackselection.TrackSelector; import com.google.android.exoplayer2.trackselection.TrackSelector;
import com.google.android.exoplayer2.video.MediaCodecVideoRenderer; import com.google.android.exoplayer2.video.MediaCodecVideoRenderer;
import com.google.android.exoplayer2.video.VideoRendererEventListener; import com.google.android.exoplayer2.video.VideoRendererEventListener;
...@@ -80,18 +82,14 @@ public final class SimpleExoPlayer implements ExoPlayer { ...@@ -80,18 +82,14 @@ public final class SimpleExoPlayer implements ExoPlayer {
/** /**
* Called when a frame is rendered for the first time since setting the surface, and when a * Called when a frame is rendered for the first time since setting the surface, and when a
* frame is rendered for the first time since the renderer was reset. * frame is rendered for the first time since a video track was selected.
*
* @param surface The {@link Surface} to which a first frame has been rendered.
*/ */
void onRenderedFirstFrame(Surface surface); void onRenderedFirstFrame();
/** /**
* Called when the renderer is disabled. * Called when a video track is no longer selected.
*
* @param counters {@link DecoderCounters} that were updated by the renderer.
*/ */
void onVideoDisabled(DecoderCounters counters); void onVideoTracksDisabled();
} }
...@@ -105,9 +103,11 @@ public final class SimpleExoPlayer implements ExoPlayer { ...@@ -105,9 +103,11 @@ public final class SimpleExoPlayer implements ExoPlayer {
private final int videoRendererCount; private final int videoRendererCount;
private final int audioRendererCount; private final int audioRendererCount;
private boolean videoTracksEnabled;
private Format videoFormat; private Format videoFormat;
private Format audioFormat; private Format audioFormat;
private Surface surface;
private SurfaceHolder surfaceHolder; private SurfaceHolder surfaceHolder;
private TextureView textureView; private TextureView textureView;
private TextRenderer.Output textOutput; private TextRenderer.Output textOutput;
...@@ -121,11 +121,12 @@ public final class SimpleExoPlayer implements ExoPlayer { ...@@ -121,11 +121,12 @@ public final class SimpleExoPlayer implements ExoPlayer {
private float volume; private float volume;
private PlaybackParamsHolder playbackParamsHolder; private PlaybackParamsHolder playbackParamsHolder;
/* package */ SimpleExoPlayer(Context context, TrackSelector trackSelector, /* package */ SimpleExoPlayer(Context context, TrackSelector<?> trackSelector,
LoadControl loadControl, DrmSessionManager drmSessionManager, LoadControl loadControl, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
boolean preferExtensionDecoders, long allowedVideoJoiningTimeMs) { boolean preferExtensionDecoders, long allowedVideoJoiningTimeMs) {
mainHandler = new Handler(); mainHandler = new Handler();
componentListener = new ComponentListener(); componentListener = new ComponentListener();
trackSelector.addListener(componentListener);
// Build the renderers. // Build the renderers.
ArrayList<Renderer> renderersList = new ArrayList<>(); ArrayList<Renderer> renderersList = new ArrayList<>();
...@@ -509,8 +510,9 @@ public final class SimpleExoPlayer implements ExoPlayer { ...@@ -509,8 +510,9 @@ public final class SimpleExoPlayer implements ExoPlayer {
// Internal methods. // Internal methods.
private void buildRenderers(Context context, DrmSessionManager drmSessionManager, private void buildRenderers(Context context,
ArrayList<Renderer> renderersList, long allowedVideoJoiningTimeMs) { DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, ArrayList<Renderer> renderersList,
long allowedVideoJoiningTimeMs) {
MediaCodecVideoRenderer videoRenderer = new MediaCodecVideoRenderer(context, MediaCodecVideoRenderer videoRenderer = new MediaCodecVideoRenderer(context,
MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT,
allowedVideoJoiningTimeMs, drmSessionManager, false, mainHandler, componentListener, allowedVideoJoiningTimeMs, drmSessionManager, false, mainHandler, componentListener,
...@@ -601,6 +603,7 @@ public final class SimpleExoPlayer implements ExoPlayer { ...@@ -601,6 +603,7 @@ public final class SimpleExoPlayer implements ExoPlayer {
} }
private void setVideoSurfaceInternal(Surface surface) { private void setVideoSurfaceInternal(Surface surface) {
this.surface = surface;
ExoPlayerMessage[] messages = new ExoPlayerMessage[videoRendererCount]; ExoPlayerMessage[] messages = new ExoPlayerMessage[videoRendererCount];
int count = 0; int count = 0;
for (Renderer renderer : renderers) { for (Renderer renderer : renderers) {
...@@ -618,7 +621,8 @@ public final class SimpleExoPlayer implements ExoPlayer { ...@@ -618,7 +621,8 @@ public final class SimpleExoPlayer implements ExoPlayer {
private final class ComponentListener implements VideoRendererEventListener, private final class ComponentListener implements VideoRendererEventListener,
AudioRendererEventListener, TextRenderer.Output, MetadataRenderer.Output<List<Id3Frame>>, AudioRendererEventListener, TextRenderer.Output, MetadataRenderer.Output<List<Id3Frame>>,
SurfaceHolder.Callback, TextureView.SurfaceTextureListener { SurfaceHolder.Callback, TextureView.SurfaceTextureListener,
TrackSelector.EventListener<Object> {
// VideoRendererEventListener implementation // VideoRendererEventListener implementation
...@@ -669,8 +673,8 @@ public final class SimpleExoPlayer implements ExoPlayer { ...@@ -669,8 +673,8 @@ public final class SimpleExoPlayer implements ExoPlayer {
@Override @Override
public void onRenderedFirstFrame(Surface surface) { public void onRenderedFirstFrame(Surface surface) {
if (videoListener != null) { if (videoListener != null && SimpleExoPlayer.this.surface == surface) {
videoListener.onRenderedFirstFrame(surface); videoListener.onRenderedFirstFrame();
} }
if (videoDebugListener != null) { if (videoDebugListener != null) {
videoDebugListener.onRenderedFirstFrame(surface); videoDebugListener.onRenderedFirstFrame(surface);
...@@ -679,9 +683,6 @@ public final class SimpleExoPlayer implements ExoPlayer { ...@@ -679,9 +683,6 @@ public final class SimpleExoPlayer implements ExoPlayer {
@Override @Override
public void onVideoDisabled(DecoderCounters counters) { public void onVideoDisabled(DecoderCounters counters) {
if (videoListener != null) {
videoListener.onVideoDisabled(counters);
}
if (videoDebugListener != null) { if (videoDebugListener != null) {
videoDebugListener.onVideoDisabled(counters); videoDebugListener.onVideoDisabled(counters);
} }
...@@ -800,6 +801,23 @@ public final class SimpleExoPlayer implements ExoPlayer { ...@@ -800,6 +801,23 @@ public final class SimpleExoPlayer implements ExoPlayer {
// Do nothing. // Do nothing.
} }
// TrackSelector.EventListener implementation
@Override
public void onTrackSelectionsChanged(TrackSelections<?> trackSelections) {
boolean videoTracksEnabled = false;
for (int i = 0; i < renderers.length; i++) {
if (renderers[i].getTrackType() == C.TRACK_TYPE_VIDEO && trackSelections.get(i) != null) {
videoTracksEnabled = true;
break;
}
}
if (videoListener != null && SimpleExoPlayer.this.videoTracksEnabled && !videoTracksEnabled) {
videoListener.onVideoTracksDisabled();
}
SimpleExoPlayer.this.videoTracksEnabled = videoTracksEnabled;
}
} }
@TargetApi(23) @TargetApi(23)
......
...@@ -453,10 +453,10 @@ public class DefaultTrackSelector extends MappingTrackSelector { ...@@ -453,10 +453,10 @@ public class DefaultTrackSelector extends MappingTrackSelector {
case C.TRACK_TYPE_VIDEO: case C.TRACK_TYPE_VIDEO:
rendererTrackSelections[i] = selectVideoTrack(rendererCapabilities[i], rendererTrackSelections[i] = selectVideoTrack(rendererCapabilities[i],
rendererTrackGroupArrays[i], rendererFormatSupports[i], params.maxVideoWidth, rendererTrackGroupArrays[i], rendererFormatSupports[i], params.maxVideoWidth,
params.maxVideoHeight, params.maxVideoHeight, params.allowNonSeamlessAdaptiveness,
params.allowNonSeamlessAdaptiveness, params.allowMixedMimeAdaptiveness, params.allowMixedMimeAdaptiveness, params.viewportWidth, params.viewportHeight,
params.viewportWidth, params.viewportHeight, params.orientationMayChange, params.orientationMayChange, adaptiveVideoTrackSelectionFactory,
adaptiveVideoTrackSelectionFactory, params.exceedVideoConstraintsIfNecessary); params.exceedVideoConstraintsIfNecessary);
break; break;
case C.TRACK_TYPE_AUDIO: case C.TRACK_TYPE_AUDIO:
rendererTrackSelections[i] = selectAudioTrack(rendererTrackGroupArrays[i], rendererTrackSelections[i] = selectAudioTrack(rendererTrackGroupArrays[i],
......
...@@ -16,39 +16,23 @@ ...@@ -16,39 +16,23 @@
package com.google.android.exoplayer2.trackselection; package com.google.android.exoplayer2.trackselection;
import android.os.Handler; import android.os.Handler;
import android.util.Pair;
import android.util.SparseArray; import android.util.SparseArray;
import android.util.SparseBooleanArray; import android.util.SparseBooleanArray;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
/** /**
* Base class for {@link TrackSelector}s that first establish a mapping between {@link TrackGroup}s * Base class for {@link TrackSelector}s that first establish a mapping between {@link TrackGroup}s
* and renderers, and then from that mapping create a {@link TrackSelection} for each renderer. * and renderers, and then from that mapping create a {@link TrackSelection} for each renderer.
*/ */
public abstract class MappingTrackSelector extends TrackSelector { public abstract class MappingTrackSelector extends TrackSelector<MappedTrackInfo> {
/**
* Listener of {@link MappingTrackSelector} events.
*/
public interface EventListener {
/**
* Called when the track information has changed.
*
* @param trackInfo Contains the new track and track selection information.
*/
void onTracksChanged(TrackInfo trackInfo);
}
/** /**
* A track selection override. * A track selection override.
...@@ -96,52 +80,20 @@ public abstract class MappingTrackSelector extends TrackSelector { ...@@ -96,52 +80,20 @@ public abstract class MappingTrackSelector extends TrackSelector {
} }
private final Handler eventHandler;
private final CopyOnWriteArraySet<EventListener> listeners;
private final SparseArray<Map<TrackGroupArray, SelectionOverride>> selectionOverrides; private final SparseArray<Map<TrackGroupArray, SelectionOverride>> selectionOverrides;
private final SparseBooleanArray rendererDisabledFlags; private final SparseBooleanArray rendererDisabledFlags;
private TrackInfo activeTrackInfo;
/** /**
* @param eventHandler A handler to use when delivering events to listeners added via * @param eventHandler A handler to use when delivering events to listeners added via
* {@link #addListener(EventListener)}. * {@link #addListener(EventListener)}.
*/ */
public MappingTrackSelector(Handler eventHandler) { public MappingTrackSelector(Handler eventHandler) {
this.eventHandler = eventHandler; super(eventHandler);
this.listeners = new CopyOnWriteArraySet<>();
selectionOverrides = new SparseArray<>(); selectionOverrides = new SparseArray<>();
rendererDisabledFlags = new SparseBooleanArray(); rendererDisabledFlags = new SparseBooleanArray();
} }
/** /**
* Register a listener to receive events from the selector. The listener's methods will be called
* using the {@link Handler} that was passed to the constructor.
*
* @param listener The listener to register.
*/
public final void addListener(EventListener listener) {
Assertions.checkState(eventHandler != null);
listeners.add(listener);
}
/**
* Unregister a listener. The listener will no longer receive events from the selector.
*
* @param listener The listener to unregister.
*/
public final void removeListener(EventListener listener) {
listeners.remove(listener);
}
/**
* Returns information about the current tracks and track selection for each renderer.
*/
public final TrackInfo getTrackInfo() {
return activeTrackInfo;
}
/**
* Sets whether the renderer at the specified index is disabled. * Sets whether the renderer at the specified index is disabled.
* *
* @param rendererIndex The renderer index. * @param rendererIndex The renderer index.
...@@ -272,13 +224,7 @@ public abstract class MappingTrackSelector extends TrackSelector { ...@@ -272,13 +224,7 @@ public abstract class MappingTrackSelector extends TrackSelector {
// TrackSelector implementation. // TrackSelector implementation.
@Override @Override
public final void onSelectionActivated(Object selectionInfo) { public final TrackSelections<MappedTrackInfo> selectTracks(
activeTrackInfo = (TrackInfo) selectionInfo;
notifyTrackInfoChanged(activeTrackInfo);
}
@Override
public final Pair<TrackSelectionArray, Object> selectTracks(
RendererCapabilities[] rendererCapabilities, TrackGroupArray trackGroups) RendererCapabilities[] rendererCapabilities, TrackGroupArray trackGroups)
throws ExoPlaybackException { throws ExoPlaybackException {
// Structures into which data will be written during the selection. The extra item at the end // Structures into which data will be written during the selection. The extra item at the end
...@@ -345,11 +291,10 @@ public abstract class MappingTrackSelector extends TrackSelector { ...@@ -345,11 +291,10 @@ public abstract class MappingTrackSelector extends TrackSelector {
} }
// Package up the track information and selections. // Package up the track information and selections.
TrackSelectionArray trackSelectionArray = new TrackSelectionArray(trackSelections); MappedTrackInfo mappedTrackInfo = new MappedTrackInfo(rendererTrackTypes,
TrackInfo trackInfo = new TrackInfo(rendererTrackTypes, rendererTrackGroupArrays, rendererTrackGroupArrays, mixedMimeTypeAdaptationSupport, rendererFormatSupports,
trackSelections, mixedMimeTypeAdaptationSupport, rendererFormatSupports,
unassociatedTrackGroupArray); unassociatedTrackGroupArray);
return Pair.<TrackSelectionArray, Object>create(trackSelectionArray, trackInfo); return new TrackSelections<>(mappedTrackInfo, trackSelections);
} }
/** /**
...@@ -446,23 +391,10 @@ public abstract class MappingTrackSelector extends TrackSelector { ...@@ -446,23 +391,10 @@ public abstract class MappingTrackSelector extends TrackSelector {
return mixedMimeTypeAdaptationSupport; return mixedMimeTypeAdaptationSupport;
} }
private void notifyTrackInfoChanged(final TrackInfo trackInfo) {
if (eventHandler != null) {
eventHandler.post(new Runnable() {
@Override
public void run() {
for (EventListener listener : listeners) {
listener.onTracksChanged(trackInfo);
}
}
});
}
}
/** /**
* Provides track information for each renderer. * Provides track information for each renderer.
*/ */
public static final class TrackInfo { public static final class MappedTrackInfo {
/** /**
* The renderer does not have any associated tracks. * The renderer does not have any associated tracks.
...@@ -477,34 +409,27 @@ public abstract class MappingTrackSelector extends TrackSelector { ...@@ -477,34 +409,27 @@ public abstract class MappingTrackSelector extends TrackSelector {
*/ */
public static final int RENDERER_SUPPORT_PLAYABLE_TRACKS = 2; public static final int RENDERER_SUPPORT_PLAYABLE_TRACKS = 2;
/**
* The number of renderers.
*/
public final int rendererCount;
private final int[] rendererTrackTypes; private final int[] rendererTrackTypes;
private final TrackGroupArray[] trackGroups; private final TrackGroupArray[] trackGroups;
private final TrackSelection[] trackSelections;
private final int[] mixedMimeTypeAdaptiveSupport; private final int[] mixedMimeTypeAdaptiveSupport;
private final int[][][] formatSupport; private final int[][][] formatSupport;
private final TrackGroupArray unassociatedTrackGroups; private final TrackGroupArray unassociatedTrackGroups;
private final int rendererCount;
/** /**
* @param rendererTrackTypes The track type supported by each renderer. * @param rendererTrackTypes The track type supported by each renderer.
* @param trackGroups The {@link TrackGroupArray}s for each renderer. * @param trackGroups The {@link TrackGroupArray}s for each renderer.
* @param trackSelections The current {@link TrackSelection}s for each renderer.
* @param mixedMimeTypeAdaptiveSupport The result of * @param mixedMimeTypeAdaptiveSupport The result of
* {@link RendererCapabilities#supportsMixedMimeTypeAdaptation()} for each renderer. * {@link RendererCapabilities#supportsMixedMimeTypeAdaptation()} for each renderer.
* @param formatSupport The result of {@link RendererCapabilities#supportsFormat} for each * @param formatSupport The result of {@link RendererCapabilities#supportsFormat} for each
* track, indexed by renderer index, group index and track index (in that order). * track, indexed by renderer index, group index and track index (in that order).
* @param unassociatedTrackGroups Contains {@link TrackGroup}s not associated with any renderer. * @param unassociatedTrackGroups Contains {@link TrackGroup}s not associated with any renderer.
*/ */
/* package */ TrackInfo(int[] rendererTrackTypes, TrackGroupArray[] trackGroups, /* package */ MappedTrackInfo(int[] rendererTrackTypes,
TrackSelection[] trackSelections, int[] mixedMimeTypeAdaptiveSupport, TrackGroupArray[] trackGroups, int[] mixedMimeTypeAdaptiveSupport,
int[][][] formatSupport, TrackGroupArray unassociatedTrackGroups) { int[][][] formatSupport, TrackGroupArray unassociatedTrackGroups) {
this.rendererTrackTypes = rendererTrackTypes; this.rendererTrackTypes = rendererTrackTypes;
this.trackGroups = trackGroups; this.trackGroups = trackGroups;
this.trackSelections = trackSelections;
this.formatSupport = formatSupport; this.formatSupport = formatSupport;
this.mixedMimeTypeAdaptiveSupport = mixedMimeTypeAdaptiveSupport; this.mixedMimeTypeAdaptiveSupport = mixedMimeTypeAdaptiveSupport;
this.unassociatedTrackGroups = unassociatedTrackGroups; this.unassociatedTrackGroups = unassociatedTrackGroups;
...@@ -522,16 +447,6 @@ public abstract class MappingTrackSelector extends TrackSelector { ...@@ -522,16 +447,6 @@ public abstract class MappingTrackSelector extends TrackSelector {
} }
/** /**
* Returns the current {@link TrackSelection} for the renderer at a specified index.
*
* @param rendererIndex The renderer index.
* @return The corresponding {@link TrackSelection}, or null if the renderer is disabled.
*/
public TrackSelection getTrackSelection(int rendererIndex) {
return trackSelections[rendererIndex];
}
/**
* Returns the extent to which a renderer can support playback of the tracks associated to it. * Returns the extent to which a renderer can support playback of the tracks associated to it.
* *
* @param rendererIndex The renderer index. * @param rendererIndex The renderer index.
...@@ -657,7 +572,7 @@ public abstract class MappingTrackSelector extends TrackSelector { ...@@ -657,7 +572,7 @@ public abstract class MappingTrackSelector extends TrackSelector {
* unplayable. False in all other cases. * unplayable. False in all other cases.
*/ */
public boolean hasOnlyUnplayableTracks(int trackType) { public boolean hasOnlyUnplayableTracks(int trackType) {
int rendererSupport = TrackInfo.RENDERER_SUPPORT_NO_TRACKS; int rendererSupport = RENDERER_SUPPORT_NO_TRACKS;
for (int i = 0; i < rendererCount; i++) { for (int i = 0; i < rendererCount; i++) {
if (rendererTrackTypes[i] == trackType) { if (rendererTrackTypes[i] == trackType) {
rendererSupport = Math.max(rendererSupport, getRendererSupport(i)); rendererSupport = Math.max(rendererSupport, getRendererSupport(i));
......
...@@ -18,12 +18,16 @@ package com.google.android.exoplayer2.trackselection; ...@@ -18,12 +18,16 @@ package com.google.android.exoplayer2.trackselection;
import java.util.Arrays; import java.util.Arrays;
/** /**
* An array of {@link TrackSelection}s generated by a {@link TrackSelector}. * The result of a {@link TrackSelector} operation.
*/ */
public final class TrackSelectionArray { public final class TrackSelections<T> {
/** /**
* The number of selections in the array. Greater than or equal to zero. * Opaque information associated with the result.
*/
public final T info;
/**
* The number of selections in the result. Greater than or equal to zero.
*/ */
public final int length; public final int length;
...@@ -33,9 +37,11 @@ public final class TrackSelectionArray { ...@@ -33,9 +37,11 @@ public final class TrackSelectionArray {
private int hashCode; private int hashCode;
/** /**
* @param info Opaque information associated with the result.
* @param trackSelections The selections. Must not be null, but may contain null elements. * @param trackSelections The selections. Must not be null, but may contain null elements.
*/ */
public TrackSelectionArray(TrackSelection... trackSelections) { public TrackSelections(T info, TrackSelection... trackSelections) {
this.info = info;
this.trackSelections = trackSelections; this.trackSelections = trackSelections;
this.length = trackSelections.length; this.length = trackSelections.length;
} }
...@@ -75,7 +81,7 @@ public final class TrackSelectionArray { ...@@ -75,7 +81,7 @@ public final class TrackSelectionArray {
if (obj == null || getClass() != obj.getClass()) { if (obj == null || getClass() != obj.getClass()) {
return false; return false;
} }
TrackSelectionArray other = (TrackSelectionArray) obj; TrackSelections<?> other = (TrackSelections<?>) obj;
return Arrays.equals(trackSelections, other.trackSelections); return Arrays.equals(trackSelections, other.trackSelections);
} }
......
...@@ -15,15 +15,15 @@ ...@@ -15,15 +15,15 @@
*/ */
package com.google.android.exoplayer2.trackselection; package com.google.android.exoplayer2.trackselection;
import android.util.Pair; import android.os.Handler;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.util.Assertions;
import java.util.concurrent.CopyOnWriteArraySet;
/** /** Selects tracks to be consumed by available renderers. */
* Selects tracks to be consumed by available renderers. public abstract class TrackSelector<T> {
*/
public abstract class TrackSelector {
/** /**
* Notified when previous selections by a {@link TrackSelector} are no longer valid. * Notified when previous selections by a {@link TrackSelector} are no longer valid.
...@@ -37,7 +37,55 @@ public abstract class TrackSelector { ...@@ -37,7 +37,55 @@ public abstract class TrackSelector {
} }
/** Listener of {@link TrackSelector} events. */
public interface EventListener<T> {
/**
* Called when the track selections have changed.
*
* @param trackSelections The new track selections.
*/
void onTrackSelectionsChanged(TrackSelections<? extends T> trackSelections);
}
private final Handler eventHandler;
private final CopyOnWriteArraySet<MappingTrackSelector.EventListener<? super T>> listeners;
private InvalidationListener listener; private InvalidationListener listener;
private TrackSelections<T> activeSelections;
/**
* @param eventHandler A handler to use when delivering events to listeners added via {@link
* #addListener(EventListener)}.
*/
public TrackSelector(Handler eventHandler) {
this.eventHandler = Assertions.checkNotNull(eventHandler);
this.listeners = new CopyOnWriteArraySet<>();
}
/**
* Registers a listener to receive events from the selector. The listener's methods will be called
* using the {@link Handler} that was passed to the constructor.
*
* @param listener The listener to register.
*/
public final void addListener(EventListener<? super T> listener) {
listeners.add(listener);
}
/**
* Unregister a listener. The listener will no longer receive events from the selector.
*
* @param listener The listener to unregister.
*/
public final void removeListener(EventListener<? super T> listener) {
listeners.remove(listener);
}
/** Returns the current track selections. */
public final TrackSelections<T> getCurrentSelections() {
return activeSelections;
}
/** /**
* Initializes the selector. * Initializes the selector.
...@@ -49,31 +97,28 @@ public abstract class TrackSelector { ...@@ -49,31 +97,28 @@ public abstract class TrackSelector {
} }
/** /**
* Generates a {@link TrackSelection} for each renderer. * Generates {@link TrackSelections} for the renderers.
* <P>
* The selections are returned in a {@link TrackSelectionArray}, together with an opaque object
* that the selector wishes to receive in an invocation of {@link #onSelectionActivated(Object)}
* should the selection be activated.
* *
* @param rendererCapabilities The {@link RendererCapabilities} of the renderers for which * @param rendererCapabilities The {@link RendererCapabilities} of the renderers for which {@link
* {@link TrackSelection}s are to be generated. * TrackSelection}s are to be generated.
* @param trackGroups The available track groups. * @param trackGroups The available track groups.
* @return A {@link TrackSelectionArray} containing a {@link TrackSelection} for each renderer, * @return The track selections.
* together with an opaque object that will be passed to {@link #onSelectionActivated(Object)}
* if the selection is activated.
* @throws ExoPlaybackException If an error occurs selecting tracks. * @throws ExoPlaybackException If an error occurs selecting tracks.
*/ */
public abstract Pair<TrackSelectionArray, Object> selectTracks( public abstract TrackSelections<T> selectTracks(
RendererCapabilities[] rendererCapabilities, TrackGroupArray trackGroups) RendererCapabilities[] rendererCapabilities, TrackGroupArray trackGroups)
throws ExoPlaybackException; throws ExoPlaybackException;
/** /**
* Called when a selection previously generated by * Called when {@link TrackSelections} previously generated by {@link
* {@link #selectTracks(RendererCapabilities[], TrackGroupArray)} is activated. * #selectTracks(RendererCapabilities[], TrackGroupArray)} are activated.
* *
* @param selectionInfo The opaque object associated with the selection. * @param activeSelections The activated {@link TrackSelections}.
*/ */
public abstract void onSelectionActivated(Object selectionInfo); public final void onSelectionActivated(TrackSelections<T> activeSelections) {
this.activeSelections = activeSelections;
notifyTrackSelectionsChanged(activeSelections);
}
/** /**
* Invalidates all previously generated track selections. * Invalidates all previously generated track selections.
...@@ -84,4 +129,18 @@ public abstract class TrackSelector { ...@@ -84,4 +129,18 @@ public abstract class TrackSelector {
} }
} }
private void notifyTrackSelectionsChanged(final TrackSelections<T> activeSelections) {
if (eventHandler != null) {
eventHandler.post(
new Runnable() {
@Override
public void run() {
for (EventListener<? super T> listener : listeners) {
listener.onTrackSelectionsChanged(activeSelections);
}
}
});
}
}
} }
...@@ -22,22 +22,18 @@ import android.util.AttributeSet; ...@@ -22,22 +22,18 @@ import android.util.AttributeSet;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceView; import android.view.SurfaceView;
import android.view.TextureView; import android.view.TextureView;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.R; import com.google.android.exoplayer2.R;
import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.decoder.DecoderCounters;
import com.google.android.exoplayer2.text.Cue; import com.google.android.exoplayer2.text.Cue;
import com.google.android.exoplayer2.text.TextRenderer; import com.google.android.exoplayer2.text.TextRenderer;
import java.util.List; import java.util.List;
/** /**
...@@ -112,7 +108,6 @@ public final class SimpleExoPlayerView extends FrameLayout { ...@@ -112,7 +108,6 @@ public final class SimpleExoPlayerView extends FrameLayout {
this.player.setVideoSurface(null); this.player.setVideoSurface(null);
} }
this.player = player; this.player = player;
if (player != null) { if (player != null) {
if (surfaceView instanceof TextureView) { if (surfaceView instanceof TextureView) {
player.setVideoTextureView((TextureView) surfaceView); player.setVideoTextureView((TextureView) surfaceView);
...@@ -122,6 +117,8 @@ public final class SimpleExoPlayerView extends FrameLayout { ...@@ -122,6 +117,8 @@ public final class SimpleExoPlayerView extends FrameLayout {
player.setVideoListener(componentListener); player.setVideoListener(componentListener);
player.addListener(componentListener); player.addListener(componentListener);
player.setTextOutput(componentListener); player.setTextOutput(componentListener);
} else {
shutterView.setVisibility(VISIBLE);
} }
setUseController(useController); setUseController(useController);
} }
...@@ -233,12 +230,12 @@ public final class SimpleExoPlayerView extends FrameLayout { ...@@ -233,12 +230,12 @@ public final class SimpleExoPlayerView extends FrameLayout {
} }
@Override @Override
public void onRenderedFirstFrame(Surface surface) { public void onRenderedFirstFrame() {
shutterView.setVisibility(GONE); shutterView.setVisibility(GONE);
} }
@Override @Override
public void onVideoDisabled(DecoderCounters counters) { public void onVideoTracksDisabled() {
shutterView.setVisibility(VISIBLE); shutterView.setVisibility(VISIBLE);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment