mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Set LogSessionId on MediaParser for HLS sources.
This requires some plumbing through HlsMediaPeriod and HlsChunkSource. PiperOrigin-RevId: 411004283
This commit is contained in:
parent
9af85d9b25
commit
0f766bc3d9
@ -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<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);
|
||||
|
@ -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<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
|
||||
|
@ -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<Format> muxedCaptionFormats,
|
||||
TimestampAdjuster timestampAdjuster,
|
||||
Map<String, List<String>> responseHeaders,
|
||||
ExtractorInput sniffingExtractorInput)
|
||||
ExtractorInput sniffingExtractorInput,
|
||||
PlayerId playerId)
|
||||
throws IOException;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -499,7 +499,8 @@ public final class HlsMediaSource extends BaseMediaSource
|
||||
compositeSequenceableLoaderFactory,
|
||||
allowChunklessPreparation,
|
||||
metadataType,
|
||||
useSessionKeys);
|
||||
useSessionKeys,
|
||||
getPlayerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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<MediaFormat> 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<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();
|
||||
}
|
||||
@ -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<MediaFormat> 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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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(
|
||||
|
Loading…
x
Reference in New Issue
Block a user