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); } /**