From 42d4afe7b6dd0f63144da3f6893b8d6dcaa2af26 Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 21 Feb 2020 17:35:37 +0000 Subject: [PATCH] Make Format.Builder, peakBitrate and averageBitrate public - Deprecate old Format.createXXX methods - Deprecate most Format.copyXXX methods - Stop using deprecated Format.copyXXX methods in the library Note: Replacing library usages of Format.createXXX method will be done in follow up CLs. These changes aren't purely mechanical because we need to decide which out of peakBitrate and averageBitrate to set in each case where currently a single bitrate is provided. Issue: #2863 PiperOrigin-RevId: 296450935 --- RELEASENOTES.md | 4 + .../com/google/android/exoplayer2/Format.java | 678 +++++++----------- .../android/exoplayer2/upstream/DataSpec.java | 6 +- .../analytics/PlaybackStatsListener.java | 3 +- .../source/ClippingMediaPeriod.java | 7 +- .../source/ProgressiveMediaPeriod.java | 7 +- .../source/chunk/ChunkExtractorWrapper.java | 4 +- .../exoplayer2/source/dash/DashUtil.java | 2 +- .../extractor/mp4/MetadataUtil.java | 22 +- .../extractor/mp4/Mp4Extractor.java | 12 +- .../source/hls/HlsSampleStreamWrapper.java | 12 +- 11 files changed, 318 insertions(+), 439 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index dd3c858c3e..37acdca262 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -32,6 +32,10 @@ * Add a sample count parameter to `MediaCodecRenderer.processOutputBuffer` and `AudioSink.handleBuffer` to allow batching multiple encoded frames in one buffer. + * Add a `Format.Builder` and deprecate all `Format.create*` methods and most + `Format.copyWith*` methods. + * Split `Format.bitrate` into `Format.averageBitrate` and `Format.peakBitrate` + ([#2863](https://github.com/google/ExoPlayer/issues/2863)). * Text: * Parse `` and `` tags in WebVTT subtitles (rendering is coming later). 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 77b04bbcbf..cf9935bfb8 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 @@ -110,12 +110,13 @@ public final class Format implements Parcelable { /** * Builds {@link Format} instances. * + *

Use Format#buildUpon() to obtain a builder representing an existing {@link Format}. + * *

When building formats, populate all fields whose values are known and relevant to the type * of format being constructed. See the {@link Format} Javadoc for information about which fields * should be set for different types of format. */ - // TODO: Make public. - /* package */ static final class Builder { + public static final class Builder { @Nullable private String id; @Nullable private String label; @@ -242,6 +243,18 @@ public final class Format implements Parcelable { return this; } + /** + * Sets {@link Format#id} to {@link Integer#toString() Integer.toString(id)}. The default value + * is {@code null}. + * + * @param id The {@link Format#id}. + * @return The builder. + */ + public Builder setId(int id) { + this.id = Integer.toString(id); + return this; + } + /** * Sets {@link Format#label}. The default value is {@code null}. * @@ -373,7 +386,7 @@ public final class Format implements Parcelable { * @param initializationData The {@link Format#initializationData}. * @return The builder. */ - public Builder setInitializationData(List initializationData) { + public Builder setInitializationData(@Nullable List initializationData) { this.initializationData = initializationData; return this; } @@ -645,8 +658,7 @@ public final class Format implements Parcelable { * the average bitrate if defined by the container. * */ - // TODO: Make public. - private final int averageBitrate; + public final int averageBitrate; /** * The peak bitrate in bits per second, or {@link #NO_VALUE} if unknown or not applicable. This * field may be populated from the following sources, depending on media type and the type of the @@ -662,8 +674,7 @@ public final class Format implements Parcelable { * the peak bitrate if defined by the container. * */ - // TODO: Make public. - private final int peakBitrate; + public final int peakBitrate; /** * The bitrate in bits per second. This is the peak bitrate if known, or else the average bitrate * if known, or else {@link Format#NO_VALUE}. Equivalent to: {@code peakBitrate != NO_VALUE ? @@ -777,6 +788,8 @@ public final class Format implements Parcelable { // Video. + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createVideoContainerFormat( @Nullable String id, @Nullable String label, @@ -791,39 +804,26 @@ public final class Format implements Parcelable { @Nullable List initializationData, @C.SelectionFlags int selectionFlags, @C.RoleFlags int roleFlags) { - return new Format( - id, - label, - /* language= */ null, - selectionFlags, - roleFlags, - /* averageBitrate= */ bitrate, - /* peakBitrate= */ bitrate, - codecs, - metadata, - containerMimeType, - sampleMimeType, - /* maxInputSize= */ NO_VALUE, - initializationData, - /* drmInitData= */ null, - OFFSET_SAMPLE_RELATIVE, - width, - height, - frameRate, - /* rotationDegrees= */ NO_VALUE, - /* pixelWidthHeightRatio= */ NO_VALUE, - /* projectionData= */ null, - /* stereoMode= */ NO_VALUE, - /* colorInfo= */ null, - /* channelCount= */ NO_VALUE, - /* sampleRate= */ NO_VALUE, - /* pcmEncoding= */ NO_VALUE, - /* encoderDelay= */ NO_VALUE, - /* encoderPadding= */ NO_VALUE, - /* accessibilityChannel= */ NO_VALUE, - /* exoMediaCryptoType= */ null); + return new Builder() + .setId(id) + .setLabel(label) + .setSelectionFlags(selectionFlags) + .setRoleFlags(roleFlags) + .setAverageBitrate(bitrate) + .setPeakBitrate(bitrate) + .setCodecs(codecs) + .setMetadata(metadata) + .setContainerMimeType(containerMimeType) + .setSampleMimeType(sampleMimeType) + .setInitializationData(initializationData) + .setWidth(width) + .setHeight(height) + .setFrameRate(frameRate) + .build(); } + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createVideoSampleFormat( @Nullable String id, @Nullable String sampleMimeType, @@ -835,21 +835,23 @@ public final class Format implements Parcelable { float frameRate, @Nullable List initializationData, @Nullable DrmInitData drmInitData) { - return createVideoSampleFormat( - id, - sampleMimeType, - codecs, - bitrate, - maxInputSize, - width, - height, - frameRate, - initializationData, - /* rotationDegrees= */ NO_VALUE, - /* pixelWidthHeightRatio= */ NO_VALUE, - drmInitData); + return new Builder() + .setId(id) + .setAverageBitrate(bitrate) + .setPeakBitrate(bitrate) + .setCodecs(codecs) + .setSampleMimeType(sampleMimeType) + .setMaxInputSize(maxInputSize) + .setInitializationData(initializationData) + .setDrmInitData(drmInitData) + .setWidth(width) + .setHeight(height) + .setFrameRate(frameRate) + .build(); } + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createVideoSampleFormat( @Nullable String id, @Nullable String sampleMimeType, @@ -863,24 +865,25 @@ public final class Format implements Parcelable { int rotationDegrees, float pixelWidthHeightRatio, @Nullable DrmInitData drmInitData) { - return createVideoSampleFormat( - id, - sampleMimeType, - codecs, - bitrate, - maxInputSize, - width, - height, - frameRate, - initializationData, - rotationDegrees, - pixelWidthHeightRatio, - /* projectionData= */ null, - /* stereoMode= */ NO_VALUE, - /* colorInfo= */ null, - drmInitData); + return new Builder() + .setId(id) + .setAverageBitrate(bitrate) + .setPeakBitrate(bitrate) + .setCodecs(codecs) + .setSampleMimeType(sampleMimeType) + .setMaxInputSize(maxInputSize) + .setInitializationData(initializationData) + .setDrmInitData(drmInitData) + .setWidth(width) + .setHeight(height) + .setFrameRate(frameRate) + .setRotationDegrees(rotationDegrees) + .setPixelWidthHeightRatio(pixelWidthHeightRatio) + .build(); } + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createVideoSampleFormat( @Nullable String id, @Nullable String sampleMimeType, @@ -897,41 +900,30 @@ public final class Format implements Parcelable { @C.StereoMode int stereoMode, @Nullable ColorInfo colorInfo, @Nullable DrmInitData drmInitData) { - return new Format( - id, - /* label= */ null, - /* language= */ null, - /* selectionFlags= */ 0, - /* roleFlags= */ 0, - /* averageBitrate= */ bitrate, - /* peakBitrate= */ bitrate, - codecs, - /* metadata= */ null, - /* containerMimeType= */ null, - sampleMimeType, - maxInputSize, - initializationData, - drmInitData, - OFFSET_SAMPLE_RELATIVE, - width, - height, - frameRate, - rotationDegrees, - pixelWidthHeightRatio, - projectionData, - stereoMode, - colorInfo, - /* channelCount= */ NO_VALUE, - /* sampleRate= */ NO_VALUE, - /* pcmEncoding= */ NO_VALUE, - /* encoderDelay= */ NO_VALUE, - /* encoderPadding= */ NO_VALUE, - /* accessibilityChannel= */ NO_VALUE, - /* exoMediaCryptoType= */ null); + return new Builder() + .setId(id) + .setAverageBitrate(bitrate) + .setPeakBitrate(bitrate) + .setCodecs(codecs) + .setSampleMimeType(sampleMimeType) + .setMaxInputSize(maxInputSize) + .setInitializationData(initializationData) + .setDrmInitData(drmInitData) + .setWidth(width) + .setHeight(height) + .setFrameRate(frameRate) + .setRotationDegrees(rotationDegrees) + .setPixelWidthHeightRatio(pixelWidthHeightRatio) + .setProjectionData(projectionData) + .setStereoMode(stereoMode) + .setColorInfo(colorInfo) + .build(); } // Audio. + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createAudioContainerFormat( @Nullable String id, @Nullable String label, @@ -946,39 +938,26 @@ public final class Format implements Parcelable { @C.SelectionFlags int selectionFlags, @C.RoleFlags int roleFlags, @Nullable String language) { - return new Format( - id, - label, - language, - selectionFlags, - roleFlags, - /* averageBitrate= */ bitrate, - /* peakBitrate= */ bitrate, - codecs, - metadata, - containerMimeType, - sampleMimeType, - /* maxInputSize= */ NO_VALUE, - initializationData, - /* drmInitData= */ null, - OFFSET_SAMPLE_RELATIVE, - /* width= */ NO_VALUE, - /* height= */ NO_VALUE, - /* frameRate= */ NO_VALUE, - /* rotationDegrees= */ NO_VALUE, - /* pixelWidthHeightRatio= */ NO_VALUE, - /* projectionData= */ null, - /* stereoMode= */ NO_VALUE, - /* colorInfo= */ null, - channelCount, - sampleRate, - /* pcmEncoding= */ NO_VALUE, - /* encoderDelay= */ NO_VALUE, - /* encoderPadding= */ NO_VALUE, - /* accessibilityChannel= */ NO_VALUE, - /* exoMediaCryptoType= */ null); + return new Builder() + .setId(id) + .setLabel(label) + .setLanguage(language) + .setSelectionFlags(selectionFlags) + .setRoleFlags(roleFlags) + .setAverageBitrate(bitrate) + .setPeakBitrate(bitrate) + .setCodecs(codecs) + .setMetadata(metadata) + .setContainerMimeType(containerMimeType) + .setSampleMimeType(sampleMimeType) + .setInitializationData(initializationData) + .setChannelCount(channelCount) + .setSampleRate(sampleRate) + .build(); } + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createAudioSampleFormat( @Nullable String id, @Nullable String sampleMimeType, @@ -991,21 +970,24 @@ public final class Format implements Parcelable { @Nullable DrmInitData drmInitData, @C.SelectionFlags int selectionFlags, @Nullable String language) { - return createAudioSampleFormat( - id, - sampleMimeType, - codecs, - bitrate, - maxInputSize, - channelCount, - sampleRate, - /* pcmEncoding= */ NO_VALUE, - initializationData, - drmInitData, - selectionFlags, - language); + return new Builder() + .setId(id) + .setLanguage(language) + .setSelectionFlags(selectionFlags) + .setAverageBitrate(bitrate) + .setPeakBitrate(bitrate) + .setCodecs(codecs) + .setSampleMimeType(sampleMimeType) + .setMaxInputSize(maxInputSize) + .setInitializationData(initializationData) + .setDrmInitData(drmInitData) + .setChannelCount(channelCount) + .setSampleRate(sampleRate) + .build(); } + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createAudioSampleFormat( @Nullable String id, @Nullable String sampleMimeType, @@ -1019,24 +1001,25 @@ public final class Format implements Parcelable { @Nullable DrmInitData drmInitData, @C.SelectionFlags int selectionFlags, @Nullable String language) { - return createAudioSampleFormat( - id, - sampleMimeType, - codecs, - bitrate, - maxInputSize, - channelCount, - sampleRate, - pcmEncoding, - /* encoderDelay= */ NO_VALUE, - /* encoderPadding= */ NO_VALUE, - initializationData, - drmInitData, - selectionFlags, - language, - /* metadata= */ null); + return new Builder() + .setId(id) + .setLanguage(language) + .setSelectionFlags(selectionFlags) + .setAverageBitrate(bitrate) + .setPeakBitrate(bitrate) + .setCodecs(codecs) + .setSampleMimeType(sampleMimeType) + .setMaxInputSize(maxInputSize) + .setInitializationData(initializationData) + .setDrmInitData(drmInitData) + .setChannelCount(channelCount) + .setSampleRate(sampleRate) + .setPcmEncoding(pcmEncoding) + .build(); } + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createAudioSampleFormat( @Nullable String id, @Nullable String sampleMimeType, @@ -1053,41 +1036,30 @@ public final class Format implements Parcelable { @C.SelectionFlags int selectionFlags, @Nullable String language, @Nullable Metadata metadata) { - return new Format( - id, - /* label= */ null, - language, - selectionFlags, - /* roleFlags= */ 0, - /* averageBitrate= */ bitrate, - /* peakBitrate= */ bitrate, - codecs, - metadata, - /* containerMimeType= */ null, - sampleMimeType, - maxInputSize, - initializationData, - drmInitData, - OFFSET_SAMPLE_RELATIVE, - /* width= */ NO_VALUE, - /* height= */ NO_VALUE, - /* frameRate= */ NO_VALUE, - /* rotationDegrees= */ NO_VALUE, - /* pixelWidthHeightRatio= */ NO_VALUE, - /* projectionData= */ null, - /* stereoMode= */ NO_VALUE, - /* colorInfo= */ null, - channelCount, - sampleRate, - pcmEncoding, - encoderDelay, - encoderPadding, - /* accessibilityChannel= */ NO_VALUE, - /* exoMediaCryptoType= */ null); + return new Builder() + .setId(id) + .setLanguage(language) + .setSelectionFlags(selectionFlags) + .setAverageBitrate(bitrate) + .setPeakBitrate(bitrate) + .setCodecs(codecs) + .setMetadata(metadata) + .setSampleMimeType(sampleMimeType) + .setMaxInputSize(maxInputSize) + .setInitializationData(initializationData) + .setDrmInitData(drmInitData) + .setChannelCount(channelCount) + .setSampleRate(sampleRate) + .setPcmEncoding(pcmEncoding) + .setEncoderDelay(encoderDelay) + .setEncoderPadding(encoderPadding) + .build(); } // Text. + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createTextContainerFormat( @Nullable String id, @Nullable String label, @@ -1098,19 +1070,22 @@ public final class Format implements Parcelable { @C.SelectionFlags int selectionFlags, @C.RoleFlags int roleFlags, @Nullable String language) { - return createTextContainerFormat( - id, - label, - containerMimeType, - sampleMimeType, - codecs, - bitrate, - selectionFlags, - roleFlags, - language, - /* accessibilityChannel= */ NO_VALUE); + return new Builder() + .setId(id) + .setLabel(label) + .setLanguage(language) + .setSelectionFlags(selectionFlags) + .setRoleFlags(roleFlags) + .setAverageBitrate(bitrate) + .setPeakBitrate(bitrate) + .setCodecs(codecs) + .setContainerMimeType(containerMimeType) + .setSampleMimeType(sampleMimeType) + .build(); } + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createTextContainerFormat( @Nullable String id, @Nullable String label, @@ -1122,54 +1097,38 @@ public final class Format implements Parcelable { @C.RoleFlags int roleFlags, @Nullable String language, int accessibilityChannel) { - return new Format( - id, - label, - language, - selectionFlags, - roleFlags, - /* averageBitrate= */ bitrate, - /* peakBitrate= */ bitrate, - codecs, - /* metadata= */ null, - containerMimeType, - sampleMimeType, - /* maxInputSize= */ NO_VALUE, - /* initializationData= */ null, - /* drmInitData= */ null, - OFFSET_SAMPLE_RELATIVE, - /* width= */ NO_VALUE, - /* height= */ NO_VALUE, - /* frameRate= */ NO_VALUE, - /* rotationDegrees= */ NO_VALUE, - /* pixelWidthHeightRatio= */ NO_VALUE, - /* projectionData= */ null, - /* stereoMode= */ NO_VALUE, - /* colorInfo= */ null, - /* channelCount= */ NO_VALUE, - /* sampleRate= */ NO_VALUE, - /* pcmEncoding= */ NO_VALUE, - /* encoderDelay= */ NO_VALUE, - /* encoderPadding= */ NO_VALUE, - accessibilityChannel, - /* exoMediaCryptoType= */ null); + return new Builder() + .setId(id) + .setLabel(label) + .setLanguage(language) + .setSelectionFlags(selectionFlags) + .setRoleFlags(roleFlags) + .setAverageBitrate(bitrate) + .setPeakBitrate(bitrate) + .setCodecs(codecs) + .setContainerMimeType(containerMimeType) + .setSampleMimeType(sampleMimeType) + .setAccessibilityChannel(accessibilityChannel) + .build(); } + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createTextSampleFormat( @Nullable String id, @Nullable String sampleMimeType, @C.SelectionFlags int selectionFlags, @Nullable String language) { - return createTextSampleFormat( - id, - sampleMimeType, - selectionFlags, - language, - NO_VALUE, - OFFSET_SAMPLE_RELATIVE, - Collections.emptyList()); + return new Builder() + .setId(id) + .setLanguage(language) + .setSelectionFlags(selectionFlags) + .setSampleMimeType(sampleMimeType) + .build(); } + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createTextSampleFormat( @Nullable String id, @Nullable String sampleMimeType, @@ -1178,82 +1137,40 @@ public final class Format implements Parcelable { int accessibilityChannel, long subsampleOffsetUs, @Nullable List initializationData) { - return new Format( - id, - /* label= */ null, - language, - selectionFlags, - /* roleFlags= */ 0, - /* averageBitrate= */ NO_VALUE, - /* peakBitrate= */ NO_VALUE, - /* codecs= */ null, - /* metadata= */ null, - /* containerMimeType= */ null, - sampleMimeType, - /* maxInputSize= */ NO_VALUE, - initializationData, - /* drmInitData= */ null, - subsampleOffsetUs, - /* width= */ NO_VALUE, - /* height= */ NO_VALUE, - /* frameRate= */ NO_VALUE, - /* rotationDegrees= */ NO_VALUE, - /* pixelWidthHeightRatio= */ NO_VALUE, - /* projectionData= */ null, - /* stereoMode= */ NO_VALUE, - /* colorInfo= */ null, - /* channelCount= */ NO_VALUE, - /* sampleRate= */ NO_VALUE, - /* pcmEncoding= */ NO_VALUE, - /* encoderDelay= */ NO_VALUE, - /* encoderPadding= */ NO_VALUE, - accessibilityChannel, - /* exoMediaCryptoType= */ null); + return new Builder() + .setId(id) + .setLanguage(language) + .setSelectionFlags(selectionFlags) + .setSampleMimeType(sampleMimeType) + .setInitializationData(initializationData) + .setSubsampleOffsetUs(subsampleOffsetUs) + .setAccessibilityChannel(accessibilityChannel) + .build(); } // Image. + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createImageSampleFormat( @Nullable String id, @Nullable String sampleMimeType, @C.SelectionFlags int selectionFlags, @Nullable List initializationData, @Nullable String language) { - return new Format( - id, - /* label= */ null, - language, - selectionFlags, - /* roleFlags= */ 0, - /* averageBitrate= */ NO_VALUE, - /* peakBitrate= */ NO_VALUE, - /* codecs= */ null, - /* metadata=*/ null, - /* containerMimeType= */ null, - sampleMimeType, - /* maxInputSize= */ NO_VALUE, - initializationData, - /* drmInitData= */ null, - OFFSET_SAMPLE_RELATIVE, - /* width= */ NO_VALUE, - /* height= */ NO_VALUE, - /* frameRate= */ NO_VALUE, - /* rotationDegrees= */ NO_VALUE, - /* pixelWidthHeightRatio= */ NO_VALUE, - /* projectionData= */ null, - /* stereoMode= */ NO_VALUE, - /* colorInfo= */ null, - /* channelCount= */ NO_VALUE, - /* sampleRate= */ NO_VALUE, - /* pcmEncoding= */ NO_VALUE, - /* encoderDelay= */ NO_VALUE, - /* encoderPadding= */ NO_VALUE, - /* accessibilityChannel= */ NO_VALUE, - /* exoMediaCryptoType= */ null); + return new Builder() + .setId(id) + .setLanguage(language) + .setSelectionFlags(selectionFlags) + .setSampleMimeType(sampleMimeType) + .setInitializationData(initializationData) + .build(); } // Generic. + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createContainerFormat( @Nullable String id, @Nullable String label, @@ -1264,71 +1181,24 @@ public final class Format implements Parcelable { @C.SelectionFlags int selectionFlags, @C.RoleFlags int roleFlags, @Nullable String language) { - return new Format( - id, - label, - language, - selectionFlags, - roleFlags, - /* averageBitrate= */ bitrate, - /* peakBitrate= */ bitrate, - codecs, - /* metadata= */ null, - containerMimeType, - sampleMimeType, - /* maxInputSize= */ NO_VALUE, - /* initializationData= */ null, - /* drmInitData= */ null, - OFFSET_SAMPLE_RELATIVE, - /* width= */ NO_VALUE, - /* height= */ NO_VALUE, - /* frameRate= */ NO_VALUE, - /* rotationDegrees= */ NO_VALUE, - /* pixelWidthHeightRatio= */ NO_VALUE, - /* projectionData= */ null, - /* stereoMode= */ NO_VALUE, - /* colorInfo= */ null, - /* channelCount= */ NO_VALUE, - /* sampleRate= */ NO_VALUE, - /* pcmEncoding= */ NO_VALUE, - /* encoderDelay= */ NO_VALUE, - /* encoderPadding= */ NO_VALUE, - /* accessibilityChannel= */ NO_VALUE, - /* exoMediaCryptoType= */ null); + return new Builder() + .setId(id) + .setLabel(label) + .setLanguage(language) + .setSelectionFlags(selectionFlags) + .setRoleFlags(roleFlags) + .setAverageBitrate(bitrate) + .setPeakBitrate(bitrate) + .setCodecs(codecs) + .setContainerMimeType(containerMimeType) + .setSampleMimeType(sampleMimeType) + .build(); } + /** @deprecated Use {@link Format.Builder}. */ + @Deprecated public static Format createSampleFormat(@Nullable String id, @Nullable String sampleMimeType) { - return new Format( - id, - /* label= */ null, - /* language= */ null, - /* selectionFlags= */ 0, - /* roleFlags= */ 0, - /* averageBitrate= */ NO_VALUE, - /* peakBitrate= */ NO_VALUE, - /* codecs= */ null, - /* metadata= */ null, - /* containerMimeType= */ null, - sampleMimeType, - /* maxInputSize= */ NO_VALUE, - /* initializationData= */ null, - /* drmInitData= */ null, - OFFSET_SAMPLE_RELATIVE, - /* width= */ NO_VALUE, - /* height= */ NO_VALUE, - /* frameRate= */ NO_VALUE, - /* rotationDegrees= */ NO_VALUE, - /* pixelWidthHeightRatio= */ NO_VALUE, - /* projectionData= */ null, - /* stereoMode= */ NO_VALUE, - /* colorInfo= */ null, - /* channelCount= */ NO_VALUE, - /* sampleRate= */ NO_VALUE, - /* pcmEncoding= */ NO_VALUE, - /* encoderDelay= */ NO_VALUE, - /* encoderPadding= */ NO_VALUE, - /* accessibilityChannel= */ NO_VALUE, - /* exoMediaCryptoType= */ null); + return new Builder().setId(id).setSampleMimeType(sampleMimeType).build(); } /* package */ Format( @@ -1454,29 +1324,25 @@ public final class Format implements Parcelable { exoMediaCryptoType = null; } - // TODO: Make public. /** Returns a {@link Format.Builder} initialized with the values of this instance. */ - /* package */ Builder buildUpon() { + public Builder buildUpon() { return new Builder(this); } - // TODO: Deprecate. - // /** @deprecated Use {@link #buildUpon()} and {@link Builder#setMaxInputSize(int)}. */ - // @Deprecated + /** @deprecated Use {@link #buildUpon()} and {@link Builder#setMaxInputSize(int)}. */ + @Deprecated public Format copyWithMaxInputSize(int maxInputSize) { return buildUpon().setMaxInputSize(maxInputSize).build(); } - // TODO: Deprecate. - // /** @deprecated Use {@link #buildUpon()} and {@link Builder#setSubsampleOffsetUs(long)}. */ - // @Deprecated + /** @deprecated Use {@link #buildUpon()} and {@link Builder#setSubsampleOffsetUs(long)}. */ + @Deprecated public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) { return buildUpon().setSubsampleOffsetUs(subsampleOffsetUs).build(); } - // TODO: Deprecate. - // /** @deprecated Use {@link #buildUpon()} and {@link Builder#setLabel(String)} . */ - // @Deprecated + /** @deprecated Use {@link #buildUpon()} and {@link Builder#setLabel(String)} . */ + @Deprecated public Format copyWithLabel(@Nullable String label) { return buildUpon().setLabel(label).build(); } @@ -1514,8 +1380,14 @@ public final class Format implements Parcelable { .build(); } - @SuppressWarnings("ReferenceEquality") + /** @deprecated Use {@link #withManifestFormatInfo(Format)}. */ + @Deprecated public Format copyWithManifestFormatInfo(Format manifestFormat) { + return withManifestFormatInfo(manifestFormat); + } + + @SuppressWarnings("ReferenceEquality") + public Format withManifestFormatInfo(Format manifestFormat) { if (this == manifestFormat) { // No need to copy from ourselves. return this; @@ -1581,57 +1453,47 @@ public final class Format implements Parcelable { .build(); } - // TODO: Deprecate. - // /** - // * @deprecated Use {@link #buildUpon()}, {@link Builder#setEncoderDelay(int)} and {@link - // * Builder#setEncoderPadding(int)}. - // */ - // @Deprecated + /** + * @deprecated Use {@link #buildUpon()}, {@link Builder#setEncoderDelay(int)} and {@link + * Builder#setEncoderPadding(int)}. + */ + @Deprecated public Format copyWithGaplessInfo(int encoderDelay, int encoderPadding) { return buildUpon().setEncoderDelay(encoderDelay).setEncoderPadding(encoderPadding).build(); } - // TODO: Deprecate. - // /** @deprecated Use {@link #buildUpon()} and {@link Builder#setFrameRate(float)}. */ - // @Deprecated + /** @deprecated Use {@link #buildUpon()} and {@link Builder#setFrameRate(float)}. */ + @Deprecated public Format copyWithFrameRate(float frameRate) { return buildUpon().setFrameRate(frameRate).build(); } + /** @deprecated Use {@link #buildUpon()} and {@link Builder#setDrmInitData(DrmInitData)}. */ + @Deprecated public Format copyWithDrmInitData(@Nullable DrmInitData drmInitData) { - return copyWithAdjustments(drmInitData, metadata); + return buildUpon().setDrmInitData(drmInitData).build(); } + /** @deprecated Use {@link #buildUpon()} and {@link Builder#setMetadata(Metadata)}. */ + @Deprecated public Format copyWithMetadata(@Nullable Metadata metadata) { - return copyWithAdjustments(drmInitData, metadata); + return buildUpon().setMetadata(metadata).build(); } - // TODO: Inline into HlsSampleStreamWrapper and remove. - @SuppressWarnings("ReferenceEquality") - public Format copyWithAdjustments( - @Nullable DrmInitData drmInitData, @Nullable Metadata metadata) { - if (drmInitData == this.drmInitData && metadata == this.metadata) { - return this; - } - return buildUpon().setDrmInitData(drmInitData).setMetadata(metadata).build(); - } - - // TODO: Deprecate. - // /** - // * @deprecated Use {@link #buildUpon()} and {@link Builder#setAverageBitrate(int)} and {@link - // * Builder#setPeakBitrate(int)}. - // */ - // @Deprecated + /** + * @deprecated Use {@link #buildUpon()} and {@link Builder#setAverageBitrate(int)} and {@link + * Builder#setPeakBitrate(int)}. + */ + @Deprecated public Format copyWithBitrate(int bitrate) { return buildUpon().setAverageBitrate(bitrate).setPeakBitrate(bitrate).build(); } - // TODO: Deprecate. - // /** - // * @deprecated Use {@link #buildUpon()}, {@link Builder#setWidth(int)} and {@link - // * Builder#setHeight(int)}. - // */ - // @Deprecated + /** + * @deprecated Use {@link #buildUpon()}, {@link Builder#setWidth(int)} and {@link + * Builder#setHeight(int)}. + */ + @Deprecated public Format copyWithVideoSize(int width, int height) { return buildUpon().setWidth(width).setHeight(height).build(); } diff --git a/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java b/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java index 571b1ac769..1fdb5b3cec 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/upstream/DataSpec.java @@ -32,7 +32,11 @@ import java.util.Map; */ public final class DataSpec { - /** Builds {@link DataSpec} instances. */ + /** + * Builds {@link DataSpec} instances. + * + *

Use DataSpec#buildUpon() to obtain a builder representing an existing {@link DataSpec}. + */ public static final class Builder { @Nullable private Uri uri; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java b/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java index 3f3803f5c0..0ca6a7919b 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java @@ -699,7 +699,8 @@ public final class PlaybackStatsListener */ public void onVideoSizeChanged(EventTime eventTime, int width, int height) { if (currentVideoFormat != null && currentVideoFormat.height == Format.NO_VALUE) { - Format formatWithHeight = currentVideoFormat.copyWithVideoSize(width, height); + Format formatWithHeight = + currentVideoFormat.buildUpon().setWidth(width).setHeight(height).build(); maybeUpdateVideoFormat(eventTime, formatWithHeight); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java index 0df3564174..38e99bdeca 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java @@ -317,7 +317,12 @@ public final class ClippingMediaPeriod implements MediaPeriod, MediaPeriod.Callb // Clear gapless playback metadata if the start/end points don't match the media. int encoderDelay = startUs != 0 ? 0 : format.encoderDelay; int encoderPadding = endUs != C.TIME_END_OF_SOURCE ? 0 : format.encoderPadding; - formatHolder.format = format.copyWithGaplessInfo(encoderDelay, encoderPadding); + formatHolder.format = + format + .buildUpon() + .setEncoderDelay(encoderDelay) + .setEncoderPadding(encoderPadding) + .build(); } return C.RESULT_FORMAT_READ; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java index 243a94bfb1..019ae11052 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriod.java @@ -734,10 +734,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; ? new Metadata(icyHeaders) : metadata.copyWithAppendedEntries(icyHeaders)); } + // Update the track format with the bitrate from the ICY header only if it declares neither + // an average or peak bitrate of its own. if (isAudio - && trackFormat.bitrate == Format.NO_VALUE + && trackFormat.averageBitrate == Format.NO_VALUE + && trackFormat.peakBitrate == Format.NO_VALUE && icyHeaders.bitrate != Format.NO_VALUE) { - trackFormat = trackFormat.copyWithBitrate(icyHeaders.bitrate); + trackFormat = trackFormat.buildUpon().setAverageBitrate(icyHeaders.bitrate).build(); } } trackArray[i] = new TrackGroup(trackFormat); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java index 0643a8ceca..c4192594e1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkExtractorWrapper.java @@ -197,8 +197,8 @@ public final class ChunkExtractorWrapper implements ExtractorOutput { @Override public void format(Format format) { - sampleFormat = manifestFormat != null ? format.copyWithManifestFormatInfo(manifestFormat) - : format; + sampleFormat = + manifestFormat != null ? format.withManifestFormatInfo(manifestFormat) : format; castNonNull(trackOutput).format(sampleFormat); } diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashUtil.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashUtil.java index 01fc5965f3..b9a1f872a6 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashUtil.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashUtil.java @@ -98,7 +98,7 @@ public final class DashUtil { Format sampleFormat = DashUtil.loadSampleFormat(dataSource, primaryTrackType, representation); return sampleFormat == null ? manifestFormat.drmInitData - : sampleFormat.copyWithManifestFormatInfo(manifestFormat).drmInitData; + : sampleFormat.withManifestFormatInfo(manifestFormat).drmInitData; } /** diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java index 85ca446b65..365e336e65 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/MetadataUtil.java @@ -284,25 +284,22 @@ import com.google.android.exoplayer2.util.ParsableByteArray; private MetadataUtil() {} - /** - * Returns a {@link Format} that is the same as the input format but includes information from the - * specified sources of metadata. - */ - public static Format getFormatWithMetadata( + /** Updates a {@link Format.Builder} to include metadata from the provided sources. */ + public static void setFormatMetadata( int trackType, - Format format, @Nullable Metadata udtaMetadata, @Nullable Metadata mdtaMetadata, - GaplessInfoHolder gaplessInfoHolder) { + GaplessInfoHolder gaplessInfoHolder, + Format.Builder formatBuilder) { if (trackType == C.TRACK_TYPE_AUDIO) { if (gaplessInfoHolder.hasGaplessInfo()) { - format = - format.copyWithGaplessInfo( - gaplessInfoHolder.encoderDelay, gaplessInfoHolder.encoderPadding); + formatBuilder + .setEncoderDelay(gaplessInfoHolder.encoderDelay) + .setEncoderPadding(gaplessInfoHolder.encoderPadding); } // We assume all udta metadata is associated with the audio track. if (udtaMetadata != null) { - format = format.copyWithMetadata(udtaMetadata); + formatBuilder.setMetadata(udtaMetadata); } } else if (trackType == C.TRACK_TYPE_VIDEO && mdtaMetadata != null) { // Populate only metadata keys that are known to be specific to video. @@ -311,12 +308,11 @@ import com.google.android.exoplayer2.util.ParsableByteArray; if (entry instanceof MdtaMetadataEntry) { MdtaMetadataEntry mdtaMetadataEntry = (MdtaMetadataEntry) entry; if (MDTA_KEY_ANDROID_CAPTURE_FPS.equals(mdtaMetadataEntry.key)) { - format = format.copyWithMetadata(new Metadata(mdtaMetadataEntry)); + formatBuilder.setMetadata(new Metadata(mdtaMetadataEntry)); } } } } - return format; } /** diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java index c35c23d858..659b97a8a9 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/Mp4Extractor.java @@ -423,17 +423,17 @@ public final class Mp4Extractor implements Extractor, SeekMap { // Each sample has up to three bytes of overhead for the start code that replaces its length. // Allow ten source samples per output sample, like the platform extractor. int maxInputSize = trackSampleTable.maximumSize + 3 * 10; - Format format = track.format.copyWithMaxInputSize(maxInputSize); + Format.Builder formatBuilder = track.format.buildUpon(); + formatBuilder.setMaxInputSize(maxInputSize); if (track.type == C.TRACK_TYPE_VIDEO && trackDurationUs > 0 && trackSampleTable.sampleCount > 1) { float frameRate = trackSampleTable.sampleCount / (trackDurationUs / 1000000f); - format = format.copyWithFrameRate(frameRate); + formatBuilder.setFrameRate(frameRate); } - format = - MetadataUtil.getFormatWithMetadata( - track.type, format, udtaMetadata, mdtaMetadata, gaplessInfoHolder); - mp4Track.trackOutput.format(format); + MetadataUtil.setFormatMetadata( + track.type, udtaMetadata, mdtaMetadata, gaplessInfoHolder, formatBuilder); + mp4Track.trackOutput.format(formatBuilder.build()); if (track.type == C.TRACK_TYPE_VIDEO && firstVideoTrackIndex == C.INDEX_UNSET) { firstVideoTrackIndex = tracks.size(); 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 c51f05e098..f773136b98 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 @@ -568,7 +568,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; chunkIndex < mediaChunks.size() ? mediaChunks.get(chunkIndex).trackFormat : Assertions.checkNotNull(upstreamTrackFormat); - format = format.copyWithManifestFormatInfo(trackFormat); + format = format.withManifestFormatInfo(trackFormat); } formatHolder.format = format; } @@ -1160,7 +1160,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; if (i == primaryExtractorTrackIndex) { Format[] formats = new Format[chunkSourceTrackCount]; if (chunkSourceTrackCount == 1) { - formats[0] = sampleFormat.copyWithManifestFormatInfo(chunkSourceTrackGroup.getFormat(0)); + formats[0] = sampleFormat.withManifestFormatInfo(chunkSourceTrackGroup.getFormat(0)); } else { for (int j = 0; j < chunkSourceTrackCount; j++) { formats[j] = deriveFormat(chunkSourceTrackGroup.getFormat(j), sampleFormat, true); @@ -1346,6 +1346,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; invalidateUpstreamFormatAdjustment(); } + @SuppressWarnings("ReferenceEquality") @Override public Format getAdjustedUpstreamFormat(Format format) { @Nullable @@ -1357,8 +1358,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; drmInitData = overridingDrmInitData; } } - return super.getAdjustedUpstreamFormat( - format.copyWithAdjustments(drmInitData, getAdjustedMetadata(format.metadata))); + @Nullable Metadata metadata = getAdjustedMetadata(format.metadata); + if (drmInitData != format.drmInitData || metadata != format.metadata) { + format = format.buildUpon().setDrmInitData(drmInitData).setMetadata(metadata).build(); + } + return super.getAdjustedUpstreamFormat(format); } /**