mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Fix shutter open/close behavior
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=134389619
This commit is contained in:
parent
d74166cd35
commit
eaf8218855
15 changed files with 220 additions and 219 deletions
|
|
@ -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;
|
||||||
/* 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;
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 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;
|
||||||
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;
|
||||||
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;
|
||||||
* 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
|
||||||
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
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
// 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
|
||||||
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;
|
||||||
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;
|
||||||
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;
|
||||||
* @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;
|
||||||
|
|
||||||
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 {
|
||||||
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;
|
||||||
|
|
||||||
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 {
|
||||||
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;
|
||||||
|
|
||||||
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 {
|
||||||
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 @@
|
||||||
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 {
|
||||||
|
|
||||||
@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;
|
||||||
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;
|
||||||
/**
|
/**
|
||||||
* 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;
|
||||||
|
|
||||||
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;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
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;
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
/**
|
/**
|
||||||
* 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;
|
||||||
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;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
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 {
|
||||||
*
|
*
|
||||||
* @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;
|
||||||
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;
|
||||||
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 {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
|
|
||||||
// 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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
|
||||||
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 {
|
||||||
|
|
||||||
@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 {
|
||||||
|
|
||||||
@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 {
|
||||||
// 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 {
|
||||||
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 @@
|
||||||
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,51 +80,19 @@ 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.
|
||||||
*
|
*
|
||||||
|
|
@ -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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
||||||
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 {
|
||||||
*/
|
*/
|
||||||
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;
|
||||||
|
|
@ -521,16 +446,6 @@ public abstract class MappingTrackSelector extends TrackSelector {
|
||||||
return trackGroups[rendererIndex];
|
return trackGroups[rendererIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
||||||
*
|
*
|
||||||
|
|
@ -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;
|
||||||
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 {
|
||||||
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 {
|
||||||
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 @@
|
||||||
*/
|
*/
|
||||||
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 {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue