private void setSelector(MappingTrackSelector selector) { this.selector = selector; setTrackInfo(selector.getCurrentMappedTrackInfo()); setTrackGroups(trackInfo.getTrackGroups(rendererIndex)); setOverride(selector.getSelectionOverride(rendererIndex, trackGroups)); 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; } // isDisabled = selector.getRendererDisabled(rendererIndex); // override = selector.getSelectionOverride(rendererIndex, trackGroups); }
/** * Retrieves a list of available tracks * * @return A list of available tracks associated with each type */ @Nullable public Map<RendererType, TrackGroupArray> getAvailableTracks() { if (getPlaybackState() == Player.STATE_IDLE) { return null; } // Retrieves the available tracks Map<RendererType, TrackGroupArray> trackMap = new ArrayMap<>(); MappingTrackSelector.MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo(); if (mappedTrackInfo == null) { return trackMap; } // Maps the available tracks RendererType[] types = new RendererType[] {RendererType.AUDIO, RendererType.VIDEO, RendererType.CLOSED_CAPTION, RendererType.METADATA}; for (RendererType type : types) { int exoPlayerTrackIndex = getExoPlayerTrackType(type); if (mappedTrackInfo.length > exoPlayerTrackIndex) { trackMap.put(type, mappedTrackInfo.getTrackGroups(exoPlayerTrackIndex)); } } return trackMap; }
public int getSelectedTrackIndex(@NonNull RendererType type) { // Retrieves the available tracks int exoPlayerTrackIndex = getExoPlayerTrackType(type); MappingTrackSelector.MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo(); TrackGroupArray trackGroupArray = mappedTrackInfo == null ? null : mappedTrackInfo.getTrackGroups(exoPlayerTrackIndex); if (trackGroupArray == null || trackGroupArray.length == 0) { return -1; } // Verifies the track selection has been overridden MappingTrackSelector.SelectionOverride selectionOverride = trackSelector.getSelectionOverride(exoPlayerTrackIndex, trackGroupArray); if (selectionOverride == null || selectionOverride.groupIndex != exoPlayerTrackIndex || selectionOverride.length <= 0) { return -1; } return selectionOverride.tracks[0]; }
public void setSelectedTrack(@NonNull RendererType type, int index) { // Retrieves the available tracks int exoPlayerTrackIndex = getExoPlayerTrackType(type); MappingTrackSelector.MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo(); TrackGroupArray trackGroupArray = mappedTrackInfo == null ? null : mappedTrackInfo.getTrackGroups(exoPlayerTrackIndex); if (trackGroupArray == null || trackGroupArray.length == 0) { return; } // Creates the track selection override int[] tracks = new int[] {index}; TrackSelection.Factory factory = tracks.length == 1 ? new FixedTrackSelection.Factory() : adaptiveTrackSelectionFactory; MappingTrackSelector.SelectionOverride selectionOverride = new MappingTrackSelector.SelectionOverride(factory, exoPlayerTrackIndex, tracks); // Specifies the correct track to use trackSelector.setSelectionOverride(exoPlayerTrackIndex, trackGroupArray, selectionOverride); }
@Override protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player, final MappingTrackSelector trackSelector, final Surface surface, final Handler handler, final ActionNode nextAction) { if (nextAction == null) { return; } Player.EventListener listener = new Player.DefaultEventListener() { @Override public void onTimelineChanged(Timeline timeline, Object manifest) { if (timeline.equals(expectedTimeline)) { player.removeListener(this); nextAction.schedule(player, trackSelector, surface, handler); } } }; player.addListener(listener); if (player.getCurrentTimeline().equals(expectedTimeline)) { player.removeListener(listener); nextAction.schedule(player, trackSelector, surface, handler); } }
@Override protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player, final MappingTrackSelector trackSelector, final Surface surface, final Handler handler, final ActionNode nextAction) { if (nextAction == null) { return; } if (targetPlaybackState == player.getPlaybackState()) { nextAction.schedule(player, trackSelector, surface, handler); } else { player.addListener(new Player.DefaultEventListener() { @Override public void onPlayerStateChanged(boolean playWhenReady, int playbackState) { if (targetPlaybackState == playbackState) { player.removeListener(this); nextAction.schedule(player, trackSelector, surface, handler); } } }); } }
private ExoPlayerTestRunner(PlayerFactory playerFactory, MediaSource mediaSource, RenderersFactory renderersFactory, MappingTrackSelector trackSelector, LoadControl loadControl, ActionSchedule actionSchedule, Player.EventListener eventListener) { this.playerFactory = playerFactory; this.mediaSource = mediaSource; this.renderersFactory = renderersFactory; this.trackSelector = trackSelector; this.loadControl = loadControl; this.actionSchedule = actionSchedule; this.eventListener = eventListener; this.timelines = new LinkedList<>(); this.manifests = new LinkedList<>(); this.periodIndices = new LinkedList<>(); this.endedCountDownLatch = new CountDownLatch(1); this.playerThread = new HandlerThread("ExoPlayerTest thread"); playerThread.start(); this.handler = new Handler(playerThread.getLooper()); }
@Override public void onQualityTrackToggle(boolean enabled) { if (mTrackSelectionHelper != null && mActivity != null) { MappingTrackSelector.MappedTrackInfo mappedTrackInfo = mTrackSelectionHelper.getSelector().getCurrentMappedTrackInfo(); if (mappedTrackInfo != null) { mTrackSelectionHelper.showSelectionDialog(0, controller); } } }
/** * Builds the quality selection list based on the media tracks * * @param selector The selector to get all the available tracks * @param rendererIndex The render index * @return The selection view */ public View buildQualityDialog(@NonNull MappingTrackSelector selector, int rendererIndex) { setRendererIndex(rendererIndex); setSelector(selector); // View for clearing the override to allow the selector to use its default selection logic. qualityAutoView = new TubiRadioButton(getContext()); qualityAutoView.setText(R.string.track_selector_alert_auto); qualityAutoView.setFocusable(true); qualityAutoView.setOnClickListener(this); mBinding.viewTubiQualityDialogLl.addView(qualityAutoView); // Per-track views. trackViews = new TubiRadioButton[trackGroups.length][]; for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { TrackGroup group = trackGroups.get(groupIndex); trackViews[groupIndex] = new TubiRadioButton[group.length]; for (int trackIndex = 0; trackIndex < group.length; trackIndex++) { TubiRadioButton trackView = new TubiRadioButton(getContext()); trackView.setText(buildTrackName(group.getFormat(trackIndex))); if (trackInfo.getTrackFormatSupport(rendererIndex, groupIndex, trackIndex) == RendererCapabilities.FORMAT_HANDLED) { trackView.setFocusable(true); trackView.setTag(Pair.create(groupIndex, trackIndex)); } else { trackView.setFocusable(false); trackView.setEnabled(false); } trackView.setOnClickListener(this); trackViews[groupIndex][trackIndex] = trackView; mBinding.viewTubiQualityDialogLl.addView(trackView); } } updateViews(); return this; }
private static int[] getTracksRemoving(@NonNull MappingTrackSelector.SelectionOverride override, int removedTrack) { int[] tracks = new int[override.length - 1]; int trackCount = 0; for (int i = 0; i < tracks.length + 1; i++) { int track = override.tracks[i]; if (track != removedTrack) { tracks[trackCount++] = track; } } return tracks; }
@SuppressWarnings("unused") protected SimpleExoPlayer buildExoPlayer(HostActivity host, Surface surface, MappingTrackSelector trackSelector, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager) { SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(host, trackSelector, new DefaultLoadControl(), drmSessionManager, SimpleExoPlayer.EXTENSION_RENDERER_MODE_OFF, 0); player.setVideoSurface(surface); return player; }
@Override protected SimpleExoPlayer buildExoPlayer(HostActivity host, Surface surface, MappingTrackSelector trackSelector, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager) { SimpleExoPlayer player = new DebugSimpleExoPlayer(host, trackSelector, new DefaultLoadControl(), drmSessionManager); player.setVideoSurface(surface); return player; }
public boolean selectAudioTrack(PlayerAudioTrack audioTrack, RendererTypeRequester rendererTypeRequester) { TrackGroupArray trackGroups = trackSelector.trackGroups(AUDIO, rendererTypeRequester); MappingTrackSelector.SelectionOverride selectionOverride = new MappingTrackSelector.SelectionOverride( trackSelectionFactory, audioTrack.groupIndex(), audioTrack.formatIndex() ); return trackSelector.setSelectionOverride(AUDIO, rendererTypeRequester, trackGroups, selectionOverride); }
boolean setSelectionOverride(TrackType trackType, RendererTypeRequester rendererTypeRequester, TrackGroupArray trackGroups, MappingTrackSelector.SelectionOverride selectionOverride) { Optional<Integer> rendererIndex = rendererTrackIndexExtractor.extract(trackType, mappedTrackInfoLength(), rendererTypeRequester); if (rendererIndex.isPresent()) { trackSelector.setSelectionOverride(rendererIndex.get(), trackGroups, selectionOverride); return true; } else { return false; } }
public boolean selectVideoTrack(PlayerVideoTrack videoTrack, RendererTypeRequester rendererTypeRequester) { TrackGroupArray trackGroups = trackSelector.trackGroups(VIDEO, rendererTypeRequester); MappingTrackSelector.SelectionOverride selectionOverride = new MappingTrackSelector.SelectionOverride( trackSelectionFactory, videoTrack.groupIndex(), videoTrack.formatIndex() ); return trackSelector.setSelectionOverride(VIDEO, rendererTypeRequester, trackGroups, selectionOverride); }
public boolean selectTextTrack(PlayerSubtitleTrack subtitleTrack, RendererTypeRequester rendererTypeRequester) { TrackGroupArray trackGroups = trackSelector.trackGroups(TEXT, rendererTypeRequester); MappingTrackSelector.SelectionOverride selectionOverride = new MappingTrackSelector.SelectionOverride( trackSelectionFactory, subtitleTrack.groupIndex(), subtitleTrack.formatIndex() ); return trackSelector.setSelectionOverride(TEXT, rendererTypeRequester, trackGroups, selectionOverride); }
@Test public void givenTrackSelectorContainsTracks_whenSelectingAudioTrack_thenSelectsTrack() { TrackGroupArray trackGroups = givenTrackSelectorContainsTracks(); ArgumentCaptor<MappingTrackSelector.SelectionOverride> argumentCaptor = whenSelectingAudioTrack(trackGroups); MappingTrackSelector.SelectionOverride selectionOverride = argumentCaptor.getValue(); assertThat(selectionOverride.factory).isEqualTo(trackSelectionFactory); assertThat(selectionOverride.groupIndex).isEqualTo(SECOND_GROUP); assertThat(selectionOverride.tracks).contains(THIRD_TRACK); }
private ArgumentCaptor<MappingTrackSelector.SelectionOverride> whenSelectingAudioTrack(TrackGroupArray trackGroups) { exoPlayerAudioTrackSelector.selectAudioTrack(AUDIO_TRACK, rendererTypeRequester); ArgumentCaptor<MappingTrackSelector.SelectionOverride> argumentCaptor = ArgumentCaptor.forClass(MappingTrackSelector.SelectionOverride.class); verify(trackSelector).setSelectionOverride(eq(TrackType.AUDIO), any(RendererTypeRequester.class), eq(trackGroups), argumentCaptor.capture()); return argumentCaptor; }
@Test public void givenTrackSelectorContainsTracks_whenSelectingVideoTrack_thenSelectsTrack() { givenTrackSelectorContainsTracks(); ArgumentCaptor<MappingTrackSelector.SelectionOverride> argumentCaptor = whenSelectingVideoTrack(ADDITIONAL_PLAYER_VIDEO_TRACK); MappingTrackSelector.SelectionOverride selectionOverride = argumentCaptor.getValue(); assertThat(selectionOverride.factory).isEqualTo(trackSelectionFactory); assertThat(selectionOverride.groupIndex).isEqualTo(FIRST_GROUP); assertThat(selectionOverride.tracks).contains(SECOND_TRACK); }
private ArgumentCaptor<MappingTrackSelector.SelectionOverride> whenSelectingVideoTrack(PlayerVideoTrack videoTrack) { exoPlayerVideoTrackSelector.selectVideoTrack(videoTrack, rendererTypeRequester); ArgumentCaptor<MappingTrackSelector.SelectionOverride> argumentCaptor = ArgumentCaptor.forClass(MappingTrackSelector.SelectionOverride.class); verify(trackSelector).setSelectionOverride(eq(TrackType.VIDEO), any(RendererTypeRequester.class), any(TrackGroupArray.class), argumentCaptor.capture()); return argumentCaptor; }
public ExoPlayerGlue(SimpleExoPlayer player, MappingTrackSelector trackSelector, Context context) { super(context, new int[] {PLAYBACK_SPEED_FAST_L0, PLAYBACK_SPEED_FAST_L1, PLAYBACK_SPEED_FAST_L2, PLAYBACK_SPEED_FAST_L3, PLAYBACK_SPEED_FAST_L4}); handler = new Handler(); this.player = player; this.trackSelector = trackSelector; player.addListener(this); trackSelector.addListener(this); playbackSpeed = new PlaybackSpeedTask(); }
@Override public void onTrackSelectionsChanged(TrackSelections<? extends MappingTrackSelector.MappedTrackInfo> trackSelections) { int textRenderIndex = getRenderIndex(C.TRACK_TYPE_TEXT); boolean status = trackSelector.getRendererDisabled(textRenderIndex); closedCaptionAction.setIndex(status ? PlaybackControlsRow.ClosedCaptioningAction.ON : PlaybackControlsRow.ClosedCaptioningAction.OFF); primaryActionsAdapter.notifyArrayItemRangeChanged(primaryActionsAdapter.indexOf(closedCaptionAction), 1); }
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_player); media = (MediaFile) getIntent().getSerializableExtra(MEDIA); videoFragment = (VideoFragment) getFragmentManager().findFragmentById(R.id.playback_fragment); VideoFragmentGlueHost glueHost = new VideoFragmentGlueHost(videoFragment); subtitleView = (SubtitleView) findViewById(R.id.subtitle_view); if (subtitleView != null) { subtitleView.setUserDefaultStyle(); subtitleView.setUserDefaultTextSize(); } Handler mainHandler = new Handler(); BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveVideoTrackSelection.Factory(bandwidthMeter); MappingTrackSelector trackSelector = new DefaultTrackSelector(mainHandler, videoTrackSelectionFactory); LoadControl loadControl = new DefaultLoadControl(); player = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl); player.addListener(this); player.setTextOutput(this); glueHelper = new ExoPlayerGlue(player, trackSelector, this); glueHelper.setHost(glueHost); session = new MediaSession(this, "ITPlayer"); session.setCallback(new ExoPlayerMediaSessionCalback(player)); session.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); session.setActive(true); MediaMetadata.Builder metaBuilder = new MediaMetadata.Builder(); session.setMetadata(metaBuilder.build()); new SourceTask().execute(media); }
@Override protected SimpleExoPlayer buildExoPlayer(HostActivity host, Surface surface, MappingTrackSelector trackSelector, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager) { SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance( new DebugRenderersFactory(host, drmSessionManager), trackSelector); player.setVideoSurface(surface); return player; }
/** * Schedules {@link #action} to be executed after {@link #delayMs}. The {@link #next} node * will be scheduled immediately after {@link #action} is executed. * * @param player The player to which actions should be applied. * @param trackSelector The track selector to which actions should be applied. * @param surface The surface to use when applying actions. * @param mainHandler A handler associated with the main thread of the host activity. */ public void schedule(SimpleExoPlayer player, MappingTrackSelector trackSelector, Surface surface, Handler mainHandler) { this.player = player; this.trackSelector = trackSelector; this.surface = surface; this.mainHandler = mainHandler; if (delayMs == 0 && Looper.myLooper() == mainHandler.getLooper()) { run(); } else { clock.postDelayed(mainHandler, this, delayMs); } }
@Override protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player, final MappingTrackSelector trackSelector, final Surface surface, final Handler handler, final ActionNode nextAction) { if (nextAction == null) { return; } player.addListener(new Player.DefaultEventListener() { @Override public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) { player.removeListener(this); nextAction.schedule(player, trackSelector, surface, handler); } }); }
@Override protected void doActionAndScheduleNextImpl(final SimpleExoPlayer player, final MappingTrackSelector trackSelector, final Surface surface, final Handler handler, final ActionNode nextAction) { if (nextAction == null) { return; } player.addListener(new Player.DefaultEventListener() { @Override public void onSeekProcessed() { player.removeListener(this); nextAction.schedule(player, trackSelector, surface, handler); } }); }
@SuppressWarnings("unused") protected SimpleExoPlayer buildExoPlayer(HostActivity host, Surface surface, MappingTrackSelector trackSelector, DrmSessionManager<FrameworkMediaCrypto> drmSessionManager) { RenderersFactory renderersFactory = new DefaultRenderersFactory(host, drmSessionManager, DefaultRenderersFactory.EXTENSION_RENDERER_MODE_OFF, 0); SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector); player.setVideoSurface(surface); return player; }
public EventLogger(MappingTrackSelector trackSelector) { this.trackSelector = trackSelector; window = new Timeline.Window(); period = new Timeline.Period(); startTimeMs = SystemClock.elapsedRealtime(); listeners = new CopyOnWriteArrayList<>(); }
public @NonNull MappingTrackSelector getSelector() { return selector; }
@Override public void onClick(View view) { if (view == qualityAutoView) { isDisabled = false; override = null; } else { isDisabled = false; @SuppressWarnings("unchecked") Pair<Integer, Integer> tag = (Pair<Integer, Integer>) view.getTag(); if(tag==null){ Toast.makeText(getContext(),"this format is not supported ",Toast.LENGTH_SHORT).show(); return; } int groupIndex = tag.first; int trackIndex = tag.second; if (!trackGroupsAdaptive[groupIndex] || override == null || override.groupIndex != groupIndex) { override = new MappingTrackSelector.SelectionOverride(FIXED_FACTORY, groupIndex, trackIndex); } else { // The group being modified is adaptive and we already have a non-null override. boolean isEnabled = ((TubiRadioButton) view).isChecked(); int overrideLength = override.length; if (isEnabled) { // Remove the track from the override. if (overrideLength == 1) { // The last track is being removed, so the override becomes empty. override = null; isDisabled = true; } else { setOverride(groupIndex, getTracksRemoving(override, trackIndex)); } } else { // Add the track to the override. setOverride(groupIndex, getTracksAdding(override, trackIndex)); } } } // Update the views with the new state. updateViews(); }
private void setOverride(int group, int[] tracks) { TrackSelection.Factory factory = tracks.length == 1 ? FIXED_FACTORY : adaptiveTrackSelectionFactory; override = new MappingTrackSelector.SelectionOverride(factory, group, tracks); }
private static int[] getTracksAdding(@NonNull MappingTrackSelector.SelectionOverride override, int addedTrack) { int[] tracks = override.tracks; tracks = Arrays.copyOf(tracks, tracks.length + 1); tracks[tracks.length - 1] = addedTrack; return tracks; }
private void setTrackInfo(@NonNull MappingTrackSelector.MappedTrackInfo trackInfo) { this.trackInfo = trackInfo; }
private void setOverride(MappingTrackSelector.SelectionOverride override) { this.override = override; }
public EventLogger(@Nullable MappingTrackSelector trackSelector) { this.trackSelector = trackSelector; window = new Timeline.Window(); period = new Timeline.Period(); startTimeMs = SystemClock.elapsedRealtime(); }
public EventLogger(MappingTrackSelector trackSelector) { this.trackSelector = trackSelector; window = new Timeline.Window(); period = new Timeline.Period(); startTimeMs = SystemClock.elapsedRealtime(); }
/** * @param selector The track selector. * @param adaptiveVideoTrackSelectionFactory A factory for adaptive video {@link TrackSelection}s, * or null if the selection helper should not support adaptive video. */ public TrackSelectionHelper(MappingTrackSelector selector, TrackSelection.Factory adaptiveVideoTrackSelectionFactory) { this.selector = selector; this.adaptiveVideoTrackSelectionFactory = adaptiveVideoTrackSelectionFactory; }
@Override protected void doActionImpl(ExoPlayer player, MappingTrackSelector trackSelector) { // Do nothing. }
@Override protected void doActionImpl(ExoPlayer player, MappingTrackSelector trackSelector) { player.seekTo(positionMs); }