@Override protected TrackSelection[] selectTracks(RendererCapabilities[] rendererCapabilities, TrackGroupArray[] rendererTrackGroupArrays, int[][][] rendererFormatSupports) throws ExoPlaybackException { Assertions.checkState(rendererCapabilities[VIDEO_RENDERER_INDEX].getTrackType() == C.TRACK_TYPE_VIDEO); Assertions.checkState(rendererCapabilities[AUDIO_RENDERER_INDEX].getTrackType() == C.TRACK_TYPE_AUDIO); Assertions.checkState(rendererTrackGroupArrays[VIDEO_RENDERER_INDEX].length == 1); Assertions.checkState(rendererTrackGroupArrays[AUDIO_RENDERER_INDEX].length == 1); TrackSelection[] selections = new TrackSelection[rendererCapabilities.length]; selections[VIDEO_RENDERER_INDEX] = new RandomTrackSelection( rendererTrackGroupArrays[VIDEO_RENDERER_INDEX].get(0), getVideoTrackIndices(rendererTrackGroupArrays[VIDEO_RENDERER_INDEX].get(0), rendererFormatSupports[VIDEO_RENDERER_INDEX][0], videoFormatIds, canIncludeAdditionalVideoFormats), 0 /* seed */); selections[AUDIO_RENDERER_INDEX] = new FixedTrackSelection( rendererTrackGroupArrays[AUDIO_RENDERER_INDEX].get(0), getTrackIndex(rendererTrackGroupArrays[AUDIO_RENDERER_INDEX].get(0), audioFormatId)); includedAdditionalVideoFormats = selections[VIDEO_RENDERER_INDEX].length() > videoFormatIds.length; return selections; }
protected TrackSelection selectVideoTrack(RendererCapabilities rendererCapabilities, TrackGroupArray groups, int[][] formatSupport, int maxVideoWidth, int maxVideoHeight, int maxVideoBitrate, boolean allowNonSeamlessAdaptiveness, boolean allowMixedMimeAdaptiveness, int viewportWidth, int viewportHeight, boolean orientationMayChange, TrackSelection.Factory adaptiveTrackSelectionFactory, boolean exceedConstraintsIfNecessary, boolean exceedRendererCapabilitiesIfNecessary) throws ExoPlaybackException { TrackSelection selection = null; if (adaptiveTrackSelectionFactory != null) { selection = selectAdaptiveVideoTrack(rendererCapabilities, groups, formatSupport, maxVideoWidth, maxVideoHeight, maxVideoBitrate, allowNonSeamlessAdaptiveness, allowMixedMimeAdaptiveness, viewportWidth, viewportHeight, orientationMayChange, adaptiveTrackSelectionFactory); } if (selection == null) { selection = selectFixedVideoTrack(groups, formatSupport, maxVideoWidth, maxVideoHeight, maxVideoBitrate, viewportWidth, viewportHeight, orientationMayChange, exceedConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary); } return selection; }
private static TrackSelection selectAdaptiveVideoTrack(RendererCapabilities rendererCapabilities, TrackGroupArray groups, int[][] formatSupport, int maxVideoWidth, int maxVideoHeight, int maxVideoBitrate, boolean allowNonSeamlessAdaptiveness, boolean allowMixedMimeAdaptiveness, int viewportWidth, int viewportHeight, boolean orientationMayChange, TrackSelection.Factory adaptiveTrackSelectionFactory) throws ExoPlaybackException { int requiredAdaptiveSupport = allowNonSeamlessAdaptiveness ? (RendererCapabilities.ADAPTIVE_NOT_SEAMLESS | RendererCapabilities.ADAPTIVE_SEAMLESS) : RendererCapabilities.ADAPTIVE_SEAMLESS; boolean allowMixedMimeTypes = allowMixedMimeAdaptiveness && (rendererCapabilities.supportsMixedMimeTypeAdaptation() & requiredAdaptiveSupport) != 0; for (int i = 0; i < groups.length; i++) { TrackGroup group = groups.get(i); int[] adaptiveTracks = getAdaptiveVideoTracksForGroup(group, formatSupport[i], allowMixedMimeTypes, requiredAdaptiveSupport, maxVideoWidth, maxVideoHeight, maxVideoBitrate, viewportWidth, viewportHeight, orientationMayChange); if (adaptiveTracks.length > 0) { return adaptiveTrackSelectionFactory.createTrackSelection(group, adaptiveTracks); } } return null; }
/** * Returns whether a renderer supports tunneling for a {@link TrackSelection}. * * @param formatSupport The result of {@link RendererCapabilities#supportsFormat} for each * track, indexed by group index and track index (in that order). * @param trackGroups The {@link TrackGroupArray}s for the renderer. * @param selection The track selection. * @return Whether the renderer supports tunneling for the {@link TrackSelection}. */ private static boolean rendererSupportsTunneling(int[][] formatSupport, TrackGroupArray trackGroups, TrackSelection selection) { if (selection == null) { return false; } int trackGroupIndex = trackGroups.indexOf(selection.getTrackGroup()); for (int i = 0; i < selection.length(); i++) { int trackFormatSupport = formatSupport[trackGroupIndex][selection.getIndexInTrackGroup(i)]; if ((trackFormatSupport & RendererCapabilities.TUNNELING_SUPPORT_MASK) != RendererCapabilities.TUNNELING_SUPPORTED) { return false; } } return true; }
public List<PlayerSubtitleTrack> getSubtitleTracks(RendererTypeRequester rendererTypeRequester) { TrackGroupArray trackGroups = trackSelector.trackGroups(TEXT, rendererTypeRequester); List<PlayerSubtitleTrack> subtitleTracks = new ArrayList<>(); for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { TrackGroup trackGroup = trackGroups.get(groupIndex); for (int formatIndex = 0; formatIndex < trackGroup.length; formatIndex++) { Format format = trackGroup.getFormat(formatIndex); PlayerSubtitleTrack playerSubtitleTrack = new PlayerSubtitleTrack( groupIndex, formatIndex, format.id, format.language, format.sampleMimeType, format.channelCount, format.bitrate ); subtitleTracks.add(playerSubtitleTrack); } } return subtitleTracks; }
protected TrackSelection selectVideoTrack(RendererCapabilities rendererCapabilities, TrackGroupArray groups, int[][] formatSupport, int maxVideoWidth, int maxVideoHeight, int maxVideoBitrate, boolean allowNonSeamlessAdaptiveness, boolean allowMixedMimeAdaptiveness, int viewportWidth, int viewportHeight, boolean orientationMayChange, TrackSelection.Factory adaptiveVideoTrackSelectionFactory, boolean exceedConstraintsIfNecessary, boolean exceedRendererCapabilitiesIfNecessary) throws ExoPlaybackException { TrackSelection selection = null; if (adaptiveVideoTrackSelectionFactory != null) { selection = selectAdaptiveVideoTrack(rendererCapabilities, groups, formatSupport, maxVideoWidth, maxVideoHeight, maxVideoBitrate, allowNonSeamlessAdaptiveness, allowMixedMimeAdaptiveness, viewportWidth, viewportHeight, orientationMayChange, adaptiveVideoTrackSelectionFactory); } if (selection == null) { selection = selectFixedVideoTrack(groups, formatSupport, maxVideoWidth, maxVideoHeight, maxVideoBitrate, viewportWidth, viewportHeight, orientationMayChange, exceedConstraintsIfNecessary, exceedRendererCapabilitiesIfNecessary); } return selection; }
private static TrackSelection selectAdaptiveVideoTrack(RendererCapabilities rendererCapabilities, TrackGroupArray groups, int[][] formatSupport, int maxVideoWidth, int maxVideoHeight, int maxVideoBitrate, boolean allowNonSeamlessAdaptiveness, boolean allowMixedMimeAdaptiveness, int viewportWidth, int viewportHeight, boolean orientationMayChange, TrackSelection.Factory adaptiveVideoTrackSelectionFactory) throws ExoPlaybackException { int requiredAdaptiveSupport = allowNonSeamlessAdaptiveness ? (RendererCapabilities.ADAPTIVE_NOT_SEAMLESS | RendererCapabilities.ADAPTIVE_SEAMLESS) : RendererCapabilities.ADAPTIVE_SEAMLESS; boolean allowMixedMimeTypes = allowMixedMimeAdaptiveness && (rendererCapabilities.supportsMixedMimeTypeAdaptation() & requiredAdaptiveSupport) != 0; for (int i = 0; i < groups.length; i++) { TrackGroup group = groups.get(i); int[] adaptiveTracks = getAdaptiveTracksForGroup(group, formatSupport[i], allowMixedMimeTypes, requiredAdaptiveSupport, maxVideoWidth, maxVideoHeight, maxVideoBitrate, viewportWidth, viewportHeight, orientationMayChange); if (adaptiveTracks.length > 0) { return adaptiveVideoTrackSelectionFactory.createTrackSelection(group, adaptiveTracks); } } return null; }
public DashMediaPeriod(int id, DashManifest manifest, int periodIndex, DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, EventDispatcher eventDispatcher, long elapsedRealtimeOffset, LoaderErrorThrower manifestLoaderErrorThrower, Allocator allocator) { this.id = id; this.manifest = manifest; this.periodIndex = periodIndex; this.chunkSourceFactory = chunkSourceFactory; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; this.elapsedRealtimeOffset = elapsedRealtimeOffset; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.allocator = allocator; sampleStreams = newSampleStreamArray(0); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); adaptationSets = manifest.getPeriod(periodIndex).adaptationSets; Pair<TrackGroupArray, EmbeddedTrackInfo[]> result = buildTrackGroups(adaptationSets); trackGroups = result.first; embeddedTrackInfos = result.second; }
/** * Constructs an instance. Must be called from a thread that has an associated {@link Looper}. * * @param renderers The {@link Renderer}s that will be used by the instance. * @param trackSelector The {@link TrackSelector} that will be used by the instance. * @param loadControl The {@link LoadControl} that will be used by the instance. */ @SuppressLint("HandlerLeak") public ExoPlayerImpl(Renderer[] renderers, TrackSelector trackSelector, LoadControl loadControl) { Log.i(TAG, "Init " + ExoPlayerLibraryInfo.VERSION + " [" + Util.DEVICE_DEBUG_INFO + "]"); Assertions.checkState(renderers.length > 0); this.renderers = Assertions.checkNotNull(renderers); this.trackSelector = Assertions.checkNotNull(trackSelector); this.playWhenReady = false; this.playbackState = STATE_IDLE; this.listeners = new CopyOnWriteArraySet<>(); emptyTrackSelections = new TrackSelectionArray(new TrackSelection[renderers.length]); timeline = Timeline.EMPTY; window = new Timeline.Window(); period = new Timeline.Period(); trackGroups = TrackGroupArray.EMPTY; trackSelections = emptyTrackSelections; eventHandler = new Handler() { @Override public void handleMessage(Message msg) { ExoPlayerImpl.this.handleEvent(msg); } }; playbackInfo = new ExoPlayerImplInternal.PlaybackInfo(0, 0); internalPlayer = new ExoPlayerImplInternal(renderers, trackSelector, loadControl, playWhenReady, eventHandler, playbackInfo, this); }
protected TrackSelection selectVideoTrack(RendererCapabilities rendererCapabilities, TrackGroupArray groups, int[][] formatSupport, int maxVideoWidth, int maxVideoHeight, boolean allowNonSeamlessAdaptiveness, boolean allowMixedMimeAdaptiveness, int viewportWidth, int viewportHeight, boolean orientationMayChange, TrackSelection.Factory adaptiveVideoTrackSelectionFactory, boolean exceedConstraintsIfNecessary) throws ExoPlaybackException { TrackSelection selection = null; if (adaptiveVideoTrackSelectionFactory != null) { selection = selectAdaptiveVideoTrack(rendererCapabilities, groups, formatSupport, maxVideoWidth, maxVideoHeight, allowNonSeamlessAdaptiveness, allowMixedMimeAdaptiveness, viewportWidth, viewportHeight, orientationMayChange, adaptiveVideoTrackSelectionFactory); } if (selection == null) { selection = selectFixedVideoTrack(groups, formatSupport, maxVideoWidth, maxVideoHeight, viewportWidth, viewportHeight, orientationMayChange, exceedConstraintsIfNecessary); } return selection; }
private static TrackSelection selectAdaptiveVideoTrack(RendererCapabilities rendererCapabilities, TrackGroupArray groups, int[][] formatSupport, int maxVideoWidth, int maxVideoHeight, boolean allowNonSeamlessAdaptiveness, boolean allowMixedMimeAdaptiveness, int viewportWidth, int viewportHeight, boolean orientationMayChange, TrackSelection.Factory adaptiveVideoTrackSelectionFactory) throws ExoPlaybackException { int requiredAdaptiveSupport = allowNonSeamlessAdaptiveness ? (RendererCapabilities.ADAPTIVE_NOT_SEAMLESS | RendererCapabilities.ADAPTIVE_SEAMLESS) : RendererCapabilities.ADAPTIVE_SEAMLESS; boolean allowMixedMimeTypes = allowMixedMimeAdaptiveness && (rendererCapabilities.supportsMixedMimeTypeAdaptation() & requiredAdaptiveSupport) != 0; for (int i = 0; i < groups.length; i++) { TrackGroup group = groups.get(i); int[] adaptiveTracks = getAdaptiveTracksForGroup(group, formatSupport[i], allowMixedMimeTypes, requiredAdaptiveSupport, maxVideoWidth, maxVideoHeight, viewportWidth, viewportHeight, orientationMayChange); if (adaptiveTracks.length > 0) { return adaptiveVideoTrackSelectionFactory.createTrackSelection(group, adaptiveTracks); } } return null; }
protected TrackSelection selectOtherTrack(int trackType, TrackGroupArray groups, int[][] formatSupport) { TrackGroup selectedGroup = null; int selectedTrackIndex = 0; int selectedTrackScore = 0; for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) { TrackGroup trackGroup = groups.get(groupIndex); int[] trackFormatSupport = formatSupport[groupIndex]; for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) { if (isSupported(trackFormatSupport[trackIndex])) { Format format = trackGroup.getFormat(trackIndex); boolean isDefault = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; int trackScore = isDefault ? 2 : 1; if (trackScore > selectedTrackScore) { selectedGroup = trackGroup; selectedTrackIndex = trackIndex; selectedTrackScore = trackScore; } } } } return selectedGroup == null ? null : new FixedTrackSelection(selectedGroup, selectedTrackIndex); }
/** * Overrides the track selection for the renderer at a specified index. * <p> * When the {@link TrackGroupArray} available to the renderer at the specified index matches the * one provided, the override is applied. When the {@link TrackGroupArray} does not match, the * override has no effect. The override replaces any previous override for the renderer and the * provided {@link TrackGroupArray}. * <p> * Passing a {@code null} override will explicitly disable the renderer. To remove overrides use * {@link #clearSelectionOverride(int, TrackGroupArray)}, {@link #clearSelectionOverrides(int)} * or {@link #clearSelectionOverrides()}. * * @param rendererIndex The renderer index. * @param groups The {@link TrackGroupArray} for which the override should be applied. * @param override The override. */ // TODO - Don't allow overrides that select unsupported tracks, unless some flag has been // explicitly set by the user to indicate that they want this. public final void setSelectionOverride(int rendererIndex, TrackGroupArray groups, SelectionOverride override) { Map<TrackGroupArray, SelectionOverride> overrides = selectionOverrides.get(rendererIndex); if (overrides == null) { overrides = new HashMap<>(); selectionOverrides.put(rendererIndex, overrides); } if (overrides.containsKey(groups) && Util.areEqual(overrides.get(groups), override)) { // The override is unchanged. return; } overrides.put(groups, override); invalidate(); }
@Override public void onTracksSelected(Renderer[] renderers, TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { targetBufferSize = 0; for (int i = 0; i < renderers.length; i++) { if (trackSelections.get(i) != null) { targetBufferSize += Util.getDefaultBufferSize(renderers[i].getTrackType()); } } allocator.setTargetBufferSize(targetBufferSize); }
@Override public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { Log.d(TAG, "onTracksChanged:" + currentWindowIndex + "_:" + player.getCurrentTimeline().getWindowCount()); if (getWindowCount() > 1) { if (isRemove) { isRemove = false; mediaSourceBuilder.removeMediaSource(resumeWindow); return; } if (windowListener != null) { windowListener.onCurrentIndex(currentWindowIndex, getWindowCount()); currentWindowIndex += 1; } if (mediaSourceBuilder.getIndexType() < 0) { return; } GestureVideoPlayer gestureVideoPlayer = null; if (ExoUserPlayer.this instanceof GestureVideoPlayer) { gestureVideoPlayer = (GestureVideoPlayer) ExoUserPlayer.this; } boolean setOpenSeek = !(mediaSourceBuilder.getIndexType() == currentWindowIndex && mediaSourceBuilder.getIndexType() > 0); if (gestureVideoPlayer != null) { gestureVideoPlayer.setPlayerGestureOnTouch(setOpenSeek); } getPlayerViewListener().setOpenSeek(setOpenSeek); } }
@Override public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { updateButtonVisibilities(); MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo(); if (mappedTrackInfo != null) { if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_VIDEO) == MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) { showToast(R.string.error_unsupported_video); } if (mappedTrackInfo.getTrackTypeRendererSupport(C.TRACK_TYPE_AUDIO) == MappedTrackInfo.RENDERER_SUPPORT_UNSUPPORTED_TRACKS) { showToast(R.string.error_unsupported_audio); } } }
private void updateButtonVisibilities() { debugRootView.removeAllViews(); retryButton.setVisibility(playerNeedsSource ? View.VISIBLE : View.GONE); debugRootView.addView(retryButton); if (player == null) { return; } MappedTrackInfo mappedTrackInfo = trackSelector.getCurrentMappedTrackInfo(); if (mappedTrackInfo == null) { return; } for (int i = 0; i < mappedTrackInfo.length; i++) { TrackGroupArray trackGroups = mappedTrackInfo.getTrackGroups(i); if (trackGroups.length != 0) { Button button = new Button(this); int label; switch (player.getRendererType(i)) { case C.TRACK_TYPE_AUDIO: label = R.string.audio; break; case C.TRACK_TYPE_VIDEO: label = R.string.video; break; case C.TRACK_TYPE_TEXT: label = R.string.text; break; default: continue; } button.setText(label); button.setTag(i); button.setOnClickListener(this); debugRootView.addView(button, debugRootView.getChildCount() - 1); } } }
@Override public void onTracksSelected(Renderer[] renderers, TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { int targetBufferSize = 0; for (int i = 0; i < renderers.length; i++) { if (trackSelections.get(i) != null) { targetBufferSize += Util.getDefaultBufferSize(renderers[i].getTrackType()); } } allocator.setTargetBufferSize(targetBufferSize); }
@Override public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { if (trackGroups.length > 0) { // update format metadata of station Format format = trackGroups.get(0).getFormat(0); mStation.setMimeType(format.sampleMimeType); mStation.setChannelCount(format.channelCount); mStation.setSampleRate(format.sampleRate); mStation.setBitrate(format.bitrate); saveAppState(); } }
protected TrackSelection selectAudioTrack(TrackGroupArray groups, int[][] formatSupport, String preferredAudioLanguage, boolean exceedRendererCapabilitiesIfNecessary, boolean allowMixedMimeAdaptiveness, TrackSelection.Factory adaptiveTrackSelectionFactory) { int selectedGroupIndex = C.INDEX_UNSET; int selectedTrackIndex = C.INDEX_UNSET; int selectedTrackScore = 0; for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) { TrackGroup trackGroup = groups.get(groupIndex); int[] trackFormatSupport = formatSupport[groupIndex]; for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) { if (isSupported(trackFormatSupport[trackIndex], exceedRendererCapabilitiesIfNecessary)) { Format format = trackGroup.getFormat(trackIndex); int trackScore = getAudioTrackScore(trackFormatSupport[trackIndex], preferredAudioLanguage, format); if (trackScore > selectedTrackScore) { selectedGroupIndex = groupIndex; selectedTrackIndex = trackIndex; selectedTrackScore = trackScore; } } } } if (selectedGroupIndex == C.INDEX_UNSET) { return null; } TrackGroup selectedGroup = groups.get(selectedGroupIndex); if (adaptiveTrackSelectionFactory != null) { // If the group of the track with the highest score allows it, try to enable adaptation. int[] adaptiveTracks = getAdaptiveAudioTracks(selectedGroup, formatSupport[selectedGroupIndex], allowMixedMimeAdaptiveness); if (adaptiveTracks.length > 0) { return adaptiveTrackSelectionFactory.createTrackSelection(selectedGroup, adaptiveTracks); } } return new FixedTrackSelection(selectedGroup, selectedTrackIndex); }
protected TrackSelection selectOtherTrack(int trackType, TrackGroupArray groups, int[][] formatSupport, boolean exceedRendererCapabilitiesIfNecessary) { TrackGroup selectedGroup = null; int selectedTrackIndex = 0; int selectedTrackScore = 0; for (int groupIndex = 0; groupIndex < groups.length; groupIndex++) { TrackGroup trackGroup = groups.get(groupIndex); int[] trackFormatSupport = formatSupport[groupIndex]; for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) { if (isSupported(trackFormatSupport[trackIndex], exceedRendererCapabilitiesIfNecessary)) { Format format = trackGroup.getFormat(trackIndex); boolean isDefault = (format.selectionFlags & C.SELECTION_FLAG_DEFAULT) != 0; int trackScore = isDefault ? 2 : 1; if (isSupported(trackFormatSupport[trackIndex], false)) { trackScore += WITHIN_RENDERER_CAPABILITIES_BONUS; } if (trackScore > selectedTrackScore) { selectedGroup = trackGroup; selectedTrackIndex = trackIndex; selectedTrackScore = trackScore; } } } } return selectedGroup == null ? null : new FixedTrackSelection(selectedGroup, selectedTrackIndex); }
/** * Clears a track selection override for the specified renderer and {@link TrackGroupArray}. * * @param rendererIndex The renderer index. * @param groups The {@link TrackGroupArray} for which the override should be cleared. */ public final void clearSelectionOverride(int rendererIndex, TrackGroupArray groups) { Map<TrackGroupArray, SelectionOverride> overrides = selectionOverrides.get(rendererIndex); if (overrides == null || !overrides.containsKey(groups)) { // Nothing to clear. return; } overrides.remove(groups); if (overrides.isEmpty()) { selectionOverrides.remove(rendererIndex); } invalidate(); }
/** * Clears all track selection override for the specified renderer. * * @param rendererIndex The renderer index. */ public final void clearSelectionOverrides(int rendererIndex) { Map<TrackGroupArray, ?> overrides = selectionOverrides.get(rendererIndex); if (overrides == null || overrides.isEmpty()) { // Nothing to clear. return; } selectionOverrides.remove(rendererIndex); invalidate(); }
/** * @param rendererTrackTypes The track type supported by each renderer. * @param trackGroups The {@link TrackGroupArray}s for each renderer. * @param mixedMimeTypeAdaptiveSupport The result of * {@link RendererCapabilities#supportsMixedMimeTypeAdaptation()} for each renderer. * @param formatSupport The result of {@link RendererCapabilities#supportsFormat} for each * track, indexed by renderer index, group index and track index (in that order). * @param unassociatedTrackGroups Contains {@link TrackGroup}s not associated with any renderer. */ /* package */ MappedTrackInfo(int[] rendererTrackTypes, TrackGroupArray[] trackGroups, int[] mixedMimeTypeAdaptiveSupport, int[][][] formatSupport, TrackGroupArray unassociatedTrackGroups) { this.rendererTrackTypes = rendererTrackTypes; this.trackGroups = trackGroups; this.formatSupport = formatSupport; this.mixedMimeTypeAdaptiveSupport = mixedMimeTypeAdaptiveSupport; this.unassociatedTrackGroups = unassociatedTrackGroups; this.length = trackGroups.length; }
/** * Constructs an instance. Must be called from a thread that has an associated {@link Looper}. * * @param renderers The {@link Renderer}s that will be used by the instance. * @param trackSelector The {@link TrackSelector} that will be used by the instance. * @param loadControl The {@link LoadControl} that will be used by the instance. */ @SuppressLint("HandlerLeak") public ExoPlayerImpl(Renderer[] renderers, TrackSelector trackSelector, LoadControl loadControl) { Log.i(TAG, "Init " + ExoPlayerLibraryInfo.VERSION_SLASHY + " [" + Util.DEVICE_DEBUG_INFO + "]"); Assertions.checkState(renderers.length > 0); this.renderers = Assertions.checkNotNull(renderers); this.trackSelector = Assertions.checkNotNull(trackSelector); this.playWhenReady = false; this.playbackState = STATE_IDLE; this.listeners = new CopyOnWriteArraySet<>(); emptyTrackSelections = new TrackSelectionArray(new TrackSelection[renderers.length]); timeline = Timeline.EMPTY; window = new Timeline.Window(); period = new Timeline.Period(); trackGroups = TrackGroupArray.EMPTY; trackSelections = emptyTrackSelections; playbackParameters = PlaybackParameters.DEFAULT; Looper eventLooper = Looper.myLooper() != null ? Looper.myLooper() : Looper.getMainLooper(); eventHandler = new Handler(eventLooper) { @Override public void handleMessage(Message msg) { ExoPlayerImpl.this.handleEvent(msg); } }; playbackInfo = new ExoPlayerImplInternal.PlaybackInfo(0, 0); internalPlayer = new ExoPlayerImplInternal(renderers, trackSelector, loadControl, playWhenReady, eventHandler, playbackInfo, this); }
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); }
public AudioTracks getAudioTracks(RendererTypeRequester rendererTypeRequester) { TrackGroupArray trackGroups = trackSelector.trackGroups(AUDIO, rendererTypeRequester); List<PlayerAudioTrack> audioTracks = new ArrayList<>(); for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { if (trackSelector.supportsTrackSwitching(AUDIO, rendererTypeRequester, trackGroups, groupIndex)) { TrackGroup trackGroup = trackGroups.get(groupIndex); for (int formatIndex = 0; formatIndex < trackGroup.length; formatIndex++) { Format format = trackGroup.getFormat(formatIndex); PlayerAudioTrack playerAudioTrack = new PlayerAudioTrack( groupIndex, formatIndex, format.id, format.language, format.sampleMimeType, format.channelCount, format.bitrate, AudioTrackType.from(format.selectionFlags) ); audioTracks.add(playerAudioTrack); } } } return AudioTracks.from(audioTracks); }
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; } }
boolean supportsTrackSwitching(TrackType trackType, RendererTypeRequester rendererTypeRequester, TrackGroupArray trackGroups, int groupIndex) { Optional<Integer> audioRendererIndex = rendererTrackIndexExtractor.extract(trackType, mappedTrackInfoLength(), rendererTypeRequester); return audioRendererIndex.isPresent() && trackGroups.get(groupIndex).length > 0 && trackInfo().getAdaptiveSupport(audioRendererIndex.get(), groupIndex, false) != RendererCapabilities.ADAPTIVE_NOT_SUPPORTED; }
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 List<PlayerVideoTrack> getVideoTracks(RendererTypeRequester rendererTypeRequester, ContentType contentType) { TrackGroupArray trackGroups = trackSelector.trackGroups(VIDEO, rendererTypeRequester); List<PlayerVideoTrack> videoTracks = new ArrayList<>(); for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { TrackGroup trackGroup = trackGroups.get(groupIndex); for (int formatIndex = 0; formatIndex < trackGroup.length; formatIndex++) { Format format = trackGroup.getFormat(formatIndex); PlayerVideoTrack playerVideoTrack = new PlayerVideoTrack( groupIndex, formatIndex, format.id, contentType, format.width, format.height, (int) format.frameRate, format.bitrate ); videoTracks.add(playerVideoTrack); } } return videoTracks; }
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); }
@Override public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) { HashMap<String, String> callingMethodParameters = new HashMap<>(); callingMethodParameters.put("trackGroups", String.valueOf(trackGroups)); callingMethodParameters.put("trackSelections", String.valueOf(trackSelections)); infoListener.onNewInfo("onTracksChanged", callingMethodParameters); }
@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 TrackGroupArray givenTrackSelectorContainsTracks() { TrackGroupArray trackGroups = new TrackGroupArray( new TrackGroup(AudioFormatFixture.anAudioFormat().build()), new TrackGroup( AudioFormatFixture.anAudioFormat().build(), AudioFormatFixture.anAudioFormat().build(), AudioFormatFixture.anAudioFormat().build() ) ); given(trackSelector.trackGroups(TrackType.AUDIO, rendererTypeRequester)).willReturn(trackGroups); return trackGroups; }
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; }
private void givenTrackSelectorContainsUnsupportedTracks() { TrackGroupArray trackGroups = new TrackGroupArray( new TrackGroup(AUDIO_FORMAT), new TrackGroup( AudioFormatFixture.anAudioFormat().build(), AudioFormatFixture.anAudioFormat().build(), AudioFormatFixture.anAudioFormat().build() ) ); given(trackSelector.trackGroups(TrackType.AUDIO, rendererTypeRequester)).willReturn(trackGroups); given(trackSelector.supportsTrackSwitching(eq(TrackType.AUDIO), any(RendererTypeRequester.class), any(TrackGroupArray.class), anyInt())) .willReturn(true) .willReturn(false); }
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; }