summaryrefslogtreecommitdiffstats
path: root/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/Format.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/Format.java')
-rw-r--r--mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/Format.java1750
1 files changed, 1750 insertions, 0 deletions
diff --git a/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/Format.java b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/Format.java
new file mode 100644
index 0000000000..9d7518f6f0
--- /dev/null
+++ b/mobile/android/exoplayer2/src/main/java/org/mozilla/thirdparty/com/google/android/exoplayer2/Format.java
@@ -0,0 +1,1750 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mozilla.thirdparty.com.google.android.exoplayer2;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import androidx.annotation.Nullable;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.drm.DrmInitData;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.drm.DrmSession;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.drm.ExoMediaCrypto;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.metadata.Metadata;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.MimeTypes;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Util;
+import org.mozilla.thirdparty.com.google.android.exoplayer2.video.ColorInfo;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Representation of a media format.
+ */
+public final class Format implements Parcelable {
+
+ /**
+ * A value for various fields to indicate that the field's value is unknown or not applicable.
+ */
+ public static final int NO_VALUE = -1;
+
+ /**
+ * A value for {@link #subsampleOffsetUs} to indicate that subsample timestamps are relative to
+ * the timestamps of their parent samples.
+ */
+ public static final long OFFSET_SAMPLE_RELATIVE = Long.MAX_VALUE;
+
+ /** An identifier for the format, or null if unknown or not applicable. */
+ @Nullable public final String id;
+ /** The human readable label, or null if unknown or not applicable. */
+ @Nullable public final String label;
+ /** Track selection flags. */
+ @C.SelectionFlags public final int selectionFlags;
+ /** Track role flags. */
+ @C.RoleFlags public final int roleFlags;
+ /**
+ * The average bandwidth in bits per second, or {@link #NO_VALUE} if unknown or not applicable.
+ */
+ public final int bitrate;
+ /** Codecs of the format as described in RFC 6381, or null if unknown or not applicable. */
+ @Nullable public final String codecs;
+ /** Metadata, or null if unknown or not applicable. */
+ @Nullable public final Metadata metadata;
+
+ // Container specific.
+
+ /** The mime type of the container, or null if unknown or not applicable. */
+ @Nullable public final String containerMimeType;
+
+ // Elementary stream specific.
+
+ /**
+ * The mime type of the elementary stream (i.e. the individual samples), or null if unknown or not
+ * applicable.
+ */
+ @Nullable public final String sampleMimeType;
+ /**
+ * The maximum size of a buffer of data (typically one sample), or {@link #NO_VALUE} if unknown or
+ * not applicable.
+ */
+ public final int maxInputSize;
+ /**
+ * Initialization data that must be provided to the decoder. Will not be null, but may be empty
+ * if initialization data is not required.
+ */
+ public final List<byte[]> initializationData;
+ /** DRM initialization data if the stream is protected, or null otherwise. */
+ @Nullable public final DrmInitData drmInitData;
+
+ /**
+ * For samples that contain subsamples, this is an offset that should be added to subsample
+ * timestamps. A value of {@link #OFFSET_SAMPLE_RELATIVE} indicates that subsample timestamps are
+ * relative to the timestamps of their parent samples.
+ */
+ public final long subsampleOffsetUs;
+
+ // Video specific.
+
+ /**
+ * The width of the video in pixels, or {@link #NO_VALUE} if unknown or not applicable.
+ */
+ public final int width;
+ /**
+ * The height of the video in pixels, or {@link #NO_VALUE} if unknown or not applicable.
+ */
+ public final int height;
+ /**
+ * The frame rate in frames per second, or {@link #NO_VALUE} if unknown or not applicable.
+ */
+ public final float frameRate;
+ /**
+ * The clockwise rotation that should be applied to the video for it to be rendered in the correct
+ * orientation, or 0 if unknown or not applicable. Only 0, 90, 180 and 270 are supported.
+ */
+ public final int rotationDegrees;
+ /** The width to height ratio of pixels in the video, or 1.0 if unknown or not applicable. */
+ public final float pixelWidthHeightRatio;
+ /**
+ * The stereo layout for 360/3D/VR video, or {@link #NO_VALUE} if not applicable. Valid stereo
+ * modes are {@link C#STEREO_MODE_MONO}, {@link C#STEREO_MODE_TOP_BOTTOM}, {@link
+ * C#STEREO_MODE_LEFT_RIGHT}, {@link C#STEREO_MODE_STEREO_MESH}.
+ */
+ @C.StereoMode
+ public final int stereoMode;
+ /** The projection data for 360/VR video, or null if not applicable. */
+ @Nullable public final byte[] projectionData;
+ /** The color metadata associated with the video, helps with accurate color reproduction. */
+ @Nullable public final ColorInfo colorInfo;
+
+ // Audio specific.
+
+ /**
+ * The number of audio channels, or {@link #NO_VALUE} if unknown or not applicable.
+ */
+ public final int channelCount;
+ /**
+ * The audio sampling rate in Hz, or {@link #NO_VALUE} if unknown or not applicable.
+ */
+ public final int sampleRate;
+ /** The {@link C.PcmEncoding} for PCM audio. Set to {@link #NO_VALUE} for other media types. */
+ public final @C.PcmEncoding int pcmEncoding;
+ /**
+ * The number of frames to trim from the start of the decoded audio stream, or 0 if not
+ * applicable.
+ */
+ public final int encoderDelay;
+ /**
+ * The number of frames to trim from the end of the decoded audio stream, or 0 if not applicable.
+ */
+ public final int encoderPadding;
+
+ // Audio and text specific.
+
+ /** The language as an IETF BCP 47 conformant tag, or null if unknown or not applicable. */
+ @Nullable public final String language;
+ /**
+ * The Accessibility channel, or {@link #NO_VALUE} if not known or applicable.
+ */
+ public final int accessibilityChannel;
+
+ // Provided by source.
+
+ /**
+ * The type of the {@link ExoMediaCrypto} provided by the media source, if the media source can
+ * acquire a {@link DrmSession} for {@link #drmInitData}. Null if the media source cannot acquire
+ * a session for {@link #drmInitData}, or if not applicable.
+ */
+ @Nullable public final Class<? extends ExoMediaCrypto> exoMediaCryptoType;
+
+ // Lazily initialized hashcode.
+ private int hashCode;
+
+ // Video.
+
+ /**
+ * @deprecated Use {@link #createVideoContainerFormat(String, String, String, String, String,
+ * Metadata, int, int, int, float, List, int, int)} instead.
+ */
+ @Deprecated
+ public static Format createVideoContainerFormat(
+ @Nullable String id,
+ @Nullable String containerMimeType,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ int width,
+ int height,
+ float frameRate,
+ @Nullable List<byte[]> initializationData,
+ @C.SelectionFlags int selectionFlags) {
+ return createVideoContainerFormat(
+ id,
+ /* label= */ null,
+ containerMimeType,
+ sampleMimeType,
+ codecs,
+ /* metadata= */ null,
+ bitrate,
+ width,
+ height,
+ frameRate,
+ initializationData,
+ selectionFlags,
+ /* roleFlags= */ 0);
+ }
+
+ public static Format createVideoContainerFormat(
+ @Nullable String id,
+ @Nullable String label,
+ @Nullable String containerMimeType,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ @Nullable Metadata metadata,
+ int bitrate,
+ int width,
+ int height,
+ float frameRate,
+ @Nullable List<byte[]> initializationData,
+ @C.SelectionFlags int selectionFlags,
+ @C.RoleFlags int roleFlags) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ 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,
+ /* language= */ null,
+ /* accessibilityChannel= */ NO_VALUE,
+ /* exoMediaCryptoType= */ null);
+ }
+
+ public static Format createVideoSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ int maxInputSize,
+ int width,
+ int height,
+ float frameRate,
+ @Nullable List<byte[]> initializationData,
+ @Nullable DrmInitData drmInitData) {
+ return createVideoSampleFormat(
+ id,
+ sampleMimeType,
+ codecs,
+ bitrate,
+ maxInputSize,
+ width,
+ height,
+ frameRate,
+ initializationData,
+ /* rotationDegrees= */ NO_VALUE,
+ /* pixelWidthHeightRatio= */ NO_VALUE,
+ drmInitData);
+ }
+
+ public static Format createVideoSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ int maxInputSize,
+ int width,
+ int height,
+ float frameRate,
+ @Nullable List<byte[]> initializationData,
+ 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);
+ }
+
+ public static Format createVideoSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ int maxInputSize,
+ int width,
+ int height,
+ float frameRate,
+ @Nullable List<byte[]> initializationData,
+ int rotationDegrees,
+ float pixelWidthHeightRatio,
+ @Nullable byte[] projectionData,
+ @C.StereoMode int stereoMode,
+ @Nullable ColorInfo colorInfo,
+ @Nullable DrmInitData drmInitData) {
+ return new Format(
+ id,
+ /* label= */ null,
+ /* selectionFlags= */ 0,
+ /* roleFlags= */ 0,
+ 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,
+ /* language= */ null,
+ /* accessibilityChannel= */ NO_VALUE,
+ /* exoMediaCryptoType= */ null);
+ }
+
+ // Audio.
+
+ /**
+ * @deprecated Use {@link #createAudioContainerFormat(String, String, String, String, String,
+ * Metadata, int, int, int, List, int, int, String)} instead.
+ */
+ @Deprecated
+ public static Format createAudioContainerFormat(
+ @Nullable String id,
+ @Nullable String containerMimeType,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ int channelCount,
+ int sampleRate,
+ @Nullable List<byte[]> initializationData,
+ @C.SelectionFlags int selectionFlags,
+ @Nullable String language) {
+ return createAudioContainerFormat(
+ id,
+ /* label= */ null,
+ containerMimeType,
+ sampleMimeType,
+ codecs,
+ /* metadata= */ null,
+ bitrate,
+ channelCount,
+ sampleRate,
+ initializationData,
+ selectionFlags,
+ /* roleFlags= */ 0,
+ language);
+ }
+
+ public static Format createAudioContainerFormat(
+ @Nullable String id,
+ @Nullable String label,
+ @Nullable String containerMimeType,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ @Nullable Metadata metadata,
+ int bitrate,
+ int channelCount,
+ int sampleRate,
+ @Nullable List<byte[]> initializationData,
+ @C.SelectionFlags int selectionFlags,
+ @C.RoleFlags int roleFlags,
+ @Nullable String language) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ 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,
+ language,
+ /* accessibilityChannel= */ NO_VALUE,
+ /* exoMediaCryptoType= */ null);
+ }
+
+ public static Format createAudioSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ int maxInputSize,
+ int channelCount,
+ int sampleRate,
+ @Nullable List<byte[]> initializationData,
+ @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);
+ }
+
+ public static Format createAudioSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ int maxInputSize,
+ int channelCount,
+ int sampleRate,
+ @C.PcmEncoding int pcmEncoding,
+ @Nullable List<byte[]> initializationData,
+ @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);
+ }
+
+ public static Format createAudioSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ int maxInputSize,
+ int channelCount,
+ int sampleRate,
+ @C.PcmEncoding int pcmEncoding,
+ int encoderDelay,
+ int encoderPadding,
+ @Nullable List<byte[]> initializationData,
+ @Nullable DrmInitData drmInitData,
+ @C.SelectionFlags int selectionFlags,
+ @Nullable String language,
+ @Nullable Metadata metadata) {
+ return new Format(
+ id,
+ /* label= */ null,
+ selectionFlags,
+ /* roleFlags= */ 0,
+ 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,
+ language,
+ /* accessibilityChannel= */ NO_VALUE,
+ /* exoMediaCryptoType= */ null);
+ }
+
+ // Text.
+
+ public static Format createTextContainerFormat(
+ @Nullable String id,
+ @Nullable String label,
+ @Nullable String containerMimeType,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ @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);
+ }
+
+ public static Format createTextContainerFormat(
+ @Nullable String id,
+ @Nullable String label,
+ @Nullable String containerMimeType,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ @C.SelectionFlags int selectionFlags,
+ @C.RoleFlags int roleFlags,
+ @Nullable String language,
+ int accessibilityChannel) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ 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,
+ language,
+ accessibilityChannel,
+ /* exoMediaCryptoType= */ null);
+ }
+
+ public static Format createTextSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @C.SelectionFlags int selectionFlags,
+ @Nullable String language) {
+ return createTextSampleFormat(id, sampleMimeType, selectionFlags, language, null);
+ }
+
+ public static Format createTextSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @C.SelectionFlags int selectionFlags,
+ @Nullable String language,
+ @Nullable DrmInitData drmInitData) {
+ return createTextSampleFormat(
+ id,
+ sampleMimeType,
+ /* codecs= */ null,
+ /* bitrate= */ NO_VALUE,
+ selectionFlags,
+ language,
+ NO_VALUE,
+ drmInitData,
+ OFFSET_SAMPLE_RELATIVE,
+ Collections.emptyList());
+ }
+
+ public static Format createTextSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ @C.SelectionFlags int selectionFlags,
+ @Nullable String language,
+ int accessibilityChannel,
+ @Nullable DrmInitData drmInitData) {
+ return createTextSampleFormat(
+ id,
+ sampleMimeType,
+ codecs,
+ bitrate,
+ selectionFlags,
+ language,
+ accessibilityChannel,
+ drmInitData,
+ OFFSET_SAMPLE_RELATIVE,
+ Collections.emptyList());
+ }
+
+ public static Format createTextSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ @C.SelectionFlags int selectionFlags,
+ @Nullable String language,
+ @Nullable DrmInitData drmInitData,
+ long subsampleOffsetUs) {
+ return createTextSampleFormat(
+ id,
+ sampleMimeType,
+ codecs,
+ bitrate,
+ selectionFlags,
+ language,
+ /* accessibilityChannel= */ NO_VALUE,
+ drmInitData,
+ subsampleOffsetUs,
+ Collections.emptyList());
+ }
+
+ public static Format createTextSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ @C.SelectionFlags int selectionFlags,
+ @Nullable String language,
+ int accessibilityChannel,
+ @Nullable DrmInitData drmInitData,
+ long subsampleOffsetUs,
+ @Nullable List<byte[]> initializationData) {
+ return new Format(
+ id,
+ /* label= */ null,
+ selectionFlags,
+ /* roleFlags= */ 0,
+ bitrate,
+ codecs,
+ /* metadata= */ null,
+ /* containerMimeType= */ null,
+ sampleMimeType,
+ /* maxInputSize= */ NO_VALUE,
+ initializationData,
+ drmInitData,
+ 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,
+ language,
+ accessibilityChannel,
+ /* exoMediaCryptoType= */ null);
+ }
+
+ // Image.
+
+ public static Format createImageSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ @C.SelectionFlags int selectionFlags,
+ @Nullable List<byte[]> initializationData,
+ @Nullable String language,
+ @Nullable DrmInitData drmInitData) {
+ return new Format(
+ id,
+ /* label= */ null,
+ selectionFlags,
+ /* roleFlags= */ 0,
+ bitrate,
+ codecs,
+ /* metadata=*/ null,
+ /* containerMimeType= */ null,
+ sampleMimeType,
+ /* maxInputSize= */ NO_VALUE,
+ 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= */ NO_VALUE,
+ /* sampleRate= */ NO_VALUE,
+ /* pcmEncoding= */ NO_VALUE,
+ /* encoderDelay= */ NO_VALUE,
+ /* encoderPadding= */ NO_VALUE,
+ language,
+ /* accessibilityChannel= */ NO_VALUE,
+ /* exoMediaCryptoType= */ null);
+ }
+
+ // Generic.
+
+ /**
+ * @deprecated Use {@link #createContainerFormat(String, String, String, String, String, int, int,
+ * int, String)} instead.
+ */
+ @Deprecated
+ public static Format createContainerFormat(
+ @Nullable String id,
+ @Nullable String containerMimeType,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ @C.SelectionFlags int selectionFlags,
+ @Nullable String language) {
+ return createContainerFormat(
+ id,
+ /* label= */ null,
+ containerMimeType,
+ sampleMimeType,
+ codecs,
+ bitrate,
+ selectionFlags,
+ /* roleFlags= */ 0,
+ language);
+ }
+
+ public static Format createContainerFormat(
+ @Nullable String id,
+ @Nullable String label,
+ @Nullable String containerMimeType,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ @C.SelectionFlags int selectionFlags,
+ @C.RoleFlags int roleFlags,
+ @Nullable String language) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ 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,
+ language,
+ /* accessibilityChannel= */ NO_VALUE,
+ /* exoMediaCryptoType= */ null);
+ }
+
+ public static Format createSampleFormat(
+ @Nullable String id, @Nullable String sampleMimeType, long subsampleOffsetUs) {
+ return new Format(
+ id,
+ /* label= */ null,
+ /* selectionFlags= */ 0,
+ /* roleFlags= */ 0,
+ /* bitrate= */ NO_VALUE,
+ /* codecs= */ null,
+ /* metadata= */ null,
+ /* containerMimeType= */ null,
+ sampleMimeType,
+ /* maxInputSize= */ NO_VALUE,
+ /* initializationData= */ null,
+ /* 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,
+ /* language= */ null,
+ /* accessibilityChannel= */ NO_VALUE,
+ /* exoMediaCryptoType= */ null);
+ }
+
+ public static Format createSampleFormat(
+ @Nullable String id,
+ @Nullable String sampleMimeType,
+ @Nullable String codecs,
+ int bitrate,
+ @Nullable DrmInitData drmInitData) {
+ return new Format(
+ id,
+ /* label= */ null,
+ /* selectionFlags= */ 0,
+ /* roleFlags= */ 0,
+ bitrate,
+ codecs,
+ /* metadata= */ null,
+ /* containerMimeType= */ null,
+ sampleMimeType,
+ /* maxInputSize= */ NO_VALUE,
+ /* initializationData= */ null,
+ 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= */ NO_VALUE,
+ /* sampleRate= */ NO_VALUE,
+ /* pcmEncoding= */ NO_VALUE,
+ /* encoderDelay= */ NO_VALUE,
+ /* encoderPadding= */ NO_VALUE,
+ /* language= */ null,
+ /* accessibilityChannel= */ NO_VALUE,
+ /* exoMediaCryptoType= */ null);
+ }
+
+ /* package */ Format(
+ @Nullable String id,
+ @Nullable String label,
+ @C.SelectionFlags int selectionFlags,
+ @C.RoleFlags int roleFlags,
+ int bitrate,
+ @Nullable String codecs,
+ @Nullable Metadata metadata,
+ // Container specific.
+ @Nullable String containerMimeType,
+ // Elementary stream specific.
+ @Nullable String sampleMimeType,
+ int maxInputSize,
+ @Nullable List<byte[]> initializationData,
+ @Nullable DrmInitData drmInitData,
+ long subsampleOffsetUs,
+ // Video specific.
+ int width,
+ int height,
+ float frameRate,
+ int rotationDegrees,
+ float pixelWidthHeightRatio,
+ @Nullable byte[] projectionData,
+ @C.StereoMode int stereoMode,
+ @Nullable ColorInfo colorInfo,
+ // Audio specific.
+ int channelCount,
+ int sampleRate,
+ @C.PcmEncoding int pcmEncoding,
+ int encoderDelay,
+ int encoderPadding,
+ // Audio and text specific.
+ @Nullable String language,
+ int accessibilityChannel,
+ // Provided by source.
+ @Nullable Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
+ this.id = id;
+ this.label = label;
+ this.selectionFlags = selectionFlags;
+ this.roleFlags = roleFlags;
+ this.bitrate = bitrate;
+ this.codecs = codecs;
+ this.metadata = metadata;
+ // Container specific.
+ this.containerMimeType = containerMimeType;
+ // Elementary stream specific.
+ this.sampleMimeType = sampleMimeType;
+ this.maxInputSize = maxInputSize;
+ this.initializationData =
+ initializationData == null ? Collections.emptyList() : initializationData;
+ this.drmInitData = drmInitData;
+ this.subsampleOffsetUs = subsampleOffsetUs;
+ // Video specific.
+ this.width = width;
+ this.height = height;
+ this.frameRate = frameRate;
+ this.rotationDegrees = rotationDegrees == Format.NO_VALUE ? 0 : rotationDegrees;
+ this.pixelWidthHeightRatio =
+ pixelWidthHeightRatio == Format.NO_VALUE ? 1 : pixelWidthHeightRatio;
+ this.projectionData = projectionData;
+ this.stereoMode = stereoMode;
+ this.colorInfo = colorInfo;
+ // Audio specific.
+ this.channelCount = channelCount;
+ this.sampleRate = sampleRate;
+ this.pcmEncoding = pcmEncoding;
+ this.encoderDelay = encoderDelay == Format.NO_VALUE ? 0 : encoderDelay;
+ this.encoderPadding = encoderPadding == Format.NO_VALUE ? 0 : encoderPadding;
+ // Audio and text specific.
+ this.language = Util.normalizeLanguageCode(language);
+ this.accessibilityChannel = accessibilityChannel;
+ // Provided by source.
+ this.exoMediaCryptoType = exoMediaCryptoType;
+ }
+
+ @SuppressWarnings("ResourceType")
+ /* package */ Format(Parcel in) {
+ id = in.readString();
+ label = in.readString();
+ selectionFlags = in.readInt();
+ roleFlags = in.readInt();
+ bitrate = in.readInt();
+ codecs = in.readString();
+ metadata = in.readParcelable(Metadata.class.getClassLoader());
+ // Container specific.
+ containerMimeType = in.readString();
+ // Elementary stream specific.
+ sampleMimeType = in.readString();
+ maxInputSize = in.readInt();
+ int initializationDataSize = in.readInt();
+ initializationData = new ArrayList<>(initializationDataSize);
+ for (int i = 0; i < initializationDataSize; i++) {
+ initializationData.add(in.createByteArray());
+ }
+ drmInitData = in.readParcelable(DrmInitData.class.getClassLoader());
+ subsampleOffsetUs = in.readLong();
+ // Video specific.
+ width = in.readInt();
+ height = in.readInt();
+ frameRate = in.readFloat();
+ rotationDegrees = in.readInt();
+ pixelWidthHeightRatio = in.readFloat();
+ boolean hasProjectionData = Util.readBoolean(in);
+ projectionData = hasProjectionData ? in.createByteArray() : null;
+ stereoMode = in.readInt();
+ colorInfo = in.readParcelable(ColorInfo.class.getClassLoader());
+ // Audio specific.
+ channelCount = in.readInt();
+ sampleRate = in.readInt();
+ pcmEncoding = in.readInt();
+ encoderDelay = in.readInt();
+ encoderPadding = in.readInt();
+ // Audio and text specific.
+ language = in.readString();
+ accessibilityChannel = in.readInt();
+ // Provided by source.
+ exoMediaCryptoType = null;
+ }
+
+ public Format copyWithMaxInputSize(int maxInputSize) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ bitrate,
+ codecs,
+ metadata,
+ containerMimeType,
+ sampleMimeType,
+ maxInputSize,
+ initializationData,
+ drmInitData,
+ subsampleOffsetUs,
+ width,
+ height,
+ frameRate,
+ rotationDegrees,
+ pixelWidthHeightRatio,
+ projectionData,
+ stereoMode,
+ colorInfo,
+ channelCount,
+ sampleRate,
+ pcmEncoding,
+ encoderDelay,
+ encoderPadding,
+ language,
+ accessibilityChannel,
+ exoMediaCryptoType);
+ }
+
+ public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ bitrate,
+ codecs,
+ metadata,
+ containerMimeType,
+ sampleMimeType,
+ maxInputSize,
+ initializationData,
+ drmInitData,
+ subsampleOffsetUs,
+ width,
+ height,
+ frameRate,
+ rotationDegrees,
+ pixelWidthHeightRatio,
+ projectionData,
+ stereoMode,
+ colorInfo,
+ channelCount,
+ sampleRate,
+ pcmEncoding,
+ encoderDelay,
+ encoderPadding,
+ language,
+ accessibilityChannel,
+ exoMediaCryptoType);
+ }
+
+ public Format copyWithLabel(@Nullable String label) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ bitrate,
+ codecs,
+ metadata,
+ containerMimeType,
+ sampleMimeType,
+ maxInputSize,
+ initializationData,
+ drmInitData,
+ subsampleOffsetUs,
+ width,
+ height,
+ frameRate,
+ rotationDegrees,
+ pixelWidthHeightRatio,
+ projectionData,
+ stereoMode,
+ colorInfo,
+ channelCount,
+ sampleRate,
+ pcmEncoding,
+ encoderDelay,
+ encoderPadding,
+ language,
+ accessibilityChannel,
+ exoMediaCryptoType);
+ }
+
+ 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 new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ bitrate,
+ codecs,
+ metadata,
+ containerMimeType,
+ sampleMimeType,
+ maxInputSize,
+ initializationData,
+ drmInitData,
+ subsampleOffsetUs,
+ width,
+ height,
+ frameRate,
+ rotationDegrees,
+ pixelWidthHeightRatio,
+ projectionData,
+ stereoMode,
+ colorInfo,
+ channelCount,
+ sampleRate,
+ pcmEncoding,
+ encoderDelay,
+ encoderPadding,
+ language,
+ accessibilityChannel,
+ exoMediaCryptoType);
+ }
+
+ @SuppressWarnings("ReferenceEquality")
+ public Format copyWithManifestFormatInfo(Format manifestFormat) {
+ if (this == manifestFormat) {
+ // No need to copy from ourselves.
+ return this;
+ }
+
+ int trackType = MimeTypes.getTrackType(sampleMimeType);
+
+ // Use manifest value only.
+ String id = manifestFormat.id;
+
+ // Prefer manifest values, but fill in from sample format if missing.
+ String label = manifestFormat.label != null ? manifestFormat.label : this.label;
+ String language = this.language;
+ if ((trackType == C.TRACK_TYPE_TEXT || trackType == C.TRACK_TYPE_AUDIO)
+ && manifestFormat.language != null) {
+ language = manifestFormat.language;
+ }
+
+ // Prefer sample format values, but fill in from manifest if missing.
+ int bitrate = this.bitrate == NO_VALUE ? manifestFormat.bitrate : this.bitrate;
+ String codecs = this.codecs;
+ if (codecs == null) {
+ // The manifest format may be muxed, so filter only codecs of this format's type. If we still
+ // have more than one codec then we're unable to uniquely identify which codec to fill in.
+ String codecsOfType = Util.getCodecsOfType(manifestFormat.codecs, trackType);
+ if (Util.splitCodecs(codecsOfType).length == 1) {
+ codecs = codecsOfType;
+ }
+ }
+
+ Metadata metadata =
+ this.metadata == null
+ ? manifestFormat.metadata
+ : this.metadata.copyWithAppendedEntriesFrom(manifestFormat.metadata);
+
+ float frameRate = this.frameRate;
+ if (frameRate == NO_VALUE && trackType == C.TRACK_TYPE_VIDEO) {
+ frameRate = manifestFormat.frameRate;
+ }
+
+ // Merge manifest and sample format values.
+ @C.SelectionFlags int selectionFlags = this.selectionFlags | manifestFormat.selectionFlags;
+ @C.RoleFlags int roleFlags = this.roleFlags | manifestFormat.roleFlags;
+ DrmInitData drmInitData =
+ DrmInitData.createSessionCreationData(manifestFormat.drmInitData, this.drmInitData);
+
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ bitrate,
+ codecs,
+ metadata,
+ containerMimeType,
+ sampleMimeType,
+ maxInputSize,
+ initializationData,
+ drmInitData,
+ subsampleOffsetUs,
+ width,
+ height,
+ frameRate,
+ rotationDegrees,
+ pixelWidthHeightRatio,
+ projectionData,
+ stereoMode,
+ colorInfo,
+ channelCount,
+ sampleRate,
+ pcmEncoding,
+ encoderDelay,
+ encoderPadding,
+ language,
+ accessibilityChannel,
+ exoMediaCryptoType);
+ }
+
+ public Format copyWithGaplessInfo(int encoderDelay, int encoderPadding) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ bitrate,
+ codecs,
+ metadata,
+ containerMimeType,
+ sampleMimeType,
+ maxInputSize,
+ initializationData,
+ drmInitData,
+ subsampleOffsetUs,
+ width,
+ height,
+ frameRate,
+ rotationDegrees,
+ pixelWidthHeightRatio,
+ projectionData,
+ stereoMode,
+ colorInfo,
+ channelCount,
+ sampleRate,
+ pcmEncoding,
+ encoderDelay,
+ encoderPadding,
+ language,
+ accessibilityChannel,
+ exoMediaCryptoType);
+ }
+
+ public Format copyWithFrameRate(float frameRate) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ bitrate,
+ codecs,
+ metadata,
+ containerMimeType,
+ sampleMimeType,
+ maxInputSize,
+ initializationData,
+ drmInitData,
+ subsampleOffsetUs,
+ width,
+ height,
+ frameRate,
+ rotationDegrees,
+ pixelWidthHeightRatio,
+ projectionData,
+ stereoMode,
+ colorInfo,
+ channelCount,
+ sampleRate,
+ pcmEncoding,
+ encoderDelay,
+ encoderPadding,
+ language,
+ accessibilityChannel,
+ exoMediaCryptoType);
+ }
+
+ public Format copyWithDrmInitData(@Nullable DrmInitData drmInitData) {
+ return copyWithAdjustments(drmInitData, metadata);
+ }
+
+ public Format copyWithMetadata(@Nullable Metadata metadata) {
+ return copyWithAdjustments(drmInitData, metadata);
+ }
+
+ @SuppressWarnings("ReferenceEquality")
+ public Format copyWithAdjustments(
+ @Nullable DrmInitData drmInitData, @Nullable Metadata metadata) {
+ if (drmInitData == this.drmInitData && metadata == this.metadata) {
+ return this;
+ }
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ bitrate,
+ codecs,
+ metadata,
+ containerMimeType,
+ sampleMimeType,
+ maxInputSize,
+ initializationData,
+ drmInitData,
+ subsampleOffsetUs,
+ width,
+ height,
+ frameRate,
+ rotationDegrees,
+ pixelWidthHeightRatio,
+ projectionData,
+ stereoMode,
+ colorInfo,
+ channelCount,
+ sampleRate,
+ pcmEncoding,
+ encoderDelay,
+ encoderPadding,
+ language,
+ accessibilityChannel,
+ exoMediaCryptoType);
+ }
+
+ public Format copyWithRotationDegrees(int rotationDegrees) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ bitrate,
+ codecs,
+ metadata,
+ containerMimeType,
+ sampleMimeType,
+ maxInputSize,
+ initializationData,
+ drmInitData,
+ subsampleOffsetUs,
+ width,
+ height,
+ frameRate,
+ rotationDegrees,
+ pixelWidthHeightRatio,
+ projectionData,
+ stereoMode,
+ colorInfo,
+ channelCount,
+ sampleRate,
+ pcmEncoding,
+ encoderDelay,
+ encoderPadding,
+ language,
+ accessibilityChannel,
+ exoMediaCryptoType);
+ }
+
+ public Format copyWithBitrate(int bitrate) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ bitrate,
+ codecs,
+ metadata,
+ containerMimeType,
+ sampleMimeType,
+ maxInputSize,
+ initializationData,
+ drmInitData,
+ subsampleOffsetUs,
+ width,
+ height,
+ frameRate,
+ rotationDegrees,
+ pixelWidthHeightRatio,
+ projectionData,
+ stereoMode,
+ colorInfo,
+ channelCount,
+ sampleRate,
+ pcmEncoding,
+ encoderDelay,
+ encoderPadding,
+ language,
+ accessibilityChannel,
+ exoMediaCryptoType);
+ }
+
+ public Format copyWithVideoSize(int width, int height) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ bitrate,
+ codecs,
+ metadata,
+ containerMimeType,
+ sampleMimeType,
+ maxInputSize,
+ initializationData,
+ drmInitData,
+ subsampleOffsetUs,
+ width,
+ height,
+ frameRate,
+ rotationDegrees,
+ pixelWidthHeightRatio,
+ projectionData,
+ stereoMode,
+ colorInfo,
+ channelCount,
+ sampleRate,
+ pcmEncoding,
+ encoderDelay,
+ encoderPadding,
+ language,
+ accessibilityChannel,
+ exoMediaCryptoType);
+ }
+
+ public Format copyWithExoMediaCryptoType(
+ @Nullable Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
+ return new Format(
+ id,
+ label,
+ selectionFlags,
+ roleFlags,
+ bitrate,
+ codecs,
+ metadata,
+ containerMimeType,
+ sampleMimeType,
+ maxInputSize,
+ initializationData,
+ drmInitData,
+ subsampleOffsetUs,
+ width,
+ height,
+ frameRate,
+ rotationDegrees,
+ pixelWidthHeightRatio,
+ projectionData,
+ stereoMode,
+ colorInfo,
+ channelCount,
+ sampleRate,
+ pcmEncoding,
+ encoderDelay,
+ encoderPadding,
+ language,
+ accessibilityChannel,
+ exoMediaCryptoType);
+ }
+
+ /**
+ * Returns the number of pixels if this is a video format whose {@link #width} and {@link #height}
+ * are known, or {@link #NO_VALUE} otherwise
+ */
+ public int getPixelCount() {
+ return width == NO_VALUE || height == NO_VALUE ? NO_VALUE : (width * height);
+ }
+
+ @Override
+ public String toString() {
+ return "Format("
+ + id
+ + ", "
+ + label
+ + ", "
+ + containerMimeType
+ + ", "
+ + sampleMimeType
+ + ", "
+ + codecs
+ + ", "
+ + bitrate
+ + ", "
+ + language
+ + ", ["
+ + width
+ + ", "
+ + height
+ + ", "
+ + frameRate
+ + "]"
+ + ", ["
+ + channelCount
+ + ", "
+ + sampleRate
+ + "])";
+ }
+
+ @Override
+ public int hashCode() {
+ if (hashCode == 0) {
+ // Some fields for which hashing is expensive are deliberately omitted.
+ int result = 17;
+ result = 31 * result + (id == null ? 0 : id.hashCode());
+ result = 31 * result + (label != null ? label.hashCode() : 0);
+ result = 31 * result + selectionFlags;
+ result = 31 * result + roleFlags;
+ result = 31 * result + bitrate;
+ result = 31 * result + (codecs == null ? 0 : codecs.hashCode());
+ result = 31 * result + (metadata == null ? 0 : metadata.hashCode());
+ // Container specific.
+ result = 31 * result + (containerMimeType == null ? 0 : containerMimeType.hashCode());
+ // Elementary stream specific.
+ result = 31 * result + (sampleMimeType == null ? 0 : sampleMimeType.hashCode());
+ result = 31 * result + maxInputSize;
+ // [Omitted] initializationData.
+ // [Omitted] drmInitData.
+ result = 31 * result + (int) subsampleOffsetUs;
+ // Video specific.
+ result = 31 * result + width;
+ result = 31 * result + height;
+ result = 31 * result + Float.floatToIntBits(frameRate);
+ result = 31 * result + rotationDegrees;
+ result = 31 * result + Float.floatToIntBits(pixelWidthHeightRatio);
+ // [Omitted] projectionData.
+ result = 31 * result + stereoMode;
+ // [Omitted] colorInfo.
+ // Audio specific.
+ result = 31 * result + channelCount;
+ result = 31 * result + sampleRate;
+ result = 31 * result + pcmEncoding;
+ result = 31 * result + encoderDelay;
+ result = 31 * result + encoderPadding;
+ // Audio and text specific.
+ result = 31 * result + (language == null ? 0 : language.hashCode());
+ result = 31 * result + accessibilityChannel;
+ // Provided by source.
+ result = 31 * result + (exoMediaCryptoType == null ? 0 : exoMediaCryptoType.hashCode());
+ hashCode = result;
+ }
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ Format other = (Format) obj;
+ if (hashCode != 0 && other.hashCode != 0 && hashCode != other.hashCode) {
+ return false;
+ }
+ // Field equality checks ordered by type, with the cheapest checks first.
+ return selectionFlags == other.selectionFlags
+ && roleFlags == other.roleFlags
+ && bitrate == other.bitrate
+ && maxInputSize == other.maxInputSize
+ && subsampleOffsetUs == other.subsampleOffsetUs
+ && width == other.width
+ && height == other.height
+ && rotationDegrees == other.rotationDegrees
+ && stereoMode == other.stereoMode
+ && channelCount == other.channelCount
+ && sampleRate == other.sampleRate
+ && pcmEncoding == other.pcmEncoding
+ && encoderDelay == other.encoderDelay
+ && encoderPadding == other.encoderPadding
+ && accessibilityChannel == other.accessibilityChannel
+ && Float.compare(frameRate, other.frameRate) == 0
+ && Float.compare(pixelWidthHeightRatio, other.pixelWidthHeightRatio) == 0
+ && Util.areEqual(exoMediaCryptoType, other.exoMediaCryptoType)
+ && Util.areEqual(id, other.id)
+ && Util.areEqual(label, other.label)
+ && Util.areEqual(codecs, other.codecs)
+ && Util.areEqual(containerMimeType, other.containerMimeType)
+ && Util.areEqual(sampleMimeType, other.sampleMimeType)
+ && Util.areEqual(language, other.language)
+ && Arrays.equals(projectionData, other.projectionData)
+ && Util.areEqual(metadata, other.metadata)
+ && Util.areEqual(colorInfo, other.colorInfo)
+ && Util.areEqual(drmInitData, other.drmInitData)
+ && initializationDataEquals(other);
+ }
+
+ /**
+ * Returns whether the {@link #initializationData}s belonging to this format and {@code other} are
+ * equal.
+ *
+ * @param other The other format whose {@link #initializationData} is being compared.
+ * @return Whether the {@link #initializationData}s belonging to this format and {@code other} are
+ * equal.
+ */
+ public boolean initializationDataEquals(Format other) {
+ if (initializationData.size() != other.initializationData.size()) {
+ return false;
+ }
+ for (int i = 0; i < initializationData.size(); i++) {
+ if (!Arrays.equals(initializationData.get(i), other.initializationData.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Utility methods
+
+ /** Returns a prettier {@link String} than {@link #toString()}, intended for logging. */
+ public static String toLogString(@Nullable Format format) {
+ if (format == null) {
+ return "null";
+ }
+ StringBuilder builder = new StringBuilder();
+ builder.append("id=").append(format.id).append(", mimeType=").append(format.sampleMimeType);
+ if (format.bitrate != Format.NO_VALUE) {
+ builder.append(", bitrate=").append(format.bitrate);
+ }
+ if (format.codecs != null) {
+ builder.append(", codecs=").append(format.codecs);
+ }
+ if (format.width != Format.NO_VALUE && format.height != Format.NO_VALUE) {
+ builder.append(", res=").append(format.width).append("x").append(format.height);
+ }
+ if (format.frameRate != Format.NO_VALUE) {
+ builder.append(", fps=").append(format.frameRate);
+ }
+ if (format.channelCount != Format.NO_VALUE) {
+ builder.append(", channels=").append(format.channelCount);
+ }
+ if (format.sampleRate != Format.NO_VALUE) {
+ builder.append(", sample_rate=").append(format.sampleRate);
+ }
+ if (format.language != null) {
+ builder.append(", language=").append(format.language);
+ }
+ if (format.label != null) {
+ builder.append(", label=").append(format.label);
+ }
+ return builder.toString();
+ }
+
+ // Parcelable implementation.
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(id);
+ dest.writeString(label);
+ dest.writeInt(selectionFlags);
+ dest.writeInt(roleFlags);
+ dest.writeInt(bitrate);
+ dest.writeString(codecs);
+ dest.writeParcelable(metadata, 0);
+ // Container specific.
+ dest.writeString(containerMimeType);
+ // Elementary stream specific.
+ dest.writeString(sampleMimeType);
+ dest.writeInt(maxInputSize);
+ int initializationDataSize = initializationData.size();
+ dest.writeInt(initializationDataSize);
+ for (int i = 0; i < initializationDataSize; i++) {
+ dest.writeByteArray(initializationData.get(i));
+ }
+ dest.writeParcelable(drmInitData, 0);
+ dest.writeLong(subsampleOffsetUs);
+ // Video specific.
+ dest.writeInt(width);
+ dest.writeInt(height);
+ dest.writeFloat(frameRate);
+ dest.writeInt(rotationDegrees);
+ dest.writeFloat(pixelWidthHeightRatio);
+ Util.writeBoolean(dest, projectionData != null);
+ if (projectionData != null) {
+ dest.writeByteArray(projectionData);
+ }
+ dest.writeInt(stereoMode);
+ dest.writeParcelable(colorInfo, flags);
+ // Audio specific.
+ dest.writeInt(channelCount);
+ dest.writeInt(sampleRate);
+ dest.writeInt(pcmEncoding);
+ dest.writeInt(encoderDelay);
+ dest.writeInt(encoderPadding);
+ // Audio and text specific.
+ dest.writeString(language);
+ dest.writeInt(accessibilityChannel);
+ }
+
+ public static final Creator<Format> CREATOR = new Creator<Format>() {
+
+ @Override
+ public Format createFromParcel(Parcel in) {
+ return new Format(in);
+ }
+
+ @Override
+ public Format[] newArray(int size) {
+ return new Format[size];
+ }
+
+ };
+}