Set LogSessionId on MediaParser for HLS sources.
This requires some plumbing through HlsMediaPeriod and HlsChunkSource. PiperOrigin-RevId: 411004283
This commit is contained in:
parent
25f408e6a9
commit
dad44a1c94
@ -22,6 +22,7 @@ import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.analytics.PlayerId;
|
||||
import com.google.android.exoplayer2.extractor.Extractor;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||
import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
|
||||
@ -94,7 +95,8 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory {
|
||||
@Nullable List<Format> muxedCaptionFormats,
|
||||
TimestampAdjuster timestampAdjuster,
|
||||
Map<String, List<String>> responseHeaders,
|
||||
ExtractorInput sniffingExtractorInput)
|
||||
ExtractorInput sniffingExtractorInput,
|
||||
PlayerId playerId)
|
||||
throws IOException {
|
||||
@FileTypes.Type
|
||||
int formatInferredFileType = FileTypes.inferFileTypeFromMimeType(format.sampleMimeType);
|
||||
|
@ -26,6 +26,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.analytics.PlayerId;
|
||||
import com.google.android.exoplayer2.source.BehindLiveWindowException;
|
||||
import com.google.android.exoplayer2.source.TrackGroup;
|
||||
import com.google.android.exoplayer2.source.chunk.BaseMediaChunkIterator;
|
||||
@ -122,6 +123,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
private final TrackGroup trackGroup;
|
||||
@Nullable private final List<Format> muxedCaptionFormats;
|
||||
private final FullSegmentEncryptionKeyCache keyCache;
|
||||
private final PlayerId playerId;
|
||||
|
||||
private boolean isTimestampMaster;
|
||||
private byte[] scratchSpace;
|
||||
@ -161,13 +163,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
HlsDataSourceFactory dataSourceFactory,
|
||||
@Nullable TransferListener mediaTransferListener,
|
||||
TimestampAdjusterProvider timestampAdjusterProvider,
|
||||
@Nullable List<Format> muxedCaptionFormats) {
|
||||
@Nullable List<Format> muxedCaptionFormats,
|
||||
PlayerId playerId) {
|
||||
this.extractorFactory = extractorFactory;
|
||||
this.playlistTracker = playlistTracker;
|
||||
this.playlistUrls = playlistUrls;
|
||||
this.playlistFormats = playlistFormats;
|
||||
this.timestampAdjusterProvider = timestampAdjusterProvider;
|
||||
this.muxedCaptionFormats = muxedCaptionFormats;
|
||||
this.playerId = playerId;
|
||||
keyCache = new FullSegmentEncryptionKeyCache(KEY_CACHE_SIZE);
|
||||
scratchSpace = Util.EMPTY_BYTE_ARRAY;
|
||||
liveEdgeInPeriodTimeUs = C.TIME_UNSET;
|
||||
@ -453,7 +457,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
previous,
|
||||
/* mediaSegmentKey= */ keyCache.get(mediaSegmentKeyUri),
|
||||
/* initSegmentKey= */ keyCache.get(initSegmentKeyUri),
|
||||
shouldSpliceIn);
|
||||
shouldSpliceIn,
|
||||
playerId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -18,6 +18,7 @@ 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.analytics.PlayerId;
|
||||
import com.google.android.exoplayer2.extractor.Extractor;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||
import com.google.android.exoplayer2.extractor.PositionHolder;
|
||||
@ -44,6 +45,7 @@ public interface HlsExtractorFactory {
|
||||
* @param sniffingExtractorInput The first extractor input that will be passed to the returned
|
||||
* extractor's {@link Extractor#read(ExtractorInput, PositionHolder)}. Must only be used to
|
||||
* call {@link Extractor#sniff(ExtractorInput)}.
|
||||
* @param playerId The {@link PlayerId} of the player using this extractors factory.
|
||||
* @return An {@link HlsMediaChunkExtractor}.
|
||||
* @throws IOException If an I/O error is encountered while sniffing.
|
||||
*/
|
||||
@ -53,6 +55,7 @@ public interface HlsExtractorFactory {
|
||||
@Nullable List<Format> muxedCaptionFormats,
|
||||
TimestampAdjuster timestampAdjuster,
|
||||
Map<String, List<String>> responseHeaders,
|
||||
ExtractorInput sniffingExtractorInput)
|
||||
ExtractorInput sniffingExtractorInput,
|
||||
PlayerId playerId)
|
||||
throws IOException;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import android.net.Uri;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.analytics.PlayerId;
|
||||
import com.google.android.exoplayer2.drm.DrmInitData;
|
||||
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||
@ -91,7 +92,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
@Nullable HlsMediaChunk previousChunk,
|
||||
@Nullable byte[] mediaSegmentKey,
|
||||
@Nullable byte[] initSegmentKey,
|
||||
boolean shouldSpliceIn) {
|
||||
boolean shouldSpliceIn,
|
||||
PlayerId playerId) {
|
||||
// Media segment.
|
||||
HlsMediaPlaylist.SegmentBase mediaSegment = segmentBaseHolder.segmentBase;
|
||||
DataSpec dataSpec =
|
||||
@ -184,7 +186,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
previousExtractor,
|
||||
id3Decoder,
|
||||
scratchId3Data,
|
||||
shouldSpliceIn);
|
||||
shouldSpliceIn,
|
||||
playerId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -256,6 +259,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
private final ParsableByteArray scratchId3Data;
|
||||
private final boolean mediaSegmentEncrypted;
|
||||
private final boolean initSegmentEncrypted;
|
||||
private final PlayerId playerId;
|
||||
|
||||
private @MonotonicNonNull HlsMediaChunkExtractor extractor;
|
||||
private @MonotonicNonNull HlsSampleStreamWrapper output;
|
||||
@ -295,7 +299,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
@Nullable HlsMediaChunkExtractor previousExtractor,
|
||||
Id3Decoder id3Decoder,
|
||||
ParsableByteArray scratchId3Data,
|
||||
boolean shouldSpliceIn) {
|
||||
boolean shouldSpliceIn,
|
||||
PlayerId playerId) {
|
||||
super(
|
||||
mediaDataSource,
|
||||
dataSpec,
|
||||
@ -324,6 +329,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
this.id3Decoder = id3Decoder;
|
||||
this.scratchId3Data = scratchId3Data;
|
||||
this.shouldSpliceIn = shouldSpliceIn;
|
||||
this.playerId = playerId;
|
||||
sampleQueueFirstSampleIndices = ImmutableList.of();
|
||||
uid = uidSource.getAndIncrement();
|
||||
}
|
||||
@ -497,7 +503,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
muxedCaptionFormats,
|
||||
timestampAdjuster,
|
||||
dataSource.getResponseHeaders(),
|
||||
extractorInput);
|
||||
extractorInput,
|
||||
playerId);
|
||||
if (extractor.isPackedAudioExtractor()) {
|
||||
output.setSampleOffsetUs(
|
||||
id3Timestamp != C.TIME_UNSET
|
||||
|
@ -21,6 +21,7 @@ import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.SeekParameters;
|
||||
import com.google.android.exoplayer2.analytics.PlayerId;
|
||||
import com.google.android.exoplayer2.drm.DrmInitData;
|
||||
import com.google.android.exoplayer2.drm.DrmSession;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
|
||||
@ -80,6 +81,7 @@ public final class HlsMediaPeriod
|
||||
private final boolean allowChunklessPreparation;
|
||||
private final @HlsMediaSource.MetadataType int metadataType;
|
||||
private final boolean useSessionKeys;
|
||||
private final PlayerId playerId;
|
||||
|
||||
@Nullable private Callback callback;
|
||||
private int pendingPrepareCount;
|
||||
@ -123,7 +125,8 @@ public final class HlsMediaPeriod
|
||||
CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory,
|
||||
boolean allowChunklessPreparation,
|
||||
@HlsMediaSource.MetadataType int metadataType,
|
||||
boolean useSessionKeys) {
|
||||
boolean useSessionKeys,
|
||||
PlayerId playerId) {
|
||||
this.extractorFactory = extractorFactory;
|
||||
this.playlistTracker = playlistTracker;
|
||||
this.dataSourceFactory = dataSourceFactory;
|
||||
@ -137,6 +140,7 @@ public final class HlsMediaPeriod
|
||||
this.allowChunklessPreparation = allowChunklessPreparation;
|
||||
this.metadataType = metadataType;
|
||||
this.useSessionKeys = useSessionKeys;
|
||||
this.playerId = playerId;
|
||||
compositeSequenceableLoader =
|
||||
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader();
|
||||
streamWrapperIndices = new IdentityHashMap<>();
|
||||
@ -771,7 +775,8 @@ public final class HlsMediaPeriod
|
||||
dataSourceFactory,
|
||||
mediaTransferListener,
|
||||
timestampAdjusterProvider,
|
||||
muxedCaptionFormats);
|
||||
muxedCaptionFormats,
|
||||
playerId);
|
||||
return new HlsSampleStreamWrapper(
|
||||
trackType,
|
||||
/* callback= */ this,
|
||||
|
@ -497,7 +497,8 @@ public final class HlsMediaSource extends BaseMediaSource
|
||||
compositeSequenceableLoaderFactory,
|
||||
allowChunklessPreparation,
|
||||
metadataType,
|
||||
useSessionKeys);
|
||||
useSessionKeys,
|
||||
getPlayerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -34,6 +34,7 @@ import android.text.TextUtils;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.analytics.PlayerId;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorOutput;
|
||||
import com.google.android.exoplayer2.source.mediaparser.InputReaderAdapterV30;
|
||||
@ -42,6 +43,7 @@ import com.google.android.exoplayer2.source.mediaparser.OutputConsumerAdapterV30
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.FileTypes;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.io.IOException;
|
||||
|
||||
@ -60,7 +62,8 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt
|
||||
muxedCaptionFormats,
|
||||
timestampAdjuster,
|
||||
responseHeaders,
|
||||
sniffingExtractorInput) -> {
|
||||
sniffingExtractorInput,
|
||||
playerId) -> {
|
||||
if (FileTypes.inferFileTypeFromMimeType(format.sampleMimeType) == FileTypes.WEBVTT) {
|
||||
// The segment contains WebVTT. MediaParser does not support WebVTT parsing, so we use the
|
||||
// bundled extractor.
|
||||
@ -100,6 +103,7 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt
|
||||
format,
|
||||
overrideInBandCaptionDeclarations,
|
||||
muxedCaptionMediaFormats,
|
||||
playerId,
|
||||
MediaParser.PARSER_NAME_FMP4,
|
||||
MediaParser.PARSER_NAME_AC3,
|
||||
MediaParser.PARSER_NAME_AC4,
|
||||
@ -119,7 +123,8 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt
|
||||
format,
|
||||
overrideInBandCaptionDeclarations,
|
||||
muxedCaptionMediaFormats,
|
||||
/* leadingBytesToSkip= */ peekingInputReader.totalPeekedBytes);
|
||||
/* leadingBytesToSkip= */ peekingInputReader.totalPeekedBytes,
|
||||
playerId);
|
||||
};
|
||||
|
||||
private final OutputConsumerAdapterV30 outputConsumerAdapter;
|
||||
@ -128,6 +133,8 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt
|
||||
private final Format format;
|
||||
private final boolean overrideInBandCaptionDeclarations;
|
||||
private final ImmutableList<MediaFormat> muxedCaptionMediaFormats;
|
||||
private final PlayerId playerId;
|
||||
|
||||
private int pendingSkipBytes;
|
||||
|
||||
/**
|
||||
@ -146,6 +153,7 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt
|
||||
* that {@link MediaParser} should expose.
|
||||
* @param leadingBytesToSkip The number of bytes to skip from the start of the input before
|
||||
* starting extraction.
|
||||
* @param playerId The {@link PlayerId} of the player using this chunk extractor.
|
||||
*/
|
||||
public MediaParserHlsMediaChunkExtractor(
|
||||
MediaParser mediaParser,
|
||||
@ -153,12 +161,14 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt
|
||||
Format format,
|
||||
boolean overrideInBandCaptionDeclarations,
|
||||
ImmutableList<MediaFormat> muxedCaptionMediaFormats,
|
||||
int leadingBytesToSkip) {
|
||||
int leadingBytesToSkip,
|
||||
PlayerId playerId) {
|
||||
this.mediaParser = mediaParser;
|
||||
this.outputConsumerAdapter = outputConsumerAdapter;
|
||||
this.overrideInBandCaptionDeclarations = overrideInBandCaptionDeclarations;
|
||||
this.muxedCaptionMediaFormats = muxedCaptionMediaFormats;
|
||||
this.format = format;
|
||||
this.playerId = playerId;
|
||||
pendingSkipBytes = leadingBytesToSkip;
|
||||
inputReaderAdapter = new InputReaderAdapterV30();
|
||||
}
|
||||
@ -203,12 +213,14 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt
|
||||
format,
|
||||
overrideInBandCaptionDeclarations,
|
||||
muxedCaptionMediaFormats,
|
||||
playerId,
|
||||
mediaParser.getParserName()),
|
||||
outputConsumerAdapter,
|
||||
format,
|
||||
overrideInBandCaptionDeclarations,
|
||||
muxedCaptionMediaFormats,
|
||||
/* leadingBytesToSkip= */ 0);
|
||||
/* leadingBytesToSkip= */ 0,
|
||||
playerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -223,6 +235,7 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt
|
||||
Format format,
|
||||
boolean overrideInBandCaptionDeclarations,
|
||||
ImmutableList<MediaFormat> muxedCaptionMediaFormats,
|
||||
PlayerId playerId,
|
||||
String... parserNames) {
|
||||
MediaParser mediaParser =
|
||||
parserNames.length == 1
|
||||
@ -248,6 +261,9 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt
|
||||
mediaParser.setParameter(PARAMETER_TS_IGNORE_AVC_STREAM, true);
|
||||
}
|
||||
}
|
||||
if (Util.SDK_INT >= 31) {
|
||||
MediaParserUtil.setLogSessionIdOnMediaParser(mediaParser, playerId);
|
||||
}
|
||||
return mediaParser;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ import android.net.Uri;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.analytics.PlayerId;
|
||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
||||
import com.google.android.exoplayer2.extractor.ExtractorInput;
|
||||
import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
|
||||
@ -79,7 +80,8 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
ac3ResponseHeaders,
|
||||
webVttExtractorInput);
|
||||
webVttExtractorInput,
|
||||
PlayerId.UNSET);
|
||||
|
||||
assertThat(result.extractor.getClass()).isEqualTo(WebvttExtractor.class);
|
||||
}
|
||||
@ -103,7 +105,8 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
ac3ResponseHeaders,
|
||||
ac3ExtractorInput);
|
||||
ac3ExtractorInput,
|
||||
PlayerId.UNSET);
|
||||
|
||||
assertThat(result.extractor.getClass()).isEqualTo(Ac3Extractor.class);
|
||||
}
|
||||
@ -125,7 +128,8 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
ac3ResponseHeaders,
|
||||
tsExtractorInput);
|
||||
tsExtractorInput,
|
||||
PlayerId.UNSET);
|
||||
|
||||
assertThat(result.extractor.getClass()).isEqualTo(TsExtractor.class);
|
||||
}
|
||||
@ -148,7 +152,8 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
ac3ResponseHeaders,
|
||||
mp3ExtractorInput);
|
||||
mp3ExtractorInput,
|
||||
PlayerId.UNSET);
|
||||
|
||||
assertThat(result.extractor.getClass()).isEqualTo(Mp3Extractor.class);
|
||||
}
|
||||
@ -170,7 +175,8 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
ImmutableMap.of("Content-Type", ImmutableList.of(MimeTypes.IMAGE_JPEG)),
|
||||
tsExtractorInput);
|
||||
tsExtractorInput,
|
||||
PlayerId.UNSET);
|
||||
|
||||
assertThat(result.extractor.getClass()).isEqualTo(TsExtractor.class);
|
||||
}
|
||||
@ -187,7 +193,8 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
ac3ResponseHeaders,
|
||||
emptyExtractorInput);
|
||||
emptyExtractorInput,
|
||||
PlayerId.UNSET);
|
||||
|
||||
// The format indicates WebVTT so we expect a WebVTT extractor.
|
||||
assertThat(result.extractor.getClass()).isEqualTo(WebvttExtractor.class);
|
||||
@ -205,7 +212,8 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
ac3ResponseHeaders,
|
||||
emptyExtractorInput);
|
||||
emptyExtractorInput,
|
||||
PlayerId.UNSET);
|
||||
|
||||
// No format info, so we expect an AC-3 Extractor, as per HTTP Content-Type header.
|
||||
assertThat(result.extractor.getClass()).isEqualTo(Ac3Extractor.class);
|
||||
@ -223,7 +231,8 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
/* responseHeaders= */ ImmutableMap.of(),
|
||||
emptyExtractorInput);
|
||||
emptyExtractorInput,
|
||||
PlayerId.UNSET);
|
||||
|
||||
// No format info, and no HTTP headers, so we expect an fMP4 extractor, as per file extension.
|
||||
assertThat(result.extractor.getClass()).isEqualTo(FragmentedMp4Extractor.class);
|
||||
@ -241,7 +250,8 @@ public class DefaultHlsExtractorFactoryTest {
|
||||
/* muxedCaptionFormats= */ null,
|
||||
timestampAdjuster,
|
||||
/* responseHeaders= */ ImmutableMap.of(),
|
||||
emptyExtractorInput);
|
||||
emptyExtractorInput,
|
||||
PlayerId.UNSET);
|
||||
|
||||
// There's no information for inferring the file type, we expect the factory to fall back on
|
||||
// Transport Stream.
|
||||
|
@ -22,6 +22,7 @@ import static org.mockito.Mockito.when;
|
||||
import android.net.Uri;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.analytics.PlayerId;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||
import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory;
|
||||
@ -92,7 +93,8 @@ public final class HlsMediaPeriodTest {
|
||||
mock(CompositeSequenceableLoaderFactory.class),
|
||||
/* allowChunklessPreparation= */ true,
|
||||
HlsMediaSource.METADATA_TYPE_ID3,
|
||||
/* useSessionKeys= */ false);
|
||||
/* useSessionKeys= */ false,
|
||||
PlayerId.UNSET);
|
||||
};
|
||||
|
||||
MediaPeriodAsserts.assertGetStreamKeysAndManifestFilterIntegration(
|
||||
|
Loading…
x
Reference in New Issue
Block a user