mirror of
https://github.com/androidx/media.git
synced 2025-05-16 12:09:50 +08:00
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:
parent
d9cd13ce74
commit
5bed2bf503
@ -29,9 +29,10 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
|
|||||||
import java.io.IOException;
|
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>
|
* <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 {
|
public final class ChunkExtractorWrapper implements ExtractorOutput {
|
||||||
|
|
||||||
@ -56,7 +57,8 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
|
|||||||
|
|
||||||
public final Extractor extractor;
|
public final Extractor extractor;
|
||||||
|
|
||||||
private final Format manifestFormat;
|
private final int primaryTrackType;
|
||||||
|
private final Format primaryTrackManifestFormat;
|
||||||
private final SparseArray<BindingTrackOutput> bindingTrackOutputs;
|
private final SparseArray<BindingTrackOutput> bindingTrackOutputs;
|
||||||
|
|
||||||
private boolean extractorInitialized;
|
private boolean extractorInitialized;
|
||||||
@ -66,12 +68,16 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param extractor The extractor to wrap.
|
* @param extractor The extractor to wrap.
|
||||||
* @param manifestFormat A manifest defined {@link Format} whose data should be merged into any
|
* @param primaryTrackType The type of the primary track. Typically one of the
|
||||||
* sample {@link Format} output from the {@link Extractor}.
|
* {@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.extractor = extractor;
|
||||||
this.manifestFormat = manifestFormat;
|
this.primaryTrackType = primaryTrackType;
|
||||||
|
this.primaryTrackManifestFormat = primaryTrackManifestFormat;
|
||||||
bindingTrackOutputs = new SparseArray<>();
|
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
|
* Initializes the wrapper to output to {@link TrackOutput}s provided by the specified
|
||||||
* receive data from a new chunk.
|
* {@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.
|
* @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) {
|
if (bindingTrackOutput == null) {
|
||||||
// Assert that if we're seeing a new track we have not seen endTracks.
|
// Assert that if we're seeing a new track we have not seen endTracks.
|
||||||
Assertions.checkState(sampleFormats == null);
|
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);
|
bindingTrackOutput.bind(trackOutputProvider);
|
||||||
bindingTrackOutputs.put(id, bindingTrackOutput);
|
bindingTrackOutputs.put(id, bindingTrackOutput);
|
||||||
}
|
}
|
||||||
@ -160,16 +168,15 @@ public final class ChunkExtractorWrapper implements ExtractorOutput {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
trackOutput = trackOutputProvider.track(id, type);
|
trackOutput = trackOutputProvider.track(id, type);
|
||||||
if (trackOutput != null) {
|
if (sampleFormat != null) {
|
||||||
trackOutput.format(sampleFormat);
|
trackOutput.format(sampleFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void format(Format format) {
|
public void format(Format format) {
|
||||||
// TODO: This should only happen for the primary track. Additional metadata/text tracks need
|
sampleFormat = manifestFormat != null ? format.copyWithManifestFormatInfo(manifestFormat)
|
||||||
// to be copied with different manifest derived formats.
|
: format;
|
||||||
sampleFormat = format.copyWithManifestFormatInfo(manifestFormat);
|
|
||||||
trackOutput.format(sampleFormat);
|
trackOutput.format(sampleFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,9 +72,11 @@ public final class DashUtil {
|
|||||||
*/
|
*/
|
||||||
public static DrmInitData loadDrmInitData(DataSource dataSource, Period period)
|
public static DrmInitData loadDrmInitData(DataSource dataSource, Period period)
|
||||||
throws IOException, InterruptedException {
|
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) {
|
if (representation == null) {
|
||||||
representation = getFirstRepresentation(period, C.TRACK_TYPE_AUDIO);
|
primaryTrackType = C.TRACK_TYPE_AUDIO;
|
||||||
|
representation = getFirstRepresentation(period, primaryTrackType);
|
||||||
if (representation == null) {
|
if (representation == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -85,7 +87,7 @@ public final class DashUtil {
|
|||||||
// as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
|
// as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
|
||||||
return drmInitData;
|
return drmInitData;
|
||||||
}
|
}
|
||||||
Format sampleFormat = DashUtil.loadSampleFormat(dataSource, representation);
|
Format sampleFormat = DashUtil.loadSampleFormat(dataSource, primaryTrackType, representation);
|
||||||
return sampleFormat == null ? null : sampleFormat.drmInitData;
|
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}.
|
* 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 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 representation The representation which initialization chunk belongs to.
|
||||||
* @return the sample {@link Format} of the given representation.
|
* @return the sample {@link Format} of the given representation.
|
||||||
* @throws IOException Thrown when there is an error while loading.
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
* @throws InterruptedException Thrown if the thread was interrupted.
|
* @throws InterruptedException Thrown if the thread was interrupted.
|
||||||
*/
|
*/
|
||||||
public static Format loadSampleFormat(DataSource dataSource, Representation representation)
|
public static Format loadSampleFormat(DataSource dataSource, int trackType,
|
||||||
throws IOException, InterruptedException {
|
Representation representation) throws IOException, InterruptedException {
|
||||||
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, representation,
|
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
|
||||||
false);
|
representation, false);
|
||||||
return extractorWrapper == null ? null : extractorWrapper.getSampleFormats()[0];
|
return extractorWrapper == null ? null : extractorWrapper.getSampleFormats()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,16 +114,18 @@ public final class DashUtil {
|
|||||||
* ChunkIndex}.
|
* ChunkIndex}.
|
||||||
*
|
*
|
||||||
* @param dataSource The source from which the data should be loaded.
|
* @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 representation The representation which initialization chunk belongs to.
|
||||||
* @return The {@link ChunkIndex} of the given representation, or null if no initialization or
|
* @return The {@link ChunkIndex} of the given representation, or null if no initialization or
|
||||||
* index data exists.
|
* index data exists.
|
||||||
* @throws IOException Thrown when there is an error while loading.
|
* @throws IOException Thrown when there is an error while loading.
|
||||||
* @throws InterruptedException Thrown if the thread was interrupted.
|
* @throws InterruptedException Thrown if the thread was interrupted.
|
||||||
*/
|
*/
|
||||||
public static ChunkIndex loadChunkIndex(DataSource dataSource, Representation representation)
|
public static ChunkIndex loadChunkIndex(DataSource dataSource, int trackType,
|
||||||
throws IOException, InterruptedException {
|
Representation representation) throws IOException, InterruptedException {
|
||||||
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, representation,
|
ChunkExtractorWrapper extractorWrapper = loadInitializationData(dataSource, trackType,
|
||||||
true);
|
representation, true);
|
||||||
return extractorWrapper == null ? null : (ChunkIndex) extractorWrapper.getSeekMap();
|
return extractorWrapper == null ? null : (ChunkIndex) extractorWrapper.getSeekMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +134,8 @@ public final class DashUtil {
|
|||||||
* returns a {@link ChunkExtractorWrapper} which contains the output.
|
* returns a {@link ChunkExtractorWrapper} which contains the output.
|
||||||
*
|
*
|
||||||
* @param dataSource The source from which the data should be loaded.
|
* @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 representation The representation which initialization chunk belongs to.
|
||||||
* @param loadIndex Whether to load index data too.
|
* @param loadIndex Whether to load index data too.
|
||||||
* @return A {@link ChunkExtractorWrapper} for the {@code representation}, or null if no
|
* @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 IOException Thrown when there is an error while loading.
|
||||||
* @throws InterruptedException Thrown if the thread was interrupted.
|
* @throws InterruptedException Thrown if the thread was interrupted.
|
||||||
*/
|
*/
|
||||||
private static ChunkExtractorWrapper loadInitializationData(DataSource dataSource,
|
private static ChunkExtractorWrapper loadInitializationData(DataSource dataSource, int trackType,
|
||||||
Representation representation, boolean loadIndex)
|
Representation representation, boolean loadIndex) throws IOException, InterruptedException {
|
||||||
throws IOException, InterruptedException {
|
|
||||||
RangedUri initializationUri = representation.getInitializationUri();
|
RangedUri initializationUri = representation.getInitializationUri();
|
||||||
if (initializationUri == null) {
|
if (initializationUri == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ChunkExtractorWrapper extractorWrapper = newWrappedExtractor(representation.format);
|
ChunkExtractorWrapper extractorWrapper = newWrappedExtractor(trackType, representation.format);
|
||||||
RangedUri requestUri;
|
RangedUri requestUri;
|
||||||
if (loadIndex) {
|
if (loadIndex) {
|
||||||
RangedUri indexUri = representation.getIndexUri();
|
RangedUri indexUri = representation.getIndexUri();
|
||||||
@ -174,12 +181,12 @@ public final class DashUtil {
|
|||||||
initializationChunk.load();
|
initializationChunk.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ChunkExtractorWrapper newWrappedExtractor(Format format) {
|
private static ChunkExtractorWrapper newWrappedExtractor(int trackType, Format format) {
|
||||||
String mimeType = format.containerMimeType;
|
String mimeType = format.containerMimeType;
|
||||||
boolean isWebm = mimeType.startsWith(MimeTypes.VIDEO_WEBM)
|
boolean isWebm = mimeType.startsWith(MimeTypes.VIDEO_WEBM)
|
||||||
|| mimeType.startsWith(MimeTypes.AUDIO_WEBM);
|
|| mimeType.startsWith(MimeTypes.AUDIO_WEBM);
|
||||||
Extractor extractor = isWebm ? new MatroskaExtractor() : new FragmentedMp4Extractor();
|
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) {
|
private static Representation getFirstRepresentation(Period period, int type) {
|
||||||
|
@ -134,8 +134,8 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
representationHolders = new RepresentationHolder[trackSelection.length()];
|
representationHolders = new RepresentationHolder[trackSelection.length()];
|
||||||
for (int i = 0; i < representationHolders.length; i++) {
|
for (int i = 0; i < representationHolders.length; i++) {
|
||||||
Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
|
Representation representation = representations.get(trackSelection.getIndexInTrackGroup(i));
|
||||||
representationHolders[i] = new RepresentationHolder(periodDurationUs, representation,
|
representationHolders[i] = new RepresentationHolder(periodDurationUs, trackType,
|
||||||
enableEventMessageTrack, enableCea608Track);
|
representation, enableEventMessageTrack, enableCea608Track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,8 +390,8 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
|||||||
private long periodDurationUs;
|
private long periodDurationUs;
|
||||||
private int segmentNumShift;
|
private int segmentNumShift;
|
||||||
|
|
||||||
/* package */ RepresentationHolder(long periodDurationUs, Representation representation,
|
/* package */ RepresentationHolder(long periodDurationUs, int trackType,
|
||||||
boolean enableEventMessageTrack, boolean enableCea608Track) {
|
Representation representation, boolean enableEventMessageTrack, boolean enableCea608Track) {
|
||||||
this.periodDurationUs = periodDurationUs;
|
this.periodDurationUs = periodDurationUs;
|
||||||
this.representation = representation;
|
this.representation = representation;
|
||||||
String containerMimeType = representation.format.containerMimeType;
|
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,
|
// 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, representation.format);
|
extractorWrapper = new ChunkExtractorWrapper(extractor, trackType, representation.format);
|
||||||
}
|
}
|
||||||
segmentIndex = representation.getIndex();
|
segmentIndex = representation.getIndex();
|
||||||
}
|
}
|
||||||
|
@ -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, null, track);
|
| FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX, null, track);
|
||||||
extractorWrappers[i] = new ChunkExtractorWrapper(extractor, format);
|
extractorWrappers[i] = new ChunkExtractorWrapper(extractor, streamElement.type, format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user