HLS: Fix key rotation
Passing EXT-X-KEY DrmInitData through the FragmentedMp4Extractor doesn't work for streams with key rotation, because an extractor instance is used for multiple segments, but is only passed the EXT-X-KEY DrmInitData corresponding to the first segment. This change removes passing DrmInitData through the extractor, and instead passes it via FormatAdjustingSampleQueue. This is in-line with how manifest DrmInitData is handled during DASH playbacks. Issue: #6903 PiperOrigin-RevId: 292323429
This commit is contained in:
parent
cf06589029
commit
ff822ff9fd
@ -25,6 +25,8 @@
|
||||
* Fix `SubtitlePainter` to render `EDGE_TYPE_OUTLINE` using the correct color
|
||||
([#6724](https://github.com/google/ExoPlayer/pull/6724)).
|
||||
* DRM: Add support for attaching DRM sessions to clear content in the demo app.
|
||||
* HLS: Fix playback of DRM protected content that uses key rotation
|
||||
([#6903](https://github.com/google/ExoPlayer/issues/6903)).
|
||||
* Downloads: Merge downloads in `SegmentDownloader` to improve overall download
|
||||
speed ([#5978](https://github.com/google/ExoPlayer/issues/5978)).
|
||||
* MP3: Add `IndexSeeker` for accurate seeks in VBR streams
|
||||
|
@ -804,10 +804,12 @@ public class DefaultDashChunkSource implements DashChunkSource {
|
||||
}
|
||||
extractor =
|
||||
new FragmentedMp4Extractor(
|
||||
flags, null, null, null, closedCaptionFormats, playerEmsgTrackOutput);
|
||||
flags,
|
||||
/* timestampAdjuster= */ null,
|
||||
/* sideloadedTrack= */ null,
|
||||
closedCaptionFormats,
|
||||
playerEmsgTrackOutput);
|
||||
}
|
||||
// Prefer drmInitData obtained from the manifest over drmInitData obtained from the stream,
|
||||
// as per DASH IF Interoperability Recommendations V3.0, 7.5.3.
|
||||
return new ChunkExtractorWrapper(extractor, trackType, representation.format);
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +129,6 @@ public class FragmentedMp4Extractor implements Extractor {
|
||||
|
||||
// Sideloaded data.
|
||||
private final List<Format> closedCaptionFormats;
|
||||
@Nullable private final DrmInitData sideloadedDrmInitData;
|
||||
|
||||
// Track-linked data bundle, accessible as a whole through trackID.
|
||||
private final SparseArray<TrackBundle> trackBundles;
|
||||
@ -185,7 +184,7 @@ public class FragmentedMp4Extractor implements Extractor {
|
||||
* @param flags Flags that control the extractor's behavior.
|
||||
*/
|
||||
public FragmentedMp4Extractor(@Flags int flags) {
|
||||
this(flags, null);
|
||||
this(flags, /* timestampAdjuster= */ null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -193,7 +192,7 @@ public class FragmentedMp4Extractor implements Extractor {
|
||||
* @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed.
|
||||
*/
|
||||
public FragmentedMp4Extractor(@Flags int flags, @Nullable TimestampAdjuster timestampAdjuster) {
|
||||
this(flags, timestampAdjuster, null, null);
|
||||
this(flags, timestampAdjuster, /* sideloadedTrack= */ null, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -201,15 +200,12 @@ public class FragmentedMp4Extractor implements Extractor {
|
||||
* @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed.
|
||||
* @param sideloadedTrack Sideloaded track information, in the case that the extractor will not
|
||||
* receive a moov box in the input data. Null if a moov box is expected.
|
||||
* @param sideloadedDrmInitData The {@link DrmInitData} to use for encrypted tracks. If null, the
|
||||
* pssh boxes (if present) will be used.
|
||||
*/
|
||||
public FragmentedMp4Extractor(
|
||||
@Flags int flags,
|
||||
@Nullable TimestampAdjuster timestampAdjuster,
|
||||
@Nullable Track sideloadedTrack,
|
||||
@Nullable DrmInitData sideloadedDrmInitData) {
|
||||
this(flags, timestampAdjuster, sideloadedTrack, sideloadedDrmInitData, Collections.emptyList());
|
||||
@Nullable Track sideloadedTrack) {
|
||||
this(flags, timestampAdjuster, sideloadedTrack, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,8 +213,6 @@ public class FragmentedMp4Extractor implements Extractor {
|
||||
* @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed.
|
||||
* @param sideloadedTrack Sideloaded track information, in the case that the extractor will not
|
||||
* receive a moov box in the input data. Null if a moov box is expected.
|
||||
* @param sideloadedDrmInitData The {@link DrmInitData} to use for encrypted tracks. If null, the
|
||||
* pssh boxes (if present) will be used.
|
||||
* @param closedCaptionFormats For tracks that contain SEI messages, the formats of the closed
|
||||
* caption channels to expose.
|
||||
*/
|
||||
@ -226,10 +220,13 @@ public class FragmentedMp4Extractor implements Extractor {
|
||||
@Flags int flags,
|
||||
@Nullable TimestampAdjuster timestampAdjuster,
|
||||
@Nullable Track sideloadedTrack,
|
||||
@Nullable DrmInitData sideloadedDrmInitData,
|
||||
List<Format> closedCaptionFormats) {
|
||||
this(flags, timestampAdjuster, sideloadedTrack, sideloadedDrmInitData,
|
||||
closedCaptionFormats, null);
|
||||
this(
|
||||
flags,
|
||||
timestampAdjuster,
|
||||
sideloadedTrack,
|
||||
closedCaptionFormats,
|
||||
/* additionalEmsgTrackOutput= */ null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -237,8 +234,6 @@ public class FragmentedMp4Extractor implements Extractor {
|
||||
* @param timestampAdjuster Adjusts sample timestamps. May be null if no adjustment is needed.
|
||||
* @param sideloadedTrack Sideloaded track information, in the case that the extractor will not
|
||||
* receive a moov box in the input data. Null if a moov box is expected.
|
||||
* @param sideloadedDrmInitData The {@link DrmInitData} to use for encrypted tracks. If null, the
|
||||
* pssh boxes (if present) will be used.
|
||||
* @param closedCaptionFormats For tracks that contain SEI messages, the formats of the closed
|
||||
* caption channels to expose.
|
||||
* @param additionalEmsgTrackOutput An extra track output that will receive all emsg messages
|
||||
@ -249,13 +244,11 @@ public class FragmentedMp4Extractor implements Extractor {
|
||||
@Flags int flags,
|
||||
@Nullable TimestampAdjuster timestampAdjuster,
|
||||
@Nullable Track sideloadedTrack,
|
||||
@Nullable DrmInitData sideloadedDrmInitData,
|
||||
List<Format> closedCaptionFormats,
|
||||
@Nullable TrackOutput additionalEmsgTrackOutput) {
|
||||
this.flags = flags | (sideloadedTrack != null ? FLAG_SIDELOADED : 0);
|
||||
this.timestampAdjuster = timestampAdjuster;
|
||||
this.sideloadedTrack = sideloadedTrack;
|
||||
this.sideloadedDrmInitData = sideloadedDrmInitData;
|
||||
this.closedCaptionFormats = Collections.unmodifiableList(closedCaptionFormats);
|
||||
this.additionalEmsgTrackOutput = additionalEmsgTrackOutput;
|
||||
eventMessageEncoder = new EventMessageEncoder();
|
||||
@ -470,8 +463,7 @@ public class FragmentedMp4Extractor implements Extractor {
|
||||
private void onMoovContainerAtomRead(ContainerAtom moov) throws ParserException {
|
||||
Assertions.checkState(sideloadedTrack == null, "Unexpected moov box.");
|
||||
|
||||
DrmInitData drmInitData = sideloadedDrmInitData != null ? sideloadedDrmInitData
|
||||
: getDrmInitDataFromAtoms(moov.leafChildren);
|
||||
@Nullable DrmInitData drmInitData = getDrmInitDataFromAtoms(moov.leafChildren);
|
||||
|
||||
// Read declaration of track fragments in the Moov box.
|
||||
ContainerAtom mvex = moov.getContainerAtomOfType(Atom.TYPE_mvex);
|
||||
@ -550,9 +542,8 @@ public class FragmentedMp4Extractor implements Extractor {
|
||||
|
||||
private void onMoofContainerAtomRead(ContainerAtom moof) throws ParserException {
|
||||
parseMoof(moof, trackBundles, flags, scratchBytes);
|
||||
// If drm init data is sideloaded, we ignore pssh boxes.
|
||||
DrmInitData drmInitData = sideloadedDrmInitData != null ? null
|
||||
: getDrmInitDataFromAtoms(moof.leafChildren);
|
||||
|
||||
@Nullable DrmInitData drmInitData = getDrmInitDataFromAtoms(moof.leafChildren);
|
||||
if (drmInitData != null) {
|
||||
int trackCount = trackBundles.size();
|
||||
for (int i = 0; i < trackCount; i++) {
|
||||
@ -1417,6 +1408,7 @@ public class FragmentedMp4Extractor implements Extractor {
|
||||
}
|
||||
|
||||
/** Returns DrmInitData from leaf atoms. */
|
||||
@Nullable
|
||||
private static DrmInitData getDrmInitDataFromAtoms(List<Atom.LeafAtom> leafChildren) {
|
||||
@Nullable ArrayList<SchemeData> schemeDatas = null;
|
||||
int leafChildrenSize = leafChildren.size();
|
||||
|
@ -47,7 +47,11 @@ public final class FragmentedMp4ExtractorTest {
|
||||
ExtractorFactory extractorFactory =
|
||||
getExtractorFactory(
|
||||
Collections.singletonList(
|
||||
Format.createTextSampleFormat(null, MimeTypes.APPLICATION_CEA608, 0, null)));
|
||||
Format.createTextSampleFormat(
|
||||
null,
|
||||
MimeTypes.APPLICATION_CEA608,
|
||||
/* selectionFlags= */ 0,
|
||||
/* language= */ null)));
|
||||
ExtractorAsserts.assertBehavior(extractorFactory, "mp4/sample_fragmented_sei.mp4");
|
||||
}
|
||||
|
||||
@ -64,6 +68,11 @@ public final class FragmentedMp4ExtractorTest {
|
||||
}
|
||||
|
||||
private static ExtractorFactory getExtractorFactory(final List<Format> closedCaptionFormats) {
|
||||
return () -> new FragmentedMp4Extractor(0, null, null, null, closedCaptionFormats);
|
||||
return () ->
|
||||
new FragmentedMp4Extractor(
|
||||
/* flags= */ 0,
|
||||
/* timestampAdjuster= */ null,
|
||||
/* sideloadedTrack= */ null,
|
||||
closedCaptionFormats);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.drm.DrmInitData;
|
||||
import com.google.android.exoplayer2.extractor.Extractor;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||
import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
|
||||
@ -89,7 +88,6 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
Uri uri,
|
||||
Format format,
|
||||
@Nullable List<Format> muxedCaptionFormats,
|
||||
@Nullable DrmInitData drmInitData,
|
||||
TimestampAdjuster timestampAdjuster,
|
||||
Map<String, List<String>> responseHeaders,
|
||||
ExtractorInput extractorInput)
|
||||
@ -111,8 +109,7 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
|
||||
// Try selecting the extractor by the file extension.
|
||||
Extractor extractorByFileExtension =
|
||||
createExtractorByFileExtension(
|
||||
uri, format, muxedCaptionFormats, drmInitData, timestampAdjuster);
|
||||
createExtractorByFileExtension(uri, format, muxedCaptionFormats, timestampAdjuster);
|
||||
extractorInput.resetPeekPosition();
|
||||
if (sniffQuietly(extractorByFileExtension, extractorInput)) {
|
||||
return buildResult(extractorByFileExtension);
|
||||
@ -159,7 +156,7 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
|
||||
if (!(extractorByFileExtension instanceof FragmentedMp4Extractor)) {
|
||||
FragmentedMp4Extractor fragmentedMp4Extractor =
|
||||
createFragmentedMp4Extractor(timestampAdjuster, format, drmInitData, muxedCaptionFormats);
|
||||
createFragmentedMp4Extractor(timestampAdjuster, format, muxedCaptionFormats);
|
||||
if (sniffQuietly(fragmentedMp4Extractor, extractorInput)) {
|
||||
return buildResult(fragmentedMp4Extractor);
|
||||
}
|
||||
@ -186,7 +183,6 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
Uri uri,
|
||||
Format format,
|
||||
@Nullable List<Format> muxedCaptionFormats,
|
||||
@Nullable DrmInitData drmInitData,
|
||||
TimestampAdjuster timestampAdjuster) {
|
||||
String lastPathSegment = uri.getLastPathSegment();
|
||||
if (lastPathSegment == null) {
|
||||
@ -209,8 +205,7 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
|| lastPathSegment.startsWith(M4_FILE_EXTENSION_PREFIX, lastPathSegment.length() - 4)
|
||||
|| lastPathSegment.startsWith(MP4_FILE_EXTENSION_PREFIX, lastPathSegment.length() - 5)
|
||||
|| lastPathSegment.startsWith(CMF_FILE_EXTENSION_PREFIX, lastPathSegment.length() - 5)) {
|
||||
return createFragmentedMp4Extractor(
|
||||
timestampAdjuster, format, drmInitData, muxedCaptionFormats);
|
||||
return createFragmentedMp4Extractor(timestampAdjuster, format, muxedCaptionFormats);
|
||||
} else {
|
||||
// For any other file extension, we assume TS format.
|
||||
return createTsExtractor(
|
||||
@ -270,7 +265,6 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
private static FragmentedMp4Extractor createFragmentedMp4Extractor(
|
||||
TimestampAdjuster timestampAdjuster,
|
||||
Format format,
|
||||
@Nullable DrmInitData drmInitData,
|
||||
@Nullable List<Format> muxedCaptionFormats) {
|
||||
// Only enable the EMSG TrackOutput if this is the 'variant' track (i.e. the main one) to avoid
|
||||
// creating a separate EMSG track for every audio track in a video stream.
|
||||
@ -278,7 +272,6 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
/* flags= */ isFmp4Variant(format) ? FragmentedMp4Extractor.FLAG_ENABLE_EMSG_TRACK : 0,
|
||||
timestampAdjuster,
|
||||
/* sideloadedTrack= */ null,
|
||||
drmInitData,
|
||||
muxedCaptionFormats != null ? muxedCaptionFormats : Collections.emptyList());
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,6 @@ package com.google.android.exoplayer2.source.hls;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.drm.DrmInitData;
|
||||
import com.google.android.exoplayer2.extractor.Extractor;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||
import com.google.android.exoplayer2.extractor.PositionHolder;
|
||||
@ -71,7 +70,6 @@ public interface HlsExtractorFactory {
|
||||
* @param format A {@link Format} associated with the chunk to extract.
|
||||
* @param muxedCaptionFormats List of muxed caption {@link Format}s. Null if no closed caption
|
||||
* information is available in the master playlist.
|
||||
* @param drmInitData {@link DrmInitData} associated with the chunk.
|
||||
* @param timestampAdjuster Adjuster corresponding to the provided discontinuity sequence number.
|
||||
* @param responseHeaders The HTTP response headers associated with the media segment or
|
||||
* initialization section to extract.
|
||||
@ -87,7 +85,6 @@ public interface HlsExtractorFactory {
|
||||
Uri uri,
|
||||
Format format,
|
||||
@Nullable List<Format> muxedCaptionFormats,
|
||||
@Nullable DrmInitData drmInitData,
|
||||
TimestampAdjuster timestampAdjuster,
|
||||
Map<String, List<String>> responseHeaders,
|
||||
ExtractorInput sniffingExtractorInput)
|
||||
|
@ -388,7 +388,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
private DefaultExtractorInput prepareExtraction(DataSource dataSource, DataSpec dataSpec)
|
||||
throws IOException, InterruptedException {
|
||||
long bytesToRead = dataSource.open(dataSpec);
|
||||
|
||||
DefaultExtractorInput extractorInput =
|
||||
new DefaultExtractorInput(dataSource, dataSpec.absoluteStreamPosition, bytesToRead);
|
||||
|
||||
@ -402,7 +401,6 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
dataSpec.uri,
|
||||
trackFormat,
|
||||
muxedCaptionFormats,
|
||||
drmInitData,
|
||||
timestampAdjuster,
|
||||
dataSource.getResponseHeaders(),
|
||||
extractorInput);
|
||||
@ -421,7 +419,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
output.onNewExtractor();
|
||||
extractor.init(output);
|
||||
}
|
||||
|
||||
output.setDrmInitData(drmInitData);
|
||||
return extractorInput;
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
private final ArrayList<HlsSampleStream> hlsSampleStreams;
|
||||
private final Map<String, DrmInitData> overridingDrmInitData;
|
||||
|
||||
private SampleQueue[] sampleQueues;
|
||||
private FormatAdjustingSampleQueue[] sampleQueues;
|
||||
private int[] sampleQueueTrackIds;
|
||||
private Set<Integer> sampleQueueMappingDoneByType;
|
||||
private SparseIntArray sampleQueueIndicesByType;
|
||||
@ -162,6 +162,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
// Accessed only by the loading thread.
|
||||
private boolean tracksEnded;
|
||||
private long sampleOffsetUs;
|
||||
@Nullable private DrmInitData drmInitData;
|
||||
private int chunkUid;
|
||||
|
||||
/**
|
||||
@ -207,7 +208,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
sampleQueueTrackIds = new int[0];
|
||||
sampleQueueMappingDoneByType = new HashSet<>(MAPPABLE_TYPES.size());
|
||||
sampleQueueIndicesByType = new SparseIntArray(MAPPABLE_TYPES.size());
|
||||
sampleQueues = new SampleQueue[0];
|
||||
sampleQueues = new FormatAdjustingSampleQueue[0];
|
||||
sampleQueueIsAudioVideoFlags = new boolean[0];
|
||||
sampleQueuesEnabledStates = new boolean[0];
|
||||
mediaChunks = new ArrayList<>();
|
||||
@ -904,8 +905,12 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
private SampleQueue createSampleQueue(int id, int type) {
|
||||
int trackCount = sampleQueues.length;
|
||||
|
||||
SampleQueue trackOutput =
|
||||
boolean isAudioVideo = type == C.TRACK_TYPE_AUDIO || type == C.TRACK_TYPE_VIDEO;
|
||||
FormatAdjustingSampleQueue trackOutput =
|
||||
new FormatAdjustingSampleQueue(allocator, drmSessionManager, overridingDrmInitData);
|
||||
if (isAudioVideo) {
|
||||
trackOutput.setDrmInitData(drmInitData);
|
||||
}
|
||||
trackOutput.setSampleOffsetUs(sampleOffsetUs);
|
||||
trackOutput.sourceId(chunkUid);
|
||||
trackOutput.setUpstreamFormatChangeListener(this);
|
||||
@ -913,8 +918,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
sampleQueueTrackIds[trackCount] = id;
|
||||
sampleQueues = Util.nullSafeArrayAppend(sampleQueues, trackOutput);
|
||||
sampleQueueIsAudioVideoFlags = Arrays.copyOf(sampleQueueIsAudioVideoFlags, trackCount + 1);
|
||||
sampleQueueIsAudioVideoFlags[trackCount] =
|
||||
type == C.TRACK_TYPE_AUDIO || type == C.TRACK_TYPE_VIDEO;
|
||||
sampleQueueIsAudioVideoFlags[trackCount] = isAudioVideo;
|
||||
haveAudioVideoSampleQueues |= sampleQueueIsAudioVideoFlags[trackCount];
|
||||
sampleQueueMappingDoneByType.add(type);
|
||||
sampleQueueIndicesByType.append(type, trackCount);
|
||||
@ -951,10 +955,53 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
sampleQueueMappingDoneByType.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an offset that will be added to the timestamps (and sub-sample timestamps) of samples that
|
||||
* are subsequently loaded by this wrapper.
|
||||
*
|
||||
* @param sampleOffsetUs The timestamp offset in microseconds.
|
||||
*/
|
||||
public void setSampleOffsetUs(long sampleOffsetUs) {
|
||||
this.sampleOffsetUs = sampleOffsetUs;
|
||||
for (SampleQueue sampleQueue : sampleQueues) {
|
||||
sampleQueue.setSampleOffsetUs(sampleOffsetUs);
|
||||
if (this.sampleOffsetUs != sampleOffsetUs) {
|
||||
this.sampleOffsetUs = sampleOffsetUs;
|
||||
for (SampleQueue sampleQueue : sampleQueues) {
|
||||
sampleQueue.setSampleOffsetUs(sampleOffsetUs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets default {@link DrmInitData} for samples that are subsequently loaded by this wrapper.
|
||||
*
|
||||
* <p>This method should be called prior to loading each {@link HlsMediaChunk}. The {@link
|
||||
* DrmInitData} passed should be that of an EXT-X-KEY tag that applies to the chunk, or {@code
|
||||
* null} otherwise.
|
||||
*
|
||||
* <p>The final {@link DrmInitData} for subsequently queued samples is determined as followed:
|
||||
*
|
||||
* <ol>
|
||||
* <li>It is initially set to {@code drmInitData}, unless {@code drmInitData} is null in which
|
||||
* case it's set to {@link Format#drmInitData} of the upstream {@link Format}.
|
||||
* <li>If the initial {@link DrmInitData} is non-null and {@link #overridingDrmInitData}
|
||||
* contains an entry whose key matches the {@link DrmInitData#schemeType}, then the sample's
|
||||
* {@link DrmInitData} is overridden to be this entry's value.
|
||||
* </ol>
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* @param drmInitData The default {@link DrmInitData} for samples that are subsequently queued. If
|
||||
* non-null then it takes precedence over {@link Format#drmInitData} of the upstream {@link
|
||||
* Format}, but will still be overridden by a matching override in {@link
|
||||
* #overridingDrmInitData}.
|
||||
*/
|
||||
public void setDrmInitData(@Nullable DrmInitData drmInitData) {
|
||||
if (!Util.areEqual(this.drmInitData, drmInitData)) {
|
||||
this.drmInitData = drmInitData;
|
||||
for (int i = 0; i < sampleQueues.length; i++) {
|
||||
if (sampleQueueIsAudioVideoFlags[i]) {
|
||||
sampleQueues[i].setDrmInitData(drmInitData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1280,6 +1327,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
private static final class FormatAdjustingSampleQueue extends SampleQueue {
|
||||
|
||||
private final Map<String, DrmInitData> overridingDrmInitData;
|
||||
@Nullable private DrmInitData drmInitData;
|
||||
|
||||
public FormatAdjustingSampleQueue(
|
||||
Allocator allocator,
|
||||
@ -1289,9 +1337,15 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
this.overridingDrmInitData = overridingDrmInitData;
|
||||
}
|
||||
|
||||
public void setDrmInitData(@Nullable DrmInitData drmInitData) {
|
||||
this.drmInitData = drmInitData;
|
||||
invalidateUpstreamFormatAdjustment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Format getAdjustedUpstreamFormat(Format format) {
|
||||
@Nullable DrmInitData drmInitData = format.drmInitData;
|
||||
@Nullable
|
||||
DrmInitData drmInitData = this.drmInitData != null ? this.drmInitData : format.drmInitData;
|
||||
if (drmInitData != null) {
|
||||
@Nullable
|
||||
DrmInitData overridingDrmInitData = this.overridingDrmInitData.get(drmInitData.schemeType);
|
||||
|
Loading…
x
Reference in New Issue
Block a user