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