From 1944ebb46304d761ca991244e2ada2d595d4b5ee Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 13 Apr 2018 06:38:23 -0700 Subject: [PATCH] Move random adaptation to an intent extra. This will help with removing selection factories from SelectionOverride. It doesn't seem worth the effort to have this togglable and in the UI of our demo app. This change will also: - Help to move TrackSelectionHelper into the UI module, since it removes the part that's obviously debug-only. - Make it possible to specify the ABR algorithm for each sample, which might be nice as we start implementing more of them. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=192760196 --- demos/main/src/main/assets/media.exolist.json | 11 +++ .../exoplayer2/demo/PlayerActivity.java | 45 +++++++---- .../demo/SampleChooserActivity.java | 75 ++++++++++++------- .../exoplayer2/demo/TrackSelectionHelper.java | 61 ++++----------- demos/main/src/main/res/values/strings.xml | 2 +- 5 files changed, 105 insertions(+), 89 deletions(-) diff --git a/demos/main/src/main/assets/media.exolist.json b/demos/main/src/main/assets/media.exolist.json index 7052e7c436..0d26f196c1 100644 --- a/demos/main/src/main/assets/media.exolist.json +++ b/demos/main/src/main/assets/media.exolist.json @@ -578,5 +578,16 @@ "ad_tag_uri": "http://vastsynthesizer.appspot.com/empty-midroll-2" } ] + }, + { + "name": "ABR", + "samples": [ + { + "name": "Random ABR - Google Glass (MP4,H264)", + "uri": "http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,source,id,as&ip=0.0.0.0&ipbits=0&expire=19000000000&signature=51AF5F39AB0CEC3E5497CD9C900EBFEAECCCB5C7.8506521BFC350652163895D4C26DEE124209AA9E&key=ik0", + "extension": "mpd", + "abr_algorithm": "random" + } + ] } ] diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java index a876364a84..4765278fcb 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/PlayerActivity.java @@ -68,6 +68,7 @@ import com.google.android.exoplayer2.source.smoothstreaming.manifest.TrackKey; import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo; +import com.google.android.exoplayer2.trackselection.RandomTrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.ui.DebugTextViewHelper; @@ -91,10 +92,10 @@ public class PlayerActivity extends Activity implements OnClickListener, PlaybackPreparer, PlayerControlView.VisibilityListener { public static final String DRM_SCHEME_EXTRA = "drm_scheme"; - public static final String DRM_LICENSE_URL = "drm_license_url"; - public static final String DRM_KEY_REQUEST_PROPERTIES = "drm_key_request_properties"; - public static final String DRM_MULTI_SESSION = "drm_multi_session"; - public static final String PREFER_EXTENSION_DECODERS = "prefer_extension_decoders"; + public static final String DRM_LICENSE_URL_EXTRA = "drm_license_url"; + public static final String DRM_KEY_REQUEST_PROPERTIES_EXTRA = "drm_key_request_properties"; + public static final String DRM_MULTI_SESSION_EXTRA = "drm_multi_session"; + public static final String PREFER_EXTENSION_DECODERS_EXTRA = "prefer_extension_decoders"; public static final String ACTION_VIEW = "com.google.android.exoplayer.demo.action.VIEW"; public static final String EXTENSION_EXTRA = "extension"; @@ -108,7 +109,11 @@ public class PlayerActivity extends Activity public static final String AD_TAG_URI_EXTRA = "ad_tag_uri"; - // For backwards compatibility. + public static final String ABR_ALGORITHM_EXTRA = "abr_algorithm"; + private static final String ABR_ALGORITHM_DEFAULT = "default"; + private static final String ABR_ALGORITHM_RANDOM = "random"; + + // For backwards compatibility only. private static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid"; private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter(); @@ -292,6 +297,7 @@ public class PlayerActivity extends Activity } } else { showToast(getString(R.string.unexpected_intent_action, action)); + finish(); return; } if (Util.maybeRequestReadExternalStoragePermission(this, uris)) { @@ -301,9 +307,10 @@ public class PlayerActivity extends Activity DefaultDrmSessionManager drmSessionManager = null; if (intent.hasExtra(DRM_SCHEME_EXTRA) || intent.hasExtra(DRM_SCHEME_UUID_EXTRA)) { - String drmLicenseUrl = intent.getStringExtra(DRM_LICENSE_URL); - String[] keyRequestPropertiesArray = intent.getStringArrayExtra(DRM_KEY_REQUEST_PROPERTIES); - boolean multiSession = intent.getBooleanExtra(DRM_MULTI_SESSION, false); + String drmLicenseUrl = intent.getStringExtra(DRM_LICENSE_URL_EXTRA); + String[] keyRequestPropertiesArray = + intent.getStringArrayExtra(DRM_KEY_REQUEST_PROPERTIES_EXTRA); + boolean multiSession = intent.getBooleanExtra(DRM_MULTI_SESSION_EXTRA, false); int errorStringId = R.string.error_drm_unknown; if (Util.SDK_INT < 18) { errorStringId = R.string.error_drm_not_supported; @@ -326,11 +333,25 @@ public class PlayerActivity extends Activity } if (drmSessionManager == null) { showToast(errorStringId); + finish(); return; } } - boolean preferExtensionDecoders = intent.getBooleanExtra(PREFER_EXTENSION_DECODERS, false); + TrackSelection.Factory trackSelectionFactory; + String abrAlgorithm = intent.getStringExtra(ABR_ALGORITHM_EXTRA); + if (abrAlgorithm == null || ABR_ALGORITHM_DEFAULT.equals(abrAlgorithm)) { + trackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER); + } else if (ABR_ALGORITHM_RANDOM.equals(abrAlgorithm)) { + trackSelectionFactory = new RandomTrackSelection.Factory(); + } else { + showToast(R.string.error_unrecognized_abr_algorithm); + finish(); + return; + } + + boolean preferExtensionDecoders = + intent.getBooleanExtra(PREFER_EXTENSION_DECODERS_EXTRA, false); @DefaultRenderersFactory.ExtensionRendererMode int extensionRendererMode = ((DemoApplication) getApplication()).useExtensionRenderers() ? (preferExtensionDecoders ? DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER @@ -339,10 +360,8 @@ public class PlayerActivity extends Activity DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(this, extensionRendererMode); - TrackSelection.Factory adaptiveTrackSelectionFactory = - new AdaptiveTrackSelection.Factory(BANDWIDTH_METER); - trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory); - trackSelectionHelper = new TrackSelectionHelper(trackSelector, adaptiveTrackSelectionFactory); + trackSelector = new DefaultTrackSelector(trackSelectionFactory); + trackSelectionHelper = new TrackSelectionHelper(trackSelector, trackSelectionFactory); lastSeenTrackGroupArray = null; player = diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/SampleChooserActivity.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/SampleChooserActivity.java index 3895ad8e84..5febb949f1 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/SampleChooserActivity.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/SampleChooserActivity.java @@ -45,7 +45,6 @@ import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.UUID; /** * An activity for selecting from a list of samples. @@ -178,13 +177,14 @@ public class SampleChooserActivity extends Activity { String sampleName = null; String uri = null; String extension = null; - UUID drmUuid = null; + String drmScheme = null; String drmLicenseUrl = null; String[] drmKeyRequestProperties = null; boolean drmMultiSession = false; boolean preferExtensionDecoders = false; ArrayList playlistSamples = null; String adTagUri = null; + String abrAlgorithm = null; reader.beginObject(); while (reader.hasNext()) { @@ -201,9 +201,7 @@ public class SampleChooserActivity extends Activity { break; case "drm_scheme": Assertions.checkState(!insidePlaylist, "Invalid attribute on nested item: drm_scheme"); - String drmScheme = reader.nextString(); - drmUuid = Util.getDrmUuid(drmScheme); - Assertions.checkState(drmUuid != null, "Invalid drm_scheme: " + drmScheme); + drmScheme = reader.nextString(); break; case "drm_license_url": Assertions.checkState(!insidePlaylist, @@ -242,21 +240,28 @@ public class SampleChooserActivity extends Activity { case "ad_tag_uri": adTagUri = reader.nextString(); break; + case "abr_algorithm": + Assertions.checkState( + !insidePlaylist, "Invalid attribute on nested item: abr_algorithm"); + abrAlgorithm = reader.nextString(); + break; default: throw new ParserException("Unsupported attribute name: " + name); } } reader.endObject(); - DrmInfo drmInfo = drmUuid == null ? null : new DrmInfo(drmUuid, drmLicenseUrl, - drmKeyRequestProperties, drmMultiSession); + DrmInfo drmInfo = + drmScheme == null + ? null + : new DrmInfo(drmScheme, drmLicenseUrl, drmKeyRequestProperties, drmMultiSession); if (playlistSamples != null) { UriSample[] playlistSamplesArray = playlistSamples.toArray( new UriSample[playlistSamples.size()]); - return new PlaylistSample(sampleName, preferExtensionDecoders, drmInfo, - playlistSamplesArray); + return new PlaylistSample( + sampleName, preferExtensionDecoders, abrAlgorithm, drmInfo, playlistSamplesArray); } else { - return new UriSample(sampleName, preferExtensionDecoders, drmInfo, uri, extension, - adTagUri); + return new UriSample( + sampleName, preferExtensionDecoders, abrAlgorithm, drmInfo, uri, extension, adTagUri); } } @@ -362,14 +367,17 @@ public class SampleChooserActivity extends Activity { } private static final class DrmInfo { - public final UUID drmSchemeUuid; + public final String drmScheme; public final String drmLicenseUrl; public final String[] drmKeyRequestProperties; public final boolean drmMultiSession; - public DrmInfo(UUID drmSchemeUuid, String drmLicenseUrl, - String[] drmKeyRequestProperties, boolean drmMultiSession) { - this.drmSchemeUuid = drmSchemeUuid; + public DrmInfo( + String drmScheme, + String drmLicenseUrl, + String[] drmKeyRequestProperties, + boolean drmMultiSession) { + this.drmScheme = drmScheme; this.drmLicenseUrl = drmLicenseUrl; this.drmKeyRequestProperties = drmKeyRequestProperties; this.drmMultiSession = drmMultiSession; @@ -377,31 +385,34 @@ public class SampleChooserActivity extends Activity { public void updateIntent(Intent intent) { Assertions.checkNotNull(intent); - intent.putExtra(PlayerActivity.DRM_SCHEME_EXTRA, drmSchemeUuid.toString()); - intent.putExtra(PlayerActivity.DRM_LICENSE_URL, drmLicenseUrl); - intent.putExtra(PlayerActivity.DRM_KEY_REQUEST_PROPERTIES, drmKeyRequestProperties); - intent.putExtra(PlayerActivity.DRM_MULTI_SESSION, drmMultiSession); + intent.putExtra(PlayerActivity.DRM_SCHEME_EXTRA, drmScheme); + intent.putExtra(PlayerActivity.DRM_LICENSE_URL_EXTRA, drmLicenseUrl); + intent.putExtra(PlayerActivity.DRM_KEY_REQUEST_PROPERTIES_EXTRA, drmKeyRequestProperties); + intent.putExtra(PlayerActivity.DRM_MULTI_SESSION_EXTRA, drmMultiSession); } } private abstract static class Sample { public final String name; public final boolean preferExtensionDecoders; + public final String abrAlgorithm; public final DrmInfo drmInfo; - public Sample(String name, boolean preferExtensionDecoders, DrmInfo drmInfo) { + public Sample( + String name, boolean preferExtensionDecoders, String abrAlgorithm, DrmInfo drmInfo) { this.name = name; this.preferExtensionDecoders = preferExtensionDecoders; + this.abrAlgorithm = abrAlgorithm; this.drmInfo = drmInfo; } public Intent buildIntent(Context context) { Intent intent = new Intent(context, PlayerActivity.class); - intent.putExtra(PlayerActivity.PREFER_EXTENSION_DECODERS, preferExtensionDecoders); + intent.putExtra(PlayerActivity.PREFER_EXTENSION_DECODERS_EXTRA, preferExtensionDecoders); + intent.putExtra(PlayerActivity.ABR_ALGORITHM_EXTRA, abrAlgorithm); if (drmInfo != null) { drmInfo.updateIntent(intent); } - return intent; } @@ -413,9 +424,15 @@ public class SampleChooserActivity extends Activity { public final String extension; public final String adTagUri; - public UriSample(String name, boolean preferExtensionDecoders, DrmInfo drmInfo, String uri, - String extension, String adTagUri) { - super(name, preferExtensionDecoders, drmInfo); + public UriSample( + String name, + boolean preferExtensionDecoders, + String abrAlgorithm, + DrmInfo drmInfo, + String uri, + String extension, + String adTagUri) { + super(name, preferExtensionDecoders, abrAlgorithm, drmInfo); this.uri = uri; this.extension = extension; this.adTagUri = adTagUri; @@ -436,9 +453,13 @@ public class SampleChooserActivity extends Activity { public final UriSample[] children; - public PlaylistSample(String name, boolean preferExtensionDecoders, DrmInfo drmInfo, + public PlaylistSample( + String name, + boolean preferExtensionDecoders, + String abrAlgorithm, + DrmInfo drmInfo, UriSample... children) { - super(name, preferExtensionDecoders, drmInfo); + super(name, preferExtensionDecoders, abrAlgorithm, drmInfo); this.children = children; } diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/TrackSelectionHelper.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/TrackSelectionHelper.java index 5fcc0cd90b..89b008dbfe 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/TrackSelectionHelper.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/TrackSelectionHelper.java @@ -31,9 +31,7 @@ import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride; -import com.google.android.exoplayer2.trackselection.FixedTrackSelection; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo; -import com.google.android.exoplayer2.trackselection.RandomTrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection; import java.util.Arrays; @@ -43,11 +41,8 @@ import java.util.Arrays; /* package */ final class TrackSelectionHelper implements View.OnClickListener, DialogInterface.OnClickListener { - private static final TrackSelection.Factory FIXED_FACTORY = new FixedTrackSelection.Factory(); - private static final TrackSelection.Factory RANDOM_FACTORY = new RandomTrackSelection.Factory(); - private final DefaultTrackSelector selector; - private final TrackSelection.Factory adaptiveTrackSelectionFactory; + private final TrackSelection.Factory trackSelectionFactory; private MappedTrackInfo trackInfo; private int rendererIndex; @@ -58,18 +53,16 @@ import java.util.Arrays; private CheckedTextView disableView; private CheckedTextView defaultView; - private CheckedTextView enableRandomAdaptationView; private CheckedTextView[][] trackViews; /** * @param selector The track selector. - * @param adaptiveTrackSelectionFactory A factory for adaptive {@link TrackSelection}s, or null if - * the selection helper should not support adaptive tracks. + * @param trackSelectionFactory A factory for overriding {@link TrackSelection}s. */ public TrackSelectionHelper( - DefaultTrackSelector selector, TrackSelection.Factory adaptiveTrackSelectionFactory) { + DefaultTrackSelector selector, TrackSelection.Factory trackSelectionFactory) { this.selector = selector; - this.adaptiveTrackSelectionFactory = adaptiveTrackSelectionFactory; + this.trackSelectionFactory = trackSelectionFactory; } /** @@ -88,10 +81,10 @@ import java.util.Arrays; trackGroups = trackInfo.getTrackGroups(rendererIndex); trackGroupsAdaptive = new boolean[trackGroups.length]; for (int i = 0; i < trackGroups.length; i++) { - trackGroupsAdaptive[i] = adaptiveTrackSelectionFactory != null - && trackInfo.getAdaptiveSupport(rendererIndex, i, false) - != RendererCapabilities.ADAPTIVE_NOT_SUPPORTED - && trackGroups.get(i).length > 1; + trackGroupsAdaptive[i] = + trackInfo.getAdaptiveSupport(rendererIndex, i, false) + != RendererCapabilities.ADAPTIVE_NOT_SUPPORTED + && trackGroups.get(i).length > 1; } isDisabled = selector.getRendererDisabled(rendererIndex); override = selector.getSelectionOverride(rendererIndex, trackGroups); @@ -136,12 +129,10 @@ import java.util.Arrays; root.addView(defaultView); // Per-track views. - boolean haveAdaptiveTracks = false; trackViews = new CheckedTextView[trackGroups.length][]; for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { TrackGroup group = trackGroups.get(groupIndex); boolean groupIsAdaptive = trackGroupsAdaptive[groupIndex]; - haveAdaptiveTracks |= groupIsAdaptive; trackViews[groupIndex] = new CheckedTextView[group.length]; for (int trackIndex = 0; trackIndex < group.length; trackIndex++) { if (trackIndex == 0) { @@ -167,17 +158,6 @@ import java.util.Arrays; } } - if (haveAdaptiveTracks) { - // View for using random adaptation. - enableRandomAdaptationView = (CheckedTextView) inflater.inflate( - android.R.layout.simple_list_item_multiple_choice, root, false); - enableRandomAdaptationView.setBackgroundResource(selectableItemBackgroundResourceId); - enableRandomAdaptationView.setText(R.string.enable_random_adaptation); - enableRandomAdaptationView.setOnClickListener(this); - root.addView(inflater.inflate(R.layout.list_divider, root, false)); - root.addView(enableRandomAdaptationView); - } - updateViews(); return view; } @@ -191,15 +171,6 @@ import java.util.Arrays; && override.containsTrack(j)); } } - if (enableRandomAdaptationView != null) { - boolean enableView = !isDisabled && override != null && override.length > 1; - enableRandomAdaptationView.setEnabled(enableView); - enableRandomAdaptationView.setFocusable(enableView); - if (enableView) { - enableRandomAdaptationView.setChecked(!isDisabled - && override.factory instanceof RandomTrackSelection.Factory); - } - } } // DialogInterface.OnClickListener @@ -224,8 +195,6 @@ import java.util.Arrays; } else if (view == defaultView) { isDisabled = false; override = null; - } else if (view == enableRandomAdaptationView) { - setOverride(override.groupIndex, override.tracks, !enableRandomAdaptationView.isChecked()); } else { isDisabled = false; @SuppressWarnings("unchecked") @@ -234,7 +203,7 @@ import java.util.Arrays; int trackIndex = tag.second; if (!trackGroupsAdaptive[groupIndex] || override == null || override.groupIndex != groupIndex) { - override = new SelectionOverride(FIXED_FACTORY, groupIndex, trackIndex); + setOverride(groupIndex, trackIndex); } else { // The group being modified is adaptive and we already have a non-null override. boolean isEnabled = ((CheckedTextView) view).isChecked(); @@ -246,13 +215,11 @@ import java.util.Arrays; override = null; isDisabled = true; } else { - setOverride(groupIndex, getTracksRemoving(override, trackIndex), - enableRandomAdaptationView.isChecked()); + setOverride(groupIndex, getTracksRemoving(override, trackIndex)); } } else { // Add the track to the override. - setOverride(groupIndex, getTracksAdding(override, trackIndex), - enableRandomAdaptationView.isChecked()); + setOverride(groupIndex, getTracksAdding(override, trackIndex)); } } } @@ -260,10 +227,8 @@ import java.util.Arrays; updateViews(); } - private void setOverride(int group, int[] tracks, boolean enableRandomAdaptation) { - TrackSelection.Factory factory = tracks.length == 1 ? FIXED_FACTORY - : (enableRandomAdaptation ? RANDOM_FACTORY : adaptiveTrackSelectionFactory); - override = new SelectionOverride(factory, group, tracks); + private void setOverride(int group, int... tracks) { + override = new SelectionOverride(trackSelectionFactory, group, tracks); } // Track array manipulation. diff --git a/demos/main/src/main/res/values/strings.xml b/demos/main/src/main/res/values/strings.xml index 43b17052fb..42ef358a1a 100644 --- a/demos/main/src/main/res/values/strings.xml +++ b/demos/main/src/main/res/values/strings.xml @@ -29,7 +29,7 @@ Unexpected intent action: %1$s - Enable random adaptation + Unrecognized ABR algorithm Protected content not supported on API levels below 18