Simplify chunk package ahead of EMSG/608 piping

Issue: #2362
Issue: #2176

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=146243681
This commit is contained in:
olly 2017-02-01 08:00:48 -08:00 committed by Oliver Woodman
parent 025a67cae9
commit ee3c5f875f
9 changed files with 75 additions and 152 deletions

View File

@ -32,6 +32,7 @@ import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase; import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase;
import com.google.android.exoplayer2.testutil.TestUtil; import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.upstream.HttpDataSource; import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.util.MimeTypes;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import org.mockito.Mock; import org.mockito.Mock;
@ -217,7 +218,11 @@ public class OfflineLicenseHelperTest extends InstrumentationTestCase {
} }
private static Representation newRepresentations(DrmInitData drmInitData) { private static Representation newRepresentations(DrmInitData drmInitData) {
Format format = Format.createVideoSampleFormat("", "", "", 0, 0, 0, 0, 0, null, drmInitData); Format format = Format.createVideoContainerFormat("id", MimeTypes.VIDEO_MP4,
MimeTypes.VIDEO_H264, "", Format.NO_VALUE, 1024, 768, Format.NO_VALUE, null, 0);
if (drmInitData != null) {
format = format.copyWithDrmInitData(drmInitData);
}
return Representation.newInstance("", 0, format, "", new SingleSegmentBase()); return Representation.newInstance("", 0, format, "", new SingleSegmentBase());
} }

View File

@ -210,11 +210,13 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
Representation representation = adaptationSet.representations.get(0); Representation representation = adaptationSet.representations.get(0);
DrmInitData drmInitData = representation.format.drmInitData; DrmInitData drmInitData = representation.format.drmInitData;
if (drmInitData == null) { if (drmInitData == null) {
InitializationChunk initializationChunk = loadInitializationChunk(dataSource, representation); ChunkExtractorWrapper extractorWrapper = newWrappedExtractor(representation.format);
InitializationChunk initializationChunk = loadInitializationChunk(dataSource, representation,
extractorWrapper);
if (initializationChunk == null) { if (initializationChunk == null) {
return null; return null;
} }
Format sampleFormat = initializationChunk.getSampleFormat(); Format sampleFormat = extractorWrapper.getSampleFormat();
if (sampleFormat != null) { if (sampleFormat != null) {
drmInitData = sampleFormat.drmInitData; drmInitData = sampleFormat.drmInitData;
} }
@ -288,8 +290,9 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
return session; return session;
} }
private static InitializationChunk loadInitializationChunk(final DataSource dataSource, private static InitializationChunk loadInitializationChunk(DataSource dataSource,
final Representation representation) throws IOException, InterruptedException { Representation representation, ChunkExtractorWrapper extractorWrapper)
throws IOException, InterruptedException {
RangedUri rangedUri = representation.getInitializationUri(); RangedUri rangedUri = representation.getInitializationUri();
if (rangedUri == null) { if (rangedUri == null) {
return null; return null;
@ -298,7 +301,7 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
rangedUri.length, representation.getCacheKey()); rangedUri.length, representation.getCacheKey());
InitializationChunk initializationChunk = new InitializationChunk(dataSource, dataSpec, InitializationChunk initializationChunk = new InitializationChunk(dataSource, dataSpec,
representation.format, C.SELECTION_REASON_UNKNOWN, null /* trackSelectionData */, representation.format, C.SELECTION_REASON_UNKNOWN, null /* trackSelectionData */,
newWrappedExtractor(representation.format)); extractorWrapper);
initializationChunk.load(); initializationChunk.load();
return initializationChunk; return initializationChunk;
} }
@ -308,8 +311,7 @@ public final class OfflineLicenseHelper<T extends ExoMediaCrypto> {
final boolean isWebm = mimeType.startsWith(MimeTypes.VIDEO_WEBM) final boolean isWebm = mimeType.startsWith(MimeTypes.VIDEO_WEBM)
|| mimeType.startsWith(MimeTypes.AUDIO_WEBM); || mimeType.startsWith(MimeTypes.AUDIO_WEBM);
final Extractor extractor = isWebm ? new MatroskaExtractor() : new FragmentedMp4Extractor(); final Extractor extractor = isWebm ? new MatroskaExtractor() : new FragmentedMp4Extractor();
return new ChunkExtractorWrapper(extractor, format, false /* preferManifestDrmInitData */, return new ChunkExtractorWrapper(extractor, format, false /* preferManifestDrmInitData */);
false /* resendFormatOnInit */);
} }
} }

View File

@ -70,6 +70,8 @@ public final class DefaultTrackOutput implements TrackOutput {
private Format downstreamFormat; private Format downstreamFormat;
// Accessed only by the loading thread (or the consuming thread when there is no loading thread). // Accessed only by the loading thread (or the consuming thread when there is no loading thread).
private boolean pendingFormatAdjustment;
private Format lastUnadjustedFormat;
private long sampleOffsetUs; private long sampleOffsetUs;
private long totalBytesWritten; private long totalBytesWritten;
private Allocation lastAllocation; private Allocation lastAllocation;
@ -445,23 +447,24 @@ public final class DefaultTrackOutput implements TrackOutput {
} }
/** /**
* Like {@link #format(Format)}, but with an offset that will be added to the timestamps of * Sets an offset that will be added to the timestamps (and sub-sample timestamps) of samples
* samples subsequently queued to the buffer. The offset is also used to adjust * subsequently queued to the buffer.
* {@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. * @param sampleOffsetUs The timestamp offset in microseconds.
*/ */
public void formatWithOffset(Format format, long sampleOffsetUs) { public void setSampleOffsetUs(long sampleOffsetUs) {
this.sampleOffsetUs = sampleOffsetUs; if (this.sampleOffsetUs != sampleOffsetUs) {
format(format); this.sampleOffsetUs = sampleOffsetUs;
pendingFormatAdjustment = true;
}
} }
@Override @Override
public void format(Format format) { public void format(Format format) {
Format adjustedFormat = getAdjustedSampleFormat(format, sampleOffsetUs); Format adjustedFormat = getAdjustedSampleFormat(format, sampleOffsetUs);
boolean formatChanged = infoQueue.format(adjustedFormat); boolean formatChanged = infoQueue.format(adjustedFormat);
lastUnadjustedFormat = format;
pendingFormatAdjustment = false;
if (upstreamFormatChangeListener != null && formatChanged) { if (upstreamFormatChangeListener != null && formatChanged) {
upstreamFormatChangeListener.onUpstreamFormatChanged(adjustedFormat); upstreamFormatChangeListener.onUpstreamFormatChanged(adjustedFormat);
} }
@ -518,6 +521,9 @@ public final class DefaultTrackOutput implements TrackOutput {
@Override @Override
public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset, public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset,
byte[] encryptionKey) { byte[] encryptionKey) {
if (pendingFormatAdjustment) {
format(lastUnadjustedFormat);
}
if (!startWriteOperation()) { if (!startWriteOperation()) {
infoQueue.commitSampleTimestamp(timeUs); infoQueue.commitSampleTimestamp(timeUs);
return; return;

View File

@ -30,33 +30,19 @@ import java.io.IOException;
/** /**
* An {@link Extractor} wrapper for loading chunks containing a single track. * An {@link Extractor} wrapper for loading chunks containing a single track.
* <p> * <p>
* The wrapper allows switching of the {@link SeekMapOutput} and {@link TrackOutput} that receive * The wrapper allows switching of the {@link TrackOutput} that receives parsed data.
* parsed data.
*/ */
public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput { public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput {
/**
* Receives {@link SeekMap}s extracted by the wrapped {@link Extractor}.
*/
public interface SeekMapOutput {
/**
* @see ExtractorOutput#seekMap(SeekMap)
*/
void seekMap(SeekMap seekMap);
}
public final Extractor extractor; public final Extractor extractor;
private final Format manifestFormat; private final Format manifestFormat;
private final boolean preferManifestDrmInitData; private final boolean preferManifestDrmInitData;
private final boolean resendFormatOnInit;
private boolean extractorInitialized; private boolean extractorInitialized;
private SeekMapOutput seekMapOutput;
private TrackOutput trackOutput; private TrackOutput trackOutput;
private Format sentFormat; private SeekMap seekMap;
private Format sampleFormat;
// Accessed only on the loader thread. // Accessed only on the loader thread.
private boolean seenTrack; private boolean seenTrack;
@ -68,34 +54,43 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput
* sample {@link Format} output from the {@link Extractor}. * sample {@link Format} output from the {@link Extractor}.
* @param preferManifestDrmInitData Whether {@link DrmInitData} defined in {@code manifestFormat} * @param preferManifestDrmInitData Whether {@link DrmInitData} defined in {@code manifestFormat}
* should be preferred when the sample and manifest {@link Format}s are merged. * should be preferred when the sample and manifest {@link Format}s are merged.
* @param resendFormatOnInit Whether the extractor should resend the previous {@link Format} when
* it is initialized via {@link #init(SeekMapOutput, TrackOutput)}.
*/ */
public ChunkExtractorWrapper(Extractor extractor, Format manifestFormat, public ChunkExtractorWrapper(Extractor extractor, Format manifestFormat,
boolean preferManifestDrmInitData, boolean resendFormatOnInit) { boolean preferManifestDrmInitData) {
this.extractor = extractor; this.extractor = extractor;
this.manifestFormat = manifestFormat; this.manifestFormat = manifestFormat;
this.preferManifestDrmInitData = preferManifestDrmInitData; this.preferManifestDrmInitData = preferManifestDrmInitData;
this.resendFormatOnInit = resendFormatOnInit;
} }
/** /**
* Initializes the extractor to output to the provided {@link SeekMapOutput} and * Returns the {@link SeekMap} most recently output by the extractor, or null.
* {@link TrackOutput} instances, and configures it to receive data from a new chunk. */
public SeekMap getSeekMap() {
return seekMap;
}
/**
* Returns the sample {@link Format} most recently output by the extractor, or null.
*/
public Format getSampleFormat() {
return sampleFormat;
}
/**
* Initializes the extractor to output to the provided {@link TrackOutput}, and configures it to
* receive data from a new chunk.
* *
* @param seekMapOutput The {@link SeekMapOutput} that will receive extracted {@link SeekMap}s.
* @param trackOutput The {@link TrackOutput} that will receive sample data. * @param trackOutput The {@link TrackOutput} that will receive sample data.
*/ */
public void init(SeekMapOutput seekMapOutput, TrackOutput trackOutput) { public void init(TrackOutput trackOutput) {
this.seekMapOutput = seekMapOutput;
this.trackOutput = trackOutput; this.trackOutput = trackOutput;
if (!extractorInitialized) { if (!extractorInitialized) {
extractor.init(this); extractor.init(this);
extractorInitialized = true; extractorInitialized = true;
} else { } else {
extractor.seek(0, 0); extractor.seek(0, 0);
if (resendFormatOnInit && sentFormat != null) { if (sampleFormat != null) {
trackOutput.format(sentFormat); trackOutput.format(sampleFormat);
} }
} }
} }
@ -117,15 +112,17 @@ public final class ChunkExtractorWrapper implements ExtractorOutput, TrackOutput
@Override @Override
public void seekMap(SeekMap seekMap) { public void seekMap(SeekMap seekMap) {
seekMapOutput.seekMap(seekMap); this.seekMap = seekMap;
} }
// TrackOutput implementation. // TrackOutput implementation.
@Override @Override
public void format(Format format) { public void format(Format format) {
sentFormat = format.copyWithManifestFormatInfo(manifestFormat, preferManifestDrmInitData); sampleFormat = format.copyWithManifestFormatInfo(manifestFormat, preferManifestDrmInitData);
trackOutput.format(sentFormat); if (trackOutput != null) {
trackOutput.format(sampleFormat);
}
} }
@Override @Override

View File

@ -20,8 +20,6 @@ import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
import com.google.android.exoplayer2.extractor.DefaultTrackOutput; import com.google.android.exoplayer2.extractor.DefaultTrackOutput;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.source.chunk.ChunkExtractorWrapper.SeekMapOutput;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
@ -31,12 +29,11 @@ import java.io.IOException;
/** /**
* A {@link BaseMediaChunk} that uses an {@link Extractor} to decode sample data. * A {@link BaseMediaChunk} that uses an {@link Extractor} to decode sample data.
*/ */
public class ContainerMediaChunk extends BaseMediaChunk implements SeekMapOutput { public class ContainerMediaChunk extends BaseMediaChunk {
private final int chunkCount; private final int chunkCount;
private final long sampleOffsetUs; private final long sampleOffsetUs;
private final ChunkExtractorWrapper extractorWrapper; private final ChunkExtractorWrapper extractorWrapper;
private final Format sampleFormat;
private volatile int bytesLoaded; private volatile int bytesLoaded;
private volatile boolean loadCanceled; private volatile boolean loadCanceled;
@ -56,19 +53,15 @@ public class ContainerMediaChunk extends BaseMediaChunk implements SeekMapOutput
* underlying media are being merged into a single load. * underlying media are being merged into a single load.
* @param sampleOffsetUs An offset to add to the sample timestamps parsed by the extractor. * @param sampleOffsetUs An offset to add to the sample timestamps parsed by the extractor.
* @param extractorWrapper A wrapped extractor to use for parsing the data. * @param extractorWrapper A wrapped extractor to use for parsing the data.
* @param sampleFormat The {@link Format} of the samples in the chunk, if known. May be null if
* the data is known to define its own sample format.
*/ */
public ContainerMediaChunk(DataSource dataSource, DataSpec dataSpec, Format trackFormat, public ContainerMediaChunk(DataSource dataSource, DataSpec dataSpec, Format trackFormat,
int trackSelectionReason, Object trackSelectionData, long startTimeUs, long endTimeUs, int trackSelectionReason, Object trackSelectionData, long startTimeUs, long endTimeUs,
int chunkIndex, int chunkCount, long sampleOffsetUs, ChunkExtractorWrapper extractorWrapper, int chunkIndex, int chunkCount, long sampleOffsetUs, ChunkExtractorWrapper extractorWrapper) {
Format sampleFormat) {
super(dataSource, dataSpec, trackFormat, trackSelectionReason, trackSelectionData, startTimeUs, super(dataSource, dataSpec, trackFormat, trackSelectionReason, trackSelectionData, startTimeUs,
endTimeUs, chunkIndex); endTimeUs, chunkIndex);
this.chunkCount = chunkCount; this.chunkCount = chunkCount;
this.sampleOffsetUs = sampleOffsetUs; this.sampleOffsetUs = sampleOffsetUs;
this.extractorWrapper = extractorWrapper; this.extractorWrapper = extractorWrapper;
this.sampleFormat = sampleFormat;
} }
@Override @Override
@ -86,13 +79,6 @@ public class ContainerMediaChunk extends BaseMediaChunk implements SeekMapOutput
return bytesLoaded; return bytesLoaded;
} }
// SeekMapOutput implementation.
@Override
public final void seekMap(SeekMap seekMap) {
// Do nothing.
}
// Loadable implementation. // Loadable implementation.
@Override @Override
@ -116,8 +102,8 @@ public class ContainerMediaChunk extends BaseMediaChunk implements SeekMapOutput
if (bytesLoaded == 0) { if (bytesLoaded == 0) {
// Set the target to ourselves. // Set the target to ourselves.
DefaultTrackOutput trackOutput = getTrackOutput(); DefaultTrackOutput trackOutput = getTrackOutput();
trackOutput.formatWithOffset(sampleFormat, sampleOffsetUs); trackOutput.setSampleOffsetUs(sampleOffsetUs);
extractorWrapper.init(this, trackOutput); extractorWrapper.init(trackOutput);
} }
// Load and decode the sample data. // Load and decode the sample data.
try { try {

View File

@ -20,30 +20,19 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput; import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput; import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.source.chunk.ChunkExtractorWrapper.SeekMapOutput;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
/** /**
* A {@link Chunk} that uses an {@link Extractor} to decode initialization data for single track. * A {@link Chunk} that uses an {@link Extractor} to decode initialization data for single track.
*/ */
public final class InitializationChunk extends Chunk implements SeekMapOutput, public final class InitializationChunk extends Chunk {
TrackOutput {
private final ChunkExtractorWrapper extractorWrapper; private final ChunkExtractorWrapper extractorWrapper;
// Initialization results. Set by the loader thread and read by any thread that knows loading
// has completed. These variables do not need to be volatile, since a memory barrier must occur
// for the reading thread to know that loading has completed.
private Format sampleFormat;
private SeekMap seekMap;
private volatile int bytesLoaded; private volatile int bytesLoaded;
private volatile boolean loadCanceled; private volatile boolean loadCanceled;
@ -68,55 +57,6 @@ public final class InitializationChunk extends Chunk implements SeekMapOutput,
return bytesLoaded; return bytesLoaded;
} }
/**
* Returns a {@link Format} parsed from the chunk, or null.
* <p>
* Should be called after loading has completed.
*/
public Format getSampleFormat() {
return sampleFormat;
}
/**
* Returns a {@link SeekMap} parsed from the chunk, or null.
* <p>
* Should be called after loading has completed.
*/
public SeekMap getSeekMap() {
return seekMap;
}
// SeekMapOutput implementation.
@Override
public void seekMap(SeekMap seekMap) {
this.seekMap = seekMap;
}
// TrackOutput implementation.
@Override
public void format(Format format) {
this.sampleFormat = format;
}
@Override
public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput)
throws IOException, InterruptedException {
throw new IllegalStateException("Unexpected sample data in initialization chunk");
}
@Override
public void sampleData(ParsableByteArray data, int length) {
throw new IllegalStateException("Unexpected sample data in initialization chunk");
}
@Override
public void sampleMetadata(long timeUs, @C.BufferFlags int flags, int size, int offset,
byte[] encryptionKey) {
throw new IllegalStateException("Unexpected sample data in initialization chunk");
}
// Loadable implementation. // Loadable implementation.
@Override @Override
@ -138,8 +78,7 @@ public final class InitializationChunk extends Chunk implements SeekMapOutput,
ExtractorInput input = new DefaultExtractorInput(dataSource, ExtractorInput input = new DefaultExtractorInput(dataSource,
loadDataSpec.absoluteStreamPosition, dataSource.open(loadDataSpec)); loadDataSpec.absoluteStreamPosition, dataSource.open(loadDataSpec));
if (bytesLoaded == 0) { if (bytesLoaded == 0) {
// Set the target to ourselves. extractorWrapper.init(null);
extractorWrapper.init(this, this);
} }
// Load and decode the initialization data. // Load and decode the initialization data.
try { try {

View File

@ -88,7 +88,8 @@ public final class SingleSampleMediaChunk extends BaseMediaChunk {
} }
ExtractorInput extractorInput = new DefaultExtractorInput(dataSource, bytesLoaded, length); ExtractorInput extractorInput = new DefaultExtractorInput(dataSource, bytesLoaded, length);
DefaultTrackOutput trackOutput = getTrackOutput(); DefaultTrackOutput trackOutput = getTrackOutput();
trackOutput.formatWithOffset(sampleFormat, 0); trackOutput.setSampleOffsetUs(0);
trackOutput.format(sampleFormat);
// Load the sample data. // Load the sample data.
int result = 0; int result = 0;
while (result != C.RESULT_END_OF_INPUT) { while (result != C.RESULT_END_OF_INPUT) {

View File

@ -176,8 +176,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
RangedUri pendingInitializationUri = null; RangedUri pendingInitializationUri = null;
RangedUri pendingIndexUri = null; RangedUri pendingIndexUri = null;
Format sampleFormat = representationHolder.sampleFormat; if (representationHolder.extractorWrapper.getSampleFormat() == null) {
if (sampleFormat == null) {
pendingInitializationUri = selectedRepresentation.getInitializationUri(); pendingInitializationUri = selectedRepresentation.getInitializationUri();
} }
if (segmentIndex == null) { if (segmentIndex == null) {
@ -233,8 +232,8 @@ public class DefaultDashChunkSource implements DashChunkSource {
int maxSegmentCount = Math.min(maxSegmentsPerLoad, lastAvailableSegmentNum - segmentNum + 1); int maxSegmentCount = Math.min(maxSegmentsPerLoad, lastAvailableSegmentNum - segmentNum + 1);
out.chunk = newMediaChunk(representationHolder, dataSource, trackSelection.getSelectedFormat(), out.chunk = newMediaChunk(representationHolder, dataSource, trackSelection.getSelectedFormat(),
trackSelection.getSelectionReason(), trackSelection.getSelectionData(), sampleFormat, trackSelection.getSelectionReason(), trackSelection.getSelectionData(), segmentNum,
segmentNum, maxSegmentCount); maxSegmentCount);
} }
@Override @Override
@ -243,15 +242,11 @@ public class DefaultDashChunkSource implements DashChunkSource {
InitializationChunk initializationChunk = (InitializationChunk) chunk; InitializationChunk initializationChunk = (InitializationChunk) chunk;
RepresentationHolder representationHolder = RepresentationHolder representationHolder =
representationHolders[trackSelection.indexOf(initializationChunk.trackFormat)]; representationHolders[trackSelection.indexOf(initializationChunk.trackFormat)];
Format sampleFormat = initializationChunk.getSampleFormat();
if (sampleFormat != null) {
representationHolder.setSampleFormat(sampleFormat);
}
// The null check avoids overwriting an index obtained from the manifest with one obtained // 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 // from the stream. If the manifest defines an index then the stream shouldn't, but in cases
// where it does we should ignore it. // where it does we should ignore it.
if (representationHolder.segmentIndex == null) { if (representationHolder.segmentIndex == null) {
SeekMap seekMap = initializationChunk.getSeekMap(); SeekMap seekMap = representationHolder.extractorWrapper.getSeekMap();
if (seekMap != null) { if (seekMap != null) {
representationHolder.segmentIndex = new DashWrappingSegmentIndex((ChunkIndex) seekMap); representationHolder.segmentIndex = new DashWrappingSegmentIndex((ChunkIndex) seekMap);
} }
@ -318,7 +313,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
private static Chunk newMediaChunk(RepresentationHolder representationHolder, private static Chunk newMediaChunk(RepresentationHolder representationHolder,
DataSource dataSource, Format trackFormat, int trackSelectionReason, DataSource dataSource, Format trackFormat, int trackSelectionReason,
Object trackSelectionData, Format sampleFormat, int firstSegmentNum, int maxSegmentCount) { Object trackSelectionData, int firstSegmentNum, int maxSegmentCount) {
Representation representation = representationHolder.representation; Representation representation = representationHolder.representation;
long startTimeUs = representationHolder.getSegmentStartTimeUs(firstSegmentNum); long startTimeUs = representationHolder.getSegmentStartTimeUs(firstSegmentNum);
RangedUri segmentUri = representationHolder.getSegmentUrl(firstSegmentNum); RangedUri segmentUri = representationHolder.getSegmentUrl(firstSegmentNum);
@ -347,7 +342,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
long sampleOffsetUs = -representation.presentationTimeOffsetUs; long sampleOffsetUs = -representation.presentationTimeOffsetUs;
return new ContainerMediaChunk(dataSource, dataSpec, trackFormat, trackSelectionReason, return new ContainerMediaChunk(dataSource, dataSpec, trackFormat, trackSelectionReason,
trackSelectionData, startTimeUs, endTimeUs, firstSegmentNum, segmentCount, trackSelectionData, startTimeUs, endTimeUs, firstSegmentNum, segmentCount,
sampleOffsetUs, representationHolder.extractorWrapper, sampleFormat); sampleOffsetUs, representationHolder.extractorWrapper);
} }
} }
@ -359,7 +354,6 @@ public class DefaultDashChunkSource implements DashChunkSource {
public Representation representation; public Representation representation;
public DashSegmentIndex segmentIndex; public DashSegmentIndex segmentIndex;
public Format sampleFormat;
private long periodDurationUs; private long periodDurationUs;
private int segmentNumShift; private int segmentNumShift;
@ -371,11 +365,9 @@ public class DefaultDashChunkSource implements DashChunkSource {
if (mimeTypeIsRawText(containerMimeType)) { if (mimeTypeIsRawText(containerMimeType)) {
extractorWrapper = null; extractorWrapper = null;
} else { } else {
boolean resendFormatOnInit = false;
Extractor extractor; Extractor extractor;
if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) { if (MimeTypes.APPLICATION_RAWCC.equals(containerMimeType)) {
extractor = new RawCcExtractor(representation.format); extractor = new RawCcExtractor(representation.format);
resendFormatOnInit = true;
} else if (mimeTypeIsWebm(containerMimeType)) { } else if (mimeTypeIsWebm(containerMimeType)) {
extractor = new MatroskaExtractor(); extractor = new MatroskaExtractor();
} else { } else {
@ -383,17 +375,12 @@ public class DefaultDashChunkSource implements DashChunkSource {
} }
// Prefer drmInitData obtained from the manifest over drmInitData obtained from the stream, // Prefer drmInitData obtained from the manifest over drmInitData obtained from the stream,
// as per DASH IF Interoperability Recommendations V3.0, 7.5.3. // as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
extractorWrapper = new ChunkExtractorWrapper(extractor, extractorWrapper = new ChunkExtractorWrapper(extractor, representation.format,
representation.format, true /* preferManifestDrmInitData */, true /* preferManifestDrmInitData */);
resendFormatOnInit);
} }
segmentIndex = representation.getIndex(); segmentIndex = representation.getIndex();
} }
public void setSampleFormat(Format sampleFormat) {
this.sampleFormat = sampleFormat;
}
public void updateRepresentation(long newPeriodDurationUs, Representation newRepresentation) public void updateRepresentation(long newPeriodDurationUs, Representation newRepresentation)
throws BehindLiveWindowException{ throws BehindLiveWindowException{
DashSegmentIndex oldIndex = representation.getIndex(); DashSegmentIndex oldIndex = representation.getIndex();

View File

@ -102,7 +102,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
FragmentedMp4Extractor extractor = new FragmentedMp4Extractor( FragmentedMp4Extractor extractor = new FragmentedMp4Extractor(
FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
| FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, track, null); | FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, track, null);
extractorWrappers[i] = new ChunkExtractorWrapper(extractor, format, false, false); extractorWrappers[i] = new ChunkExtractorWrapper(extractor, format, false);
} }
} }
@ -219,7 +219,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
long sampleOffsetUs = chunkStartTimeUs; long sampleOffsetUs = chunkStartTimeUs;
return new ContainerMediaChunk(dataSource, dataSpec, format, trackSelectionReason, return new ContainerMediaChunk(dataSource, dataSpec, format, trackSelectionReason,
trackSelectionData, chunkStartTimeUs, chunkEndTimeUs, chunkIndex, 1, sampleOffsetUs, trackSelectionData, chunkStartTimeUs, chunkEndTimeUs, chunkIndex, 1, sampleOffsetUs,
extractorWrapper, format); extractorWrapper);
} }
} }