Don't copy primary-track format to non-primary tracks

This time plumbing the track type in from the other side.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=166898172
This commit is contained in:
olly 2017-08-29 13:55:19 -07:00 committed by Oliver Woodman
parent d9cd13ce74
commit 5bed2bf503
4 changed files with 51 additions and 37 deletions

View File

@ -29,9 +29,10 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
import java.io.IOException;
/**
* An {@link Extractor} wrapper for loading chunks containing a single track.
* An {@link Extractor} wrapper for loading chunks that contain a single primary track, and possibly
* additional embedded tracks.
* <p>
* The wrapper allows switching of the {@link TrackOutput} that receives parsed data.
* The wrapper allows switching of the {@link TrackOutput}s that receive parsed data.
*/
public final class ChunkExtractorWrapper implements ExtractorOutput {
@ -56,7 +57,8 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
public final Extractor extractor;
private final Format manifestFormat;
private final int primaryTrackType;
private final Format primaryTrackManifestFormat;
private final SparseArray<BindingTrackOutput> bindingTrackOutputs;
private boolean extractorInitialized;
@ -66,12 +68,16 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
/**
* @param extractor The extractor to wrap.
* @param manifestFormat A manifest defined {@link Format} whose data should be merged into any
* sample {@link Format} output from the {@link Extractor}.
* @param primaryTrackType The type of the primary track. Typically one of the
* {@link com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
* @param primaryTrackManifestFormat A manifest defined {@link Format} whose data should be merged
* into any sample {@link Format} output from the {@link Extractor} for the primary track.
*/
public ChunkExtractorWrapper(Extractor extractor, Format manifestFormat) {
public ChunkExtractorWrapper(Extractor extractor, int primaryTrackType,
Format primaryTrackManifestFormat) {
this.extractor = extractor;
this.manifestFormat = manifestFormat;
this.primaryTrackType = primaryTrackType;
this.primaryTrackManifestFormat = primaryTrackManifestFormat;
bindingTrackOutputs = new SparseArray<>();
}
@ -90,8 +96,8 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
}
/**
* Initializes the extractor to output to the provided {@link TrackOutput}, and configures it to
* receive data from a new chunk.
* Initializes the wrapper to output to {@link TrackOutput}s provided by the specified
* {@link TrackOutputProvider}, and configures the extractor to receive data from a new chunk.
*
* @param trackOutputProvider The provider of {@link TrackOutput}s that will receive sample data.
*/
@ -116,7 +122,9 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
if (bindingTrackOutput == null) {
// Assert that if we're seeing a new track we have not seen endTracks.
Assertions.checkState(sampleFormats == null);
bindingTrackOutput = new BindingTrackOutput(id, type, manifestFormat);
// TODO: Manifest formats for embedded tracks should also be passed here.
bindingTrackOutput = new BindingTrackOutput(id, type,
type == primaryTrackType ? primaryTrackManifestFormat : null);
bindingTrackOutput.bind(trackOutputProvider);
bindingTrackOutputs.put(id, bindingTrackOutput);
}
@ -160,16 +168,15 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
return;
}
trackOutput = trackOutputProvider.track(id, type);
if (trackOutput != null) {
if (sampleFormat != null) {
trackOutput.format(sampleFormat);
}
}
@Override
public void format(Format format) {
// TODO: This should only happen for the primary track. Additional metadata/text tracks need
// to be copied with different manifest derived formats.
sampleFormat = format.copyWithManifestFormatInfo(manifestFormat);
sampleFormat = manifestFormat != null ? format.copyWithManifestFormatInfo(manifestFormat)
: format;
trackOutput.format(sampleFormat);
}

View File

@ -72,9 +72,11 @@ public final class DashUtil {
*/
public static DrmInitData loadDrmInitData(DataSource dataSource, Period period)
throws IOException, InterruptedException {
Representation representation = getFirstRepresentation(period, C.TRACK_TYPE_VIDEO);
int primaryTrackType = C.TRACK_TYPE_VIDEO;
Representation representation = getFirstRepresentation(period, primaryTrackType);
if (representation == null) {
representation = getFirstRepresentation(period, C.TRACK_TYPE_AUDIO);
primaryTrackType = C.TRACK_TYPE_AUDIO;
representation = getFirstRepresentation(period, primaryTrackType);
if (representation == null) {
return null;
}
@ -85,7 +87,7 @@ public final class DashUtil {
// as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
return drmInitData;
}
Format sampleFormat = DashUtil.loadSampleFormat(dataSource, representation);
Format sampleFormat = DashUtil.loadSampleFormat(dataSource, primaryTrackType, representation);
return sampleFormat == null ? null : sampleFormat.drmInitData;
}
@ -93,15 +95,17 @@ public final class DashUtil {
* Loads initialization data for the {@code representation} and returns the sample {@link Format}.
*
* @param dataSource The source from which the data should be loaded.
* @param trackType The type of the representation. Typically one of the
* {@link com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
* @param representation The representation which initialization chunk belongs to.
* @return the sample {@link Format} of the given representation.
* @throws IOException Thrown when there is an error while loading.
* @throws InterruptedException Thrown if the thread was interrupted.
*/
public static Format loadSampleFormat(DataSource dataSource, Representation representation)
throws IOException, InterruptedException {
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, representation,
false);
public static Format loadSampleFormat(DataSource dataSource, int trackType,
Representation representation) throws IOException, InterruptedException {
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
representation, false);
return extractorWrapper == null ? null : extractorWrapper.getSampleFormats()[0];
}
@ -110,16 +114,18 @@ public final class DashUtil {
* ChunkIndex}.
*
* @param dataSource The source from which the data should be loaded.
* @param trackType The type of the representation. Typically one of the
* {@link com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
* @param representation The representation which initialization chunk belongs to.
* @return The {@link ChunkIndex} of the given representation, or null if no initialization or
* index data exists.
* @throws IOException Thrown when there is an error while loading.
* @throws InterruptedException Thrown if the thread was interrupted.
*/
public static ChunkIndex loadChunkIndex(DataSource dataSource, Representation representation)
throws IOException, InterruptedException {
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, representation,
true);
public static ChunkIndex loadChunkIndex(DataSource dataSource, int trackType,
Representation representation) throws IOException, InterruptedException {
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
representation, true);
return extractorWrapper == null ? null : (ChunkIndex) extractorWrapper.getSeekMap();
}
@ -128,6 +134,8 @@ public final class DashUtil {
* returns a {@link ChunkExtractorWrapper} which contains the output.
*
* @param dataSource The source from which the data should be loaded.
* @param trackType The type of the representation. Typically one of the
* {@link com.google.android.exoplayer2.C} {@code TRACK_TYPE_*} constants.
* @param representation The representation which initialization chunk belongs to.
* @param loadIndex Whether to load index data too.
* @return A {@link ChunkExtractorWrapper} for the {@code representation}, or null if no
@ -135,14 +143,13 @@ public final class DashUtil {
* @throws IOException Thrown when there is an error while loading.
* @throws InterruptedException Thrown if the thread was interrupted.
*/
private static ChunkExtractorWrapper loadInitializationData(DataSource dataSource,
Representation representation, boolean loadIndex)
throws IOException, InterruptedException {
private static ChunkExtractorWrapper loadInitializationData(DataSource dataSource, int trackType,
Representation representation, boolean loadIndex) throws IOException, InterruptedException {
RangedUri initializationUri = representation.getInitializationUri();
if (initializationUri == null) {
return null;
}
ChunkExtractorWrapper extractorWrapper = newWrappedExtractor(representation.format);
ChunkExtractorWrapper extractorWrapper = newWrappedExtractor(trackType, representation.format);
RangedUri requestUri;
if (loadIndex) {
RangedUri indexUri = representation.getIndexUri();
@ -174,12 +181,12 @@ public final class DashUtil {
initializationChunk.load();
}
private static ChunkExtractorWrapper newWrappedExtractor(Format format) {
private static ChunkExtractorWrapper newWrappedExtractor(int trackType, Format format) {
String mimeType = format.containerMimeType;
boolean isWebm = mimeType.startsWith(MimeTypes.VIDEO_WEBM)
|| mimeType.startsWith(MimeTypes.AUDIO_WEBM);
Extractor extractor = isWebm ? new MatroskaExtractor() : new FragmentedMp4Extractor();
return new ChunkExtractorWrapper(extractor, format);
return new ChunkExtractorWrapper(extractor, trackType, format);
}
private static Representation getFirstRepresentation(Period period, int type) {

View File

@ -134,8 +134,8 @@ public class DefaultDashChunkSource implements DashChunkSource {
representationHolders = new RepresentationHolder[trackSelection.length()];
for (int i = 0; i < representationHolders.length; i++) {
Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
representationHolders[i] = new RepresentationHolder(periodDurationUs, representation,
enableEventMessageTrack, enableCea608Track);
representationHolders[i] = new RepresentationHolder(periodDurationUs, trackType,
representation, enableEventMessageTrack, enableCea608Track);
}
}
@ -390,8 +390,8 @@ public class DefaultDashChunkSource implements DashChunkSource {
private long periodDurationUs;
private int segmentNumShift;
/* package */ RepresentationHolder(long periodDurationUs, Representation representation,
boolean enableEventMessageTrack, boolean enableCea608Track) {
/* package */ RepresentationHolder(long periodDurationUs, int trackType,
Representation representation, boolean enableEventMessageTrack, boolean enableCea608Track) {
this.periodDurationUs = periodDurationUs;
this.representation = representation;
String containerMimeType = representation.format.containerMimeType;
@ -415,7 +415,7 @@ public class DefaultDashChunkSource implements DashChunkSource {
}
// Prefer drmInitData obtained from the manifest over drmInitData obtained from the stream,
// as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
extractorWrapper = new ChunkExtractorWrapper(extractor, representation.format);
extractorWrapper = new ChunkExtractorWrapper(extractor, trackType, representation.format);
}
segmentIndex = representation.getIndex();
}

View File

@ -102,7 +102,7 @@ public class DefaultSsChunkSource implements SsChunkSource {
FragmentedMp4Extractor extractor = new FragmentedMp4Extractor(
FragmentedMp4Extractor.FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
| FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, null, track);
extractorWrappers[i] = new ChunkExtractorWrapper(extractor, format);
extractorWrappers[i] = new ChunkExtractorWrapper(extractor, streamElement.type, format);
}
}