diff --git a/library/common/src/main/java/com/google/android/exoplayer2/Format.java b/library/common/src/main/java/com/google/android/exoplayer2/Format.java index cf9935bfb8..5f08704e74 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/Format.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/Format.java @@ -1347,39 +1347,6 @@ public final class Format implements Parcelable { return buildUpon().setLabel(label).build(); } - // TODO: Inline into HlsSampleStreamWrapper and remove. - public Format copyWithContainerInfo( - @Nullable String id, - @Nullable String label, - @Nullable String sampleMimeType, - @Nullable String codecs, - @Nullable Metadata metadata, - int bitrate, - int width, - int height, - int channelCount, - @C.SelectionFlags int selectionFlags, - @Nullable String language) { - if (this.metadata != null) { - metadata = this.metadata.copyWithAppendedEntriesFrom(metadata); - } - - return buildUpon() - .setId(id) - .setLabel(label) - .setLanguage(language) - .setSelectionFlags(selectionFlags) - .setAverageBitrate(bitrate) - .setPeakBitrate(bitrate) - .setMetadata(metadata) - .setCodecs(codecs) - .setSampleMimeType(sampleMimeType) - .setWidth(width) - .setHeight(height) - .setChannelCount(channelCount) - .build(); - } - /** @deprecated Use {@link #withManifestFormatInfo(Format)}. */ @Deprecated public Format copyWithManifestFormatInfo(Format manifestFormat) { diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.java index de4c425c7d..0532904d7a 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/DefaultHlsExtractorFactory.java @@ -235,15 +235,11 @@ public final class DefaultHlsExtractorFactory implements HlsExtractorFactory { // closed caption track on channel 0. muxedCaptionFormats = Collections.singletonList( - Format.createTextSampleFormat( - /* id= */ null, - MimeTypes.APPLICATION_CEA608, - /* selectionFlags= */ 0, - /* language= */ null)); + new Format.Builder().setSampleMimeType(MimeTypes.APPLICATION_CEA608).build()); } else { muxedCaptionFormats = Collections.emptyList(); } - String codecs = format.codecs; + @Nullable String codecs = format.codecs; if (!TextUtils.isEmpty(codecs)) { // Sometimes AAC and H264 streams are declared in TS chunks even though they don't really // exist. If we know from the codec attribute that they don't exist, then we can diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java index b38cc4fefd..5b06c74d2a 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java @@ -659,7 +659,11 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper } TrackGroup id3TrackGroup = - new TrackGroup(Format.createSampleFormat(/* id= */ "ID3", MimeTypes.APPLICATION_ID3)); + new TrackGroup( + new Format.Builder() + .setId("ID3") + .setSampleMimeType(MimeTypes.APPLICATION_ID3) + .build()); muxedTrackGroups.add(id3TrackGroup); sampleStreamWrapper.prepareWithMasterPlaylistInfo( @@ -785,33 +789,34 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper } private static Format deriveVideoFormat(Format variantFormat) { - String codecs = Util.getCodecsOfType(variantFormat.codecs, C.TRACK_TYPE_VIDEO); - String sampleMimeType = MimeTypes.getMediaMimeType(codecs); - return Format.createVideoContainerFormat( - variantFormat.id, - variantFormat.label, - variantFormat.containerMimeType, - sampleMimeType, - codecs, - variantFormat.metadata, - variantFormat.bitrate, - variantFormat.width, - variantFormat.height, - variantFormat.frameRate, - /* initializationData= */ null, - variantFormat.selectionFlags, - variantFormat.roleFlags); + @Nullable String codecs = Util.getCodecsOfType(variantFormat.codecs, C.TRACK_TYPE_VIDEO); + @Nullable String sampleMimeType = MimeTypes.getMediaMimeType(codecs); + return new Format.Builder() + .setId(variantFormat.id) + .setLabel(variantFormat.label) + .setContainerMimeType(variantFormat.containerMimeType) + .setSampleMimeType(sampleMimeType) + .setCodecs(codecs) + .setMetadata(variantFormat.metadata) + .setAverageBitrate(variantFormat.averageBitrate) + .setPeakBitrate(variantFormat.peakBitrate) + .setWidth(variantFormat.width) + .setHeight(variantFormat.height) + .setFrameRate(variantFormat.frameRate) + .setSelectionFlags(variantFormat.selectionFlags) + .setRoleFlags(variantFormat.roleFlags) + .build(); } private static Format deriveAudioFormat( Format variantFormat, @Nullable Format mediaTagFormat, boolean isPrimaryTrackInVariant) { - String codecs; - Metadata metadata; + @Nullable String codecs; + @Nullable Metadata metadata; int channelCount = Format.NO_VALUE; int selectionFlags = 0; int roleFlags = 0; - String language = null; - String label = null; + @Nullable String language = null; + @Nullable String label = null; if (mediaTagFormat != null) { codecs = mediaTagFormat.codecs; metadata = mediaTagFormat.metadata; @@ -831,22 +836,23 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper label = variantFormat.label; } } - String sampleMimeType = MimeTypes.getMediaMimeType(codecs); - int bitrate = isPrimaryTrackInVariant ? variantFormat.bitrate : Format.NO_VALUE; - return Format.createAudioContainerFormat( - variantFormat.id, - label, - variantFormat.containerMimeType, - sampleMimeType, - codecs, - metadata, - bitrate, - channelCount, - /* sampleRate= */ Format.NO_VALUE, - /* initializationData= */ null, - selectionFlags, - roleFlags, - language); + @Nullable String sampleMimeType = MimeTypes.getMediaMimeType(codecs); + int averageBitrate = isPrimaryTrackInVariant ? variantFormat.averageBitrate : Format.NO_VALUE; + int peakBitrate = isPrimaryTrackInVariant ? variantFormat.peakBitrate : Format.NO_VALUE; + return new Format.Builder() + .setId(variantFormat.id) + .setLabel(label) + .setContainerMimeType(variantFormat.containerMimeType) + .setSampleMimeType(sampleMimeType) + .setCodecs(codecs) + .setMetadata(metadata) + .setAverageBitrate(averageBitrate) + .setPeakBitrate(peakBitrate) + .setChannelCount(channelCount) + .setSelectionFlags(selectionFlags) + .setRoleFlags(roleFlags) + .setLanguage(language) + .build(); } } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java index f773136b98..96c3a3c4c6 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java @@ -1269,38 +1269,50 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; * * @param playlistFormat The format information obtained from the master playlist. * @param sampleFormat The format information obtained from the samples. - * @param propagateBitrate Whether the bitrate from the playlist format should be included in the - * derived format. + * @param propagateBitrates Whether the bitrates from the playlist format should be included in + * the derived format. * @return The derived track format. */ private static Format deriveFormat( - @Nullable Format playlistFormat, Format sampleFormat, boolean propagateBitrate) { + @Nullable Format playlistFormat, Format sampleFormat, boolean propagateBitrates) { if (playlistFormat == null) { return sampleFormat; } - int bitrate = propagateBitrate ? playlistFormat.bitrate : Format.NO_VALUE; - int channelCount = - playlistFormat.channelCount != Format.NO_VALUE - ? playlistFormat.channelCount - : sampleFormat.channelCount; + int sampleTrackType = MimeTypes.getTrackType(sampleFormat.sampleMimeType); @Nullable String codecs = Util.getCodecsOfType(playlistFormat.codecs, sampleTrackType); - @Nullable String mimeType = MimeTypes.getMediaMimeType(codecs); - if (mimeType == null) { - mimeType = sampleFormat.sampleMimeType; + @Nullable String sampleMimeType = MimeTypes.getMediaMimeType(codecs); + + Format.Builder formatBuilder = + sampleFormat + .buildUpon() + .setId(playlistFormat.id) + .setLabel(playlistFormat.label) + .setLanguage(playlistFormat.language) + .setSelectionFlags(playlistFormat.selectionFlags) + .setAverageBitrate(propagateBitrates ? playlistFormat.averageBitrate : Format.NO_VALUE) + .setPeakBitrate(propagateBitrates ? playlistFormat.peakBitrate : Format.NO_VALUE) + .setCodecs(codecs) + .setWidth(playlistFormat.width) + .setHeight(playlistFormat.height); + + if (sampleMimeType != null) { + formatBuilder.setSampleMimeType(sampleMimeType); } - return sampleFormat.copyWithContainerInfo( - playlistFormat.id, - playlistFormat.label, - mimeType, - codecs, - playlistFormat.metadata, - bitrate, - playlistFormat.width, - playlistFormat.height, - channelCount, - playlistFormat.selectionFlags, - playlistFormat.language); + + if (playlistFormat.channelCount != Format.NO_VALUE) { + formatBuilder.setChannelCount(playlistFormat.channelCount); + } + + if (playlistFormat.metadata != null) { + Metadata metadata = playlistFormat.metadata; + if (sampleFormat.metadata != null) { + metadata = sampleFormat.metadata.copyWithAppendedEntriesFrom(metadata); + } + formatBuilder.setMetadata(metadata); + } + + return formatBuilder.build(); } private static boolean isMediaChunk(Chunk chunk) { @@ -1409,9 +1421,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; // TODO(ibaker): Create a Formats util class with common constants like this. private static final Format ID3_FORMAT = - Format.createSampleFormat(/* id= */ null, MimeTypes.APPLICATION_ID3); + new Format.Builder().setSampleMimeType(MimeTypes.APPLICATION_ID3).build(); private static final Format EMSG_FORMAT = - Format.createSampleFormat(/* id= */ null, MimeTypes.APPLICATION_EMSG); + new Format.Builder().setSampleMimeType(MimeTypes.APPLICATION_EMSG).build(); private final EventMessageDecoder emsgDecoder; private final TrackOutput delegate; diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java index f8526a81bb..dcc658a608 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java @@ -187,9 +187,11 @@ public final class WebvttExtractor implements Extractor { private TrackOutput buildTrackOutput(long subsampleOffsetUs) { TrackOutput trackOutput = output.track(0, C.TRACK_TYPE_TEXT); trackOutput.format( - Format.createTextSampleFormat( - /* id= */ null, MimeTypes.TEXT_VTT, /* selectionFlags= */ 0, language) - .copyWithSubsampleOffsetUs(subsampleOffsetUs)); + new Format.Builder() + .setSampleMimeType(MimeTypes.TEXT_VTT) + .setLanguage(language) + .setSubsampleOffsetUs(subsampleOffsetUs) + .build()); output.endTracks(); return trackOutput; } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylist.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylist.java index f96c7dfa92..72f6a361d7 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylist.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsMasterPlaylist.java @@ -102,16 +102,7 @@ public final class HlsMasterPlaylist extends HlsPlaylist { */ public static Variant createMediaPlaylistVariantUrl(Uri url) { Format format = - Format.createContainerFormat( - "0", - /* label= */ null, - MimeTypes.APPLICATION_M3U8, - /* sampleMimeType= */ null, - /* codecs= */ null, - /* bitrate= */ Format.NO_VALUE, - /* selectionFlags= */ 0, - /* roleFlags= */ 0, - /* language= */ null); + new Format.Builder().setId("0").setContainerMimeType(MimeTypes.APPLICATION_M3U8).build(); return new Variant( url, format, diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java index edd04735f2..32feb987b8 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/HlsPlaylistParser.java @@ -342,22 +342,17 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser(); } - muxedCaptionFormats.add( - Format.createTextContainerFormat( - /* id= */ formatId, - /* label= */ name, - /* containerMimeType= */ null, - /* sampleMimeType= */ mimeType, - /* codecs= */ null, - /* bitrate= */ Format.NO_VALUE, - selectionFlags, - roleFlags, - language, - accessibilityChannel)); + formatBuilder + .setSampleMimeType(sampleMimeType) + .setAccessibilityChannel(accessibilityChannel); + muxedCaptionFormats.add(formatBuilder.build()); // TODO: Remove muxedCaptionFormats and add a Rendition with a null uri to closedCaptions. break; default: diff --git a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriodTest.java b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriodTest.java index 820c39c197..fe42ebb07e 100644 --- a/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriodTest.java +++ b/library/hls/src/test/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriodTest.java @@ -55,11 +55,11 @@ public final class HlsMediaPeriodTest { HlsMasterPlaylist testMasterPlaylist = createMasterPlaylist( /* variants= */ Arrays.asList( - createAudioOnlyVariant(/* bitrate= */ 10000), - createMuxedVideoAudioVariant(/* bitrate= */ 200000), - createAudioOnlyVariant(/* bitrate= */ 300000), - createMuxedVideoAudioVariant(/* bitrate= */ 400000), - createMuxedVideoAudioVariant(/* bitrate= */ 600000)), + createAudioOnlyVariant(/* peakBitrate= */ 10000), + createMuxedVideoAudioVariant(/* peakBitrate= */ 200000), + createAudioOnlyVariant(/* peakBitrate= */ 300000), + createMuxedVideoAudioVariant(/* peakBitrate= */ 400000), + createMuxedVideoAudioVariant(/* peakBitrate= */ 600000)), /* audios= */ Arrays.asList( createAudioRendition(/* language= */ "spa"), createAudioRendition(/* language= */ "ger"), @@ -121,40 +121,22 @@ public final class HlsMediaPeriodTest { /* sessionKeyDrmInitData= */ Collections.emptyList()); } - private static Variant createMuxedVideoAudioVariant(int bitrate) { + private static Variant createMuxedVideoAudioVariant(int peakBitrate) { return createVariant( - Format.createVideoContainerFormat( - /* id= */ null, - /* label= */ null, - /* containerMimeType= */ MimeTypes.APPLICATION_M3U8, - /* sampleMimeType= */ null, - /* codecs= */ "avc1.100.41,mp4a.40.2", - /* metadata= */ null, - bitrate, - /* width= */ Format.NO_VALUE, - /* height= */ Format.NO_VALUE, - /* frameRate= */ Format.NO_VALUE, - /* initializationData= */ null, - /* selectionFlags= */ 0, - /* roleFlags= */ 0)); + new Format.Builder() + .setContainerMimeType(MimeTypes.APPLICATION_M3U8) + .setCodecs("avc1.100.41,mp4a.40.2") + .setPeakBitrate(peakBitrate) + .build()); } - private static Variant createAudioOnlyVariant(int bitrate) { + private static Variant createAudioOnlyVariant(int peakBitrate) { return createVariant( - Format.createVideoContainerFormat( - /* id= */ null, - /* label= */ null, - /* containerMimeType= */ MimeTypes.APPLICATION_M3U8, - /* sampleMimeType= */ null, - /* codecs= */ "mp4a.40.2", - /* metadata= */ null, - bitrate, - /* width= */ Format.NO_VALUE, - /* height= */ Format.NO_VALUE, - /* frameRate= */ Format.NO_VALUE, - /* initializationData= */ null, - /* selectionFlags= */ 0, - /* roleFlags= */ 0)); + new Format.Builder() + .setContainerMimeType(MimeTypes.APPLICATION_M3U8) + .setCodecs("mp4a.40.2") + .setPeakBitrate(peakBitrate) + .build()); } private static Rendition createAudioRendition(String language) { @@ -174,32 +156,19 @@ public final class HlsMediaPeriodTest { } private static Format createAudioFormat(String language) { - return Format.createAudioContainerFormat( - /* id= */ null, - /* label= */ null, - /* containerMimeType= */ MimeTypes.APPLICATION_M3U8, - MimeTypes.getMediaMimeType("mp4a.40.2"), - /* codecs= */ "mp4a.40.2", - /* metadata= */ null, - /* bitrate= */ Format.NO_VALUE, - /* channelCount= */ Format.NO_VALUE, - /* sampleRate= */ Format.NO_VALUE, - /* initializationData= */ null, - /* selectionFlags= */ 0, - /* roleFlags= */ 0, - language); + return new Format.Builder() + .setContainerMimeType(MimeTypes.APPLICATION_M3U8) + .setSampleMimeType(MimeTypes.getMediaMimeType("mp4a.40.2")) + .setCodecs("mp4a.40.2") + .setLanguage(language) + .build(); } private static Format createSubtitleFormat(String language) { - return Format.createTextContainerFormat( - /* id= */ null, - /* label= */ null, - /* containerMimeType= */ MimeTypes.APPLICATION_M3U8, - /* sampleMimeType= */ MimeTypes.TEXT_VTT, - /* codecs= */ null, - /* bitrate= */ Format.NO_VALUE, - /* selectionFlags= */ 0, - /* roleFlags= */ 0, - language); + return new Format.Builder() + .setContainerMimeType(MimeTypes.APPLICATION_M3U8) + .setSampleMimeType(MimeTypes.TEXT_VTT) + .setLanguage(language) + .build(); } }