• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 
17 package android.media;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.icu.util.ULocale;
22 
23 import java.lang.annotation.Retention;
24 import java.lang.annotation.RetentionPolicy;
25 import java.util.HashMap;
26 import java.util.Locale;
27 import java.util.Map;
28 import java.util.Objects;
29 
30 
31 /**
32  * The AudioPresentation class encapsulates the information that describes an audio presentation
33  * which is available in next generation audio content.
34  *
35  * Used by {@link MediaExtractor} {@link MediaExtractor#getAudioPresentations(int)} and
36  * {@link AudioTrack} {@link AudioTrack#setPresentation(AudioPresentation)} to query available
37  * presentations and to select one, respectively.
38  *
39  * A list of available audio presentations in a media source can be queried using
40  * {@link MediaExtractor#getAudioPresentations(int)}. This list can be presented to a user for
41  * selection.
42  * An AudioPresentation can be passed to an offloaded audio decoder via
43  * {@link AudioTrack#setPresentation(AudioPresentation)} to request decoding of the selected
44  * presentation. An audio stream may contain multiple presentations that differ by language,
45  * accessibility, end point mastering and dialogue enhancement. An audio presentation may also have
46  * a set of description labels in different languages to help the user to make an informed
47  * selection.
48  *
49  * Applications that parse media streams and extract presentation information on their own
50  * can create instances of AudioPresentation by using {@link AudioPresentation.Builder} class.
51  */
52 public final class AudioPresentation {
53     private final int mPresentationId;
54     private final int mProgramId;
55     private final ULocale mLanguage;
56 
57     /** @hide */
58     @IntDef(
59         value = {
60         CONTENT_UNKNOWN,
61         CONTENT_MAIN,
62         CONTENT_MUSIC_AND_EFFECTS,
63         CONTENT_VISUALLY_IMPAIRED,
64         CONTENT_HEARING_IMPAIRED,
65         CONTENT_DIALOG,
66         CONTENT_COMMENTARY,
67         CONTENT_EMERGENCY,
68         CONTENT_VOICEOVER,
69     })
70 
71     /**
72      * The ContentClassifier int definitions represent the AudioPresentation content
73      * classifier (as per TS 103 190-1 v1.2.1 4.3.3.8.1)
74     */
75     @Retention(RetentionPolicy.SOURCE)
76     public @interface ContentClassifier {}
77 
78     /**
79      * Audio presentation classifier: Unknown.
80      */
81     public static final int CONTENT_UNKNOWN                 = -1;
82     /**
83      * Audio presentation classifier: Complete main.
84      */
85     public static final int CONTENT_MAIN                    = 0;
86     /**
87      * Audio presentation content classifier: Music and effects.
88      */
89     public static final int CONTENT_MUSIC_AND_EFFECTS       = 1;
90     /**
91      * Audio presentation content classifier: Visually impaired.
92      */
93     public static final int CONTENT_VISUALLY_IMPAIRED       = 2;
94     /**
95      * Audio presentation content classifier: Hearing impaired.
96      */
97     public static final int CONTENT_HEARING_IMPAIRED        = 3;
98     /**
99      * Audio presentation content classifier: Dialog.
100      */
101     public static final int CONTENT_DIALOG                  = 4;
102     /**
103      * Audio presentation content classifier: Commentary.
104      */
105     public static final int CONTENT_COMMENTARY              = 5;
106     /**
107      * Audio presentation content classifier: Emergency.
108      */
109     public static final int CONTENT_EMERGENCY               = 6;
110     /**
111      * Audio presentation content classifier: Voice over.
112      */
113     public static final int CONTENT_VOICEOVER               = 7;
114 
115     /** @hide */
116     @IntDef(
117         value = {
118             MASTERING_NOT_INDICATED,
119             MASTERED_FOR_STEREO,
120             MASTERED_FOR_SURROUND,
121             MASTERED_FOR_3D,
122             MASTERED_FOR_HEADPHONE,
123     })
124     @Retention(RetentionPolicy.SOURCE)
125     public @interface MasteringIndicationType {}
126     private final @MasteringIndicationType int mMasteringIndication;
127     private final boolean mAudioDescriptionAvailable;
128     private final boolean mSpokenSubtitlesAvailable;
129     private final boolean mDialogueEnhancementAvailable;
130     private final Map<ULocale, CharSequence> mLabels;
131 
132     /**
133      * No preferred reproduction channel layout.
134      *
135      * @see Builder#setMasteringIndication(int)
136      */
137     public static final int MASTERING_NOT_INDICATED         = 0;
138     /**
139      * Stereo speaker layout.
140      *
141      * @see Builder#setMasteringIndication(int)
142      */
143     public static final int MASTERED_FOR_STEREO             = 1;
144     /**
145      * Two-dimensional (e.g. 5.1) speaker layout.
146      *
147      * @see Builder#setMasteringIndication(int)
148      */
149     public static final int MASTERED_FOR_SURROUND           = 2;
150     /**
151      * Three-dimensional (e.g. 5.1.2) speaker layout.
152      *
153      * @see Builder#setMasteringIndication(int)
154      */
155     public static final int MASTERED_FOR_3D                 = 3;
156     /**
157      * Prerendered for headphone playback.
158      *
159      * @see Builder#setMasteringIndication(int)
160      */
161     public static final int MASTERED_FOR_HEADPHONE          = 4;
162 
163     /**
164      * This ID is reserved. No items can be explicitly assigned this ID.
165      */
166     private static final int UNKNOWN_ID = -1;
167 
168     /**
169      * This allows an application developer to construct an AudioPresentation object with all the
170      * parameters.
171      * The IDs are all that is required for an
172      * {@link AudioTrack#setPresentation(AudioPresentation)} to be successful.
173      * The rest of the metadata is informative only so as to distinguish features
174      * of different presentations.
175      * @param presentationId Presentation ID to be decoded by a next generation audio decoder.
176      * @param programId Program ID to be decoded by a next generation audio decoder.
177      * @param language Locale corresponding to ISO 639-1/639-2 language code.
178      * @param masteringIndication One of {@link AudioPresentation#MASTERING_NOT_INDICATED},
179      *     {@link AudioPresentation#MASTERED_FOR_STEREO},
180      *     {@link AudioPresentation#MASTERED_FOR_SURROUND},
181      *     {@link AudioPresentation#MASTERED_FOR_3D},
182      *     {@link AudioPresentation#MASTERED_FOR_HEADPHONE}.
183      * @param audioDescriptionAvailable Audio description for the visually impaired.
184      * @param spokenSubtitlesAvailable Spoken subtitles for the visually impaired.
185      * @param dialogueEnhancementAvailable Dialogue enhancement.
186      * @param labels Text label indexed by its locale corresponding to the language code.
187      */
AudioPresentation(int presentationId, int programId, @NonNull ULocale language, @MasteringIndicationType int masteringIndication, boolean audioDescriptionAvailable, boolean spokenSubtitlesAvailable, boolean dialogueEnhancementAvailable, @NonNull Map<ULocale, CharSequence> labels)188     private AudioPresentation(int presentationId,
189                              int programId,
190                              @NonNull ULocale language,
191                              @MasteringIndicationType int masteringIndication,
192                              boolean audioDescriptionAvailable,
193                              boolean spokenSubtitlesAvailable,
194                              boolean dialogueEnhancementAvailable,
195                              @NonNull Map<ULocale, CharSequence> labels) {
196         mPresentationId = presentationId;
197         mProgramId = programId;
198         mLanguage = language;
199         mMasteringIndication = masteringIndication;
200         mAudioDescriptionAvailable = audioDescriptionAvailable;
201         mSpokenSubtitlesAvailable = spokenSubtitlesAvailable;
202         mDialogueEnhancementAvailable = dialogueEnhancementAvailable;
203         mLabels = new HashMap<ULocale, CharSequence>(labels);
204     }
205 
206     /**
207      * Returns presentation ID used by the framework to select an audio presentation rendered by a
208      * decoder. Presentation ID is typically sequential, but does not have to be.
209      */
getPresentationId()210     public int getPresentationId() {
211         return mPresentationId;
212     }
213 
214     /**
215      * Returns program ID used by the framework to select an audio presentation rendered by a
216      * decoder. Program ID can be used to further uniquely identify the presentation to a decoder.
217      */
getProgramId()218     public int getProgramId() {
219         return mProgramId;
220     }
221 
222     /**
223      * @return a map of available text labels for this presentation. Each label is indexed by its
224      * locale corresponding to the language code as specified by ISO 639-2. Either ISO 639-2/B
225      * or ISO 639-2/T could be used.
226      */
getLabels()227     public Map<Locale, String> getLabels() {
228         Map<Locale, String> localeLabels = new HashMap<Locale, String>(mLabels.size());
229         for (Map.Entry<ULocale, CharSequence> entry : mLabels.entrySet()) {
230             localeLabels.put(entry.getKey().toLocale(), entry.getValue().toString());
231         }
232         return localeLabels;
233     }
234 
getULabels()235     private Map<ULocale, CharSequence> getULabels() {
236         return mLabels;
237     }
238 
239     /**
240      * @return the locale corresponding to audio presentation's ISO 639-1/639-2 language code.
241      */
getLocale()242     public Locale getLocale() {
243         return mLanguage.toLocale();
244     }
245 
getULocale()246     private ULocale getULocale() {
247         return mLanguage;
248     }
249 
250     /**
251      * @return the mastering indication of the audio presentation.
252      * See {@link AudioPresentation#MASTERING_NOT_INDICATED},
253      *     {@link AudioPresentation#MASTERED_FOR_STEREO},
254      *     {@link AudioPresentation#MASTERED_FOR_SURROUND},
255      *     {@link AudioPresentation#MASTERED_FOR_3D},
256      *     {@link AudioPresentation#MASTERED_FOR_HEADPHONE}
257      */
258     @MasteringIndicationType
getMasteringIndication()259     public int getMasteringIndication() {
260         return mMasteringIndication;
261     }
262 
263     /**
264      * Indicates whether an audio description for the visually impaired is available.
265      * @return {@code true} if audio description is available.
266      */
hasAudioDescription()267     public boolean hasAudioDescription() {
268         return mAudioDescriptionAvailable;
269     }
270 
271     /**
272      * Indicates whether spoken subtitles for the visually impaired are available.
273      * @return {@code true} if spoken subtitles are available.
274      */
hasSpokenSubtitles()275     public boolean hasSpokenSubtitles() {
276         return mSpokenSubtitlesAvailable;
277     }
278 
279     /**
280      * Indicates whether dialogue enhancement is available.
281      * @return {@code true} if dialogue enhancement is available.
282      */
hasDialogueEnhancement()283     public boolean hasDialogueEnhancement() {
284         return mDialogueEnhancementAvailable;
285     }
286 
287     @Override
equals(Object o)288     public boolean equals(Object o) {
289         if (this == o) {
290             return true;
291         }
292         if (!(o instanceof AudioPresentation)) {
293             return false;
294         }
295         AudioPresentation obj = (AudioPresentation) o;
296         return mPresentationId == obj.getPresentationId()
297                 && mProgramId == obj.getProgramId()
298                 && mLanguage.equals(obj.getULocale())
299                 && mMasteringIndication == obj.getMasteringIndication()
300                 && mAudioDescriptionAvailable == obj.hasAudioDescription()
301                 && mSpokenSubtitlesAvailable == obj.hasSpokenSubtitles()
302                 && mDialogueEnhancementAvailable == obj.hasDialogueEnhancement()
303                 && mLabels.equals(obj.getULabels());
304     }
305 
306     @Override
hashCode()307     public int hashCode() {
308         return Objects.hash(mPresentationId,
309                 mProgramId,
310                 mLanguage.hashCode(),
311                 mMasteringIndication,
312                 mAudioDescriptionAvailable,
313                 mSpokenSubtitlesAvailable,
314                 mDialogueEnhancementAvailable,
315                 mLabels.hashCode());
316     }
317 
318     @Override
toString()319     public String toString() {
320         StringBuilder sb = new StringBuilder();
321         sb.append(getClass().getSimpleName() + " ");
322         sb.append("{ presentation id=" + mPresentationId);
323         sb.append(", program id=" + mProgramId);
324         sb.append(", language=" + mLanguage);
325         sb.append(", labels=" + mLabels);
326         sb.append(", mastering indication=" + mMasteringIndication);
327         sb.append(", audio description=" + mAudioDescriptionAvailable);
328         sb.append(", spoken subtitles=" + mSpokenSubtitlesAvailable);
329         sb.append(", dialogue enhancement=" + mDialogueEnhancementAvailable);
330         sb.append(" }");
331         return sb.toString();
332     }
333 
334     /**
335      * A builder class for creating {@link AudioPresentation} objects.
336      */
337     public static final class Builder {
338         private final int mPresentationId;
339         private int mProgramId = UNKNOWN_ID;
340         private ULocale mLanguage = new ULocale("");
341         private int mMasteringIndication = MASTERING_NOT_INDICATED;
342         private boolean mAudioDescriptionAvailable = false;
343         private boolean mSpokenSubtitlesAvailable = false;
344         private boolean mDialogueEnhancementAvailable = false;
345         private Map<ULocale, CharSequence> mLabels = new HashMap<ULocale, CharSequence>();
346 
347         /**
348          * Create a {@link Builder}. Any field that should be included in the
349          * {@link AudioPresentation} must be added.
350          *
351          * @param presentationId The presentation ID of this audio presentation.
352          */
Builder(int presentationId)353         public Builder(int presentationId) {
354             mPresentationId = presentationId;
355         }
356         /**
357          * Sets the ProgramId to which this audio presentation refers.
358          *
359          * @param programId The program ID to be decoded.
360          */
setProgramId(int programId)361         public @NonNull Builder setProgramId(int programId) {
362             mProgramId = programId;
363             return this;
364         }
365         /**
366          * Sets the language information of the audio presentation.
367          *
368          * @param language Locale corresponding to ISO 639-1/639-2 language code.
369          */
setLocale(@onNull ULocale language)370         public @NonNull Builder setLocale(@NonNull ULocale language) {
371             mLanguage = language;
372             return this;
373         }
374 
375         /**
376          * Sets the mastering indication.
377          *
378          * @param masteringIndication Input to set mastering indication.
379          * @throws IllegalArgumentException if the mastering indication is not any of
380          * {@link AudioPresentation#MASTERING_NOT_INDICATED},
381          * {@link AudioPresentation#MASTERED_FOR_STEREO},
382          * {@link AudioPresentation#MASTERED_FOR_SURROUND},
383          * {@link AudioPresentation#MASTERED_FOR_3D},
384          * and {@link AudioPresentation#MASTERED_FOR_HEADPHONE}
385          */
setMasteringIndication( @asteringIndicationType int masteringIndication)386         public @NonNull Builder setMasteringIndication(
387                 @MasteringIndicationType int masteringIndication) {
388             if (masteringIndication != MASTERING_NOT_INDICATED
389                     && masteringIndication != MASTERED_FOR_STEREO
390                     && masteringIndication != MASTERED_FOR_SURROUND
391                     && masteringIndication != MASTERED_FOR_3D
392                     && masteringIndication != MASTERED_FOR_HEADPHONE) {
393                 throw new IllegalArgumentException("Unknown mastering indication: "
394                                                         + masteringIndication);
395             }
396             mMasteringIndication = masteringIndication;
397             return this;
398         }
399 
400         /**
401          * Sets locale / text label pairs describing the presentation.
402          *
403          * @param labels Text label indexed by its locale corresponding to the language code.
404          */
setLabels(@onNull Map<ULocale, CharSequence> labels)405         public @NonNull Builder setLabels(@NonNull Map<ULocale, CharSequence> labels) {
406             mLabels = new HashMap<ULocale, CharSequence>(labels);
407             return this;
408         }
409 
410         /**
411          * Indicate whether the presentation contains audio description for the visually impaired.
412          *
413          * @param audioDescriptionAvailable Audio description for the visually impaired.
414          */
setHasAudioDescription(boolean audioDescriptionAvailable)415         public @NonNull Builder setHasAudioDescription(boolean audioDescriptionAvailable) {
416             mAudioDescriptionAvailable = audioDescriptionAvailable;
417             return this;
418         }
419 
420         /**
421          * Indicate whether the presentation contains spoken subtitles for the visually impaired.
422          *
423          * @param spokenSubtitlesAvailable Spoken subtitles for the visually impaired.
424          */
setHasSpokenSubtitles(boolean spokenSubtitlesAvailable)425         public @NonNull Builder setHasSpokenSubtitles(boolean spokenSubtitlesAvailable) {
426             mSpokenSubtitlesAvailable = spokenSubtitlesAvailable;
427             return this;
428         }
429 
430         /**
431          * Indicate whether the presentation supports dialogue enhancement.
432          *
433          * @param dialogueEnhancementAvailable Dialogue enhancement.
434          */
setHasDialogueEnhancement(boolean dialogueEnhancementAvailable)435         public @NonNull Builder setHasDialogueEnhancement(boolean dialogueEnhancementAvailable) {
436             mDialogueEnhancementAvailable = dialogueEnhancementAvailable;
437             return this;
438         }
439 
440         /**
441          * Creates a {@link AudioPresentation} instance with the specified fields.
442          *
443          * @return The new {@link AudioPresentation} instance
444          */
build()445         public @NonNull AudioPresentation build() {
446             return new AudioPresentation(mPresentationId, mProgramId,
447                                            mLanguage, mMasteringIndication,
448                                            mAudioDescriptionAvailable, mSpokenSubtitlesAvailable,
449                                            mDialogueEnhancementAvailable, mLabels);
450         }
451     }
452 }
453