/** * @param trackType The type of the track. One of the {@link C} {@code TRACK_TYPE_*} constants. * @param callback A callback for the wrapper. * @param chunkSource A {@link HlsChunkSource} from which chunks to load are obtained. * @param allocator An {@link Allocator} from which to obtain media buffer allocations. * @param positionUs The position from which to start loading media. * @param muxedAudioFormat Optional muxed audio {@link Format} as defined by the master playlist. * @param minLoadableRetryCount The minimum number of times that the source should retry a load * before propagating an error. * @param eventDispatcher A dispatcher to notify of events. */ public HlsSampleStreamWrapper(int trackType, Callback callback, HlsChunkSource chunkSource, Allocator allocator, long positionUs, Format muxedAudioFormat, int minLoadableRetryCount, EventDispatcher eventDispatcher) { this.trackType = trackType; this.callback = callback; this.chunkSource = chunkSource; this.allocator = allocator; this.muxedAudioFormat = muxedAudioFormat; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; loader = new Loader("Loader:HlsSampleStreamWrapper"); nextChunkHolder = new HlsChunkSource.HlsChunkHolder(); sampleQueues = new SparseArray<>(); mediaChunks = new LinkedList<>(); maybeFinishPrepareRunnable = new Runnable() { @Override public void run() { maybeFinishPrepare(); } }; handler = new Handler(); lastSeekPositionUs = positionUs; pendingResetPositionUs = positionUs; }
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; }
public SsMediaPeriod(SsManifest manifest, SsChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, EventDispatcher eventDispatcher, LoaderErrorThrower manifestLoaderErrorThrower, Allocator allocator) { this.chunkSourceFactory = chunkSourceFactory; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; this.allocator = allocator; trackGroups = buildTrackGroups(manifest); ProtectionElement protectionElement = manifest.protectionElement; if (protectionElement != null) { byte[] keyId = getProtectionElementKeyId(protectionElement.data); trackEncryptionBoxes = new TrackEncryptionBox[] { new TrackEncryptionBox(true, INITIALIZATION_VECTOR_SIZE, keyId)}; } else { trackEncryptionBoxes = null; } this.manifest = manifest; sampleStreams = newSampleStreamArray(0); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); }
public HlsMediaPeriod(Uri manifestUri, DataSource.Factory dataSourceFactory, int minLoadableRetryCount, EventDispatcher eventDispatcher, MediaSource.Listener sourceListener, Allocator allocator, long positionUs) { this.manifestUri = manifestUri; this.dataSourceFactory = dataSourceFactory; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; this.sourceListener = sourceListener; this.allocator = allocator; streamWrapperIndices = new IdentityHashMap<>(); timestampAdjusterProvider = new TimestampAdjusterProvider(); manifestParser = new HlsPlaylistParser(); continueLoadingHandler = new Handler(); manifestFetcher = new Loader("Loader:ManifestFetcher"); preparePositionUs = positionUs; continueLoadingRunnable = new Runnable() { @Override public void run() { callback.onContinueLoadingRequested(HlsMediaPeriod.this); } }; }
/** * @param trackType The type of the track. One of the {@link C} {@code TRACK_TYPE_*} constants. * @param callback A callback for the wrapper. * @param chunkSource A {@link HlsChunkSource} from which chunks to load are obtained. * @param allocator An {@link Allocator} from which to obtain media buffer allocations. * @param positionUs The position from which to start loading media. * @param muxedAudioFormat If HLS master playlist indicates that the stream contains muxed audio, * this is the audio {@link Format} as defined by the playlist. * @param muxedCaptionFormat If HLS master playlist indicates that the stream contains muxed * captions, this is the audio {@link Format} as defined by the playlist. * @param minLoadableRetryCount The minimum number of times that the source should retry a load * before propagating an error. * @param eventDispatcher A dispatcher to notify of events. */ public HlsSampleStreamWrapper(int trackType, Callback callback, HlsChunkSource chunkSource, Allocator allocator, long positionUs, Format muxedAudioFormat, Format muxedCaptionFormat, int minLoadableRetryCount, EventDispatcher eventDispatcher) { this.trackType = trackType; this.callback = callback; this.chunkSource = chunkSource; this.allocator = allocator; this.muxedAudioFormat = muxedAudioFormat; this.muxedCaptionFormat = muxedCaptionFormat; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; loader = new Loader("Loader:HlsSampleStreamWrapper"); nextChunkHolder = new HlsChunkSource.HlsChunkHolder(); sampleQueues = new SparseArray<>(); mediaChunks = new LinkedList<>(); maybeFinishPrepareRunnable = new Runnable() { @Override public void run() { maybeFinishPrepare(); } }; handler = new Handler(); lastSeekPositionUs = positionUs; pendingResetPositionUs = positionUs; }
/** * @param trackType The type of the track. One of the {@link C} {@code TRACK_TYPE_*} constants. * @param chunkSource A {@link ChunkSource} from which chunks to load are obtained. * @param callback An {@link Callback} for the stream. * @param allocator An {@link Allocator} from which allocations can be obtained. * @param positionUs The position from which to start loading media. * @param minLoadableRetryCount The minimum number of times that the source should retry a load * before propagating an error. * @param eventDispatcher A dispatcher to notify of events. */ public ChunkSampleStream(int trackType, T chunkSource, SequenceableLoader.Callback<ChunkSampleStream<T>> callback, Allocator allocator, long positionUs, int minLoadableRetryCount, EventDispatcher eventDispatcher) { this.trackType = trackType; this.chunkSource = chunkSource; this.callback = callback; this.eventDispatcher = eventDispatcher; this.minLoadableRetryCount = minLoadableRetryCount; loader = new Loader("Loader:ChunkSampleStream"); nextChunkHolder = new ChunkHolder(); mediaChunks = new LinkedList<>(); readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks); sampleQueue = new DefaultTrackOutput(allocator); lastSeekPositionUs = positionUs; pendingResetPositionUs = positionUs; }
public DashMediaPeriod(int id, DashManifest manifest, int index, DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, EventDispatcher eventDispatcher, long elapsedRealtimeOffset, LoaderErrorThrower manifestLoaderErrorThrower, Allocator allocator) { this.id = id; this.manifest = manifest; this.index = index; 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); period = manifest.getPeriod(index); trackGroups = buildTrackGroups(period); }
/** * @param trackType The type of the track. One of the {@link C} {@code TRACK_TYPE_*} constants. * @param callback A callback for the wrapper. * @param chunkSource A {@link HlsChunkSource} from which chunks to load are obtained. * @param allocator An {@link Allocator} from which to obtain media buffer allocations. * @param positionUs The position from which to start loading media. * @param muxedAudioFormat Optional muxed audio {@link Format} as defined by the master playlist. * @param minLoadableRetryCount The minimum number of times that the source should retry a load * before propagating an error. * @param eventDispatcher A dispatcher to notify of events. */ public HlsSampleStreamWrapper(int trackType, Callback callback, HlsChunkSource chunkSource, Allocator allocator, long positionUs, Format muxedAudioFormat, int minLoadableRetryCount, EventDispatcher eventDispatcher) { this.trackType = trackType; this.callback = callback; this.chunkSource = chunkSource; this.allocator = allocator; this.muxedAudioFormat = muxedAudioFormat; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; loader = new Loader("Loader:HlsSampleStreamWrapper"); nextChunkHolder = new HlsChunkSource.HlsChunkHolder(); sampleQueueTrackIds = new int[0]; sampleQueues = new SampleQueue[0]; mediaChunks = new LinkedList<>(); maybeFinishPrepareRunnable = new Runnable() { @Override public void run() { maybeFinishPrepare(); } }; handler = new Handler(); lastSeekPositionUs = positionUs; pendingResetPositionUs = positionUs; }
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); Pair<TrackGroupArray, TrackGroupInfo[]> result = buildTrackGroups(manifest.getPeriod(periodIndex).adaptationSets); trackGroups = result.first; trackGroupInfos = result.second; }
@Override public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) { int mediaSourceHolderIndex = findMediaSourceHolderByPeriodIndex(id.periodIndex); MediaSourceHolder holder = mediaSourceHolders.get(mediaSourceHolderIndex); MediaPeriodId idInSource = id.copyWithPeriodIndex( id.periodIndex - holder.firstPeriodIndexInChild); MediaPeriod mediaPeriod; if (!holder.isPrepared) { mediaPeriod = new DeferredMediaPeriod(holder.mediaSource, idInSource, allocator); deferredMediaPeriods.add((DeferredMediaPeriod) mediaPeriod); } else { mediaPeriod = holder.mediaSource.createPeriod(idInSource, allocator); } mediaSourceByMediaPeriod.put(mediaPeriod, holder.mediaSource); return mediaPeriod; }
public SsMediaPeriod(SsManifest manifest, SsChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, EventDispatcher eventDispatcher, LoaderErrorThrower manifestLoaderErrorThrower, Allocator allocator) { this.chunkSourceFactory = chunkSourceFactory; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; this.allocator = allocator; trackGroups = buildTrackGroups(manifest); ProtectionElement protectionElement = manifest.protectionElement; if (protectionElement != null) { byte[] keyId = getProtectionElementKeyId(protectionElement.data); // We assume pattern encryption does not apply. trackEncryptionBoxes = new TrackEncryptionBox[] { new TrackEncryptionBox(true, null, INITIALIZATION_VECTOR_SIZE, keyId, 0, 0, null)}; } else { trackEncryptionBoxes = null; } this.manifest = manifest; sampleStreams = newSampleStreamArray(0); sequenceableLoader = new CompositeSequenceableLoader(sampleStreams); }
public HlsMediaPeriod(HlsPlaylistTracker playlistTracker, HlsDataSourceFactory dataSourceFactory, int minLoadableRetryCount, EventDispatcher eventDispatcher, Allocator allocator, long positionUs) { this.playlistTracker = playlistTracker; this.dataSourceFactory = dataSourceFactory; this.minLoadableRetryCount = minLoadableRetryCount; this.eventDispatcher = eventDispatcher; this.allocator = allocator; streamWrapperIndices = new IdentityHashMap<>(); timestampAdjusterProvider = new TimestampAdjusterProvider(); continueLoadingHandler = new Handler(); preparePositionUs = positionUs; }
/** * @param allocator An {@link Allocator} from which allocations for sample data can be obtained. */ public DefaultTrackOutput(Allocator allocator) { this.allocator = allocator; allocationLength = allocator.getIndividualAllocationLength(); infoQueue = new InfoQueue(); dataQueue = new LinkedBlockingDeque<>(); extrasHolder = new BufferExtrasHolder(); scratch = new ParsableByteArray(INITIAL_SCRATCH_SIZE); state = new AtomicInteger(); lastAllocationOffset = allocationLength; }
@Override public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) { ClippingMediaPeriod mediaPeriod = new ClippingMediaPeriod( mediaSource.createPeriod(index, allocator, startUs + positionUs)); mediaPeriods.add(mediaPeriod); mediaPeriod.setClipping(clippingTimeline.startUs, clippingTimeline.endUs); return mediaPeriod; }
/** * @param uri The {@link Uri} of the media stream. * @param dataSource The data source to read the media. * @param extractors The extractors to use to read the data source. * @param minLoadableRetryCount The minimum number of times to retry if a loading error occurs. * @param eventHandler A handler for events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. * @param sourceListener A listener to notify when the timeline has been loaded. * @param allocator An {@link Allocator} from which to obtain media buffer allocations. * @param customCacheKey A custom key that uniquely identifies the original stream. Used for cache * indexing. May be null. */ public ExtractorMediaPeriod(Uri uri, DataSource dataSource, Extractor[] extractors, int minLoadableRetryCount, Handler eventHandler, ExtractorMediaSource.EventListener eventListener, MediaSource.Listener sourceListener, Allocator allocator, String customCacheKey) { this.uri = uri; this.dataSource = dataSource; this.minLoadableRetryCount = minLoadableRetryCount; this.eventHandler = eventHandler; this.eventListener = eventListener; this.sourceListener = sourceListener; this.allocator = allocator; this.customCacheKey = customCacheKey; loader = new Loader("Loader:ExtractorMediaPeriod"); extractorHolder = new ExtractorHolder(extractors, this); loadCondition = new ConditionVariable(); maybeFinishPrepareRunnable = new Runnable() { @Override public void run() { maybeFinishPrepare(); } }; onContinueLoadingRequestedRunnable = new Runnable() { @Override public void run() { if (!released) { callback.onContinueLoadingRequested(ExtractorMediaPeriod.this); } } }; handler = new Handler(); pendingResetPositionUs = C.TIME_UNSET; sampleQueues = new SparseArray<>(); length = C.LENGTH_UNSET; }
@Override public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) { int sourceIndex = timeline.getSourceIndexForPeriod(index); int periodIndexInSource = index - timeline.getFirstPeriodIndexInSource(sourceIndex); MediaPeriod mediaPeriod = mediaSources[sourceIndex].createPeriod(periodIndexInSource, allocator, positionUs); sourceIndexByMediaPeriod.put(mediaPeriod, sourceIndex); return mediaPeriod; }
/** * @param primaryTrackType The type of the primary track. One of the {@link C} * {@code TRACK_TYPE_*} constants. * @param embeddedTrackTypes The types of any embedded tracks, or null. * @param chunkSource A {@link ChunkSource} from which chunks to load are obtained. * @param callback An {@link Callback} for the stream. * @param allocator An {@link Allocator} from which allocations can be obtained. * @param positionUs The position from which to start loading media. * @param minLoadableRetryCount The minimum number of times that the source should retry a load * before propagating an error. * @param eventDispatcher A dispatcher to notify of events. */ public ChunkSampleStream(int primaryTrackType, int[] embeddedTrackTypes, T chunkSource, Callback<ChunkSampleStream<T>> callback, Allocator allocator, long positionUs, int minLoadableRetryCount, EventDispatcher eventDispatcher) { this.primaryTrackType = primaryTrackType; this.embeddedTrackTypes = embeddedTrackTypes; this.chunkSource = chunkSource; this.callback = callback; this.eventDispatcher = eventDispatcher; this.minLoadableRetryCount = minLoadableRetryCount; loader = new Loader("Loader:ChunkSampleStream"); nextChunkHolder = new ChunkHolder(); mediaChunks = new LinkedList<>(); readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks); int embeddedTrackCount = embeddedTrackTypes == null ? 0 : embeddedTrackTypes.length; embeddedSampleQueues = new DefaultTrackOutput[embeddedTrackCount]; embeddedTracksSelected = new boolean[embeddedTrackCount]; int[] trackTypes = new int[1 + embeddedTrackCount]; DefaultTrackOutput[] sampleQueues = new DefaultTrackOutput[1 + embeddedTrackCount]; primarySampleQueue = new DefaultTrackOutput(allocator); trackTypes[0] = primaryTrackType; sampleQueues[0] = primarySampleQueue; for (int i = 0; i < embeddedTrackCount; i++) { DefaultTrackOutput trackOutput = new DefaultTrackOutput(allocator); embeddedSampleQueues[i] = trackOutput; sampleQueues[i + 1] = trackOutput; trackTypes[i + 1] = embeddedTrackTypes[i]; } mediaChunkOutput = new BaseMediaChunkOutput(trackTypes, sampleQueues); pendingResetPositionUs = positionUs; lastSeekPositionUs = positionUs; }
@Override public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) { Assertions.checkArgument(index == 0); return new ExtractorMediaPeriod(uri, dataSourceFactory.createDataSource(), extractorsFactory.createExtractors(), minLoadableRetryCount, eventHandler, eventListener, this, allocator, customCacheKey); }
@Override public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) { MediaPeriod[] periods = new MediaPeriod[mediaSources.length]; for (int i = 0; i < periods.length; i++) { periods[i] = mediaSources[i].createPeriod(index, allocator, positionUs); } return new MergingMediaPeriod(periods); }
/** * @param allocator An {@link Allocator} from which allocations for sample data can be obtained. */ public DefaultTrackOutput(Allocator allocator) { this.allocator = allocator; allocationLength = allocator.getIndividualAllocationLength(); infoQueue = new InfoQueue(); dataQueue = new LinkedBlockingDeque<>(); extrasHolder = new BufferExtrasHolder(); scratch = new ParsableByteArray(INITIAL_SCRATCH_SIZE); state = new AtomicInteger(); lastAllocationOffset = allocationLength; needKeyframe = true; }
@Override public MediaPeriod createPeriod(int periodIndex, Allocator allocator, long positionUs) { EventDispatcher periodEventDispatcher = eventDispatcher.copyWithMediaTimeOffsetMs( manifest.getPeriod(periodIndex).startMs); DashMediaPeriod mediaPeriod = new DashMediaPeriod(firstPeriodId + periodIndex, manifest, periodIndex, chunkSourceFactory, minLoadableRetryCount, periodEventDispatcher, elapsedRealtimeOffsetMs, loaderErrorThrower, allocator); periodsById.put(mediaPeriod.id, mediaPeriod); return mediaPeriod; }
@Override public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) { Assertions.checkArgument(index == 0); SsMediaPeriod period = new SsMediaPeriod(manifest, chunkSourceFactory, minLoadableRetryCount, eventDispatcher, manifestLoaderErrorThrower, allocator); mediaPeriods.add(period); return period; }
/** * @param uri The {@link Uri} of the media stream. * @param dataSource The data source to read the media. * @param extractors The extractors to use to read the data source. * @param minLoadableRetryCount The minimum number of times to retry if a loading error occurs. * @param eventHandler A handler for events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. * @param sourceListener A listener to notify when the timeline has been loaded. * @param allocator An {@link Allocator} from which to obtain media buffer allocations. */ public ExtractorMediaPeriod(Uri uri, DataSource dataSource, Extractor[] extractors, int minLoadableRetryCount, Handler eventHandler, ExtractorMediaSource.EventListener eventListener, MediaSource.Listener sourceListener, Allocator allocator) { this.uri = uri; this.dataSource = dataSource; this.minLoadableRetryCount = minLoadableRetryCount; this.eventHandler = eventHandler; this.eventListener = eventListener; this.sourceListener = sourceListener; this.allocator = allocator; loader = new Loader("Loader:ExtractorMediaPeriod"); extractorHolder = new ExtractorHolder(extractors, this); loadCondition = new ConditionVariable(); maybeFinishPrepareRunnable = new Runnable() { @Override public void run() { maybeFinishPrepare(); } }; onContinueLoadingRequestedRunnable = new Runnable() { @Override public void run() { if (!released) { callback.onContinueLoadingRequested(ExtractorMediaPeriod.this); } } }; handler = new Handler(); pendingResetPositionUs = C.TIME_UNSET; sampleQueues = new SparseArray<>(); length = C.LENGTH_UNSET; }
@Override public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) { Assertions.checkArgument(index == 0); return new ExtractorMediaPeriod(uri, dataSourceFactory.createDataSource(), extractorsFactory.createExtractors(), minLoadableRetryCount, eventHandler, eventListener, this, allocator); }
@Override public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) { DashMediaPeriod mediaPeriod = new DashMediaPeriod(firstPeriodId + index, manifest, index, chunkSourceFactory, minLoadableRetryCount, eventDispatcher, elapsedRealtimeOffsetMs, loader, allocator); periodsById.put(mediaPeriod.id, mediaPeriod); return mediaPeriod; }
@Override public MediaPeriod createPeriod(int index, Allocator allocator, long positionUs) { Assertions.checkArgument(index == 0); SsMediaPeriod period = new SsMediaPeriod(manifest, chunkSourceFactory, minLoadableRetryCount, eventDispatcher, manifestLoader, allocator); mediaPeriods.add(period); return period; }
/** * @param mediaSource The source under test. * @param allocator The allocator to use during the test run. */ public MediaSourceTestRunner(MediaSource mediaSource, Allocator allocator) { this.mediaSource = mediaSource; this.allocator = allocator; playbackThread = new HandlerThread("PlaybackThread"); playbackThread.start(); Looper playbackLooper = playbackThread.getLooper(); playbackHandler = new Handler(playbackLooper); player = new EventHandlingExoPlayer(playbackLooper); mediaSourceListener = new MediaSourceListener(); timelines = new LinkedBlockingDeque<>(); }
@Override protected FakeMediaPeriod createFakeMediaPeriod(MediaPeriodId id, TrackGroupArray trackGroupArray, Allocator allocator) { Period period = timeline.getPeriod(id.periodIndex, new Period()); return new FakeAdaptiveMediaPeriod(trackGroupArray, eventDispatcher, allocator, chunkSourceFactory, period.durationUs); }