private Chunk newInitializationChunk(RangedUri initializationUri, RangedUri indexUri, Representation representation, ChunkExtractorWrapper extractor, DataSource dataSource, int trigger) { RangedUri requestUri; if (initializationUri != null) { // It's common for initialization and index data to be stored adjacently. Attempt to merge // the two requests together to request both at once. requestUri = initializationUri.attemptMerge(indexUri); if (requestUri == null) { requestUri = initializationUri; } } else { requestUri = indexUri; } DataSpec dataSpec = new DataSpec(requestUri.getUri(), requestUri.start, requestUri.length, representation.getCacheKey()); return new InitializationChunk(dataSource, dataSpec, trigger, representation.format, extractor); }
private Chunk newInitializationChunk(RangedUri initializationUri, RangedUri indexUri, Representation representation, ChunkExtractorWrapper extractor, DataSource dataSource, int manifestIndex, int trigger) { RangedUri requestUri; if (initializationUri != null) { // It's common for initialization and index data to be stored adjacently. Attempt to merge // the two requests together to request both at once. requestUri = initializationUri.attemptMerge(indexUri); if (requestUri == null) { requestUri = initializationUri; } } else { requestUri = indexUri; } DataSpec dataSpec = new DataSpec(requestUri.getUri(), requestUri.start, requestUri.length, representation.getCacheKey()); return new InitializationChunk(dataSource, dataSpec, trigger, representation.format, extractor, manifestIndex); }
private void loadDrmInitData(Representation representation) throws IOException { Uri initFile = representation.getInitializationUri().getUri(); FileDataSource initChunkSource = new FileDataSource(); DataSpec initDataSpec = new DataSpec(initFile); int trigger = 2; ChunkExtractorWrapper extractorWrapper = new ChunkExtractorWrapper(new FragmentedMp4Extractor()); InitializationChunk chunk = new InitializationChunk(initChunkSource, initDataSpec, trigger, format, extractorWrapper); try { chunk.load(); } catch (InterruptedException e) { Log.d(TAG, "Interrupted!", e); } if (!chunk.isLoadCanceled()) { drmInitData = chunk.getDrmInitData(); } if (drmInitData != null) { DrmInitData.SchemeInitData schemeInitData = OfflineDrmManager.getWidevineInitData(drmInitData); if (schemeInitData != null) { widevineInitData = schemeInitData.data; } } }
private static MediaChunk newMediaChunk(Format formatInfo, Uri uri, String cacheKey, ChunkExtractorWrapper extractorWrapper, DrmInitData drmInitData, DataSource dataSource, int chunkIndex, boolean isLast, long chunkStartTimeUs, long chunkEndTimeUs, int trigger, MediaFormat mediaFormat) { long offset = 0; DataSpec dataSpec = new DataSpec(uri, offset, -1, cacheKey); // In SmoothStreaming each chunk contains sample timestamps relative to the start of the chunk. // To convert them the absolute timestamps, we need to set sampleOffsetUs to -chunkStartTimeUs. return new ContainerMediaChunk(dataSource, dataSpec, trigger, formatInfo, chunkStartTimeUs, chunkEndTimeUs, chunkIndex, isLast, chunkStartTimeUs, extractorWrapper, mediaFormat, drmInitData, true); }
public RepresentationHolder(long periodStartTimeUs, long periodDurationUs, Representation representation) { this.periodStartTimeUs = periodStartTimeUs; this.periodDurationUs = periodDurationUs; this.representation = representation; String mimeType = representation.format.mimeType; mimeTypeIsRawText = mimeTypeIsRawText(mimeType); extractorWrapper = mimeTypeIsRawText ? null : new ChunkExtractorWrapper( mimeTypeIsWebm(mimeType) ? new WebmExtractor() : new FragmentedMp4Extractor()); segmentIndex = representation.getIndex(); }
private static MediaChunk newMediaChunk(Format formatInfo, Uri uri, String cacheKey, ChunkExtractorWrapper extractorWrapper, DrmInitData drmInitData, DataSource dataSource, int chunkIndex, long chunkStartTimeUs, long chunkEndTimeUs, int trigger, MediaFormat mediaFormat, int adaptiveMaxWidth, int adaptiveMaxHeight) { long offset = 0; DataSpec dataSpec = new DataSpec(uri, offset, -1, cacheKey); // In SmoothStreaming each chunk contains sample timestamps relative to the start of the chunk. // To convert them the absolute timestamps, we need to set sampleOffsetUs to -chunkStartTimeUs. return new ContainerMediaChunk(dataSource, dataSpec, trigger, formatInfo, chunkStartTimeUs, chunkEndTimeUs, chunkIndex, chunkStartTimeUs, extractorWrapper, mediaFormat, adaptiveMaxWidth, adaptiveMaxHeight, drmInitData, true, Chunk.NO_PARENT_ID); }
DashChunkSource(ManifestFetcher<MediaPresentationDescription> manifestFetcher, MediaPresentationDescription initialManifest, int adaptationSetIndex, int[] representationIndices, DataSource dataSource, FormatEvaluator formatEvaluator, Clock systemClock, long liveEdgeLatencyUs, long elapsedRealtimeOffsetUs, boolean startAtLiveEdge, Handler eventHandler, EventListener eventListener) { this.manifestFetcher = manifestFetcher; this.currentManifest = initialManifest; this.adaptationSetIndex = adaptationSetIndex; this.representationIndices = representationIndices; this.dataSource = dataSource; this.formatEvaluator = formatEvaluator; this.systemClock = systemClock; this.liveEdgeLatencyUs = liveEdgeLatencyUs; this.elapsedRealtimeOffsetUs = elapsedRealtimeOffsetUs; this.startAtLiveEdge = startAtLiveEdge; this.eventHandler = eventHandler; this.eventListener = eventListener; this.evaluation = new Evaluation(); this.headerBuilder = new StringBuilder(); this.seekRangeValues = new long[2]; drmInitData = getDrmInitData(currentManifest, adaptationSetIndex); Representation[] representations = getFilteredRepresentations(currentManifest, adaptationSetIndex, representationIndices); long periodDurationUs = (representations[0].periodDurationMs == TrackRenderer.UNKNOWN_TIME_US) ? TrackRenderer.UNKNOWN_TIME_US : representations[0].periodDurationMs * 1000; this.trackInfo = new TrackInfo(representations[0].format.mimeType, periodDurationUs); this.formats = new Format[representations.length]; this.representationHolders = new HashMap<>(); int maxWidth = 0; int maxHeight = 0; for (int i = 0; i < representations.length; i++) { formats[i] = representations[i].format; maxWidth = Math.max(formats[i].width, maxWidth); maxHeight = Math.max(formats[i].height, maxHeight); Extractor extractor = mimeTypeIsWebm(formats[i].mimeType) ? new WebmExtractor() : new FragmentedMp4Extractor(); representationHolders.put(formats[i].id, new RepresentationHolder(representations[i], new ChunkExtractorWrapper(extractor))); } this.maxWidth = maxWidth; this.maxHeight = maxHeight; Arrays.sort(formats, new DecreasingBandwidthComparator()); }
public RepresentationHolder(Representation representation, ChunkExtractorWrapper extractorWrapper) { this.representation = representation; this.extractorWrapper = extractorWrapper; this.segmentIndex = representation.getIndex(); }
private SmoothStreamingChunkSource(ManifestFetcher<SmoothStreamingManifest> manifestFetcher, SmoothStreamingManifest initialManifest, int streamElementIndex, int[] trackIndices, DataSource dataSource, FormatEvaluator formatEvaluator, long liveEdgeLatencyMs) { this.manifestFetcher = manifestFetcher; this.streamElementIndex = streamElementIndex; this.currentManifest = initialManifest; this.dataSource = dataSource; this.formatEvaluator = formatEvaluator; this.liveEdgeLatencyUs = liveEdgeLatencyMs * 1000; StreamElement streamElement = getElement(initialManifest); trackInfo = new TrackInfo(streamElement.tracks[0].format.mimeType, initialManifest.durationUs); evaluation = new Evaluation(); TrackEncryptionBox[] trackEncryptionBoxes = null; ProtectionElement protectionElement = initialManifest.protectionElement; if (protectionElement != null) { byte[] keyId = getKeyId(protectionElement.data); trackEncryptionBoxes = new TrackEncryptionBox[1]; trackEncryptionBoxes[0] = new TrackEncryptionBox(true, INITIALIZATION_VECTOR_SIZE, keyId); DrmInitData.Mapped drmInitData = new DrmInitData.Mapped(MimeTypes.VIDEO_MP4); drmInitData.put(protectionElement.uuid, protectionElement.data); this.drmInitData = drmInitData; } else { drmInitData = null; } int trackCount = trackIndices != null ? trackIndices.length : streamElement.tracks.length; formats = new Format[trackCount]; extractorWrappers = new SparseArray<>(); mediaFormats = new SparseArray<>(); int maxWidth = 0; int maxHeight = 0; for (int i = 0; i < trackCount; i++) { int trackIndex = trackIndices != null ? trackIndices[i] : i; formats[i] = streamElement.tracks[trackIndex].format; maxWidth = Math.max(maxWidth, formats[i].width); maxHeight = Math.max(maxHeight, formats[i].height); MediaFormat mediaFormat = getMediaFormat(streamElement, trackIndex); int trackType = streamElement.type == StreamElement.TYPE_VIDEO ? Track.TYPE_VIDEO : Track.TYPE_AUDIO; FragmentedMp4Extractor extractor = new FragmentedMp4Extractor( FragmentedMp4Extractor.WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME); extractor.setTrack(new Track(trackIndex, trackType, streamElement.timescale, initialManifest.durationUs, mediaFormat, trackEncryptionBoxes, trackType == Track.TYPE_VIDEO ? 4 : -1)); extractorWrappers.put(trackIndex, new ChunkExtractorWrapper(extractor)); mediaFormats.put(trackIndex, mediaFormat); } this.maxWidth = maxWidth; this.maxHeight = maxHeight; Arrays.sort(formats, new DecreasingBandwidthComparator()); }