/*** * 创建实例播放实例,并不开始缓冲 **/ private SimpleExoPlayer createFullPlayer() { TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(new DefaultBandwidthMeter()); TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); BufferingLoadControl loadControl = new BufferingLoadControl(); if (null == modelType) { setDefaultLoadModel(); } else { loadControl.setListener(new LoadListener() { @Override public void onProgress(long pro) { getPlayerViewListener().showNetSpeed(String.valueOf(pro) + "%"); } }); } DefaultRenderersFactory rf = new DefaultRenderersFactory(activity, drmSessionManager, DefaultRenderersFactory.EXTENSION_RENDERER_MODE_ON); SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(rf, trackSelector, loadControl); player.setPlaybackParameters(playbackParameters); getPlayerViewListener().setPlayer(player); return player; }
@Override public IBinder onBind(final Intent intent) { bandwidthMeter = new DefaultBandwidthMeter(); TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "SyncPlayer"), bandwidthMeter); extractorsFactory = new DefaultExtractorsFactory(); TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); LoadControl loadControl = new DefaultLoadControl(); SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(getApplicationContext(), trackSelector, loadControl); mMediaPlayer = player; setCompletionListener(); nbuilder.setSmallIcon(R.mipmap.ic_launcher); return mBinder; }
protected void initPlayer() { // 1. Create a default TrackSelector mMainHandler = new Handler(); TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER); mTrackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); mTrackSelectionHelper = new TrackSelectionHelper(this, mTrackSelector,videoTrackSelectionFactory); // 3. Create the mTubiExoPlayer mTubiExoPlayer = ExoPlayerFactory.newSimpleInstance(this, mTrackSelector); mEventLogger = new EventLogger(mTrackSelector); mTubiExoPlayer.addListener(mEventLogger); mTubiExoPlayer.setAudioDebugListener(mEventLogger); mTubiExoPlayer.setVideoDebugListener(mEventLogger); mTubiExoPlayer.setMetadataOutput(mEventLogger); mTubiPlayerView.setPlayer(mTubiExoPlayer, this); mTubiPlayerView.setMediaModel(mediaModel,true); mTubiPlayerView.setTrackSelectionHelper(mTrackSelectionHelper); }
@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; }
private void initializePlayer() { if (player == null) { // a factory to create an AdaptiveVideoTrackSelection TrackSelection.Factory adaptiveTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER); // using a DefaultTrackSelector with an adaptive video selection factory player = ExoPlayerFactory.newSimpleInstance(new DefaultRenderersFactory(this), new DefaultTrackSelector(adaptiveTrackSelectionFactory), new DefaultLoadControl()); player.addListener(componentListener); player.addVideoDebugListener(componentListener); player.addAudioDebugListener(componentListener); playerView.setPlayer(player); player.setPlayWhenReady(playWhenReady); player.seekTo(currentWindow, playbackPosition); } MediaSource mediaSource = buildMediaSource(Uri.parse(getString(R.string.media_url_dash))); player.prepare(mediaSource, true, false); }
@Override public void prepareAsync() throws IllegalStateException { TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER); DefaultTrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); mInternalMediaPlayer = InternalExoPlayer.newInstance(mAppContext, trackSelector); mEventListener = new ExoEventListener(); mInternalMediaPlayer.addListener(mEventListener); mVideoListener = new ExoVideoListener(); mInternalMediaPlayer.addVideoListener(mVideoListener); MediaSource mediaSource = buildMediaSource(mUri, mHeaders); mInternalMediaPlayer.setVideoSurface(mSurface); mInternalMediaPlayer.prepare(mediaSource); notifyOnPrepared(); }
private void setExoViewSource(@NonNull MasterSecret masterSecret, @NonNull VideoSlide videoSource) throws IOException { BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); LoadControl loadControl = new DefaultLoadControl(); exoPlayer = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, loadControl); exoView.setPlayer(exoPlayer); DefaultDataSourceFactory defaultDataSourceFactory = new DefaultDataSourceFactory(getContext(), "GenericUserAgent", null); AttachmentDataSourceFactory attachmentDataSourceFactory = new AttachmentDataSourceFactory(getContext(), masterSecret, defaultDataSourceFactory, null); ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory(); MediaSource mediaSource = new ExtractorMediaSource(videoSource.getUri(), attachmentDataSourceFactory, extractorsFactory, null, null); exoPlayer.prepare(mediaSource); exoPlayer.setPlayWhenReady(true); }
@Override public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { sampleStreams = new ClippingSampleStream[streams.length]; SampleStream[] internalStreams = new SampleStream[streams.length]; for (int i = 0; i < streams.length; i++) { sampleStreams[i] = (ClippingSampleStream) streams[i]; internalStreams[i] = sampleStreams[i] != null ? sampleStreams[i].stream : null; } long enablePositionUs = mediaPeriod.selectTracks(selections, mayRetainStreamFlags, internalStreams, streamResetFlags, positionUs + startUs); Assertions.checkState(enablePositionUs == positionUs + startUs || (enablePositionUs >= startUs && (endUs == C.TIME_END_OF_SOURCE || enablePositionUs <= endUs))); for (int i = 0; i < streams.length; i++) { if (internalStreams[i] == null) { sampleStreams[i] = null; } else if (streams[i] == null || sampleStreams[i].stream != internalStreams[i]) { sampleStreams[i] = new ClippingSampleStream(this, internalStreams[i], startUs, endUs, pendingInitialDiscontinuity); } streams[i] = sampleStreams[i]; } return enablePositionUs - startUs; }
/** * Blacklists {@code trackSelectionIndex} in {@code trackSelection} for * {@code blacklistDurationMs} if calling {@link #shouldBlacklist(Exception)} for {@code e} * returns true. Else does nothing. Note that blacklisting will fail if the track is the only * non-blacklisted track in the selection. * * @param trackSelection The track selection. * @param trackSelectionIndex The index in the selection to consider blacklisting. * @param e The error to inspect. * @param blacklistDurationMs The duration to blacklist the track for, if it is blacklisted. * @return Whether the track was blacklisted. */ public static boolean maybeBlacklistTrack(TrackSelection trackSelection, int trackSelectionIndex, Exception e, long blacklistDurationMs) { if (shouldBlacklist(e)) { boolean blacklisted = trackSelection.blacklist(trackSelectionIndex, blacklistDurationMs); int responseCode = ((InvalidResponseCodeException) e).responseCode; if (blacklisted) { Log.w(TAG, "Blacklisted: duration=" + blacklistDurationMs + ", responseCode=" + responseCode + ", format=" + trackSelection.getFormat(trackSelectionIndex)); } else { Log.w(TAG, "Blacklisting failed (cannot blacklist last enabled track): responseCode=" + responseCode + ", format=" + trackSelection.getFormat(trackSelectionIndex)); } return blacklisted; } return false; }
@Override public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { for (int i = 0; i < selections.length; i++) { if (streams[i] != null && (selections[i] == null || !mayRetainStreamFlags[i])) { sampleStreams.remove(streams[i]); streams[i] = null; } if (streams[i] == null && selections[i] != null) { SampleStreamImpl stream = new SampleStreamImpl(); sampleStreams.add(stream); streams[i] = stream; streamResetFlags[i] = true; } } return positionUs; }
private void setupExoPlayer() { TrackSelection.Factory adaptiveTrackSelectionFactory = new AdaptiveTrackSelection.Factory(new DefaultBandwidthMeter()); exoPlayer = ExoPlayerFactory.newSimpleInstance( new DefaultRenderersFactory(this), new DefaultTrackSelector(adaptiveTrackSelectionFactory), new DefaultLoadControl()); pvVideoPreview.setPlayer(exoPlayer); exoPlayer.setPlayWhenReady(true); Uri uri = Uri.parse("asset:///sample_video.mp4"); MediaSource mediaSource = createMediaSource(this, uri); LoopingMediaSource loopingMediaSource = new LoopingMediaSource(mediaSource); exoPlayer.prepare(loopingMediaSource, true, false); }
private void initExoPlayer(MediaSource sampleSource) { if (exoPlayer == null) { TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(new DefaultBandwidthMeter()); TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); // 2. Create the player exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector); } exoPlayer.prepare(sampleSource); exoPlayer.setVideoSurfaceView(svPlayer); exoPlayer.setPlayWhenReady(true); initMediaControls(); }
/** * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests. * @param manifest The initial manifest. * @param periodIndex The index of the period in the manifest. * @param adaptationSetIndex The index of the adaptation set in the period. * @param trackSelection The track selection. * @param dataSource A {@link DataSource} suitable for loading the media data. * @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between * server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified * as the server's unix time minus the local elapsed time. If unknown, set to 0. * @param maxSegmentsPerLoad The maximum number of segments to combine into a single request. * Note that segments will only be combined if their {@link Uri}s are the same and if their * data ranges are adjacent. * @param enableEventMessageTrack Whether the chunks generated by the source may output an event * message track. * @param enableEventMessageTrack Whether the chunks generated by the source may output a CEA-608 * track. */ public DefaultDashChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, DashManifest manifest, int periodIndex, int adaptationSetIndex, TrackSelection trackSelection, DataSource dataSource, long elapsedRealtimeOffsetMs, int maxSegmentsPerLoad, boolean enableEventMessageTrack, boolean enableCea608Track) { this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.manifest = manifest; this.adaptationSetIndex = adaptationSetIndex; this.trackSelection = trackSelection; this.dataSource = dataSource; this.periodIndex = periodIndex; this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs; this.maxSegmentsPerLoad = maxSegmentsPerLoad; long periodDurationUs = manifest.getPeriodDurationUs(periodIndex); AdaptationSet adaptationSet = getAdaptationSet(); List<Representation> representations = adaptationSet.representations; representationHolders = new RepresentationHolder[trackSelection.length()]; for (int i = 0; i < representationHolders.length; i++) { Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i)); representationHolders[i] = new RepresentationHolder(periodDurationUs, representation, enableEventMessageTrack, enableCea608Track, adaptationSet.type); } }
private ChunkSampleStream<DashChunkSource> buildSampleStream(int adaptationSetIndex, TrackSelection selection, long positionUs) { AdaptationSet adaptationSet = adaptationSets.get(adaptationSetIndex); int embeddedTrackCount = 0; int[] embeddedTrackTypes = new int[2]; boolean enableEventMessageTrack = hasEventMessageTrack(adaptationSet); if (enableEventMessageTrack) { embeddedTrackTypes[embeddedTrackCount++] = C.TRACK_TYPE_METADATA; } boolean enableCea608Track = hasCea608Track(adaptationSet); if (enableCea608Track) { embeddedTrackTypes[embeddedTrackCount++] = C.TRACK_TYPE_TEXT; } if (embeddedTrackCount < embeddedTrackTypes.length) { embeddedTrackTypes = Arrays.copyOf(embeddedTrackTypes, embeddedTrackCount); } DashChunkSource chunkSource = chunkSourceFactory.createDashChunkSource( manifestLoaderErrorThrower, manifest, periodIndex, adaptationSetIndex, selection, elapsedRealtimeOffset, enableEventMessageTrack, enableCea608Track); ChunkSampleStream<DashChunkSource> stream = new ChunkSampleStream<>(adaptationSet.type, embeddedTrackTypes, chunkSource, this, allocator, positionUs, minLoadableRetryCount, eventDispatcher); return stream; }
/** * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests. * @param manifest The initial manifest. * @param elementIndex The index of the stream element in the manifest. * @param trackSelection The track selection. * @param dataSource A {@link DataSource} suitable for loading the media data. * @param trackEncryptionBoxes Track encryption boxes for the stream. */ public DefaultSsChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, SsManifest manifest, int elementIndex, TrackSelection trackSelection, DataSource dataSource, TrackEncryptionBox[] trackEncryptionBoxes) { this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.manifest = manifest; this.elementIndex = elementIndex; this.trackSelection = trackSelection; this.dataSource = dataSource; StreamElement streamElement = manifest.streamElements[elementIndex]; extractorWrappers = new ChunkExtractorWrapper[trackSelection.length()]; for (int i = 0; i < extractorWrappers.length; i++) { int manifestTrackIndex = trackSelection.getIndexInTrackGroup(i); Format format = streamElement.formats[manifestTrackIndex]; int nalUnitLengthFieldLength = streamElement.type == C.TRACK_TYPE_VIDEO ? 4 : 0; Track track = new Track(manifestTrackIndex, streamElement.type, streamElement.timescale, C.TIME_UNSET, manifest.durationUs, format, Track.TRANSFORMATION_NONE, trackEncryptionBoxes, nalUnitLengthFieldLength, null, null); FragmentedMp4Extractor extractor = new FragmentedMp4Extractor( FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME | FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, null, track); extractorWrappers[i] = new ChunkExtractorWrapper(extractor, format); } }
/** * 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); }
public void loadVideo(){ // CommonTools.showErrorLog("test"+"11111111111"); // CommonTools.showErrorLog("test"+playerPosition); if (player == null){ TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveVideoTrackSelection.Factory(BANDWIDTH_METER); trackSelector = new DefaultTrackSelector(mainHandler, videoTrackSelectionFactory); player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, new DefaultLoadControl(), null, false); player.addListener(this); setPlayer(player); // CommonTools.showErrorLog("test"+"222222222"); if (playerPosition > 0){ // CommonTools.showErrorLog("test"+"3333333333"); player.seekTo(playerPosition); } player.setPlayWhenReady(isAutoPlay); } if (uri == null){ // CommonTools.showToast(getContext(), "请选择一个视频来播放"); return; } MediaSource mediaSource = buildMediaSource(uri, null); player.prepare(mediaSource); }
/** * Blacklists {@code trackSelectionIndex} in {@code trackSelection} for * {@code blacklistDurationMs} if {@code e} is an {@link InvalidResponseCodeException} with * {@link InvalidResponseCodeException#responseCode} equal to 404 or 410. Else does nothing. Note * that blacklisting will fail if the track is the only non-blacklisted track in the selection. * * @param trackSelection The track selection. * @param trackSelectionIndex The index in the selection to consider blacklisting. * @param e The error to inspect. * @param blacklistDurationMs The duration to blacklist the track for, if it is blacklisted. * @return Whether the track was blacklisted. */ public static boolean maybeBlacklistTrack(TrackSelection trackSelection, int trackSelectionIndex, Exception e, long blacklistDurationMs) { if (trackSelection.length() == 1) { // Blacklisting won't ever work if there's only one track in the selection. return false; } if (e instanceof InvalidResponseCodeException) { InvalidResponseCodeException responseCodeException = (InvalidResponseCodeException) e; int responseCode = responseCodeException.responseCode; if (responseCode == 404 || responseCode == 410) { boolean blacklisted = trackSelection.blacklist(trackSelectionIndex, blacklistDurationMs); if (blacklisted) { Log.w(TAG, "Blacklisted: duration=" + blacklistDurationMs + ", responseCode=" + responseCode + ", format=" + trackSelection.getFormat(trackSelectionIndex)); } else { Log.w(TAG, "Blacklisting failed (cannot blacklist last enabled track): responseCode=" + responseCode + ", format=" + trackSelection.getFormat(trackSelectionIndex)); } return blacklisted; } } return false; }
/** * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests. * @param manifest The initial manifest. * @param periodIndex The index of the period in the manifest. * @param adaptationSetIndex The index of the adaptation set in the period. * @param trackSelection The track selection. * @param dataSource A {@link DataSource} suitable for loading the media data. * @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between * server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified * as the server's unix time minus the local elapsed time. If unknown, set to 0. */ public DefaultDashChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, DashManifest manifest, int periodIndex, int adaptationSetIndex, TrackSelection trackSelection, DataSource dataSource, long elapsedRealtimeOffsetMs) { this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.manifest = manifest; this.adaptationSetIndex = adaptationSetIndex; this.trackSelection = trackSelection; this.dataSource = dataSource; this.periodIndex = periodIndex; this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs; long periodDurationUs = manifest.getPeriodDurationUs(periodIndex); List<Representation> representations = getRepresentations(); representationHolders = new RepresentationHolder[trackSelection.length()]; for (int i = 0; i < representationHolders.length; i++) { Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i)); representationHolders[i] = new RepresentationHolder(periodDurationUs, representation); } }
/** * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests. * @param manifest The initial manifest. * @param elementIndex The index of the stream element in the manifest. * @param trackSelection The track selection. * @param dataSource A {@link DataSource} suitable for loading the media data. * @param trackEncryptionBoxes Track encryption boxes for the stream. */ public DefaultSsChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, SsManifest manifest, int elementIndex, TrackSelection trackSelection, DataSource dataSource, TrackEncryptionBox[] trackEncryptionBoxes) { this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.manifest = manifest; this.elementIndex = elementIndex; this.trackSelection = trackSelection; this.dataSource = dataSource; StreamElement streamElement = manifest.streamElements[elementIndex]; extractorWrappers = new ChunkExtractorWrapper[trackSelection.length()]; for (int i = 0; i < extractorWrappers.length; i++) { int manifestTrackIndex = trackSelection.getIndexInTrackGroup(i); Format format = streamElement.formats[manifestTrackIndex]; int nalUnitLengthFieldLength = streamElement.type == C.TRACK_TYPE_VIDEO ? 4 : 0; Track track = new Track(manifestTrackIndex, streamElement.type, streamElement.timescale, C.TIME_UNSET, manifest.durationUs, format, Track.TRANSFORMATION_NONE, trackEncryptionBoxes, nalUnitLengthFieldLength, null, null); FragmentedMp4Extractor extractor = new FragmentedMp4Extractor( FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME | FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, track, null); extractorWrappers[i] = new ChunkExtractorWrapper(extractor, format, false, false); } }
private void initializePlayer() { simpleExoPlayerView.requestFocus(); TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); player = ExoPlayerFactory.newSimpleInstance(this, trackSelector); simpleExoPlayerView.setPlayer(player); MediaSource[] mediaSources = new MediaSource[videos.size()]; for (int i = 0; i < videos.size(); i++) { mediaSources[i] = buildMediaSource(Uri.parse(videos.get(i).videoUrl)); } MediaSource mediaSource = mediaSources.length == 1 ? mediaSources[0] : new ConcatenatingMediaSource(mediaSources); player.prepare(mediaSource); }
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 public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { Assert.assertTrue(preparedPeriod); int rendererCount = selections.length; for (int i = 0; i < rendererCount; i++) { if (streams[i] != null && (selections[i] == null || !mayRetainStreamFlags[i])) { streams[i] = null; } if (streams[i] == null && selections[i] != null) { TrackSelection selection = selections[i]; Assert.assertTrue(1 <= selection.length()); TrackGroup trackGroup = selection.getTrackGroup(); Assert.assertTrue(trackGroupArray.indexOf(trackGroup) != C.INDEX_UNSET); int indexInTrackGroup = selection.getIndexInTrackGroup(selection.getSelectedIndex()); Assert.assertTrue(0 <= indexInTrackGroup); Assert.assertTrue(indexInTrackGroup < trackGroup.length); streams[i] = createSampleStream(selection); streamResetFlags[i] = true; } } return positionUs; }
@Override @SuppressWarnings("unchecked") public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamFlags, SampleStream[] streams, boolean[] streamResetFlags, long positionUs) { long returnPositionUs = super.selectTracks(selections, mayRetainStreamFlags, streams, streamResetFlags, positionUs); List<ChunkSampleStream<FakeChunkSource>> validStreams = new ArrayList<>(); for (SampleStream stream : streams) { if (stream != null) { validStreams.add((ChunkSampleStream<FakeChunkSource>) stream); } } this.sampleStreams = validStreams.toArray(new ChunkSampleStream[validStreams.size()]); this.sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); return returnPositionUs; }
/** * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests. * @param manifest The initial manifest. * @param periodIndex The index of the period in the manifest. * @param adaptationSetIndices The indices of the adaptation sets in the period. * @param trackSelection The track selection. * @param trackType The type of the tracks in the selection. * @param dataSource A {@link DataSource} suitable for loading the media data. * @param elapsedRealtimeOffsetMs If known, an estimate of the instantaneous difference between * server-side unix time and {@link SystemClock#elapsedRealtime()} in milliseconds, specified * as the server's unix time minus the local elapsed time. If unknown, set to 0. * @param maxSegmentsPerLoad The maximum number of segments to combine into a single request. * Note that segments will only be combined if their {@link Uri}s are the same and if their * data ranges are adjacent. * @param enableEventMessageTrack Whether the chunks generated by the source may output an event * message track. * @param enableCea608Track Whether the chunks generated by the source may output a CEA-608 track. */ public DefaultDashChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, DashManifest manifest, int periodIndex, int[] adaptationSetIndices, TrackSelection trackSelection, int trackType, DataSource dataSource, long elapsedRealtimeOffsetMs, int maxSegmentsPerLoad, boolean enableEventMessageTrack, boolean enableCea608Track) { this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.manifest = manifest; this.adaptationSetIndices = adaptationSetIndices; this.trackSelection = trackSelection; this.trackType = trackType; this.dataSource = dataSource; this.periodIndex = periodIndex; this.elapsedRealtimeOffsetMs = elapsedRealtimeOffsetMs; this.maxSegmentsPerLoad = maxSegmentsPerLoad; long periodDurationUs = manifest.getPeriodDurationUs(periodIndex); liveEdgeTimeUs = C.TIME_UNSET; List<Representation> representations = getRepresentations(); representationHolders = new RepresentationHolder[trackSelection.length()]; for (int i = 0; i < representationHolders.length; i++) { Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i)); representationHolders[i] = new RepresentationHolder(periodDurationUs, trackType, representation, enableEventMessageTrack, enableCea608Track); } }
private ChunkSampleStream<DashChunkSource> buildSampleStream(TrackGroupInfo trackGroupInfo, TrackSelection selection, long positionUs) { int embeddedTrackCount = 0; int[] embeddedTrackTypes = new int[2]; boolean enableEventMessageTrack = trackGroupInfo.hasEmbeddedEventMessageTrack; if (enableEventMessageTrack) { embeddedTrackTypes[embeddedTrackCount++] = C.TRACK_TYPE_METADATA; } boolean enableCea608Track = trackGroupInfo.hasEmbeddedCea608Track; if (enableCea608Track) { embeddedTrackTypes[embeddedTrackCount++] = C.TRACK_TYPE_TEXT; } if (embeddedTrackCount < embeddedTrackTypes.length) { embeddedTrackTypes = Arrays.copyOf(embeddedTrackTypes, embeddedTrackCount); } DashChunkSource chunkSource = chunkSourceFactory.createDashChunkSource( manifestLoaderErrorThrower, manifest, periodIndex, trackGroupInfo.adaptationSetIndices, selection, trackGroupInfo.trackType, elapsedRealtimeOffset, enableEventMessageTrack, enableCea608Track); ChunkSampleStream<DashChunkSource> stream = new ChunkSampleStream<>(trackGroupInfo.trackType, embeddedTrackTypes, chunkSource, this, allocator, positionUs, minLoadableRetryCount, eventDispatcher); return stream; }
private static boolean shouldKeepInitialDiscontinuity(TrackSelection[] selections) { // If the clipping start position is non-zero, the clipping sample streams will adjust // timestamps on buffers they read from the unclipped sample streams. These adjusted buffer // timestamps can be negative, because sample streams provide buffers starting at a key-frame, // which may be before the clipping start point. When the renderer reads a buffer with a // negative timestamp, its offset timestamp can jump backwards compared to the last timestamp // read in the previous period. Renderer implementations may not allow this, so we signal a // discontinuity which resets the renderers before they read the clipping sample stream. // However, for audio-only track selections we assume to have random access seek behaviour and // do not need an initial discontinuity to reset the renderer. for (TrackSelection trackSelection : selections) { if (trackSelection != null) { Format selectedFormat = trackSelection.getSelectedFormat(); if (!MimeTypes.isAudio(selectedFormat.sampleMimeType)) { return true; } } } return false; }
/** * @param manifestLoaderErrorThrower Throws errors affecting loading of manifests. * @param manifest The initial manifest. * @param elementIndex The index of the stream element in the manifest. * @param trackSelection The track selection. * @param dataSource A {@link DataSource} suitable for loading the media data. * @param trackEncryptionBoxes Track encryption boxes for the stream. */ public DefaultSsChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, SsManifest manifest, int elementIndex, TrackSelection trackSelection, DataSource dataSource, TrackEncryptionBox[] trackEncryptionBoxes) { this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.manifest = manifest; this.elementIndex = elementIndex; this.trackSelection = trackSelection; this.dataSource = dataSource; StreamElement streamElement = manifest.streamElements[elementIndex]; extractorWrappers = new ChunkExtractorWrapper[trackSelection.length()]; for (int i = 0; i < extractorWrappers.length; i++) { int manifestTrackIndex = trackSelection.getIndexInTrackGroup(i); Format format = streamElement.formats[manifestTrackIndex]; int nalUnitLengthFieldLength = streamElement.type == C.TRACK_TYPE_VIDEO ? 4 : 0; Track track = new Track(manifestTrackIndex, streamElement.type, streamElement.timescale, C.TIME_UNSET, manifest.durationUs, format, Track.TRANSFORMATION_NONE, trackEncryptionBoxes, nalUnitLengthFieldLength, null, null); FragmentedMp4Extractor extractor = new FragmentedMp4Extractor( FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME | FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, null, track, null); extractorWrappers[i] = new ChunkExtractorWrapper(extractor, streamElement.type, format); } }
private void initializePlayer() { BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); mTrackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); mPlayer = ExoPlayerFactory.newSimpleInstance(getActivity(), mTrackSelector); mPlayerAdapter = new LeanbackPlayerAdapter(getActivity(), mPlayer, UPDATE_DELAY); mPlaylistActionListener = new PlaylistActionListener(mPlaylist); mPlayerGlue = new VideoPlayerGlue(getActivity(), mPlayerAdapter, mPlaylistActionListener); mPlayerGlue.setHost(new VideoFragmentGlueHost(this)); mPlayerGlue.playWhenPrepared(); play(mVideo); ArrayObjectAdapter mRowsAdapter = initializeRelatedVideosRow(); setAdapter(mRowsAdapter); }
private void initializePlayer() { if (player == null) { TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveVideoTrackSelection.Factory(BANDWIDTH_METER); trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, new DefaultLoadControl()); player.addListener(this); exoPlayerView.setPlayer(player); if (isTimelineStatic) { if (playerPosition == C.TIME_UNSET) { player.seekToDefaultPosition(playerWindow); } else { player.seekTo(playerWindow, playerPosition); } } audioBecomingNoisyReceiver.setListener(this); setPlayWhenReady(!isPaused); playerNeedsSource = true; } if (playerNeedsSource && srcUri != null) { MediaSource mediaSource = buildMediaSource(srcUri, extension); mediaSource = repeat ? new LoopingMediaSource(mediaSource) : mediaSource; player.prepare(mediaSource, !shouldRestorePosition, true); playerNeedsSource = false; eventEmitter.loadStart(); loadVideoStarted = true; } }
private void updateForCurrentTrackSelections() { if (player == null) { return; } TrackSelectionArray selections = player.getCurrentTrackSelections(); for (int i = 0; i < selections.length; i++) { if (player.getRendererType(i) == C.TRACK_TYPE_VIDEO && selections.get(i) != null) { // Video enabled so artwork must be hidden. If the shutter is closed, it will be opened in // onRenderedFirstFrame(). hideArtwork(); return; } } // Video disabled so the shutter must be closed. if (shutterView != null) { shutterView.setVisibility(VISIBLE); } // Display artwork if enabled and available, else hide it. if (useArtwork) { for (int i = 0; i < selections.length; i++) { TrackSelection selection = selections.get(i); if (selection != null) { for (int j = 0; j < selection.length(); j++) { Metadata metadata = selection.getFormat(j).metadata; if (metadata != null && setArtworkFromMetadata(metadata)) { return; } } } } if (setArtworkFromBitmap(null)) { return; } } // Artwork disabled or unavailable. hideArtwork(); }