From 0f766bc3d9f782c5376ba38f5799f9d1ac0681af Mon Sep 17 00:00:00 2001 From: tonihei Date: Fri, 19 Nov 2021 09:50:40 +0000 Subject: [PATCH] Set LogSessionId on MediaParser for HLS sources. This requires some plumbing through HlsMediaPeriod and HlsChunkSource. PiperOrigin-RevId: 411004283 --- .../hls/DefaultHlsExtractorFactory.java | 4 ++- .../media3/exoplayer/hls/HlsChunkSource.java | 9 ++++-- .../exoplayer/hls/HlsExtractorFactory.java | 5 +++- .../media3/exoplayer/hls/HlsMediaChunk.java | 15 +++++++--- .../media3/exoplayer/hls/HlsMediaPeriod.java | 9 ++++-- .../media3/exoplayer/hls/HlsMediaSource.java | 3 +- .../MediaParserHlsMediaChunkExtractor.java | 24 +++++++++++++--- .../hls/DefaultHlsExtractorFactoryTest.java | 28 +++++++++++++------ .../exoplayer/hls/HlsMediaPeriodTest.java | 4 ++- 9 files changed, 76 insertions(+), 25 deletions(-) diff --git a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/DefaultHlsExtractorFactory.java b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/DefaultHlsExtractorFactory.java index f82afa7ebd..46b1eef247 100644 --- a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/DefaultHlsExtractorFactory.java +++ b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/DefaultHlsExtractorFactory.java @@ -27,6 +27,7 @@ import androidx.media3.common.Metadata; import androidx.media3.common.MimeTypes; import androidx.media3.common.util.TimestampAdjuster; import androidx.media3.common.util.UnstableApi; +import androidx.media3.exoplayer.analytics.PlayerId; import androidx.media3.extractor.Extractor; import androidx.media3.extractor.ExtractorInput; import androidx.media3.extractor.mp3.Mp3Extractor; @@ -96,7 +97,8 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory { @Nullable List muxedCaptionFormats, TimestampAdjuster timestampAdjuster, Map> responseHeaders, - ExtractorInput sniffingExtractorInput) + ExtractorInput sniffingExtractorInput, + PlayerId playerId) throws IOException { @FileTypes.Type int formatInferredFileType = FileTypes.inferFileTypeFromMimeType(format.sampleMimeType); diff --git a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsChunkSource.java b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsChunkSource.java index f7c6f1a6ec..1ed52ee6f9 100644 --- a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsChunkSource.java +++ b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsChunkSource.java @@ -33,6 +33,7 @@ import androidx.media3.common.util.Util; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DataSpec; import androidx.media3.datasource.TransferListener; +import androidx.media3.exoplayer.analytics.PlayerId; import androidx.media3.exoplayer.hls.playlist.HlsMediaPlaylist; import androidx.media3.exoplayer.hls.playlist.HlsMediaPlaylist.Segment; import androidx.media3.exoplayer.hls.playlist.HlsPlaylistTracker; @@ -122,6 +123,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private final TrackGroup trackGroup; @Nullable private final List 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 muxedCaptionFormats) { + @Nullable List 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 diff --git a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsExtractorFactory.java b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsExtractorFactory.java index 97eed51939..d5a7908786 100644 --- a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsExtractorFactory.java +++ b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsExtractorFactory.java @@ -20,6 +20,7 @@ import androidx.annotation.Nullable; import androidx.media3.common.Format; import androidx.media3.common.util.TimestampAdjuster; import androidx.media3.common.util.UnstableApi; +import androidx.media3.exoplayer.analytics.PlayerId; import androidx.media3.extractor.Extractor; import androidx.media3.extractor.ExtractorInput; import androidx.media3.extractor.PositionHolder; @@ -46,6 +47,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. */ @@ -55,6 +57,7 @@ public interface HlsExtractorFactory { @Nullable List muxedCaptionFormats, TimestampAdjuster timestampAdjuster, Map> responseHeaders, - ExtractorInput sniffingExtractorInput) + ExtractorInput sniffingExtractorInput, + PlayerId playerId) throws IOException; } diff --git a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaChunk.java b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaChunk.java index 5b138d35cd..d39d0561f7 100644 --- a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaChunk.java +++ b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaChunk.java @@ -30,6 +30,7 @@ import androidx.media3.common.util.UriUtil; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DataSourceUtil; import androidx.media3.datasource.DataSpec; +import androidx.media3.exoplayer.analytics.PlayerId; import androidx.media3.exoplayer.hls.playlist.HlsMediaPlaylist; import androidx.media3.exoplayer.source.chunk.MediaChunk; import androidx.media3.extractor.DefaultExtractorInput; @@ -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 diff --git a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaPeriod.java b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaPeriod.java index 8432d69205..dac6de0673 100644 --- a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaPeriod.java +++ b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaPeriod.java @@ -32,6 +32,7 @@ import androidx.media3.common.util.Util; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.TransferListener; import androidx.media3.exoplayer.SeekParameters; +import androidx.media3.exoplayer.analytics.PlayerId; import androidx.media3.exoplayer.drm.DrmSession; import androidx.media3.exoplayer.drm.DrmSessionEventListener; import androidx.media3.exoplayer.drm.DrmSessionManager; @@ -82,6 +83,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; @@ -125,7 +127,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; @@ -139,6 +142,7 @@ public final class HlsMediaPeriod this.allowChunklessPreparation = allowChunklessPreparation; this.metadataType = metadataType; this.useSessionKeys = useSessionKeys; + this.playerId = playerId; compositeSequenceableLoader = compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(); streamWrapperIndices = new IdentityHashMap<>(); @@ -773,7 +777,8 @@ public final class HlsMediaPeriod dataSourceFactory, mediaTransferListener, timestampAdjusterProvider, - muxedCaptionFormats); + muxedCaptionFormats, + playerId); return new HlsSampleStreamWrapper( trackType, /* callback= */ this, diff --git a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaSource.java b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaSource.java index 7549468ac7..66c2612465 100644 --- a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaSource.java +++ b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/HlsMediaSource.java @@ -499,7 +499,8 @@ public final class HlsMediaSource extends BaseMediaSource compositeSequenceableLoaderFactory, allowChunklessPreparation, metadataType, - useSessionKeys); + useSessionKeys, + getPlayerId()); } @Override diff --git a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/MediaParserHlsMediaChunkExtractor.java b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/MediaParserHlsMediaChunkExtractor.java index 50a568c5c6..744dea5bec 100644 --- a/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/MediaParserHlsMediaChunkExtractor.java +++ b/libraries/exoplayer_hls/src/main/java/androidx/media3/exoplayer/hls/MediaParserHlsMediaChunkExtractor.java @@ -38,6 +38,8 @@ import androidx.media3.common.Format; import androidx.media3.common.MimeTypes; import androidx.media3.common.util.Assertions; import androidx.media3.common.util.UnstableApi; +import androidx.media3.common.util.Util; +import androidx.media3.exoplayer.analytics.PlayerId; import androidx.media3.exoplayer.source.mediaparser.InputReaderAdapterV30; import androidx.media3.exoplayer.source.mediaparser.MediaParserUtil; import androidx.media3.exoplayer.source.mediaparser.OutputConsumerAdapterV30; @@ -62,7 +64,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. @@ -102,6 +105,7 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt format, overrideInBandCaptionDeclarations, muxedCaptionMediaFormats, + playerId, MediaParser.PARSER_NAME_FMP4, MediaParser.PARSER_NAME_AC3, MediaParser.PARSER_NAME_AC4, @@ -121,7 +125,8 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt format, overrideInBandCaptionDeclarations, muxedCaptionMediaFormats, - /* leadingBytesToSkip= */ peekingInputReader.totalPeekedBytes); + /* leadingBytesToSkip= */ peekingInputReader.totalPeekedBytes, + playerId); }; private final OutputConsumerAdapterV30 outputConsumerAdapter; @@ -130,6 +135,8 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt private final Format format; private final boolean overrideInBandCaptionDeclarations; private final ImmutableList muxedCaptionMediaFormats; + private final PlayerId playerId; + private int pendingSkipBytes; /** @@ -148,6 +155,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, @@ -155,12 +163,14 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt Format format, boolean overrideInBandCaptionDeclarations, ImmutableList 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(); } @@ -205,12 +215,14 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt format, overrideInBandCaptionDeclarations, muxedCaptionMediaFormats, + playerId, mediaParser.getParserName()), outputConsumerAdapter, format, overrideInBandCaptionDeclarations, muxedCaptionMediaFormats, - /* leadingBytesToSkip= */ 0); + /* leadingBytesToSkip= */ 0, + playerId); } @Override @@ -225,6 +237,7 @@ public final class MediaParserHlsMediaChunkExtractor implements HlsMediaChunkExt Format format, boolean overrideInBandCaptionDeclarations, ImmutableList muxedCaptionMediaFormats, + PlayerId playerId, String... parserNames) { MediaParser mediaParser = parserNames.length == 1 @@ -250,6 +263,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; } diff --git a/libraries/exoplayer_hls/src/test/java/androidx/media3/exoplayer/hls/DefaultHlsExtractorFactoryTest.java b/libraries/exoplayer_hls/src/test/java/androidx/media3/exoplayer/hls/DefaultHlsExtractorFactoryTest.java index bf511648e2..f030705e66 100644 --- a/libraries/exoplayer_hls/src/test/java/androidx/media3/exoplayer/hls/DefaultHlsExtractorFactoryTest.java +++ b/libraries/exoplayer_hls/src/test/java/androidx/media3/exoplayer/hls/DefaultHlsExtractorFactoryTest.java @@ -21,6 +21,7 @@ import android.net.Uri; import androidx.media3.common.Format; import androidx.media3.common.MimeTypes; import androidx.media3.common.util.TimestampAdjuster; +import androidx.media3.exoplayer.analytics.PlayerId; import androidx.media3.extractor.DefaultExtractorsFactory; import androidx.media3.extractor.ExtractorInput; import androidx.media3.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. diff --git a/libraries/exoplayer_hls/src/test/java/androidx/media3/exoplayer/hls/HlsMediaPeriodTest.java b/libraries/exoplayer_hls/src/test/java/androidx/media3/exoplayer/hls/HlsMediaPeriodTest.java index 6caa371c15..1ffa5e7339 100644 --- a/libraries/exoplayer_hls/src/test/java/androidx/media3/exoplayer/hls/HlsMediaPeriodTest.java +++ b/libraries/exoplayer_hls/src/test/java/androidx/media3/exoplayer/hls/HlsMediaPeriodTest.java @@ -24,6 +24,7 @@ import androidx.media3.common.Format; import androidx.media3.common.MimeTypes; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.TransferListener; +import androidx.media3.exoplayer.analytics.PlayerId; import androidx.media3.exoplayer.drm.DrmSessionEventListener; import androidx.media3.exoplayer.drm.DrmSessionManager; import androidx.media3.exoplayer.hls.playlist.HlsMasterPlaylist; @@ -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(