Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1322fa1e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Allow apps to construct AudioPresentation object"

parents 4f906f88 5272e68c
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -22927,6 +22927,8 @@ package android.media {
    method public java.util.Map<java.util.Locale, java.lang.String> getLabels();
    method public java.util.Locale getLocale();
    method public int getMasteringIndication();
    method public int getPresentationId();
    method public int getProgramId();
    method public boolean hasAudioDescription();
    method public boolean hasDialogueEnhancement();
    method public boolean hasSpokenSubtitles();
@@ -22937,6 +22939,18 @@ package android.media {
    field public static final int MASTERING_NOT_INDICATED = 0; // 0x0
  }
  public static class AudioPresentation.Builder {
    ctor public AudioPresentation.Builder(int);
    method public android.media.AudioPresentation build();
    method public android.media.AudioPresentation.Builder setHasAudioDescription(boolean);
    method public android.media.AudioPresentation.Builder setHasDialogueEnhancement(boolean);
    method public android.media.AudioPresentation.Builder setHasSpokenSubtitles(boolean);
    method public android.media.AudioPresentation.Builder setLabels(java.util.Map<android.icu.util.ULocale, java.lang.String>);
    method public android.media.AudioPresentation.Builder setLocale(android.icu.util.ULocale);
    method public android.media.AudioPresentation.Builder setMasteringIndication(int);
    method public android.media.AudioPresentation.Builder setProgramId(int);
  }
  public class AudioRecord implements android.media.AudioRouting {
    ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException;
    method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
+0 −6
Original line number Diff line number Diff line
@@ -578,12 +578,6 @@ package android.media {
    method public static boolean isEncodingLinearPcm(int);
  }

  public final class AudioPresentation {
    ctor public AudioPresentation(int, int, java.util.Map<java.lang.String, java.lang.String>, java.lang.String, int, boolean, boolean, boolean);
    method public int getPresentationId();
    method public int getProgramId();
  }

  public final class BufferingParams implements android.os.Parcelable {
    method public int describeContents();
    method public int getInitialMarkMs();
+215 −39
Original line number Diff line number Diff line
@@ -19,13 +19,14 @@ package android.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.icu.util.ULocale;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;


/**
@@ -34,7 +35,7 @@ import java.util.Map;
 *
 * Used by {@link MediaExtractor} {@link MediaExtractor#getAudioPresentations(int)} and
 * {@link AudioTrack} {@link AudioTrack#setPresentation(AudioPresentation)} to query available
 * presentations and to select one.
 * presentations and to select one, respectively.
 *
 * A list of available audio presentations in a media source can be queried using
 * {@link MediaExtractor#getAudioPresentations(int)}. This list can be presented to a user for
@@ -49,8 +50,7 @@ import java.util.Map;
public final class AudioPresentation {
    private final int mPresentationId;
    private final int mProgramId;
    private final Map<String, String> mLabels;
    private final String mLanguage;
    private final ULocale mLanguage;

    /** @hide */
    @IntDef(
@@ -63,72 +63,98 @@ public final class AudioPresentation {
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface MasteringIndicationType {}

    private final @MasteringIndicationType int mMasteringIndication;
    private final boolean mAudioDescriptionAvailable;
    private final boolean mSpokenSubtitlesAvailable;
    private final boolean mDialogueEnhancementAvailable;
    private final Map<ULocale, String> mLabels;

    /**
     * No preferred reproduction channel layout.
     *
     * @see Builder#setMasteringIndication(int)
     */
    public static final int MASTERING_NOT_INDICATED         = 0;
    /**
     * Stereo speaker layout.
     *
     * @see Builder#setMasteringIndication(int)
     */
    public static final int MASTERED_FOR_STEREO             = 1;
    /**
     * Two-dimensional (e.g. 5.1) speaker layout.
     *
     * @see Builder#setMasteringIndication(int)
     */
    public static final int MASTERED_FOR_SURROUND           = 2;
    /**
     * Three-dimensional (e.g. 5.1.2) speaker layout.
     *
     * @see Builder#setMasteringIndication(int)
     */
    public static final int MASTERED_FOR_3D                 = 3;
    /**
     * Prerendered for headphone playback.
     *
     * @see Builder#setMasteringIndication(int)
     */
    public static final int MASTERED_FOR_HEADPHONE          = 4;

    /**
     * @hide
     * This ID is reserved. No items can be explicitly assigned this ID.
     */
    @TestApi
    public AudioPresentation(int presentationId,
    private static final int UNKNOWN_ID = -1;

    /**
     * This allows an application developer to construct an AudioPresentation object with all the
     * parameters.
     * The IDs are all that is required for an
     * {@link AudioTrack#setPresentation(AudioPresentation)} to be successful.
     * The rest of the metadata is informative only so as to distinguish features
     * of different presentations.
     * @param presentationId Presentation ID to be decoded by a next generation audio decoder.
     * @param programId Program ID to be decoded by a next generation audio decoder.
     * @param language Locale corresponding to ISO 639-1/639-2 language code.
     * @param masteringIndication One of {@link AudioPresentation#MASTERING_NOT_INDICATED},
     *     {@link AudioPresentation#MASTERED_FOR_STEREO},
     *     {@link AudioPresentation#MASTERED_FOR_SURROUND},
     *     {@link AudioPresentation#MASTERED_FOR_3D},
     *     {@link AudioPresentation#MASTERED_FOR_HEADPHONE}.
     * @param audioDescriptionAvailable Audio description for the visually impaired.
     * @param spokenSubtitlesAvailable Spoken subtitles for the visually impaired.
     * @param dialogueEnhancementAvailable Dialogue enhancement.
     * @param labels Text label indexed by its locale corresponding to the language code.
     */
    private AudioPresentation(int presentationId,
                             int programId,
                        @NonNull Map<String, String> labels,
                        @NonNull String language,
                             @NonNull ULocale language,
                             @MasteringIndicationType int masteringIndication,
                             boolean audioDescriptionAvailable,
                             boolean spokenSubtitlesAvailable,
                        boolean dialogueEnhancementAvailable) {
        this.mPresentationId = presentationId;
        this.mProgramId = programId;
        this.mLanguage = language;
        this.mMasteringIndication = masteringIndication;
        this.mAudioDescriptionAvailable = audioDescriptionAvailable;
        this.mSpokenSubtitlesAvailable = spokenSubtitlesAvailable;
        this.mDialogueEnhancementAvailable = dialogueEnhancementAvailable;

        this.mLabels = new HashMap<String, String>(labels);
                             boolean dialogueEnhancementAvailable,
                             @NonNull Map<ULocale, String> labels) {
        mPresentationId = presentationId;
        mProgramId = programId;
        mLanguage = language;
        mMasteringIndication = masteringIndication;
        mAudioDescriptionAvailable = audioDescriptionAvailable;
        mSpokenSubtitlesAvailable = spokenSubtitlesAvailable;
        mDialogueEnhancementAvailable = dialogueEnhancementAvailable;
        mLabels = new HashMap<ULocale, String>(labels);
    }

    /**
     * The framework uses this presentation id to select an audio presentation rendered by a
     * decoder. Presentation id is typically sequential, but does not have to be.
     * @hide
     * Returns presentation ID used by the framework to select an audio presentation rendered by a
     * decoder. Presentation ID is typically sequential, but does not have to be.
     */
    @TestApi
    public int getPresentationId() {
        return mPresentationId;
    }

    /**
     * The framework uses this program id to select an audio presentation rendered by a decoder.
     * Program id can be used to further uniquely identify the presentation to a decoder.
     * @hide
     * Returns program ID used by the framework to select an audio presentation rendered by a
     * decoder. Program ID can be used to further uniquely identify the presentation to a decoder.
     */
    @TestApi
    public int getProgramId() {
        return mProgramId;
    }
@@ -139,9 +165,9 @@ public final class AudioPresentation {
     * or ISO 639-2/T could be used.
     */
    public Map<Locale, String> getLabels() {
        Map<Locale, String> localeLabels = new HashMap<>();
        for (Map.Entry<String, String> entry : mLabels.entrySet()) {
            localeLabels.put(new Locale(entry.getKey()), entry.getValue());
        Map<Locale, String> localeLabels = new HashMap<Locale, String>();
        for (Map.Entry<ULocale, String> entry : mLabels.entrySet()) {
            localeLabels.put(entry.getKey().toLocale(), entry.getValue());
        }
        return localeLabels;
    }
@@ -150,13 +176,20 @@ public final class AudioPresentation {
     * @return the locale corresponding to audio presentation's ISO 639-1/639-2 language code.
     */
    public Locale getLocale() {
        return new Locale(mLanguage);
        return mLanguage.toLocale();
    }

    private ULocale getULocale() {
        return mLanguage;
    }

    /**
     * @return the mastering indication of the audio presentation.
     * See {@link #MASTERING_NOT_INDICATED}, {@link #MASTERED_FOR_STEREO},
     * {@link #MASTERED_FOR_SURROUND}, {@link #MASTERED_FOR_3D}, {@link #MASTERED_FOR_HEADPHONE}
     * See {@link AudioPresentation#MASTERING_NOT_INDICATED},
     *     {@link AudioPresentation#MASTERED_FOR_STEREO},
     *     {@link AudioPresentation#MASTERED_FOR_SURROUND},
     *     {@link AudioPresentation#MASTERED_FOR_3D},
     *     {@link AudioPresentation#MASTERED_FOR_HEADPHONE}
     */
    @MasteringIndicationType
    public int getMasteringIndication() {
@@ -186,4 +219,147 @@ public final class AudioPresentation {
    public boolean hasDialogueEnhancement() {
        return mDialogueEnhancementAvailable;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof AudioPresentation)) {
            return false;
        }
        AudioPresentation obj = (AudioPresentation) o;
        return mPresentationId == obj.getPresentationId()
                && mProgramId == obj.getProgramId()
                && mLanguage == obj.getULocale()
                && mMasteringIndication == obj.getMasteringIndication()
                && mAudioDescriptionAvailable == obj.hasAudioDescription()
                && mSpokenSubtitlesAvailable == obj.hasSpokenSubtitles()
                && mDialogueEnhancementAvailable == obj.hasDialogueEnhancement()
                && mLabels.equals(obj.getLabels());
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(mPresentationId);
    }

    /**
     * A builder class for creating {@link AudioPresentation} objects.
     */
    public static class Builder {
        private final int mPresentationId;
        private int mProgramId = UNKNOWN_ID;
        private ULocale mLanguage = new ULocale("");
        private int mMasteringIndication = MASTERING_NOT_INDICATED;
        private boolean mAudioDescriptionAvailable = false;
        private boolean mSpokenSubtitlesAvailable = false;
        private boolean mDialogueEnhancementAvailable = false;
        private Map<ULocale, String> mLabels = new HashMap<ULocale, String>();

        /**
         * Create a {@link Builder}. Any field that should be included in the
         * {@link AudioPresentation} must be added.
         *
         * @param presentationId the presentation ID of this audio presentation
         */
        public Builder(int presentationId) {
            mPresentationId = presentationId;
        }
        /**
         * Sets the ProgramId to which this audio presentation refers.
         *
         * @param programId
         */
        public @NonNull Builder setProgramId(int programId) {
            mProgramId = programId;
            return this;
        }
        /**
         * Sets the language information of the audio presentation.
         *
         * @param language code
         */
        public @NonNull Builder setLocale(ULocale language) {
            mLanguage = language;
            return this;
        }

        /**
         * Sets the mastering indication.
         *
         * @param masteringIndication Input to set mastering indication.
         * @throws IllegalArgumentException if the mastering indication is not any of
         * {@link AudioPresentation#MASTERING_NOT_INDICATED},
         * {@link AudioPresentation#MASTERED_FOR_STEREO},
         * {@link AudioPresentation#MASTERED_FOR_SURROUND},
         * {@link AudioPresentation#MASTERED_FOR_3D},
         * and {@link AudioPresentation#MASTERED_FOR_HEADPHONE}
         */
        public @NonNull Builder setMasteringIndication(
                @MasteringIndicationType int masteringIndication) {
            if (masteringIndication != MASTERING_NOT_INDICATED
                    && masteringIndication != MASTERED_FOR_STEREO
                    && masteringIndication != MASTERED_FOR_SURROUND
                    && masteringIndication != MASTERED_FOR_3D
                    && masteringIndication != MASTERED_FOR_HEADPHONE) {
                throw new IllegalArgumentException("Unknown mastering indication: "
                                                        + masteringIndication);
            }
            mMasteringIndication = masteringIndication;
            return this;
        }

        /**
         * Sets locale / text label pairs describing the presentation.
         *
         * @param labels
         */
        public @NonNull Builder setLabels(@NonNull Map<ULocale, String> labels) {
            mLabels = new HashMap<ULocale, String>(labels);
            return this;
        }

        /**
         * Indicate whether the presentation contains audio description for the visually impaired.
         *
         * @param audioDescriptionAvailable
         */
        public @NonNull Builder setHasAudioDescription(boolean audioDescriptionAvailable) {
            mAudioDescriptionAvailable = audioDescriptionAvailable;
            return this;
        }

        /**
         * Indicate whether the presentation contains spoken subtitles for the visually impaired.
         *
         * @param spokenSubtitlesAvailable
         */
        public @NonNull Builder setHasSpokenSubtitles(boolean spokenSubtitlesAvailable) {
            mSpokenSubtitlesAvailable = spokenSubtitlesAvailable;
            return this;
        }

        /**
         * Indicate whether the presentation supports dialogue enhancement.
         *
         * @param dialogueEnhancementAvailable
         */
        public @NonNull Builder setHasDialogueEnhancement(boolean dialogueEnhancementAvailable) {
            mDialogueEnhancementAvailable = dialogueEnhancementAvailable;
            return this;
        }

        /**
         * Creates a {@link AudioPresentation} instance with the specified fields.
         *
         * @return The new {@link AudioPresentation} instance
         */
        public @NonNull AudioPresentation build() {
            return new AudioPresentation(mPresentationId, mProgramId,
                                           mLanguage, mMasteringIndication,
                                           mAudioDescriptionAvailable, mSpokenSubtitlesAvailable,
                                           mDialogueEnhancementAvailable, mLabels);
        }
    }
}
+30 −15
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ struct JAudioPresentationInfo {
            }

            constructID = env->GetMethodID(clazz, "<init>",
                                "(IILjava/util/Map;Ljava/lang/String;IZZZ)V");
                                "(IILandroid/icu/util/ULocale;IZZZLjava/util/Map;)V");
            env->DeleteLocalRef(lclazz);

            // list objects
@@ -104,21 +104,26 @@ struct JAudioPresentationInfo {
                // don't expose private keys (starting with android._)
                continue;
            }

            jobject valueObj = NULL;

            AString val;
            CHECK(msg->findString(key, &val));

            valueObj = env->NewStringUTF(val.c_str());

            if (valueObj != NULL) {
                jstring keyObj = env->NewStringUTF(key);

                env->CallObjectMethod(hashMap, hashMapPutID, keyObj, valueObj);

                env->DeleteLocalRef(keyObj); keyObj = NULL;
                ScopedLocalRef<jclass> localeClazz(env, env->FindClass("android/icu/util/ULocale"));
                if (localeClazz.get() == NULL) {
                    return -EINVAL;
                }
                jmethodID localeConstructID =
                        env->GetMethodID(localeClazz.get(), "<init>", "(Ljava/lang/String;)V");
                if (localeConstructID == NULL) {
                    return -EINVAL;
                }
                jstring jLanguage = env->NewStringUTF(key);
                jobject jLocale = env->NewObject(localeClazz.get(), localeConstructID, jLanguage);
                env->CallObjectMethod(hashMap, hashMapPutID, jLocale, valueObj);
                env->DeleteLocalRef(jLocale); jLocale = NULL;
                env->DeleteLocalRef(valueObj); valueObj = NULL;
                env->DeleteLocalRef(jLanguage); jLanguage = NULL;
            }
        }

@@ -142,26 +147,36 @@ struct JAudioPresentationInfo {
            if (ConvertMessageToMap(env, labelMessage, &jLabelObject) != OK) {
                return NULL;
            }
            jstring jLanguage = env->NewStringUTF(ap->mLanguage.string());

            ScopedLocalRef<jclass> localeClazz(env, env->FindClass("android/icu/util/ULocale"));
            if (localeClazz.get() == NULL) {
                return NULL;
            }
            jmethodID localeConstructID =
                    env->GetMethodID(localeClazz.get(), "<init>", "(Ljava/lang/String;)V");
            if (localeConstructID == NULL) {
                return NULL;
            }
            jstring jLanguage = env->NewStringUTF(ap->mLanguage.c_str());
            jobject jLocale = env->NewObject(localeClazz.get(), localeConstructID, jLanguage);
            jobject jValueObj = env->NewObject(fields.clazz, fields.constructID,
                                static_cast<jint>(ap->mPresentationId),
                                static_cast<jint>(ap->mProgramId),
                                jLabelObject,
                                jLanguage,
                                jLocale,
                                static_cast<jint>(ap->mMasteringIndication),
                                static_cast<jboolean>((ap->mAudioDescriptionAvailable == 1) ?
                                    1 : 0),
                                static_cast<jboolean>((ap->mSpokenSubtitlesAvailable == 1) ?
                                    1 : 0),
                                static_cast<jboolean>((ap->mDialogueEnhancementAvailable == 1) ?
                                    1 : 0));
                                    1 : 0),
                                jLabelObject);
            if (jValueObj == NULL) {
                env->DeleteLocalRef(jLanguage); jLanguage = NULL;
                return NULL;
            }

            env->CallBooleanMethod(list, fields.listAddId, jValueObj);
            env->DeleteLocalRef(jLocale); jLocale = NULL;
            env->DeleteLocalRef(jValueObj); jValueObj = NULL;
            env->DeleteLocalRef(jLanguage); jLanguage = NULL;
        }