mirror of
https://github.com/samsonjs/media.git
synced 2026-03-26 09:35:47 +00:00
Add MediaChunkIterator for FakeAdaptiveDataSet.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=203102464
This commit is contained in:
parent
55ce085a0d
commit
97120bc6cb
3 changed files with 124 additions and 31 deletions
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.source.chunk;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* Base class for {@link MediaChunkIterator}s. Handles {@link #next()} and {@link #isEnded()}, and
|
||||
* provides a bounds check for child classes.
|
||||
*/
|
||||
public abstract class BaseMediaChunkIterator implements MediaChunkIterator {
|
||||
|
||||
private final long fromIndex;
|
||||
private final long toIndex;
|
||||
|
||||
private long currentIndex;
|
||||
|
||||
/**
|
||||
* Creates base iterator.
|
||||
*
|
||||
* @param fromIndex The index at which the iterator will start.
|
||||
* @param toIndex The last available index.
|
||||
*/
|
||||
public BaseMediaChunkIterator(long fromIndex, long toIndex) {
|
||||
this.fromIndex = fromIndex;
|
||||
this.toIndex = toIndex;
|
||||
currentIndex = fromIndex - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnded() {
|
||||
return currentIndex > toIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean next() {
|
||||
currentIndex++;
|
||||
return !isEnded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the iterator points to a valid element.
|
||||
*
|
||||
* @throws NoSuchElementException If the iterator does not point to a valid element.
|
||||
*/
|
||||
protected void checkInBounds() {
|
||||
if (currentIndex < fromIndex || currentIndex > toIndex) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the current index this iterator is pointing to. */
|
||||
protected long getCurrentIndex() {
|
||||
return currentIndex;
|
||||
}
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@ import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
|
|||
import com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor;
|
||||
import com.google.android.exoplayer2.extractor.rawcc.RawCcExtractor;
|
||||
import com.google.android.exoplayer2.source.BehindLiveWindowException;
|
||||
import com.google.android.exoplayer2.source.chunk.BaseMediaChunkIterator;
|
||||
import com.google.android.exoplayer2.source.chunk.Chunk;
|
||||
import com.google.android.exoplayer2.source.chunk.ChunkExtractorWrapper;
|
||||
import com.google.android.exoplayer2.source.chunk.ChunkHolder;
|
||||
|
|
@ -55,7 +56,6 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* A default {@link DashChunkSource} implementation.
|
||||
|
|
@ -509,13 +509,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||
// Protected classes.
|
||||
|
||||
/** {@link MediaChunkIterator} wrapping a {@link RepresentationHolder}. */
|
||||
protected static final class RepresentationSegmentIterator implements MediaChunkIterator {
|
||||
protected static final class RepresentationSegmentIterator extends BaseMediaChunkIterator {
|
||||
|
||||
private final RepresentationHolder representationHolder;
|
||||
private final long firstSegmentNum;
|
||||
private final long lastAvailableSegmentNum;
|
||||
|
||||
private long segmentNum;
|
||||
|
||||
/**
|
||||
* Creates iterator.
|
||||
|
|
@ -526,28 +522,15 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||
*/
|
||||
public RepresentationSegmentIterator(
|
||||
RepresentationHolder representation, long segmentNum, long lastAvailableSegmentNum) {
|
||||
super(/* fromIndex= */ segmentNum, /* toIndex= */ lastAvailableSegmentNum);
|
||||
this.representationHolder = representation;
|
||||
this.firstSegmentNum = segmentNum;
|
||||
this.segmentNum = segmentNum - 1;
|
||||
this.lastAvailableSegmentNum = lastAvailableSegmentNum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnded() {
|
||||
return segmentNum > lastAvailableSegmentNum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean next() {
|
||||
segmentNum++;
|
||||
return segmentNum <= lastAvailableSegmentNum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable DataSpec getDataSpec() {
|
||||
public DataSpec getDataSpec() {
|
||||
checkInBounds();
|
||||
Representation representation = representationHolder.representation;
|
||||
RangedUri segmentUri = representationHolder.getSegmentUrl(segmentNum);
|
||||
RangedUri segmentUri = representationHolder.getSegmentUrl(getCurrentIndex());
|
||||
Uri resolvedUri = segmentUri.resolveUri(representation.baseUrl);
|
||||
String cacheKey = representation.getCacheKey();
|
||||
return new DataSpec(resolvedUri, segmentUri.start, segmentUri.length, cacheKey);
|
||||
|
|
@ -556,19 +539,13 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||
@Override
|
||||
public long getChunkStartTimeUs() {
|
||||
checkInBounds();
|
||||
return representationHolder.getSegmentStartTimeUs(segmentNum);
|
||||
return representationHolder.getSegmentStartTimeUs(getCurrentIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChunkEndTimeUs() {
|
||||
checkInBounds();
|
||||
return representationHolder.getSegmentEndTimeUs(segmentNum);
|
||||
}
|
||||
|
||||
private void checkInBounds() {
|
||||
if (segmentNum < firstSegmentNum || segmentNum > lastAvailableSegmentNum) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
return representationHolder.getSegmentEndTimeUs(getCurrentIndex());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,9 +15,14 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2.testutil;
|
||||
|
||||
import android.net.Uri;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.source.TrackGroup;
|
||||
import com.google.android.exoplayer2.source.chunk.BaseMediaChunkIterator;
|
||||
import com.google.android.exoplayer2.source.chunk.MediaChunkIterator;
|
||||
import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData.Segment;
|
||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
|
|
@ -63,6 +68,49 @@ public final class FakeAdaptiveDataSet extends FakeDataSet {
|
|||
|
||||
}
|
||||
|
||||
/** {@link MediaChunkIterator} for the chunks defined by a fake adaptive data set. */
|
||||
public static final class Iterator extends BaseMediaChunkIterator {
|
||||
|
||||
private final FakeAdaptiveDataSet dataSet;
|
||||
private final int trackGroupIndex;
|
||||
|
||||
/**
|
||||
* Create iterator.
|
||||
*
|
||||
* @param dataSet The data set to iterate over.
|
||||
* @param trackGroupIndex The index of the track group to iterate over.
|
||||
* @param chunkIndex The chunk index to which the iterator points initially.
|
||||
*/
|
||||
public Iterator(FakeAdaptiveDataSet dataSet, int trackGroupIndex, int chunkIndex) {
|
||||
super(/* fromIndex= */ chunkIndex, /* toIndex= */ dataSet.getChunkCount() - 1);
|
||||
this.dataSet = dataSet;
|
||||
this.trackGroupIndex = trackGroupIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSpec getDataSpec() {
|
||||
checkInBounds();
|
||||
String uri = dataSet.getUri(trackGroupIndex);
|
||||
int chunkIndex = (int) getCurrentIndex();
|
||||
Segment fakeDataChunk = dataSet.getData(uri).getSegments().get(chunkIndex);
|
||||
return new DataSpec(
|
||||
Uri.parse(uri), fakeDataChunk.byteOffset, fakeDataChunk.length, /* key= */ null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChunkStartTimeUs() {
|
||||
checkInBounds();
|
||||
return dataSet.getStartTime((int) getCurrentIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChunkEndTimeUs() {
|
||||
checkInBounds();
|
||||
int chunkIndex = (int) getCurrentIndex();
|
||||
return dataSet.getStartTime(chunkIndex) + dataSet.getChunkDuration(chunkIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private final int chunkCount;
|
||||
private final long chunkDurationUs;
|
||||
private final long lastChunkDurationUs;
|
||||
|
|
@ -124,5 +172,4 @@ public final class FakeAdaptiveDataSet extends FakeDataSet {
|
|||
public int getChunkIndexByPosition(long positionUs) {
|
||||
return (int) (positionUs / chunkDurationUs);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue