Add MediaChunkIterator for FakeAdaptiveDataSet.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=203102464
This commit is contained in:
tonihei 2018-07-03 04:39:09 -07:00 committed by Oliver Woodman
parent 55ce085a0d
commit 97120bc6cb
3 changed files with 124 additions and 31 deletions

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -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);
}
}