public void testSegmentIndexInitializationOnVod() { DashChunkSource chunkSource = new DashChunkSource(buildVodMpd(), DefaultDashTrackSelector.newVideoInstance(null, false, false), mock(DataSource.class), null); chunkSource.prepare(); chunkSource.enable(0); List<MediaChunk> queue = new ArrayList<>(); ChunkOperationHolder out = new ChunkOperationHolder(); // request first chunk; should get back initialization chunk chunkSource.getChunkOperation(queue, 0, out); assertNotNull(out.chunk); assertNotNull(((InitializationChunk) out.chunk).dataSpec); }
public HlsSampleSource(HlsChunkSource chunkSource, LoadControl loadControl, int bufferSizeContribution, Handler eventHandler, EventListener eventListener, int eventSourceId, int minLoadableRetryCount) { this.chunkSource = chunkSource; this.loadControl = loadControl; this.bufferSizeContribution = bufferSizeContribution; this.minLoadableRetryCount = minLoadableRetryCount; this.eventHandler = eventHandler; this.eventListener = eventListener; this.eventSourceId = eventSourceId; this.pendingResetPositionUs = NO_RESET_PENDING; extractors = new LinkedList<>(); chunkOperationHolder = new ChunkOperationHolder(); }
private static void checkLiveEdgeConsistency(MediaPresentationDescription mpd, long liveEdgeLatencyMs, long seekPositionMs, long availableRangeStartMs, long availableRangeEndMs, long chunkStartTimeMs, long chunkEndTimeMs) { DashChunkSource chunkSource = buildDashChunkSource(mpd, true, liveEdgeLatencyMs); List<MediaChunk> queue = new ArrayList<>(); ChunkOperationHolder out = new ChunkOperationHolder(); checkLiveEdgeConsistency(chunkSource, queue, out, seekPositionMs, availableRangeStartMs, availableRangeEndMs, chunkStartTimeMs, chunkEndTimeMs); }
private static void checkLiveEdgeConsistency(DashChunkSource chunkSource, List<MediaChunk> queue, ChunkOperationHolder out, long seekPositionMs, long availableRangeStartMs, long availableRangeEndMs, long chunkStartTimeMs, long chunkEndTimeMs) { chunkSource.getChunkOperation(queue, seekPositionMs * 1000, out); TimeRange availableRange = chunkSource.getAvailableRange(); checkAvailableRange(availableRange, availableRangeStartMs * 1000, availableRangeEndMs * 1000); if (chunkStartTimeMs < availableRangeEndMs) { assertNotNull(out.chunk); assertEquals(chunkStartTimeMs * 1000, ((MediaChunk) out.chunk).startTimeUs); assertEquals(chunkEndTimeMs * 1000, ((MediaChunk) out.chunk).endTimeUs); } else { assertNull(out.chunk); } }
@Override public final void getChunkOperation(List<? extends MediaChunk> queue, long seekPositionUs, long playbackPositionUs, ChunkOperationHolder out) { evaluation.queueSize = queue.size(); formatEvaluator.evaluate(queue, playbackPositionUs, formats, evaluation); SmoothStreamingFormat selectedFormat = (SmoothStreamingFormat) evaluation.format; out.queueSize = evaluation.queueSize; if (selectedFormat == null) { out.chunk = null; return; } else if (out.queueSize == queue.size() && out.chunk != null && out.chunk.format.id.equals(evaluation.format.id)) { // We already have a chunk, and the evaluation hasn't changed either the format or the size // of the queue. Do nothing. return; } int nextChunkIndex; if (queue.isEmpty()) { nextChunkIndex = streamElement.getChunkIndex(seekPositionUs); } else { nextChunkIndex = queue.get(out.queueSize - 1).nextChunkIndex; } if (nextChunkIndex == -1) { out.chunk = null; return; } boolean isLastChunk = nextChunkIndex == streamElement.chunkCount - 1; String requestUrl = streamElement.buildRequestUrl(selectedFormat.trackIndex, nextChunkIndex); Uri uri = Uri.parse(baseUrl + '/' + requestUrl); Chunk mediaChunk = newMediaChunk(selectedFormat, uri, null, extractors.get(Integer.parseInt(selectedFormat.id)), dataSource, nextChunkIndex, isLastChunk, streamElement.getStartTimeUs(nextChunkIndex), isLastChunk ? -1 : streamElement.getStartTimeUs(nextChunkIndex + 1), 0); out.chunk = mediaChunk; }
private void checkLiveEdgeLatency(DashChunkSource chunkSource, List<MediaChunk> queue, ChunkOperationHolder out, long seekPositionMs, long seekRangeStartMs, long seekRangeEndMs, long chunkStartTimeMs, long chunkEndTimeMs) { chunkSource.getChunkOperation(queue, seekPositionMs * 1000, 0, out); TimeRange seekRange = chunkSource.getSeekRange(); assertNotNull(out.chunk); checkSeekRange(seekRange, seekRangeStartMs * 1000, seekRangeEndMs * 1000); assertEquals(chunkStartTimeMs * 1000, ((MediaChunk) out.chunk).startTimeUs); assertEquals(chunkEndTimeMs * 1000, ((MediaChunk) out.chunk).endTimeUs); }
private void checkLiveEdgeLatency(MediaPresentationDescription mpd, long periodStartMs, long liveEdgeLatencyMs, long seekPositionMs, long seekRangeStartMs, long seekRangeEndMs, long chunkStartTimeMs, long chunkEndTimeMs) { DashChunkSource chunkSource = setupDashChunkSource(mpd, periodStartMs, liveEdgeLatencyMs); List<MediaChunk> queue = new ArrayList<>(); ChunkOperationHolder out = new ChunkOperationHolder(); checkLiveEdgeLatency(chunkSource, queue, out, seekPositionMs, seekRangeStartMs, seekRangeEndMs, chunkStartTimeMs, chunkEndTimeMs); }
@Override public final void getChunkOperation(List<? extends MediaChunk> queue, long seekPositionUs, long playbackPositionUs, ChunkOperationHolder out) { evaluation.queueSize = queue.size(); if (evaluation.format == null || !lastChunkWasInitialization) { evaluator.evaluate(queue, playbackPositionUs, formats, evaluation); } Format selectedFormat = evaluation.format; out.queueSize = evaluation.queueSize; if (selectedFormat == null) { out.chunk = null; return; } else if (out.queueSize == queue.size() && out.chunk != null && out.chunk.format.id.equals(selectedFormat.id)) { // We already have a chunk, and the evaluation hasn't changed either the format or the size // of the queue. Leave unchanged. return; } Representation selectedRepresentation = representations.get(selectedFormat.id); Extractor extractor = extractors.get(selectedRepresentation.format.id); RangedUri pendingInitializationUri = null; RangedUri pendingIndexUri = null; if (extractor.getFormat() == null) { pendingInitializationUri = selectedRepresentation.getInitializationUri(); } if (!segmentIndexes.containsKey(selectedRepresentation.format.id)) { pendingIndexUri = selectedRepresentation.getIndexUri(); } if (pendingInitializationUri != null || pendingIndexUri != null) { // We have initialization and/or index requests to make. Chunk initializationChunk = newInitializationChunk(pendingInitializationUri, pendingIndexUri, selectedRepresentation, extractor, dataSource, evaluation.trigger); lastChunkWasInitialization = true; out.chunk = initializationChunk; return; } int nextSegmentNum; DashSegmentIndex segmentIndex = segmentIndexes.get(selectedRepresentation.format.id); if (queue.isEmpty()) { nextSegmentNum = segmentIndex.getSegmentNum(seekPositionUs); } else { nextSegmentNum = queue.get(out.queueSize - 1).nextChunkIndex; } if (nextSegmentNum == -1) { out.chunk = null; return; } Chunk nextMediaChunk = newMediaChunk(selectedRepresentation, segmentIndex, extractor, dataSource, nextSegmentNum, evaluation.trigger); lastChunkWasInitialization = false; out.chunk = nextMediaChunk; }