• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.android.exoplayer2;
17 
18 import android.os.Parcel;
19 import android.os.Parcelable;
20 import androidx.annotation.Nullable;
21 import com.google.android.exoplayer2.drm.DrmInitData;
22 import com.google.android.exoplayer2.drm.ExoMediaCrypto;
23 import com.google.android.exoplayer2.metadata.Metadata;
24 import com.google.android.exoplayer2.util.MimeTypes;
25 import com.google.android.exoplayer2.util.Util;
26 import com.google.android.exoplayer2.video.ColorInfo;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Collections;
30 import java.util.List;
31 
32 /**
33  * Represents a media format.
34  *
35  * <p>When building formats, populate all fields whose values are known and relevant to the type of
36  * format being constructed. For information about different types of format, see ExoPlayer's <a
37  * href="https://exoplayer.dev/supported-formats.html">Supported formats page</a>.
38  *
39  * <h3>Fields commonly relevant to all formats</h3>
40  *
41  * <ul>
42  *   <li>{@link #id}
43  *   <li>{@link #label}
44  *   <li>{@link #language}
45  *   <li>{@link #selectionFlags}
46  *   <li>{@link #roleFlags}
47  *   <li>{@link #averageBitrate}
48  *   <li>{@link #peakBitrate}
49  *   <li>{@link #codecs}
50  *   <li>{@link #metadata}
51  * </ul>
52  *
53  * <h3 id="container-formats">Fields relevant to container formats</h3>
54  *
55  * <ul>
56  *   <li>{@link #containerMimeType}
57  *   <li>If the container only contains a single media track, <a href="#sample-formats">fields
58  *       relevant to sample formats</a> can are also be relevant and can be set to describe the
59  *       sample format of that track.
60  *   <li>If the container only contains one track of a given type (possibly alongside tracks of
61  *       other types), then fields relevant to that track type can be set to describe the properties
62  *       of the track. See the sections below for <a href="#video-formats">video</a>, <a
63  *       href="#audio-formats">audio</a> and <a href="#text-formats">text</a> formats.
64  * </ul>
65  *
66  * <h3 id="sample-formats">Fields relevant to sample formats</h3>
67  *
68  * <ul>
69  *   <li>{@link #sampleMimeType}
70  *   <li>{@link #maxInputSize}
71  *   <li>{@link #initializationData}
72  *   <li>{@link #drmInitData}
73  *   <li>{@link #subsampleOffsetUs}
74  *   <li>Fields relevant to the sample format's track type are also relevant. See the sections below
75  *       for <a href="#video-formats">video</a>, <a href="#audio-formats">audio</a> and <a
76  *       href="#text-formats">text</a> formats.
77  * </ul>
78  *
79  * <h3 id="video-formats">Fields relevant to video formats</h3>
80  *
81  * <ul>
82  *   <li>{@link #width}
83  *   <li>{@link #height}
84  *   <li>{@link #frameRate}
85  *   <li>{@link #rotationDegrees}
86  *   <li>{@link #pixelWidthHeightRatio}
87  *   <li>{@link #projectionData}
88  *   <li>{@link #stereoMode}
89  *   <li>{@link #colorInfo}
90  * </ul>
91  *
92  * <h3 id="audio-formats">Fields relevant to audio formats</h3>
93  *
94  * <ul>
95  *   <li>{@link #channelCount}
96  *   <li>{@link #sampleRate}
97  *   <li>{@link #pcmEncoding}
98  *   <li>{@link #encoderDelay}
99  *   <li>{@link #encoderPadding}
100  * </ul>
101  *
102  * <h3 id="text-formats">Fields relevant to text formats</h3>
103  *
104  * <ul>
105  *   <li>{@link #accessibilityChannel}
106  * </ul>
107  */
108 public final class Format implements Parcelable {
109 
110   /**
111    * Builds {@link Format} instances.
112    *
113    * <p>Use Format#buildUpon() to obtain a builder representing an existing {@link Format}.
114    *
115    * <p>When building formats, populate all fields whose values are known and relevant to the type
116    * of format being constructed. See the {@link Format} Javadoc for information about which fields
117    * should be set for different types of format.
118    */
119   public static final class Builder {
120 
121     @Nullable private String id;
122     @Nullable private String label;
123     @Nullable private String language;
124     @C.SelectionFlags private int selectionFlags;
125     @C.RoleFlags private int roleFlags;
126     private int averageBitrate;
127     private int peakBitrate;
128     @Nullable private String codecs;
129     @Nullable private Metadata metadata;
130 
131     // Container specific.
132 
133     @Nullable private String containerMimeType;
134 
135     // Sample specific.
136 
137     @Nullable private String sampleMimeType;
138     private int maxInputSize;
139     @Nullable private List<byte[]> initializationData;
140     @Nullable private DrmInitData drmInitData;
141     private long subsampleOffsetUs;
142 
143     // Video specific.
144 
145     private int width;
146     private int height;
147     private float frameRate;
148     private int rotationDegrees;
149     private float pixelWidthHeightRatio;
150     @Nullable private byte[] projectionData;
151     @C.StereoMode private int stereoMode;
152     @Nullable private ColorInfo colorInfo;
153 
154     // Audio specific.
155 
156     private int channelCount;
157     private int sampleRate;
158     @C.PcmEncoding private int pcmEncoding;
159     private int encoderDelay;
160     private int encoderPadding;
161 
162     // Text specific.
163 
164     private int accessibilityChannel;
165 
166     // Provided by source.
167 
168     @Nullable private Class<? extends ExoMediaCrypto> exoMediaCryptoType;
169 
170     /** Creates a new instance with default values. */
Builder()171     public Builder() {
172       averageBitrate = NO_VALUE;
173       peakBitrate = NO_VALUE;
174       // Sample specific.
175       maxInputSize = NO_VALUE;
176       subsampleOffsetUs = OFFSET_SAMPLE_RELATIVE;
177       // Video specific.
178       width = NO_VALUE;
179       height = NO_VALUE;
180       frameRate = NO_VALUE;
181       pixelWidthHeightRatio = 1.0f;
182       stereoMode = NO_VALUE;
183       // Audio specific.
184       channelCount = NO_VALUE;
185       sampleRate = NO_VALUE;
186       pcmEncoding = NO_VALUE;
187       // Text specific.
188       accessibilityChannel = NO_VALUE;
189     }
190 
191     /**
192      * Creates a new instance to build upon the provided {@link Format}.
193      *
194      * @param format The {@link Format} to build upon.
195      */
Builder(Format format)196     private Builder(Format format) {
197       this.id = format.id;
198       this.label = format.label;
199       this.language = format.language;
200       this.selectionFlags = format.selectionFlags;
201       this.roleFlags = format.roleFlags;
202       this.averageBitrate = format.averageBitrate;
203       this.peakBitrate = format.peakBitrate;
204       this.codecs = format.codecs;
205       this.metadata = format.metadata;
206       // Container specific.
207       this.containerMimeType = format.containerMimeType;
208       // Sample specific.
209       this.sampleMimeType = format.sampleMimeType;
210       this.maxInputSize = format.maxInputSize;
211       this.initializationData = format.initializationData;
212       this.drmInitData = format.drmInitData;
213       this.subsampleOffsetUs = format.subsampleOffsetUs;
214       // Video specific.
215       this.width = format.width;
216       this.height = format.height;
217       this.frameRate = format.frameRate;
218       this.rotationDegrees = format.rotationDegrees;
219       this.pixelWidthHeightRatio = format.pixelWidthHeightRatio;
220       this.projectionData = format.projectionData;
221       this.stereoMode = format.stereoMode;
222       this.colorInfo = format.colorInfo;
223       // Audio specific.
224       this.channelCount = format.channelCount;
225       this.sampleRate = format.sampleRate;
226       this.pcmEncoding = format.pcmEncoding;
227       this.encoderDelay = format.encoderDelay;
228       this.encoderPadding = format.encoderPadding;
229       // Text specific.
230       this.accessibilityChannel = format.accessibilityChannel;
231       // Provided by source.
232       this.exoMediaCryptoType = format.exoMediaCryptoType;
233     }
234 
235     /**
236      * Sets {@link Format#id}. The default value is {@code null}.
237      *
238      * @param id The {@link Format#id}.
239      * @return The builder.
240      */
setId(@ullable String id)241     public Builder setId(@Nullable String id) {
242       this.id = id;
243       return this;
244     }
245 
246     /**
247      * Sets {@link Format#id} to {@link Integer#toString() Integer.toString(id)}. The default value
248      * is {@code null}.
249      *
250      * @param id The {@link Format#id}.
251      * @return The builder.
252      */
setId(int id)253     public Builder setId(int id) {
254       this.id = Integer.toString(id);
255       return this;
256     }
257 
258     /**
259      * Sets {@link Format#label}. The default value is {@code null}.
260      *
261      * @param label The {@link Format#label}.
262      * @return The builder.
263      */
setLabel(@ullable String label)264     public Builder setLabel(@Nullable String label) {
265       this.label = label;
266       return this;
267     }
268 
269     /**
270      * Sets {@link Format#language}. The default value is {@code null}.
271      *
272      * @param language The {@link Format#language}.
273      * @return The builder.
274      */
setLanguage(@ullable String language)275     public Builder setLanguage(@Nullable String language) {
276       this.language = language;
277       return this;
278     }
279 
280     /**
281      * Sets {@link Format#selectionFlags}. The default value is 0.
282      *
283      * @param selectionFlags The {@link Format#selectionFlags}.
284      * @return The builder.
285      */
setSelectionFlags(@.SelectionFlags int selectionFlags)286     public Builder setSelectionFlags(@C.SelectionFlags int selectionFlags) {
287       this.selectionFlags = selectionFlags;
288       return this;
289     }
290 
291     /**
292      * Sets {@link Format#roleFlags}. The default value is 0.
293      *
294      * @param roleFlags The {@link Format#roleFlags}.
295      * @return The builder.
296      */
setRoleFlags(@.RoleFlags int roleFlags)297     public Builder setRoleFlags(@C.RoleFlags int roleFlags) {
298       this.roleFlags = roleFlags;
299       return this;
300     }
301 
302     /**
303      * Sets {@link Format#averageBitrate}. The default value is {@link #NO_VALUE}.
304      *
305      * @param averageBitrate The {@link Format#averageBitrate}.
306      * @return The builder.
307      */
setAverageBitrate(int averageBitrate)308     public Builder setAverageBitrate(int averageBitrate) {
309       this.averageBitrate = averageBitrate;
310       return this;
311     }
312 
313     /**
314      * Sets {@link Format#peakBitrate}. The default value is {@link #NO_VALUE}.
315      *
316      * @param peakBitrate The {@link Format#peakBitrate}.
317      * @return The builder.
318      */
setPeakBitrate(int peakBitrate)319     public Builder setPeakBitrate(int peakBitrate) {
320       this.peakBitrate = peakBitrate;
321       return this;
322     }
323 
324     /**
325      * Sets {@link Format#codecs}. The default value is {@code null}.
326      *
327      * @param codecs The {@link Format#codecs}.
328      * @return The builder.
329      */
setCodecs(@ullable String codecs)330     public Builder setCodecs(@Nullable String codecs) {
331       this.codecs = codecs;
332       return this;
333     }
334 
335     /**
336      * Sets {@link Format#metadata}. The default value is {@code null}.
337      *
338      * @param metadata The {@link Format#metadata}.
339      * @return The builder.
340      */
setMetadata(@ullable Metadata metadata)341     public Builder setMetadata(@Nullable Metadata metadata) {
342       this.metadata = metadata;
343       return this;
344     }
345 
346     // Container specific.
347 
348     /**
349      * Sets {@link Format#containerMimeType}. The default value is {@code null}.
350      *
351      * @param containerMimeType The {@link Format#containerMimeType}.
352      * @return The builder.
353      */
setContainerMimeType(@ullable String containerMimeType)354     public Builder setContainerMimeType(@Nullable String containerMimeType) {
355       this.containerMimeType = containerMimeType;
356       return this;
357     }
358 
359     // Sample specific.
360 
361     /**
362      * Sets {@link Format#sampleMimeType}. The default value is {@code null}.
363      *
364      * @param sampleMimeType {@link Format#sampleMimeType}.
365      * @return The builder.
366      */
setSampleMimeType(@ullable String sampleMimeType)367     public Builder setSampleMimeType(@Nullable String sampleMimeType) {
368       this.sampleMimeType = sampleMimeType;
369       return this;
370     }
371 
372     /**
373      * Sets {@link Format#maxInputSize}. The default value is {@link #NO_VALUE}.
374      *
375      * @param maxInputSize The {@link Format#maxInputSize}.
376      * @return The builder.
377      */
setMaxInputSize(int maxInputSize)378     public Builder setMaxInputSize(int maxInputSize) {
379       this.maxInputSize = maxInputSize;
380       return this;
381     }
382 
383     /**
384      * Sets {@link Format#initializationData}. The default value is {@code null}.
385      *
386      * @param initializationData The {@link Format#initializationData}.
387      * @return The builder.
388      */
setInitializationData(@ullable List<byte[]> initializationData)389     public Builder setInitializationData(@Nullable List<byte[]> initializationData) {
390       this.initializationData = initializationData;
391       return this;
392     }
393 
394     /**
395      * Sets {@link Format#drmInitData}. The default value is {@code null}.
396      *
397      * @param drmInitData The {@link Format#drmInitData}.
398      * @return The builder.
399      */
setDrmInitData(@ullable DrmInitData drmInitData)400     public Builder setDrmInitData(@Nullable DrmInitData drmInitData) {
401       this.drmInitData = drmInitData;
402       return this;
403     }
404 
405     /**
406      * Sets {@link Format#subsampleOffsetUs}. The default value is {@link #OFFSET_SAMPLE_RELATIVE}.
407      *
408      * @param subsampleOffsetUs The {@link Format#subsampleOffsetUs}.
409      * @return The builder.
410      */
setSubsampleOffsetUs(long subsampleOffsetUs)411     public Builder setSubsampleOffsetUs(long subsampleOffsetUs) {
412       this.subsampleOffsetUs = subsampleOffsetUs;
413       return this;
414     }
415 
416     // Video specific.
417 
418     /**
419      * Sets {@link Format#width}. The default value is {@link #NO_VALUE}.
420      *
421      * @param width The {@link Format#width}.
422      * @return The builder.
423      */
setWidth(int width)424     public Builder setWidth(int width) {
425       this.width = width;
426       return this;
427     }
428 
429     /**
430      * Sets {@link Format#height}. The default value is {@link #NO_VALUE}.
431      *
432      * @param height The {@link Format#height}.
433      * @return The builder.
434      */
setHeight(int height)435     public Builder setHeight(int height) {
436       this.height = height;
437       return this;
438     }
439 
440     /**
441      * Sets {@link Format#frameRate}. The default value is {@link #NO_VALUE}.
442      *
443      * @param frameRate The {@link Format#frameRate}.
444      * @return The builder.
445      */
setFrameRate(float frameRate)446     public Builder setFrameRate(float frameRate) {
447       this.frameRate = frameRate;
448       return this;
449     }
450 
451     /**
452      * Sets {@link Format#rotationDegrees}. The default value is 0.
453      *
454      * @param rotationDegrees The {@link Format#rotationDegrees}.
455      * @return The builder.
456      */
setRotationDegrees(int rotationDegrees)457     public Builder setRotationDegrees(int rotationDegrees) {
458       this.rotationDegrees = rotationDegrees;
459       return this;
460     }
461 
462     /**
463      * Sets {@link Format#pixelWidthHeightRatio}. The default value is 1.0f.
464      *
465      * @param pixelWidthHeightRatio The {@link Format#pixelWidthHeightRatio}.
466      * @return The builder.
467      */
setPixelWidthHeightRatio(float pixelWidthHeightRatio)468     public Builder setPixelWidthHeightRatio(float pixelWidthHeightRatio) {
469       this.pixelWidthHeightRatio = pixelWidthHeightRatio;
470       return this;
471     }
472 
473     /**
474      * Sets {@link Format#projectionData}. The default value is {@code null}.
475      *
476      * @param projectionData The {@link Format#projectionData}.
477      * @return The builder.
478      */
setProjectionData(@ullable byte[] projectionData)479     public Builder setProjectionData(@Nullable byte[] projectionData) {
480       this.projectionData = projectionData;
481       return this;
482     }
483 
484     /**
485      * Sets {@link Format#stereoMode}. The default value is {@link #NO_VALUE}.
486      *
487      * @param stereoMode The {@link Format#stereoMode}.
488      * @return The builder.
489      */
setStereoMode(@.StereoMode int stereoMode)490     public Builder setStereoMode(@C.StereoMode int stereoMode) {
491       this.stereoMode = stereoMode;
492       return this;
493     }
494 
495     /**
496      * Sets {@link Format#colorInfo}. The default value is {@code null}.
497      *
498      * @param colorInfo The {@link Format#colorInfo}.
499      * @return The builder.
500      */
setColorInfo(@ullable ColorInfo colorInfo)501     public Builder setColorInfo(@Nullable ColorInfo colorInfo) {
502       this.colorInfo = colorInfo;
503       return this;
504     }
505 
506     // Audio specific.
507 
508     /**
509      * Sets {@link Format#channelCount}. The default value is {@link #NO_VALUE}.
510      *
511      * @param channelCount The {@link Format#channelCount}.
512      * @return The builder.
513      */
setChannelCount(int channelCount)514     public Builder setChannelCount(int channelCount) {
515       this.channelCount = channelCount;
516       return this;
517     }
518 
519     /**
520      * Sets {@link Format#sampleRate}. The default value is {@link #NO_VALUE}.
521      *
522      * @param sampleRate The {@link Format#sampleRate}.
523      * @return The builder.
524      */
setSampleRate(int sampleRate)525     public Builder setSampleRate(int sampleRate) {
526       this.sampleRate = sampleRate;
527       return this;
528     }
529 
530     /**
531      * Sets {@link Format#pcmEncoding}. The default value is {@link #NO_VALUE}.
532      *
533      * @param pcmEncoding The {@link Format#pcmEncoding}.
534      * @return The builder.
535      */
setPcmEncoding(@.PcmEncoding int pcmEncoding)536     public Builder setPcmEncoding(@C.PcmEncoding int pcmEncoding) {
537       this.pcmEncoding = pcmEncoding;
538       return this;
539     }
540 
541     /**
542      * Sets {@link Format#encoderDelay}. The default value is 0.
543      *
544      * @param encoderDelay The {@link Format#encoderDelay}.
545      * @return The builder.
546      */
setEncoderDelay(int encoderDelay)547     public Builder setEncoderDelay(int encoderDelay) {
548       this.encoderDelay = encoderDelay;
549       return this;
550     }
551 
552     /**
553      * Sets {@link Format#encoderPadding}. The default value is 0.
554      *
555      * @param encoderPadding The {@link Format#encoderPadding}.
556      * @return The builder.
557      */
setEncoderPadding(int encoderPadding)558     public Builder setEncoderPadding(int encoderPadding) {
559       this.encoderPadding = encoderPadding;
560       return this;
561     }
562 
563     // Text specific.
564 
565     /**
566      * Sets {@link Format#accessibilityChannel}. The default value is {@link #NO_VALUE}.
567      *
568      * @param accessibilityChannel The {@link Format#accessibilityChannel}.
569      * @return The builder.
570      */
setAccessibilityChannel(int accessibilityChannel)571     public Builder setAccessibilityChannel(int accessibilityChannel) {
572       this.accessibilityChannel = accessibilityChannel;
573       return this;
574     }
575 
576     // Provided by source.
577 
578     /**
579      * Sets {@link Format#exoMediaCryptoType}. The default value is {@code null}.
580      *
581      * @param exoMediaCryptoType The {@link Format#exoMediaCryptoType}.
582      * @return The builder.
583      */
setExoMediaCryptoType( @ullable Class<? extends ExoMediaCrypto> exoMediaCryptoType)584     public Builder setExoMediaCryptoType(
585         @Nullable Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
586       this.exoMediaCryptoType = exoMediaCryptoType;
587       return this;
588     }
589 
590     // Build.
591 
build()592     public Format build() {
593       return new Format(
594           id,
595           label,
596           language,
597           selectionFlags,
598           roleFlags,
599           averageBitrate,
600           peakBitrate,
601           codecs,
602           metadata,
603           containerMimeType,
604           sampleMimeType,
605           maxInputSize,
606           initializationData,
607           drmInitData,
608           subsampleOffsetUs,
609           width,
610           height,
611           frameRate,
612           rotationDegrees,
613           pixelWidthHeightRatio,
614           projectionData,
615           stereoMode,
616           colorInfo,
617           channelCount,
618           sampleRate,
619           pcmEncoding,
620           encoderDelay,
621           encoderPadding,
622           accessibilityChannel,
623           exoMediaCryptoType);
624     }
625   }
626 
627   /** A value for various fields to indicate that the field's value is unknown or not applicable. */
628   public static final int NO_VALUE = -1;
629 
630   /**
631    * A value for {@link #subsampleOffsetUs} to indicate that subsample timestamps are relative to
632    * the timestamps of their parent samples.
633    */
634   public static final long OFFSET_SAMPLE_RELATIVE = Long.MAX_VALUE;
635 
636   /** An identifier for the format, or null if unknown or not applicable. */
637   @Nullable public final String id;
638   /** The human readable label, or null if unknown or not applicable. */
639   @Nullable public final String label;
640   /** The language as an IETF BCP 47 conformant tag, or null if unknown or not applicable. */
641   @Nullable public final String language;
642   /** Track selection flags. */
643   @C.SelectionFlags public final int selectionFlags;
644   /** Track role flags. */
645   @C.RoleFlags public final int roleFlags;
646   /**
647    * The average bitrate in bits per second, or {@link #NO_VALUE} if unknown or not applicable. The
648    * way in which this field is populated depends on the type of media to which the format
649    * corresponds:
650    *
651    * <ul>
652    *   <li>DASH representations: Always {@link Format#NO_VALUE}.
653    *   <li>HLS variants: The {@code AVERAGE-BANDWIDTH} attribute defined on the corresponding {@code
654    *       EXT-X-STREAM-INF} tag in the master playlist, or {@link Format#NO_VALUE} if not present.
655    *   <li>SmoothStreaming track elements: The {@code Bitrate} attribute defined on the
656    *       corresponding {@code TrackElement} in the manifest, or {@link Format#NO_VALUE} if not
657    *       present.
658    *   <li>Progressive container formats: Often {@link Format#NO_VALUE}, but may be populated with
659    *       the average bitrate of the container if known.
660    *   <li>Sample formats: Often {@link Format#NO_VALUE}, but may be populated with the average
661    *       bitrate of the stream of samples with type {@link #sampleMimeType} if known. Note that if
662    *       {@link #sampleMimeType} is a compressed format (e.g., {@link MimeTypes#AUDIO_AAC}), then
663    *       this bitrate is for the stream of still compressed samples.
664    * </ul>
665    */
666   public final int averageBitrate;
667   /**
668    * The peak bitrate in bits per second, or {@link #NO_VALUE} if unknown or not applicable. The way
669    * in which this field is populated depends on the type of media to which the format corresponds:
670    *
671    * <ul>
672    *   <li>DASH representations: The {@code @bandwidth} attribute of the corresponding {@code
673    *       Representation} element in the manifest.
674    *   <li>HLS variants: The {@code BANDWIDTH} attribute defined on the corresponding {@code
675    *       EXT-X-STREAM-INF} tag.
676    *   <li>SmoothStreaming track elements: Always {@link Format#NO_VALUE}.
677    *   <li>Progressive container formats: Often {@link Format#NO_VALUE}, but may be populated with
678    *       the peak bitrate of the container if known.
679    *   <li>Sample formats: Often {@link Format#NO_VALUE}, but may be populated with the peak bitrate
680    *       of the stream of samples with type {@link #sampleMimeType} if known. Note that if {@link
681    *       #sampleMimeType} is a compressed format (e.g., {@link MimeTypes#AUDIO_AAC}), then this
682    *       bitrate is for the stream of still compressed samples.
683    * </ul>
684    */
685   public final int peakBitrate;
686   /**
687    * The bitrate in bits per second. This is the peak bitrate if known, or else the average bitrate
688    * if known, or else {@link Format#NO_VALUE}. Equivalent to: {@code peakBitrate != NO_VALUE ?
689    * peakBitrate : averageBitrate}.
690    */
691   public final int bitrate;
692   /** Codecs of the format as described in RFC 6381, or null if unknown or not applicable. */
693   @Nullable public final String codecs;
694   /** Metadata, or null if unknown or not applicable. */
695   @Nullable public final Metadata metadata;
696 
697   // Container specific.
698 
699   /** The mime type of the container, or null if unknown or not applicable. */
700   @Nullable public final String containerMimeType;
701 
702   // Sample specific.
703 
704   /** The sample mime type, or null if unknown or not applicable. */
705   @Nullable public final String sampleMimeType;
706   /**
707    * The maximum size of a buffer of data (typically one sample), or {@link #NO_VALUE} if unknown or
708    * not applicable.
709    */
710   public final int maxInputSize;
711   /**
712    * Initialization data that must be provided to the decoder. Will not be null, but may be empty
713    * if initialization data is not required.
714    */
715   public final List<byte[]> initializationData;
716   /** DRM initialization data if the stream is protected, or null otherwise. */
717   @Nullable public final DrmInitData drmInitData;
718 
719   /**
720    * For samples that contain subsamples, this is an offset that should be added to subsample
721    * timestamps. A value of {@link #OFFSET_SAMPLE_RELATIVE} indicates that subsample timestamps are
722    * relative to the timestamps of their parent samples.
723    */
724   public final long subsampleOffsetUs;
725 
726   // Video specific.
727 
728   /**
729    * The width of the video in pixels, or {@link #NO_VALUE} if unknown or not applicable.
730    */
731   public final int width;
732   /**
733    * The height of the video in pixels, or {@link #NO_VALUE} if unknown or not applicable.
734    */
735   public final int height;
736   /**
737    * The frame rate in frames per second, or {@link #NO_VALUE} if unknown or not applicable.
738    */
739   public final float frameRate;
740   /**
741    * The clockwise rotation that should be applied to the video for it to be rendered in the correct
742    * orientation, or 0 if unknown or not applicable. Only 0, 90, 180 and 270 are supported.
743    */
744   public final int rotationDegrees;
745   /** The width to height ratio of pixels in the video, or 1.0 if unknown or not applicable. */
746   public final float pixelWidthHeightRatio;
747   /** The projection data for 360/VR video, or null if not applicable. */
748   @Nullable public final byte[] projectionData;
749   /**
750    * The stereo layout for 360/3D/VR video, or {@link #NO_VALUE} if not applicable. Valid stereo
751    * modes are {@link C#STEREO_MODE_MONO}, {@link C#STEREO_MODE_TOP_BOTTOM}, {@link
752    * C#STEREO_MODE_LEFT_RIGHT}, {@link C#STEREO_MODE_STEREO_MESH}.
753    */
754   @C.StereoMode public final int stereoMode;
755   /** The color metadata associated with the video, or null if not applicable. */
756   @Nullable public final ColorInfo colorInfo;
757 
758   // Audio specific.
759 
760   /**
761    * The number of audio channels, or {@link #NO_VALUE} if unknown or not applicable.
762    */
763   public final int channelCount;
764   /**
765    * The audio sampling rate in Hz, or {@link #NO_VALUE} if unknown or not applicable.
766    */
767   public final int sampleRate;
768   /** The {@link C.PcmEncoding} for PCM audio. Set to {@link #NO_VALUE} for other media types. */
769   @C.PcmEncoding public final int pcmEncoding;
770   /**
771    * The number of frames to trim from the start of the decoded audio stream, or 0 if not
772    * applicable.
773    */
774   public final int encoderDelay;
775   /**
776    * The number of frames to trim from the end of the decoded audio stream, or 0 if not applicable.
777    */
778   public final int encoderPadding;
779 
780   // Text specific.
781 
782   /** The Accessibility channel, or {@link #NO_VALUE} if not known or applicable. */
783   public final int accessibilityChannel;
784 
785   // Provided by source.
786 
787   /**
788    * The type of the {@link ExoMediaCrypto} provided by the media source, if the media source can
789    * acquire a DRM session for {@link #drmInitData}. Null if the media source cannot acquire a
790    * session for {@link #drmInitData}, or if not applicable.
791    */
792   @Nullable public final Class<? extends ExoMediaCrypto> exoMediaCryptoType;
793 
794   // Lazily initialized hashcode.
795   private int hashCode;
796 
797   // Video.
798 
799   /** @deprecated Use {@link Format.Builder}. */
800   @Deprecated
createVideoContainerFormat( @ullable 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)801   public static Format createVideoContainerFormat(
802       @Nullable String id,
803       @Nullable String label,
804       @Nullable String containerMimeType,
805       @Nullable String sampleMimeType,
806       @Nullable String codecs,
807       @Nullable Metadata metadata,
808       int bitrate,
809       int width,
810       int height,
811       float frameRate,
812       @Nullable List<byte[]> initializationData,
813       @C.SelectionFlags int selectionFlags,
814       @C.RoleFlags int roleFlags) {
815     return new Builder()
816         .setId(id)
817         .setLabel(label)
818         .setSelectionFlags(selectionFlags)
819         .setRoleFlags(roleFlags)
820         .setAverageBitrate(bitrate)
821         .setPeakBitrate(bitrate)
822         .setCodecs(codecs)
823         .setMetadata(metadata)
824         .setContainerMimeType(containerMimeType)
825         .setSampleMimeType(sampleMimeType)
826         .setInitializationData(initializationData)
827         .setWidth(width)
828         .setHeight(height)
829         .setFrameRate(frameRate)
830         .build();
831   }
832 
833   /** @deprecated Use {@link Format.Builder}. */
834   @Deprecated
createVideoSampleFormat( @ullable 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)835   public static Format createVideoSampleFormat(
836       @Nullable String id,
837       @Nullable String sampleMimeType,
838       @Nullable String codecs,
839       int bitrate,
840       int maxInputSize,
841       int width,
842       int height,
843       float frameRate,
844       @Nullable List<byte[]> initializationData,
845       @Nullable DrmInitData drmInitData) {
846     return new Builder()
847         .setId(id)
848         .setAverageBitrate(bitrate)
849         .setPeakBitrate(bitrate)
850         .setCodecs(codecs)
851         .setSampleMimeType(sampleMimeType)
852         .setMaxInputSize(maxInputSize)
853         .setInitializationData(initializationData)
854         .setDrmInitData(drmInitData)
855         .setWidth(width)
856         .setHeight(height)
857         .setFrameRate(frameRate)
858         .build();
859   }
860 
861   /** @deprecated Use {@link Format.Builder}. */
862   @Deprecated
createVideoSampleFormat( @ullable 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)863   public static Format createVideoSampleFormat(
864       @Nullable String id,
865       @Nullable String sampleMimeType,
866       @Nullable String codecs,
867       int bitrate,
868       int maxInputSize,
869       int width,
870       int height,
871       float frameRate,
872       @Nullable List<byte[]> initializationData,
873       int rotationDegrees,
874       float pixelWidthHeightRatio,
875       @Nullable DrmInitData drmInitData) {
876     return new Builder()
877         .setId(id)
878         .setAverageBitrate(bitrate)
879         .setPeakBitrate(bitrate)
880         .setCodecs(codecs)
881         .setSampleMimeType(sampleMimeType)
882         .setMaxInputSize(maxInputSize)
883         .setInitializationData(initializationData)
884         .setDrmInitData(drmInitData)
885         .setWidth(width)
886         .setHeight(height)
887         .setFrameRate(frameRate)
888         .setRotationDegrees(rotationDegrees)
889         .setPixelWidthHeightRatio(pixelWidthHeightRatio)
890         .build();
891   }
892 
893   /** @deprecated Use {@link Format.Builder}. */
894   @Deprecated
createVideoSampleFormat( @ullable 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)895   public static Format createVideoSampleFormat(
896       @Nullable String id,
897       @Nullable String sampleMimeType,
898       @Nullable String codecs,
899       int bitrate,
900       int maxInputSize,
901       int width,
902       int height,
903       float frameRate,
904       @Nullable List<byte[]> initializationData,
905       int rotationDegrees,
906       float pixelWidthHeightRatio,
907       @Nullable byte[] projectionData,
908       @C.StereoMode int stereoMode,
909       @Nullable ColorInfo colorInfo,
910       @Nullable DrmInitData drmInitData) {
911     return new Builder()
912         .setId(id)
913         .setAverageBitrate(bitrate)
914         .setPeakBitrate(bitrate)
915         .setCodecs(codecs)
916         .setSampleMimeType(sampleMimeType)
917         .setMaxInputSize(maxInputSize)
918         .setInitializationData(initializationData)
919         .setDrmInitData(drmInitData)
920         .setWidth(width)
921         .setHeight(height)
922         .setFrameRate(frameRate)
923         .setRotationDegrees(rotationDegrees)
924         .setPixelWidthHeightRatio(pixelWidthHeightRatio)
925         .setProjectionData(projectionData)
926         .setStereoMode(stereoMode)
927         .setColorInfo(colorInfo)
928         .build();
929   }
930 
931   // Audio.
932 
933   /** @deprecated Use {@link Format.Builder}. */
934   @Deprecated
createAudioContainerFormat( @ullable 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)935   public static Format createAudioContainerFormat(
936       @Nullable String id,
937       @Nullable String label,
938       @Nullable String containerMimeType,
939       @Nullable String sampleMimeType,
940       @Nullable String codecs,
941       @Nullable Metadata metadata,
942       int bitrate,
943       int channelCount,
944       int sampleRate,
945       @Nullable List<byte[]> initializationData,
946       @C.SelectionFlags int selectionFlags,
947       @C.RoleFlags int roleFlags,
948       @Nullable String language) {
949     return new Builder()
950         .setId(id)
951         .setLabel(label)
952         .setLanguage(language)
953         .setSelectionFlags(selectionFlags)
954         .setRoleFlags(roleFlags)
955         .setAverageBitrate(bitrate)
956         .setPeakBitrate(bitrate)
957         .setCodecs(codecs)
958         .setMetadata(metadata)
959         .setContainerMimeType(containerMimeType)
960         .setSampleMimeType(sampleMimeType)
961         .setInitializationData(initializationData)
962         .setChannelCount(channelCount)
963         .setSampleRate(sampleRate)
964         .build();
965   }
966 
967   /** @deprecated Use {@link Format.Builder}. */
968   @Deprecated
createAudioSampleFormat( @ullable 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)969   public static Format createAudioSampleFormat(
970       @Nullable String id,
971       @Nullable String sampleMimeType,
972       @Nullable String codecs,
973       int bitrate,
974       int maxInputSize,
975       int channelCount,
976       int sampleRate,
977       @Nullable List<byte[]> initializationData,
978       @Nullable DrmInitData drmInitData,
979       @C.SelectionFlags int selectionFlags,
980       @Nullable String language) {
981     return new Builder()
982         .setId(id)
983         .setLanguage(language)
984         .setSelectionFlags(selectionFlags)
985         .setAverageBitrate(bitrate)
986         .setPeakBitrate(bitrate)
987         .setCodecs(codecs)
988         .setSampleMimeType(sampleMimeType)
989         .setMaxInputSize(maxInputSize)
990         .setInitializationData(initializationData)
991         .setDrmInitData(drmInitData)
992         .setChannelCount(channelCount)
993         .setSampleRate(sampleRate)
994         .build();
995   }
996 
997   /** @deprecated Use {@link Format.Builder}. */
998   @Deprecated
createAudioSampleFormat( @ullable 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)999   public static Format createAudioSampleFormat(
1000       @Nullable String id,
1001       @Nullable String sampleMimeType,
1002       @Nullable String codecs,
1003       int bitrate,
1004       int maxInputSize,
1005       int channelCount,
1006       int sampleRate,
1007       @C.PcmEncoding int pcmEncoding,
1008       @Nullable List<byte[]> initializationData,
1009       @Nullable DrmInitData drmInitData,
1010       @C.SelectionFlags int selectionFlags,
1011       @Nullable String language) {
1012     return new Builder()
1013         .setId(id)
1014         .setLanguage(language)
1015         .setSelectionFlags(selectionFlags)
1016         .setAverageBitrate(bitrate)
1017         .setPeakBitrate(bitrate)
1018         .setCodecs(codecs)
1019         .setSampleMimeType(sampleMimeType)
1020         .setMaxInputSize(maxInputSize)
1021         .setInitializationData(initializationData)
1022         .setDrmInitData(drmInitData)
1023         .setChannelCount(channelCount)
1024         .setSampleRate(sampleRate)
1025         .setPcmEncoding(pcmEncoding)
1026         .build();
1027   }
1028 
1029   /** @deprecated Use {@link Format.Builder}. */
1030   @Deprecated
createAudioSampleFormat( @ullable 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)1031   public static Format createAudioSampleFormat(
1032       @Nullable String id,
1033       @Nullable String sampleMimeType,
1034       @Nullable String codecs,
1035       int bitrate,
1036       int maxInputSize,
1037       int channelCount,
1038       int sampleRate,
1039       @C.PcmEncoding int pcmEncoding,
1040       int encoderDelay,
1041       int encoderPadding,
1042       @Nullable List<byte[]> initializationData,
1043       @Nullable DrmInitData drmInitData,
1044       @C.SelectionFlags int selectionFlags,
1045       @Nullable String language,
1046       @Nullable Metadata metadata) {
1047     return new Builder()
1048         .setId(id)
1049         .setLanguage(language)
1050         .setSelectionFlags(selectionFlags)
1051         .setAverageBitrate(bitrate)
1052         .setPeakBitrate(bitrate)
1053         .setCodecs(codecs)
1054         .setMetadata(metadata)
1055         .setSampleMimeType(sampleMimeType)
1056         .setMaxInputSize(maxInputSize)
1057         .setInitializationData(initializationData)
1058         .setDrmInitData(drmInitData)
1059         .setChannelCount(channelCount)
1060         .setSampleRate(sampleRate)
1061         .setPcmEncoding(pcmEncoding)
1062         .setEncoderDelay(encoderDelay)
1063         .setEncoderPadding(encoderPadding)
1064         .build();
1065   }
1066 
1067   // Text.
1068 
1069   /** @deprecated Use {@link Format.Builder}. */
1070   @Deprecated
createTextContainerFormat( @ullable 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)1071   public static Format createTextContainerFormat(
1072       @Nullable String id,
1073       @Nullable String label,
1074       @Nullable String containerMimeType,
1075       @Nullable String sampleMimeType,
1076       @Nullable String codecs,
1077       int bitrate,
1078       @C.SelectionFlags int selectionFlags,
1079       @C.RoleFlags int roleFlags,
1080       @Nullable String language) {
1081     return new Builder()
1082         .setId(id)
1083         .setLabel(label)
1084         .setLanguage(language)
1085         .setSelectionFlags(selectionFlags)
1086         .setRoleFlags(roleFlags)
1087         .setAverageBitrate(bitrate)
1088         .setPeakBitrate(bitrate)
1089         .setCodecs(codecs)
1090         .setContainerMimeType(containerMimeType)
1091         .setSampleMimeType(sampleMimeType)
1092         .build();
1093   }
1094 
1095   /** @deprecated Use {@link Format.Builder}. */
1096   @Deprecated
createTextContainerFormat( @ullable 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)1097   public static Format createTextContainerFormat(
1098       @Nullable String id,
1099       @Nullable String label,
1100       @Nullable String containerMimeType,
1101       @Nullable String sampleMimeType,
1102       @Nullable String codecs,
1103       int bitrate,
1104       @C.SelectionFlags int selectionFlags,
1105       @C.RoleFlags int roleFlags,
1106       @Nullable String language,
1107       int accessibilityChannel) {
1108     return new Builder()
1109         .setId(id)
1110         .setLabel(label)
1111         .setLanguage(language)
1112         .setSelectionFlags(selectionFlags)
1113         .setRoleFlags(roleFlags)
1114         .setAverageBitrate(bitrate)
1115         .setPeakBitrate(bitrate)
1116         .setCodecs(codecs)
1117         .setContainerMimeType(containerMimeType)
1118         .setSampleMimeType(sampleMimeType)
1119         .setAccessibilityChannel(accessibilityChannel)
1120         .build();
1121   }
1122 
1123   /** @deprecated Use {@link Format.Builder}. */
1124   @Deprecated
createTextSampleFormat( @ullable String id, @Nullable String sampleMimeType, @C.SelectionFlags int selectionFlags, @Nullable String language)1125   public static Format createTextSampleFormat(
1126       @Nullable String id,
1127       @Nullable String sampleMimeType,
1128       @C.SelectionFlags int selectionFlags,
1129       @Nullable String language) {
1130     return new Builder()
1131         .setId(id)
1132         .setLanguage(language)
1133         .setSelectionFlags(selectionFlags)
1134         .setSampleMimeType(sampleMimeType)
1135         .build();
1136   }
1137 
1138   /** @deprecated Use {@link Format.Builder}. */
1139   @Deprecated
createTextSampleFormat( @ullable String id, @Nullable String sampleMimeType, @C.SelectionFlags int selectionFlags, @Nullable String language, int accessibilityChannel, long subsampleOffsetUs, @Nullable List<byte[]> initializationData)1140   public static Format createTextSampleFormat(
1141       @Nullable String id,
1142       @Nullable String sampleMimeType,
1143       @C.SelectionFlags int selectionFlags,
1144       @Nullable String language,
1145       int accessibilityChannel,
1146       long subsampleOffsetUs,
1147       @Nullable List<byte[]> initializationData) {
1148     return new Builder()
1149         .setId(id)
1150         .setLanguage(language)
1151         .setSelectionFlags(selectionFlags)
1152         .setSampleMimeType(sampleMimeType)
1153         .setInitializationData(initializationData)
1154         .setSubsampleOffsetUs(subsampleOffsetUs)
1155         .setAccessibilityChannel(accessibilityChannel)
1156         .build();
1157   }
1158 
1159   // Image.
1160 
1161   /** @deprecated Use {@link Format.Builder}. */
1162   @Deprecated
createImageSampleFormat( @ullable String id, @Nullable String sampleMimeType, @C.SelectionFlags int selectionFlags, @Nullable List<byte[]> initializationData, @Nullable String language)1163   public static Format createImageSampleFormat(
1164       @Nullable String id,
1165       @Nullable String sampleMimeType,
1166       @C.SelectionFlags int selectionFlags,
1167       @Nullable List<byte[]> initializationData,
1168       @Nullable String language) {
1169     return new Builder()
1170         .setId(id)
1171         .setLanguage(language)
1172         .setSelectionFlags(selectionFlags)
1173         .setSampleMimeType(sampleMimeType)
1174         .setInitializationData(initializationData)
1175         .build();
1176   }
1177 
1178   // Generic.
1179 
1180   /** @deprecated Use {@link Format.Builder}. */
1181   @Deprecated
createContainerFormat( @ullable 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)1182   public static Format createContainerFormat(
1183       @Nullable String id,
1184       @Nullable String label,
1185       @Nullable String containerMimeType,
1186       @Nullable String sampleMimeType,
1187       @Nullable String codecs,
1188       int bitrate,
1189       @C.SelectionFlags int selectionFlags,
1190       @C.RoleFlags int roleFlags,
1191       @Nullable String language) {
1192     return new Builder()
1193         .setId(id)
1194         .setLabel(label)
1195         .setLanguage(language)
1196         .setSelectionFlags(selectionFlags)
1197         .setRoleFlags(roleFlags)
1198         .setAverageBitrate(bitrate)
1199         .setPeakBitrate(bitrate)
1200         .setCodecs(codecs)
1201         .setContainerMimeType(containerMimeType)
1202         .setSampleMimeType(sampleMimeType)
1203         .build();
1204   }
1205 
1206   /** @deprecated Use {@link Format.Builder}. */
1207   @Deprecated
createSampleFormat(@ullable String id, @Nullable String sampleMimeType)1208   public static Format createSampleFormat(@Nullable String id, @Nullable String sampleMimeType) {
1209     return new Builder().setId(id).setSampleMimeType(sampleMimeType).build();
1210   }
1211 
Format( @ullable String id, @Nullable String label, @Nullable String language, @C.SelectionFlags int selectionFlags, @C.RoleFlags int roleFlags, int averageBitrate, int peakBitrate, @Nullable String codecs, @Nullable Metadata metadata, @Nullable String containerMimeType, @Nullable String sampleMimeType, int maxInputSize, @Nullable List<byte[]> initializationData, @Nullable DrmInitData drmInitData, long subsampleOffsetUs, int width, int height, float frameRate, int rotationDegrees, float pixelWidthHeightRatio, @Nullable byte[] projectionData, @C.StereoMode int stereoMode, @Nullable ColorInfo colorInfo, int channelCount, int sampleRate, @C.PcmEncoding int pcmEncoding, int encoderDelay, int encoderPadding, int accessibilityChannel, @Nullable Class<? extends ExoMediaCrypto> exoMediaCryptoType)1212   /* package */ Format(
1213       @Nullable String id,
1214       @Nullable String label,
1215       @Nullable String language,
1216       @C.SelectionFlags int selectionFlags,
1217       @C.RoleFlags int roleFlags,
1218       int averageBitrate,
1219       int peakBitrate,
1220       @Nullable String codecs,
1221       @Nullable Metadata metadata,
1222       // Container specific.
1223       @Nullable String containerMimeType,
1224       // Sample specific.
1225       @Nullable String sampleMimeType,
1226       int maxInputSize,
1227       @Nullable List<byte[]> initializationData,
1228       @Nullable DrmInitData drmInitData,
1229       long subsampleOffsetUs,
1230       // Video specific.
1231       int width,
1232       int height,
1233       float frameRate,
1234       int rotationDegrees,
1235       float pixelWidthHeightRatio,
1236       @Nullable byte[] projectionData,
1237       @C.StereoMode int stereoMode,
1238       @Nullable ColorInfo colorInfo,
1239       // Audio specific.
1240       int channelCount,
1241       int sampleRate,
1242       @C.PcmEncoding int pcmEncoding,
1243       int encoderDelay,
1244       int encoderPadding,
1245       // Text specific.
1246       int accessibilityChannel,
1247       // Provided by source.
1248       @Nullable Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
1249     this.id = id;
1250     this.label = label;
1251     this.language = Util.normalizeLanguageCode(language);
1252     this.selectionFlags = selectionFlags;
1253     this.roleFlags = roleFlags;
1254     this.averageBitrate = averageBitrate;
1255     this.peakBitrate = peakBitrate;
1256     this.bitrate = peakBitrate != NO_VALUE ? peakBitrate : averageBitrate;
1257     this.codecs = codecs;
1258     this.metadata = metadata;
1259     // Container specific.
1260     this.containerMimeType = containerMimeType;
1261     // Sample specific.
1262     this.sampleMimeType = sampleMimeType;
1263     this.maxInputSize = maxInputSize;
1264     this.initializationData =
1265         initializationData == null ? Collections.emptyList() : initializationData;
1266     this.drmInitData = drmInitData;
1267     this.subsampleOffsetUs = subsampleOffsetUs;
1268     // Video specific.
1269     this.width = width;
1270     this.height = height;
1271     this.frameRate = frameRate;
1272     this.rotationDegrees = rotationDegrees == NO_VALUE ? 0 : rotationDegrees;
1273     this.pixelWidthHeightRatio = pixelWidthHeightRatio == NO_VALUE ? 1 : pixelWidthHeightRatio;
1274     this.projectionData = projectionData;
1275     this.stereoMode = stereoMode;
1276     this.colorInfo = colorInfo;
1277     // Audio specific.
1278     this.channelCount = channelCount;
1279     this.sampleRate = sampleRate;
1280     this.pcmEncoding = pcmEncoding;
1281     this.encoderDelay = encoderDelay == NO_VALUE ? 0 : encoderDelay;
1282     this.encoderPadding = encoderPadding == NO_VALUE ? 0 : encoderPadding;
1283     // Text specific.
1284     this.accessibilityChannel = accessibilityChannel;
1285     // Provided by source.
1286     this.exoMediaCryptoType = exoMediaCryptoType;
1287   }
1288 
1289   @SuppressWarnings("ResourceType")
Format(Parcel in)1290   /* package */ Format(Parcel in) {
1291     id = in.readString();
1292     label = in.readString();
1293     language = in.readString();
1294     selectionFlags = in.readInt();
1295     roleFlags = in.readInt();
1296     averageBitrate = in.readInt();
1297     peakBitrate = in.readInt();
1298     bitrate = peakBitrate != NO_VALUE ? peakBitrate : averageBitrate;
1299     codecs = in.readString();
1300     metadata = in.readParcelable(Metadata.class.getClassLoader());
1301     // Container specific.
1302     containerMimeType = in.readString();
1303     // Sample specific.
1304     sampleMimeType = in.readString();
1305     maxInputSize = in.readInt();
1306     int initializationDataSize = in.readInt();
1307     initializationData = new ArrayList<>(initializationDataSize);
1308     for (int i = 0; i < initializationDataSize; i++) {
1309       initializationData.add(in.createByteArray());
1310     }
1311     drmInitData = in.readParcelable(DrmInitData.class.getClassLoader());
1312     subsampleOffsetUs = in.readLong();
1313     // Video specific.
1314     width = in.readInt();
1315     height = in.readInt();
1316     frameRate = in.readFloat();
1317     rotationDegrees = in.readInt();
1318     pixelWidthHeightRatio = in.readFloat();
1319     boolean hasProjectionData = Util.readBoolean(in);
1320     projectionData = hasProjectionData ? in.createByteArray() : null;
1321     stereoMode = in.readInt();
1322     colorInfo = in.readParcelable(ColorInfo.class.getClassLoader());
1323     // Audio specific.
1324     channelCount = in.readInt();
1325     sampleRate = in.readInt();
1326     pcmEncoding = in.readInt();
1327     encoderDelay = in.readInt();
1328     encoderPadding = in.readInt();
1329     // Text specific.
1330     accessibilityChannel = in.readInt();
1331     // Provided by source.
1332     exoMediaCryptoType = null;
1333   }
1334 
1335   /** Returns a {@link Format.Builder} initialized with the values of this instance. */
buildUpon()1336   public Builder buildUpon() {
1337     return new Builder(this);
1338   }
1339 
1340   /** @deprecated Use {@link #buildUpon()} and {@link Builder#setMaxInputSize(int)}. */
1341   @Deprecated
copyWithMaxInputSize(int maxInputSize)1342   public Format copyWithMaxInputSize(int maxInputSize) {
1343     return buildUpon().setMaxInputSize(maxInputSize).build();
1344   }
1345 
1346   /** @deprecated Use {@link #buildUpon()} and {@link Builder#setSubsampleOffsetUs(long)}. */
1347   @Deprecated
copyWithSubsampleOffsetUs(long subsampleOffsetUs)1348   public Format copyWithSubsampleOffsetUs(long subsampleOffsetUs) {
1349     return buildUpon().setSubsampleOffsetUs(subsampleOffsetUs).build();
1350   }
1351 
1352   /** @deprecated Use {@link #buildUpon()} and {@link Builder#setLabel(String)} . */
1353   @Deprecated
copyWithLabel(@ullable String label)1354   public Format copyWithLabel(@Nullable String label) {
1355     return buildUpon().setLabel(label).build();
1356   }
1357 
1358   /** @deprecated Use {@link #withManifestFormatInfo(Format)}. */
1359   @Deprecated
copyWithManifestFormatInfo(Format manifestFormat)1360   public Format copyWithManifestFormatInfo(Format manifestFormat) {
1361     return withManifestFormatInfo(manifestFormat);
1362   }
1363 
1364   @SuppressWarnings("ReferenceEquality")
withManifestFormatInfo(Format manifestFormat)1365   public Format withManifestFormatInfo(Format manifestFormat) {
1366     if (this == manifestFormat) {
1367       // No need to copy from ourselves.
1368       return this;
1369     }
1370 
1371     int trackType = MimeTypes.getTrackType(sampleMimeType);
1372 
1373     // Use manifest value only.
1374     @Nullable String id = manifestFormat.id;
1375 
1376     // Prefer manifest values, but fill in from sample format if missing.
1377     @Nullable String label = manifestFormat.label != null ? manifestFormat.label : this.label;
1378     @Nullable String language = this.language;
1379     if ((trackType == C.TRACK_TYPE_TEXT || trackType == C.TRACK_TYPE_AUDIO)
1380         && manifestFormat.language != null) {
1381       language = manifestFormat.language;
1382     }
1383 
1384     // Prefer sample format values, but fill in from manifest if missing.
1385     int averageBitrate =
1386         this.averageBitrate == NO_VALUE ? manifestFormat.averageBitrate : this.averageBitrate;
1387     int peakBitrate = this.peakBitrate == NO_VALUE ? manifestFormat.peakBitrate : this.peakBitrate;
1388     @Nullable String codecs = this.codecs;
1389     if (codecs == null) {
1390       // The manifest format may be muxed, so filter only codecs of this format's type. If we still
1391       // have more than one codec then we're unable to uniquely identify which codec to fill in.
1392       @Nullable String codecsOfType = Util.getCodecsOfType(manifestFormat.codecs, trackType);
1393       if (Util.splitCodecs(codecsOfType).length == 1) {
1394         codecs = codecsOfType;
1395       }
1396     }
1397 
1398     @Nullable
1399     Metadata metadata =
1400         this.metadata == null
1401             ? manifestFormat.metadata
1402             : this.metadata.copyWithAppendedEntriesFrom(manifestFormat.metadata);
1403 
1404     float frameRate = this.frameRate;
1405     if (frameRate == NO_VALUE && trackType == C.TRACK_TYPE_VIDEO) {
1406       frameRate = manifestFormat.frameRate;
1407     }
1408 
1409     // Merge manifest and sample format values.
1410     @C.SelectionFlags int selectionFlags = this.selectionFlags | manifestFormat.selectionFlags;
1411     @C.RoleFlags int roleFlags = this.roleFlags | manifestFormat.roleFlags;
1412     @Nullable
1413     DrmInitData drmInitData =
1414         DrmInitData.createSessionCreationData(manifestFormat.drmInitData, this.drmInitData);
1415 
1416     return buildUpon()
1417         .setId(id)
1418         .setLabel(label)
1419         .setLanguage(language)
1420         .setSelectionFlags(selectionFlags)
1421         .setRoleFlags(roleFlags)
1422         .setAverageBitrate(averageBitrate)
1423         .setPeakBitrate(peakBitrate)
1424         .setCodecs(codecs)
1425         .setMetadata(metadata)
1426         .setDrmInitData(drmInitData)
1427         .setFrameRate(frameRate)
1428         .build();
1429   }
1430 
1431   /**
1432    * @deprecated Use {@link #buildUpon()}, {@link Builder#setEncoderDelay(int)} and {@link
1433    *     Builder#setEncoderPadding(int)}.
1434    */
1435   @Deprecated
copyWithGaplessInfo(int encoderDelay, int encoderPadding)1436   public Format copyWithGaplessInfo(int encoderDelay, int encoderPadding) {
1437     return buildUpon().setEncoderDelay(encoderDelay).setEncoderPadding(encoderPadding).build();
1438   }
1439 
1440   /** @deprecated Use {@link #buildUpon()} and {@link Builder#setFrameRate(float)}. */
1441   @Deprecated
copyWithFrameRate(float frameRate)1442   public Format copyWithFrameRate(float frameRate) {
1443     return buildUpon().setFrameRate(frameRate).build();
1444   }
1445 
1446   /** @deprecated Use {@link #buildUpon()} and {@link Builder#setDrmInitData(DrmInitData)}. */
1447   @Deprecated
copyWithDrmInitData(@ullable DrmInitData drmInitData)1448   public Format copyWithDrmInitData(@Nullable DrmInitData drmInitData) {
1449     return buildUpon().setDrmInitData(drmInitData).build();
1450   }
1451 
1452   /** @deprecated Use {@link #buildUpon()} and {@link Builder#setMetadata(Metadata)}. */
1453   @Deprecated
copyWithMetadata(@ullable Metadata metadata)1454   public Format copyWithMetadata(@Nullable Metadata metadata) {
1455     return buildUpon().setMetadata(metadata).build();
1456   }
1457 
1458   /**
1459    * @deprecated Use {@link #buildUpon()} and {@link Builder#setAverageBitrate(int)} and {@link
1460    *     Builder#setPeakBitrate(int)}.
1461    */
1462   @Deprecated
copyWithBitrate(int bitrate)1463   public Format copyWithBitrate(int bitrate) {
1464     return buildUpon().setAverageBitrate(bitrate).setPeakBitrate(bitrate).build();
1465   }
1466 
1467   /**
1468    * @deprecated Use {@link #buildUpon()}, {@link Builder#setWidth(int)} and {@link
1469    *     Builder#setHeight(int)}.
1470    */
1471   @Deprecated
copyWithVideoSize(int width, int height)1472   public Format copyWithVideoSize(int width, int height) {
1473     return buildUpon().setWidth(width).setHeight(height).build();
1474   }
1475 
1476   /** Returns a copy of this format with the specified {@link #exoMediaCryptoType}. */
copyWithExoMediaCryptoType( @ullable Class<? extends ExoMediaCrypto> exoMediaCryptoType)1477   public Format copyWithExoMediaCryptoType(
1478       @Nullable Class<? extends ExoMediaCrypto> exoMediaCryptoType) {
1479     return buildUpon().setExoMediaCryptoType(exoMediaCryptoType).build();
1480   }
1481 
1482   /**
1483    * Returns the number of pixels if this is a video format whose {@link #width} and {@link #height}
1484    * are known, or {@link #NO_VALUE} otherwise
1485    */
getPixelCount()1486   public int getPixelCount() {
1487     return width == NO_VALUE || height == NO_VALUE ? NO_VALUE : (width * height);
1488   }
1489 
1490   @Override
toString()1491   public String toString() {
1492     return "Format("
1493         + id
1494         + ", "
1495         + label
1496         + ", "
1497         + containerMimeType
1498         + ", "
1499         + sampleMimeType
1500         + ", "
1501         + codecs
1502         + ", "
1503         + bitrate
1504         + ", "
1505         + language
1506         + ", ["
1507         + width
1508         + ", "
1509         + height
1510         + ", "
1511         + frameRate
1512         + "]"
1513         + ", ["
1514         + channelCount
1515         + ", "
1516         + sampleRate
1517         + "])";
1518   }
1519 
1520   @Override
hashCode()1521   public int hashCode() {
1522     if (hashCode == 0) {
1523       // Some fields for which hashing is expensive are deliberately omitted.
1524       int result = 17;
1525       result = 31 * result + (id == null ? 0 : id.hashCode());
1526       result = 31 * result + (label != null ? label.hashCode() : 0);
1527       result = 31 * result + (language == null ? 0 : language.hashCode());
1528       result = 31 * result + selectionFlags;
1529       result = 31 * result + roleFlags;
1530       result = 31 * result + averageBitrate;
1531       result = 31 * result + peakBitrate;
1532       result = 31 * result + (codecs == null ? 0 : codecs.hashCode());
1533       result = 31 * result + (metadata == null ? 0 : metadata.hashCode());
1534       // Container specific.
1535       result = 31 * result + (containerMimeType == null ? 0 : containerMimeType.hashCode());
1536       // Sample specific.
1537       result = 31 * result + (sampleMimeType == null ? 0 : sampleMimeType.hashCode());
1538       result = 31 * result + maxInputSize;
1539       // [Omitted] initializationData.
1540       // [Omitted] drmInitData.
1541       result = 31 * result + (int) subsampleOffsetUs;
1542       // Video specific.
1543       result = 31 * result + width;
1544       result = 31 * result + height;
1545       result = 31 * result + Float.floatToIntBits(frameRate);
1546       result = 31 * result + rotationDegrees;
1547       result = 31 * result + Float.floatToIntBits(pixelWidthHeightRatio);
1548       // [Omitted] projectionData.
1549       result = 31 * result + stereoMode;
1550       // [Omitted] colorInfo.
1551       // Audio specific.
1552       result = 31 * result + channelCount;
1553       result = 31 * result + sampleRate;
1554       result = 31 * result + pcmEncoding;
1555       result = 31 * result + encoderDelay;
1556       result = 31 * result + encoderPadding;
1557       // Text specific.
1558       result = 31 * result + accessibilityChannel;
1559       // Provided by source.
1560       result = 31 * result + (exoMediaCryptoType == null ? 0 : exoMediaCryptoType.hashCode());
1561       hashCode = result;
1562     }
1563     return hashCode;
1564   }
1565 
1566   @Override
equals(@ullable Object obj)1567   public boolean equals(@Nullable Object obj) {
1568     if (this == obj) {
1569       return true;
1570     }
1571     if (obj == null || getClass() != obj.getClass()) {
1572       return false;
1573     }
1574     Format other = (Format) obj;
1575     if (hashCode != 0 && other.hashCode != 0 && hashCode != other.hashCode) {
1576       return false;
1577     }
1578     // Field equality checks ordered by type, with the cheapest checks first.
1579     return selectionFlags == other.selectionFlags
1580         && roleFlags == other.roleFlags
1581         && averageBitrate == other.averageBitrate
1582         && peakBitrate == other.peakBitrate
1583         && maxInputSize == other.maxInputSize
1584         && subsampleOffsetUs == other.subsampleOffsetUs
1585         && width == other.width
1586         && height == other.height
1587         && rotationDegrees == other.rotationDegrees
1588         && stereoMode == other.stereoMode
1589         && channelCount == other.channelCount
1590         && sampleRate == other.sampleRate
1591         && pcmEncoding == other.pcmEncoding
1592         && encoderDelay == other.encoderDelay
1593         && encoderPadding == other.encoderPadding
1594         && accessibilityChannel == other.accessibilityChannel
1595         && Float.compare(frameRate, other.frameRate) == 0
1596         && Float.compare(pixelWidthHeightRatio, other.pixelWidthHeightRatio) == 0
1597         && Util.areEqual(exoMediaCryptoType, other.exoMediaCryptoType)
1598         && Util.areEqual(id, other.id)
1599         && Util.areEqual(label, other.label)
1600         && Util.areEqual(codecs, other.codecs)
1601         && Util.areEqual(containerMimeType, other.containerMimeType)
1602         && Util.areEqual(sampleMimeType, other.sampleMimeType)
1603         && Util.areEqual(language, other.language)
1604         && Arrays.equals(projectionData, other.projectionData)
1605         && Util.areEqual(metadata, other.metadata)
1606         && Util.areEqual(colorInfo, other.colorInfo)
1607         && Util.areEqual(drmInitData, other.drmInitData)
1608         && initializationDataEquals(other);
1609   }
1610 
1611   /**
1612    * Returns whether the {@link #initializationData}s belonging to this format and {@code other} are
1613    * equal.
1614    *
1615    * @param other The other format whose {@link #initializationData} is being compared.
1616    * @return Whether the {@link #initializationData}s belonging to this format and {@code other} are
1617    *     equal.
1618    */
initializationDataEquals(Format other)1619   public boolean initializationDataEquals(Format other) {
1620     if (initializationData.size() != other.initializationData.size()) {
1621       return false;
1622     }
1623     for (int i = 0; i < initializationData.size(); i++) {
1624       if (!Arrays.equals(initializationData.get(i), other.initializationData.get(i))) {
1625         return false;
1626       }
1627     }
1628     return true;
1629   }
1630 
1631   // Utility methods
1632 
1633   /** Returns a prettier {@link String} than {@link #toString()}, intended for logging. */
toLogString(@ullable Format format)1634   public static String toLogString(@Nullable Format format) {
1635     if (format == null) {
1636       return "null";
1637     }
1638     StringBuilder builder = new StringBuilder();
1639     builder.append("id=").append(format.id).append(", mimeType=").append(format.sampleMimeType);
1640     if (format.bitrate != NO_VALUE) {
1641       builder.append(", bitrate=").append(format.bitrate);
1642     }
1643     if (format.codecs != null) {
1644       builder.append(", codecs=").append(format.codecs);
1645     }
1646     if (format.width != NO_VALUE && format.height != NO_VALUE) {
1647       builder.append(", res=").append(format.width).append("x").append(format.height);
1648     }
1649     if (format.frameRate != NO_VALUE) {
1650       builder.append(", fps=").append(format.frameRate);
1651     }
1652     if (format.channelCount != NO_VALUE) {
1653       builder.append(", channels=").append(format.channelCount);
1654     }
1655     if (format.sampleRate != NO_VALUE) {
1656       builder.append(", sample_rate=").append(format.sampleRate);
1657     }
1658     if (format.language != null) {
1659       builder.append(", language=").append(format.language);
1660     }
1661     if (format.label != null) {
1662       builder.append(", label=").append(format.label);
1663     }
1664     return builder.toString();
1665   }
1666 
1667   // Parcelable implementation.
1668 
1669   @Override
describeContents()1670   public int describeContents() {
1671     return 0;
1672   }
1673 
1674   @Override
writeToParcel(Parcel dest, int flags)1675   public void writeToParcel(Parcel dest, int flags) {
1676     dest.writeString(id);
1677     dest.writeString(label);
1678     dest.writeString(language);
1679     dest.writeInt(selectionFlags);
1680     dest.writeInt(roleFlags);
1681     dest.writeInt(averageBitrate);
1682     dest.writeInt(peakBitrate);
1683     dest.writeString(codecs);
1684     dest.writeParcelable(metadata, 0);
1685     // Container specific.
1686     dest.writeString(containerMimeType);
1687     // Sample specific.
1688     dest.writeString(sampleMimeType);
1689     dest.writeInt(maxInputSize);
1690     int initializationDataSize = initializationData.size();
1691     dest.writeInt(initializationDataSize);
1692     for (int i = 0; i < initializationDataSize; i++) {
1693       dest.writeByteArray(initializationData.get(i));
1694     }
1695     dest.writeParcelable(drmInitData, 0);
1696     dest.writeLong(subsampleOffsetUs);
1697     // Video specific.
1698     dest.writeInt(width);
1699     dest.writeInt(height);
1700     dest.writeFloat(frameRate);
1701     dest.writeInt(rotationDegrees);
1702     dest.writeFloat(pixelWidthHeightRatio);
1703     Util.writeBoolean(dest, projectionData != null);
1704     if (projectionData != null) {
1705       dest.writeByteArray(projectionData);
1706     }
1707     dest.writeInt(stereoMode);
1708     dest.writeParcelable(colorInfo, flags);
1709     // Audio specific.
1710     dest.writeInt(channelCount);
1711     dest.writeInt(sampleRate);
1712     dest.writeInt(pcmEncoding);
1713     dest.writeInt(encoderDelay);
1714     dest.writeInt(encoderPadding);
1715     // Text specific.
1716     dest.writeInt(accessibilityChannel);
1717   }
1718 
1719   public static final Creator<Format> CREATOR = new Creator<Format>() {
1720 
1721     @Override
1722     public Format createFromParcel(Parcel in) {
1723       return new Format(in);
1724     }
1725 
1726     @Override
1727     public Format[] newArray(int size) {
1728       return new Format[size];
1729     }
1730 
1731   };
1732 }
1733