mirror of
https://github.com/samsonjs/media.git
synced 2026-04-01 10:35:48 +00:00
Propagate format information through RollingSampleBuffer.
At this point the only reason preventing the chunk package from using RollingSampleBuffer directly, rather than DefaultTrackOutput, is that the latter maintains the largest parsed timestamp. This will be pushed inside the former in the next CL. Following that, splicing logic will also be pushed inside of RollingSampleBuffer, and HLS will be moved over to using a single RollingSampleBuffer per track, with the splicing done inline. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=120206658
This commit is contained in:
parent
febf86c54e
commit
5ce210e374
11 changed files with 98 additions and 112 deletions
|
|
@ -28,13 +28,6 @@ import com.google.android.exoplayer.upstream.DataSpec;
|
|||
*/
|
||||
public abstract class BaseMediaChunk extends MediaChunk {
|
||||
|
||||
/**
|
||||
* Whether {@link #getSampleFormat()} and {@link #getDrmInitData()} can be called at any time to
|
||||
* obtain the chunk's sample format and drm initialization data. If false, these methods are only
|
||||
* guaranteed to return correct data after the first sample data has been output from the chunk.
|
||||
*/
|
||||
public final boolean isSampleFormatFinal;
|
||||
|
||||
private DefaultTrackOutput trackOutput;
|
||||
private int firstSampleIndex;
|
||||
|
||||
|
|
@ -46,15 +39,10 @@ public abstract class BaseMediaChunk extends MediaChunk {
|
|||
* @param startTimeUs The start time of the media contained by the chunk, in microseconds.
|
||||
* @param endTimeUs The end time of the media contained by the chunk, in microseconds.
|
||||
* @param chunkIndex The index of the chunk.
|
||||
* @param isSampleFormatFinal True if {@link #getSampleFormat()} and {@link #getDrmInitData()} can
|
||||
* be called at any time to obtain the sample format and drm initialization data. False if
|
||||
* these methods are only guaranteed to return correct data after the first sample data has
|
||||
* been output from the chunk.
|
||||
*/
|
||||
public BaseMediaChunk(DataSource dataSource, DataSpec dataSpec, int trigger, Format format,
|
||||
long startTimeUs, long endTimeUs, int chunkIndex, boolean isSampleFormatFinal) {
|
||||
long startTimeUs, long endTimeUs, int chunkIndex) {
|
||||
super(dataSource, dataSpec, trigger, format, startTimeUs, endTimeUs, chunkIndex);
|
||||
this.isSampleFormatFinal = isSampleFormatFinal;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -76,21 +64,8 @@ public abstract class BaseMediaChunk extends MediaChunk {
|
|||
return firstSampleIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Format} of the samples in the chunk.
|
||||
* <p>
|
||||
* See {@link #isSampleFormatFinal} for information about when this method is guaranteed to return
|
||||
* correct data.
|
||||
*
|
||||
* @return The {@link Format} of the samples in the chunk.
|
||||
*/
|
||||
public abstract Format getSampleFormat();
|
||||
|
||||
/**
|
||||
* Gets the {@link DrmInitData} corresponding to the chunk.
|
||||
* <p>
|
||||
* See {@link #isSampleFormatFinal} for information about when this method is guaranteed to return
|
||||
* correct data.
|
||||
*
|
||||
* @return The {@link DrmInitData} corresponding to this chunk.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -50,11 +50,6 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput
|
|||
*/
|
||||
void drmInitData(DrmInitData drmInitData);
|
||||
|
||||
/**
|
||||
* @see TrackOutput#format(Format)
|
||||
*/
|
||||
void format(Format format);
|
||||
|
||||
}
|
||||
|
||||
private final Extractor extractor;
|
||||
|
|
@ -132,8 +127,7 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput
|
|||
|
||||
@Override
|
||||
public void format(Format format) {
|
||||
// Redirect the format to the metadata output. The track output doesn't need it.
|
||||
metadataOutput.format(format);
|
||||
trackOutput.format(format);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -300,14 +300,12 @@ public class ChunkSampleSource implements SampleSource, TrackStream, Loader.Call
|
|||
downstreamFormat = currentChunk.format;
|
||||
}
|
||||
|
||||
if (haveSamples || currentChunk.isSampleFormatFinal) {
|
||||
Format sampleFormat = currentChunk.getSampleFormat();
|
||||
if (!sampleFormat.equals(downstreamSampleFormat)) {
|
||||
formatHolder.format = sampleFormat;
|
||||
formatHolder.drmInitData = currentChunk.getDrmInitData();
|
||||
downstreamSampleFormat = sampleFormat;
|
||||
return FORMAT_READ;
|
||||
}
|
||||
Format sampleFormat = sampleQueue.getDownstreamFormat();
|
||||
if (sampleFormat != null && !sampleFormat.equals(downstreamSampleFormat)) {
|
||||
formatHolder.format = sampleFormat;
|
||||
formatHolder.drmInitData = currentChunk.getDrmInitData();
|
||||
downstreamSampleFormat = sampleFormat;
|
||||
return FORMAT_READ;
|
||||
}
|
||||
|
||||
if (!haveSamples) {
|
||||
|
|
|
|||
|
|
@ -60,11 +60,10 @@ public class ContainerMediaChunk extends BaseMediaChunk implements SingleTrackMe
|
|||
public ContainerMediaChunk(DataSource dataSource, DataSpec dataSpec, int trigger, Format format,
|
||||
long startTimeUs, long endTimeUs, int chunkIndex, long sampleOffsetUs,
|
||||
ChunkExtractorWrapper extractorWrapper, Format sampleFormat, DrmInitData drmInitData) {
|
||||
super(dataSource, dataSpec, trigger, format, startTimeUs, endTimeUs, chunkIndex,
|
||||
sampleFormat != null);
|
||||
super(dataSource, dataSpec, trigger, format, startTimeUs, endTimeUs, chunkIndex);
|
||||
this.extractorWrapper = extractorWrapper;
|
||||
this.sampleOffsetUs = sampleOffsetUs;
|
||||
this.sampleFormat = getAdjustedSampleFormat(sampleFormat, sampleOffsetUs);
|
||||
this.sampleFormat = sampleFormat;
|
||||
this.drmInitData = drmInitData;
|
||||
}
|
||||
|
||||
|
|
@ -73,11 +72,6 @@ public class ContainerMediaChunk extends BaseMediaChunk implements SingleTrackMe
|
|||
return bytesLoaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Format getSampleFormat() {
|
||||
return sampleFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DrmInitData getDrmInitData() {
|
||||
return drmInitData;
|
||||
|
|
@ -95,11 +89,6 @@ public class ContainerMediaChunk extends BaseMediaChunk implements SingleTrackMe
|
|||
this.drmInitData = drmInitData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void format(Format format) {
|
||||
this.sampleFormat = getAdjustedSampleFormat(format, sampleOffsetUs);
|
||||
}
|
||||
|
||||
// Loadable implementation.
|
||||
|
||||
@Override
|
||||
|
|
@ -123,7 +112,7 @@ public class ContainerMediaChunk extends BaseMediaChunk implements SingleTrackMe
|
|||
if (bytesLoaded == 0) {
|
||||
// Set the target to ourselves.
|
||||
DefaultTrackOutput trackOutput = getTrackOutput();
|
||||
trackOutput.setSampleOffsetUs(sampleOffsetUs);
|
||||
trackOutput.formatWithOffset(sampleFormat, sampleOffsetUs);
|
||||
extractorWrapper.init(this, trackOutput);
|
||||
}
|
||||
// Load and parse the sample data.
|
||||
|
|
@ -140,16 +129,4 @@ public class ContainerMediaChunk extends BaseMediaChunk implements SingleTrackMe
|
|||
}
|
||||
}
|
||||
|
||||
// Private methods.
|
||||
|
||||
private static Format getAdjustedSampleFormat(Format format, long sampleOffsetUs) {
|
||||
if (format == null) {
|
||||
return null;
|
||||
}
|
||||
if (sampleOffsetUs != 0 && format.subsampleOffsetUs != Format.OFFSET_SAMPLE_RELATIVE) {
|
||||
format = format.copyWithSubsampleOffsetUs(format.subsampleOffsetUs + sampleOffsetUs);
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,15 +86,6 @@ public final class InitializationChunk extends Chunk implements SingleTrackMetad
|
|||
return drmInitData;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if a {@link SeekMap} was parsed from the chunk. False otherwise.
|
||||
* <p>
|
||||
* Should be called after loading has completed.
|
||||
*/
|
||||
public boolean hasSeekMap() {
|
||||
return seekMap != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link SeekMap} parsed from the chunk, or null.
|
||||
* <p>
|
||||
|
|
@ -116,13 +107,13 @@ public final class InitializationChunk extends Chunk implements SingleTrackMetad
|
|||
this.drmInitData = drmInitData;
|
||||
}
|
||||
|
||||
// TrackOutput implementation.
|
||||
|
||||
@Override
|
||||
public void format(Format format) {
|
||||
this.sampleFormat = format;
|
||||
}
|
||||
|
||||
// TrackOutput implementation.
|
||||
|
||||
@Override
|
||||
public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput)
|
||||
throws IOException, InterruptedException {
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ import com.google.android.exoplayer.C;
|
|||
import com.google.android.exoplayer.Format;
|
||||
import com.google.android.exoplayer.drm.DrmInitData;
|
||||
import com.google.android.exoplayer.extractor.DefaultExtractorInput;
|
||||
import com.google.android.exoplayer.extractor.DefaultTrackOutput;
|
||||
import com.google.android.exoplayer.extractor.ExtractorInput;
|
||||
import com.google.android.exoplayer.extractor.TrackOutput;
|
||||
import com.google.android.exoplayer.upstream.DataSource;
|
||||
import com.google.android.exoplayer.upstream.DataSpec;
|
||||
import com.google.android.exoplayer.util.Util;
|
||||
|
|
@ -53,7 +53,7 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
|
|||
public SingleSampleMediaChunk(DataSource dataSource, DataSpec dataSpec, int trigger,
|
||||
Format format, long startTimeUs, long endTimeUs, int chunkIndex, Format sampleFormat,
|
||||
DrmInitData sampleDrmInitData) {
|
||||
super(dataSource, dataSpec, trigger, format, startTimeUs, endTimeUs, chunkIndex, true);
|
||||
super(dataSource, dataSpec, trigger, format, startTimeUs, endTimeUs, chunkIndex);
|
||||
this.sampleFormat = sampleFormat;
|
||||
this.sampleDrmInitData = sampleDrmInitData;
|
||||
}
|
||||
|
|
@ -63,11 +63,6 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
|
|||
return bytesLoaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Format getSampleFormat() {
|
||||
return sampleFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DrmInitData getDrmInitData() {
|
||||
return sampleDrmInitData;
|
||||
|
|
@ -96,7 +91,8 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
|
|||
length += bytesLoaded;
|
||||
}
|
||||
ExtractorInput extractorInput = new DefaultExtractorInput(dataSource, bytesLoaded, length);
|
||||
TrackOutput trackOutput = getTrackOutput();
|
||||
DefaultTrackOutput trackOutput = getTrackOutput();
|
||||
trackOutput.formatWithOffset(sampleFormat, 0);
|
||||
// Load the sample data.
|
||||
int result = 0;
|
||||
while (result != C.RESULT_END_OF_INPUT) {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import com.google.android.exoplayer.dash.mpd.RangedUri;
|
|||
import com.google.android.exoplayer.dash.mpd.Representation;
|
||||
import com.google.android.exoplayer.drm.DrmInitData;
|
||||
import com.google.android.exoplayer.extractor.ChunkIndex;
|
||||
import com.google.android.exoplayer.extractor.SeekMap;
|
||||
import com.google.android.exoplayer.extractor.mkv.MatroskaExtractor;
|
||||
import com.google.android.exoplayer.extractor.mp4.FragmentedMp4Extractor;
|
||||
import com.google.android.exoplayer.upstream.DataSource;
|
||||
|
|
@ -296,10 +297,12 @@ public class DashChunkSource implements ChunkSource {
|
|||
// The null check avoids overwriting an index obtained from the manifest with one obtained
|
||||
// from the stream. If the manifest defines an index then the stream shouldn't, but in cases
|
||||
// where it does we should ignore it.
|
||||
if (representationHolder.segmentIndex == null && initializationChunk.hasSeekMap()) {
|
||||
representationHolder.segmentIndex = new DashWrappingSegmentIndex(
|
||||
(ChunkIndex) initializationChunk.getSeekMap(),
|
||||
initializationChunk.dataSpec.uri.toString());
|
||||
if (representationHolder.segmentIndex == null) {
|
||||
SeekMap seekMap = initializationChunk.getSeekMap();
|
||||
if (seekMap != null) {
|
||||
representationHolder.segmentIndex = new DashWrappingSegmentIndex((ChunkIndex) seekMap,
|
||||
initializationChunk.dataSpec.uri.toString());
|
||||
}
|
||||
}
|
||||
// The null check avoids overwriting drmInitData obtained from the manifest with drmInitData
|
||||
// obtained from the stream, as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
|
||||
|
|
|
|||
|
|
@ -92,12 +92,19 @@ public final class DefaultTrackOutput implements TrackOutput {
|
|||
}
|
||||
|
||||
/**
|
||||
* The format most recently received by the output, or null if a format has yet to be received.
|
||||
* Returns the current upstream {@link Format}.
|
||||
*/
|
||||
public Format getFormat() {
|
||||
public Format getUpstreamFormat() {
|
||||
return rollingBuffer.getUpstreamFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current downstream {@link Format}.
|
||||
*/
|
||||
public Format getDownstreamFormat() {
|
||||
return rollingBuffer.getDownstreamFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
* The largest timestamp of any sample received by the output, or {@link Long#MIN_VALUE} if a
|
||||
* sample has yet to be received.
|
||||
|
|
@ -210,13 +217,16 @@ public final class DefaultTrackOutput implements TrackOutput {
|
|||
// Called by the loading thread.
|
||||
|
||||
/**
|
||||
* Sets an offset that will be added to the timestamps passed to
|
||||
* {@link #sampleMetadata(long, int, int, int, byte[])}.
|
||||
* Like {@link #format(Format)}, but with an offset that will be added to the timestamps of
|
||||
* samples subsequently queued to the buffer. The offset is also used to adjust
|
||||
* {@link Format#subsampleOffsetUs} for both the {@link Format} passed and those subsequently
|
||||
* passed to {@link #format(Format)}.
|
||||
*
|
||||
* @param format The format.
|
||||
* @param sampleOffsetUs The offset in microseconds.
|
||||
*/
|
||||
public void setSampleOffsetUs(long sampleOffsetUs) {
|
||||
rollingBuffer.setSampleOffsetUs(sampleOffsetUs);
|
||||
public void formatWithOffset(Format format, long sampleOffsetUs) {
|
||||
rollingBuffer.formatWithOffset(format, sampleOffsetUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -343,7 +343,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
|
|||
pendingMediaFormat = new boolean[trackCount];
|
||||
durationUs = seekMap.getDurationUs();
|
||||
for (int i = 0; i < trackCount; i++) {
|
||||
trackArray[i] = new TrackGroup(sampleQueues.valueAt(i).getFormat());
|
||||
trackArray[i] = new TrackGroup(sampleQueues.valueAt(i).getUpstreamFormat());
|
||||
}
|
||||
tracks = new TrackGroupArray(trackArray);
|
||||
if (minLoadableRetryCount == MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA && !seekMap.isSeekable()
|
||||
|
|
@ -476,7 +476,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
|
|||
|
||||
DefaultTrackOutput sampleQueue = sampleQueues.valueAt(track);
|
||||
if (pendingMediaFormat[track]) {
|
||||
formatHolder.format = sampleQueue.getFormat();
|
||||
formatHolder.format = sampleQueue.getUpstreamFormat();
|
||||
formatHolder.drmInitData = drmInitData;
|
||||
pendingMediaFormat[track] = false;
|
||||
return TrackStream.FORMAT_READ;
|
||||
|
|
@ -649,7 +649,7 @@ public final class ExtractorSampleSource implements SampleSource, ExtractorOutpu
|
|||
|
||||
private boolean haveFormatsForAllTracks() {
|
||||
for (int i = 0; i < sampleQueues.size(); i++) {
|
||||
if (sampleQueues.valueAt(i).getFormat() == null) {
|
||||
if (sampleQueues.valueAt(i).getUpstreamFormat() == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,12 +137,20 @@ import java.util.concurrent.LinkedBlockingDeque;
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the current upstream format.
|
||||
* Returns the current upstream {@link Format}.
|
||||
*/
|
||||
public Format getUpstreamFormat() {
|
||||
return upstreamFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current downstream {@link Format}.
|
||||
*/
|
||||
public Format getDownstreamFormat() {
|
||||
Format nextSampleFormat = infoQueue.peekFormat();
|
||||
return nextSampleFormat != null ? nextSampleFormat : upstreamFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills {@code buffer} with information about the current sample, but does not write its data.
|
||||
* <p>
|
||||
|
|
@ -357,17 +365,22 @@ import java.util.concurrent.LinkedBlockingDeque;
|
|||
// Called by the loading thread.
|
||||
|
||||
/**
|
||||
* Sets an offset that will be added to the timestamps of subsequently queued samples.
|
||||
* Like {@link #format(Format)}, but with an offset that will be added to the timestamps of
|
||||
* samples subsequently queued to the buffer. The offset is also used to adjust
|
||||
* {@link Format#subsampleOffsetUs} for both the {@link Format} passed and those subsequently
|
||||
* passed to {@link #format(Format)}.
|
||||
*
|
||||
* @param format The format.
|
||||
* @param sampleOffsetUs The timestamp offset in microseconds.
|
||||
*/
|
||||
public void setSampleOffsetUs(long sampleOffsetUs) {
|
||||
public void formatWithOffset(Format format, long sampleOffsetUs) {
|
||||
this.sampleOffsetUs = sampleOffsetUs;
|
||||
upstreamFormat = getAdjustedSampleFormat(format, sampleOffsetUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void format(Format format) {
|
||||
upstreamFormat = format;
|
||||
upstreamFormat = getAdjustedSampleFormat(format, sampleOffsetUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -403,7 +416,7 @@ import java.util.concurrent.LinkedBlockingDeque;
|
|||
public void sampleMetadata(long timeUs, int flags, int size, int offset, byte[] encryptionKey) {
|
||||
timeUs += sampleOffsetUs;
|
||||
long absoluteOffset = totalBytesWritten - size - offset;
|
||||
infoQueue.commitSample(timeUs, flags, absoluteOffset, size, encryptionKey);
|
||||
infoQueue.commitSample(timeUs, flags, absoluteOffset, size, encryptionKey, upstreamFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -419,6 +432,23 @@ import java.util.concurrent.LinkedBlockingDeque;
|
|||
return Math.min(length, allocationLength - lastAllocationOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts a {@link Format} to incorporate a sample offset into {@link Format#subsampleOffsetUs}.
|
||||
*
|
||||
* @param format The {@link Format} to adjust.
|
||||
* @param sampleOffsetUs The offset to apply.
|
||||
* @return The adjusted {@link Format}.
|
||||
*/
|
||||
private static Format getAdjustedSampleFormat(Format format, long sampleOffsetUs) {
|
||||
if (format == null) {
|
||||
return null;
|
||||
}
|
||||
if (sampleOffsetUs != 0 && format.subsampleOffsetUs != Format.OFFSET_SAMPLE_RELATIVE) {
|
||||
format = format.copyWithSubsampleOffsetUs(format.subsampleOffsetUs + sampleOffsetUs);
|
||||
}
|
||||
return format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds information about the samples in the rolling buffer.
|
||||
*/
|
||||
|
|
@ -433,6 +463,7 @@ import java.util.concurrent.LinkedBlockingDeque;
|
|||
private int[] flags;
|
||||
private long[] timesUs;
|
||||
private byte[][] encryptionKeys;
|
||||
private Format[] formats;
|
||||
|
||||
private int queueSize;
|
||||
private int absoluteReadIndex;
|
||||
|
|
@ -446,6 +477,7 @@ import java.util.concurrent.LinkedBlockingDeque;
|
|||
flags = new int[capacity];
|
||||
sizes = new int[capacity];
|
||||
encryptionKeys = new byte[capacity][];
|
||||
formats = new Format[capacity];
|
||||
}
|
||||
|
||||
// Called by the consuming thread, but only when there is no loading thread.
|
||||
|
|
@ -500,6 +532,16 @@ import java.util.concurrent.LinkedBlockingDeque;
|
|||
return absoluteReadIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Format} of the next sample, or null of the queue is empty.
|
||||
*/
|
||||
public synchronized Format peekFormat() {
|
||||
if (queueSize == 0) {
|
||||
return null;
|
||||
}
|
||||
return formats[relativeReadIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills {@code buffer} with information about the current sample, but does not write its data.
|
||||
* The absolute position of the sample's data in the rolling buffer is stored in
|
||||
|
|
@ -609,12 +651,13 @@ import java.util.concurrent.LinkedBlockingDeque;
|
|||
// Called by the loading thread.
|
||||
|
||||
public synchronized void commitSample(long timeUs, int sampleFlags, long offset, int size,
|
||||
byte[] encryptionKey) {
|
||||
byte[] encryptionKey, Format format) {
|
||||
timesUs[relativeWriteIndex] = timeUs;
|
||||
offsets[relativeWriteIndex] = offset;
|
||||
sizes[relativeWriteIndex] = size;
|
||||
flags[relativeWriteIndex] = sampleFlags;
|
||||
encryptionKeys[relativeWriteIndex] = encryptionKey;
|
||||
formats[relativeWriteIndex] = format;
|
||||
// Increment the write index.
|
||||
queueSize++;
|
||||
if (queueSize == capacity) {
|
||||
|
|
@ -625,23 +668,27 @@ import java.util.concurrent.LinkedBlockingDeque;
|
|||
int[] newFlags = new int[newCapacity];
|
||||
int[] newSizes = new int[newCapacity];
|
||||
byte[][] newEncryptionKeys = new byte[newCapacity][];
|
||||
Format[] newFormats = new Format[newCapacity];
|
||||
int beforeWrap = capacity - relativeReadIndex;
|
||||
System.arraycopy(offsets, relativeReadIndex, newOffsets, 0, beforeWrap);
|
||||
System.arraycopy(timesUs, relativeReadIndex, newTimesUs, 0, beforeWrap);
|
||||
System.arraycopy(flags, relativeReadIndex, newFlags, 0, beforeWrap);
|
||||
System.arraycopy(sizes, relativeReadIndex, newSizes, 0, beforeWrap);
|
||||
System.arraycopy(encryptionKeys, relativeReadIndex, newEncryptionKeys, 0, beforeWrap);
|
||||
System.arraycopy(formats, relativeReadIndex, newFormats, 0, beforeWrap);
|
||||
int afterWrap = relativeReadIndex;
|
||||
System.arraycopy(offsets, 0, newOffsets, beforeWrap, afterWrap);
|
||||
System.arraycopy(timesUs, 0, newTimesUs, beforeWrap, afterWrap);
|
||||
System.arraycopy(flags, 0, newFlags, beforeWrap, afterWrap);
|
||||
System.arraycopy(sizes, 0, newSizes, beforeWrap, afterWrap);
|
||||
System.arraycopy(encryptionKeys, 0, newEncryptionKeys, beforeWrap, afterWrap);
|
||||
System.arraycopy(formats, 0, newFormats, beforeWrap, afterWrap);
|
||||
offsets = newOffsets;
|
||||
timesUs = newTimesUs;
|
||||
flags = newFlags;
|
||||
sizes = newSizes;
|
||||
encryptionKeys = newEncryptionKeys;
|
||||
formats = newFormats;
|
||||
relativeReadIndex = 0;
|
||||
relativeWriteIndex = capacity;
|
||||
queueSize = capacity;
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ public final class HlsExtractorWrapper implements ExtractorOutput {
|
|||
private final SparseArray<DefaultTrackOutput> sampleQueues;
|
||||
private final boolean shouldSpliceIn;
|
||||
|
||||
private Format[] sampleFormats;
|
||||
private Allocator allocator;
|
||||
|
||||
private volatile boolean tracksBuilt;
|
||||
|
|
@ -81,15 +80,11 @@ public final class HlsExtractorWrapper implements ExtractorOutput {
|
|||
public boolean isPrepared() {
|
||||
if (!prepared && tracksBuilt) {
|
||||
for (int i = 0; i < sampleQueues.size(); i++) {
|
||||
if (sampleQueues.valueAt(i).getFormat() == null) {
|
||||
if (sampleQueues.valueAt(i).getUpstreamFormat() == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
prepared = true;
|
||||
sampleFormats = new Format[sampleQueues.size()];
|
||||
for (int i = 0; i < sampleFormats.length; i++) {
|
||||
sampleFormats[i] = sampleQueues.valueAt(i).getFormat();
|
||||
}
|
||||
}
|
||||
return prepared;
|
||||
}
|
||||
|
|
@ -173,7 +168,7 @@ public final class HlsExtractorWrapper implements ExtractorOutput {
|
|||
*/
|
||||
public Format getSampleFormat(int track) {
|
||||
Assertions.checkState(isPrepared());
|
||||
return sampleFormats[track];
|
||||
return sampleQueues.valueAt(track).getUpstreamFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue