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

Commit f97b6e5a authored by Wonsik Kim's avatar Wonsik Kim Committed by Android (Google) Code Review
Browse files

Merge "MediaCodec: add methods to query/subscribe vendor parameters" into sc-dev

parents 048f9ac0 8798c8cc
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -21345,7 +21345,9 @@ package android.media {
    method @NonNull public android.media.MediaFormat getOutputFormat(int);
    method @NonNull public android.media.MediaCodec.OutputFrame getOutputFrame(int);
    method @Nullable public android.media.Image getOutputImage(int);
    method @Nullable public android.media.MediaCodec.ParameterDescriptor getParameterDescriptor(@NonNull String);
    method @NonNull public android.media.MediaCodec.QueueRequest getQueueRequest(int);
    method @NonNull public java.util.List<java.lang.String> getSupportedVendorParameters();
    method @Nullable public static android.media.Image mapHardwareBuffer(@NonNull android.hardware.HardwareBuffer);
    method public void queueInputBuffer(int, int, int, long, int) throws android.media.MediaCodec.CryptoException;
    method public void queueSecureInputBuffer(int, int, @NonNull android.media.MediaCodec.CryptoInfo, long, int) throws android.media.MediaCodec.CryptoException;
@@ -21365,6 +21367,8 @@ package android.media {
    method public void signalEndOfInputStream();
    method public void start();
    method public void stop();
    method public void subscribeToVendorParameters(@NonNull java.util.List<java.lang.String>);
    method public void unsubscribeFromVendorParameters(@NonNull java.util.List<java.lang.String>);
    field public static final int BUFFER_FLAG_CODEC_CONFIG = 2; // 0x2
    field public static final int BUFFER_FLAG_END_OF_STREAM = 4; // 0x4
    field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1
@@ -21492,6 +21496,11 @@ package android.media {
    method public long getPresentationTimeUs();
  }
  public class MediaCodec.ParameterDescriptor {
    method @NonNull public String getName();
    method public int getType();
  }
  public final class MediaCodec.QueueRequest {
    method public void queue();
    method @NonNull public android.media.MediaCodec.QueueRequest setByteBufferParameter(@NonNull String, @NonNull java.nio.ByteBuffer);
+123 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -4690,6 +4691,128 @@ final public class MediaCodec {

    private native void native_enableOnFrameRenderedListener(boolean enable);

    /**
     * Returns a list of vendor parameter names.
     * <p>
     * This method can be called in any codec state except for released state.
     *
     * @return a list containing supported vendor parameters; an empty
     *         list if no vendor parameters are supported. The order of the
     *         parameters is arbitrary.
     * @throws IllegalStateException if in the Released state.
     */
    @NonNull
    public List<String> getSupportedVendorParameters() {
        return native_getSupportedVendorParameters();
    }

    @NonNull
    private native List<String> native_getSupportedVendorParameters();

    /**
     * Contains description of a parameter.
     */
    public class ParameterDescriptor {
        private ParameterDescriptor() {}

        /**
         * Returns the name of the parameter.
         */
        @NonNull
        public String getName() {
            return mName;
        }

        /**
         * Returns the type of the parameter.
         * {@link MediaFormat#TYPE_NULL} is never returned.
         */
        @MediaFormat.Type
        public int getType() {
            return mType;
        }

        private String mName;
        private @MediaFormat.Type int mType;
    }

    /**
     * Describe a parameter with the name.
     * <p>
     * This method can be called in any codec state except for released state.
     *
     * @param name name of the parameter to describe, typically one from
     *             {@link #getSupportedVendorParameters}.
     * @return {@link ParameterDescriptor} object that describes the parameter.
     *         {@code null} if unrecognized / not able to describe.
     * @throws IllegalStateException if in the Released state.
     */
    @Nullable
    public ParameterDescriptor getParameterDescriptor(@NonNull String name) {
        return native_getParameterDescriptor(name);
    }

    @Nullable
    private native ParameterDescriptor native_getParameterDescriptor(@NonNull String name);

    /**
     * Subscribe to vendor parameters, so that changes to these parameters generate
     * output format change event.
     * <p>
     * Unrecognized parameter names or standard (non-vendor) parameter names will be ignored.
     * {@link #reset} also resets the list of subscribed parameters.
     * If a parameter in {@code names} is already subscribed, it will remain subscribed.
     * <p>
     * This method can be called in any codec state except for released state. When called in
     * running state with newly subscribed parameters, it takes effect no later than the
     * processing of the subsequently queued buffer. For the new parameters, the codec will generate
     * output format change event.
     * <p>
     * Note that any vendor parameters set in a {@link #configure} or
     * {@link #setParameters} call are automatically subscribed.
     * <p>
     * See also {@link #INFO_OUTPUT_FORMAT_CHANGED} or {@link Callback#onOutputFormatChanged}
     * for output format change events.
     *
     * @param names names of the vendor parameters to subscribe. This may be an empty list,
     *              and in that case this method will not change the list of subscribed parameters.
     * @throws IllegalStateException if in the Released state.
     */
    public void subscribeToVendorParameters(@NonNull List<String> names) {
        native_subscribeToVendorParameters(names);
    }

    private native void native_subscribeToVendorParameters(@NonNull List<String> names);

    /**
     * Unsubscribe from vendor parameters, so that changes to these parameters
     * no longer generate output format change event.
     * <p>
     * Unrecognized parameter names, standard (non-vendor) parameter names will be ignored.
     * {@link #reset} also resets the list of subscribed parameters.
     * If a parameter in {@code names} is already unsubscribed, it will remain unsubscribed.
     * <p>
     * This method can be called in any codec state except for released state. When called in
     * running state with newly unsubscribed parameters, it takes effect no later than the
     * processing of the subsequently queued buffer.
     * <p>
     * Note that any vendor parameters set in a {@link #configure} or
     * {@link #setParameters} call are automatically subscribed, and with this method
     * they can be unsubscribed.
     * <p>
     * See also {@link #INFO_OUTPUT_FORMAT_CHANGED} or {@link Callback#onOutputFormatChanged}
     * for output format change events.
     *
     * @param names names of the vendor parameters to unsubscribe. This may be an empty list,
     *              and in that case this method will not change the list of subscribed parameters.
     * @throws IllegalStateException if in the Released state.
     */
    public void unsubscribeFromVendorParameters(@NonNull List<String> names) {
        native_unsubscribeFromVendorParameters(names);
    }

    private native void native_unsubscribeFromVendorParameters(@NonNull List<String> names);

    private EventHandler getEventHandlerOn(
            @Nullable Handler handler, @NonNull EventHandler lastHandler) {
        if (handler == null) {
+187 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@

#include <media/MediaCodecBuffer.h>
#include <media/hardware/VideoAPI.h>
#include <media/stagefright/CodecBase.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -84,6 +85,16 @@ enum {
    EVENT_FIRST_TUNNEL_FRAME_READY = 4,
};

// From MediaFormat.java
enum {
    TYPE_NULL           = 0,
    TYPE_INTEGER        = 1,
    TYPE_LONG           = 2,
    TYPE_FLOAT          = 3,
    TYPE_STRING         = 4,
    TYPE_BYTE_BUFFER    = 5,
};

static struct CryptoErrorCodes {
    jint cryptoErrorNoKey;
    jint cryptoErrorKeyExpired;
@@ -140,6 +151,8 @@ static struct {
} gByteBufferInfo;

static struct {
    jclass clazz;
    jmethodID ctorId;
    jmethodID sizeId;
    jmethodID getId;
    jmethodID addId;
@@ -154,6 +167,13 @@ static struct {
    jfieldID lockId;
} gLinearBlockInfo;

static struct {
    jclass clazz;
    jmethodID ctorId;
    jfieldID nameId;
    jfieldID typeId;
} gDescriptorInfo;

struct fields_t {
    jmethodID postEventFromNativeID;
    jmethodID lockAndGetContextID;
@@ -937,6 +957,74 @@ void JMediaCodec::selectAudioPresentation(const int32_t presentationId, const in
    (void)mCodec->setParameters(msg);
}

status_t JMediaCodec::querySupportedVendorParameters(JNIEnv *env, jobject *namesObj) {
    std::vector<std::string> names;
    status_t status = mCodec->querySupportedVendorParameters(&names);
    if (status != OK) {
        return status;
    }
    *namesObj = env->NewObject(gArrayListInfo.clazz, gArrayListInfo.ctorId);
    for (const std::string &name : names) {
        ScopedLocalRef<jstring> nameStr{env, env->NewStringUTF(name.c_str())};
        (void)env->CallBooleanMethod(*namesObj, gArrayListInfo.addId, nameStr.get());
    }
    return OK;
}

status_t JMediaCodec::describeParameter(JNIEnv *env, jstring name, jobject *descObj) {
    const char *tmp = env->GetStringUTFChars(name, nullptr);
    CodecParameterDescriptor desc;
    status_t status = mCodec->describeParameter(tmp, &desc);
    env->ReleaseStringUTFChars(name, tmp);
    if (status != OK) {
        return status;
    }
    jint type = TYPE_NULL;
    switch (desc.type) {
        case AMessage::kTypeInt32:  type = TYPE_INTEGER;     break;
        case AMessage::kTypeSize:
        case AMessage::kTypeInt64:  type = TYPE_LONG;        break;
        case AMessage::kTypeFloat:  type = TYPE_FLOAT;       break;
        case AMessage::kTypeString: type = TYPE_STRING;      break;
        case AMessage::kTypeBuffer: type = TYPE_BYTE_BUFFER; break;
        default:                    type = TYPE_NULL;        break;
    }
    if (type == TYPE_NULL) {
        return BAD_VALUE;
    }
    *descObj = env->NewObject(gDescriptorInfo.clazz, gDescriptorInfo.ctorId);
    env->SetObjectField(*descObj, gDescriptorInfo.nameId, name);
    env->SetIntField(*descObj, gDescriptorInfo.typeId, type);
    return OK;
}

static void BuildVectorFromList(JNIEnv *env, jobject list, std::vector<std::string> *vec) {
    ScopedLocalRef<jclass> listClazz{env, env->FindClass("java/util/List")};
    ScopedLocalRef<jclass> iterClazz{env, env->FindClass("java/util/Iterator")};
    jmethodID hasNextID = env->GetMethodID(iterClazz.get(), "hasNext", "()Z");
    jmethodID nextID = env->GetMethodID(iterClazz.get(), "next", "()Ljava/lang/Object;");
    jobject it = env->CallObjectMethod(
            list, env->GetMethodID(listClazz.get(), "iterator", "()Ljava/util/Iterator;"));
    while (env->CallBooleanMethod(it, hasNextID)) {
        jstring name = (jstring)env->CallObjectMethod(it, nextID);
        const char *tmp = env->GetStringUTFChars(name, nullptr);
        vec->push_back(tmp);
        env->ReleaseStringUTFChars(name, tmp);
    }
}

status_t JMediaCodec::subscribeToVendorParameters(JNIEnv *env, jobject namesObj) {
    std::vector<std::string> names;
    BuildVectorFromList(env, namesObj, &names);
    return mCodec->subscribeToVendorParameters(names);
}

status_t JMediaCodec::unsubscribeFromVendorParameters(JNIEnv *env, jobject namesObj) {
    std::vector<std::string> names;
    BuildVectorFromList(env, namesObj, &names);
    return mCodec->unsubscribeFromVendorParameters(names);
}

static jthrowable createCodecException(
        JNIEnv *env, status_t err, int32_t actionCode, const char *msg = NULL) {
    ScopedLocalRef<jclass> clazz(
@@ -2671,6 +2759,73 @@ static void android_media_MediaCodec_setAudioPresentation(
    codec->selectAudioPresentation((int32_t)presentationId, (int32_t)programId);
}

static jobject android_media_MediaCodec_getSupportedVendorParameters(
        JNIEnv *env, jobject thiz) {
    sp<JMediaCodec> codec = getMediaCodec(env, thiz);

    if (codec == NULL || codec->initCheck() != OK) {
        throwExceptionAsNecessary(env, INVALID_OPERATION);
        return NULL;
    }

    jobject ret = NULL;
    status_t status = codec->querySupportedVendorParameters(env, &ret);
    if (status != OK) {
        throwExceptionAsNecessary(env, status);
    }

    return ret;
}

static jobject android_media_MediaCodec_getParameterDescriptor(
        JNIEnv *env, jobject thiz, jstring name) {
    sp<JMediaCodec> codec = getMediaCodec(env, thiz);

    if (codec == NULL || codec->initCheck() != OK) {
        throwExceptionAsNecessary(env, INVALID_OPERATION);
        return NULL;
    }

    jobject ret = NULL;
    status_t status = codec->describeParameter(env, name, &ret);
    if (status != OK) {
        ret = NULL;
    }
    return ret;
}

static void android_media_MediaCodec_subscribeToVendorParameters(
        JNIEnv *env, jobject thiz, jobject names) {
    sp<JMediaCodec> codec = getMediaCodec(env, thiz);

    if (codec == NULL || codec->initCheck() != OK) {
        throwExceptionAsNecessary(env, INVALID_OPERATION);
        return;
    }

    status_t status = codec->subscribeToVendorParameters(env, names);
    if (status != OK) {
        throwExceptionAsNecessary(env, status);
    }
    return;
}

static void android_media_MediaCodec_unsubscribeFromVendorParameters(
        JNIEnv *env, jobject thiz, jobject names) {
    sp<JMediaCodec> codec = getMediaCodec(env, thiz);

    if (codec == NULL || codec->initCheck() != OK) {
        throwExceptionAsNecessary(env, INVALID_OPERATION);
        return;
    }

    status_t status = codec->unsubscribeFromVendorParameters(env, names);
    if (status != OK) {
        throwExceptionAsNecessary(env, status);
    }
    return;
}

static void android_media_MediaCodec_native_init(JNIEnv *env, jclass) {
    ScopedLocalRef<jclass> clazz(
            env, env->FindClass("android/media/MediaCodec"));
@@ -2930,6 +3085,10 @@ static void android_media_MediaCodec_native_init(JNIEnv *env, jclass) {

    clazz.reset(env->FindClass("java/util/ArrayList"));
    CHECK(clazz.get() != NULL);
    gArrayListInfo.clazz = (jclass)env->NewGlobalRef(clazz.get());

    gArrayListInfo.ctorId = env->GetMethodID(clazz.get(), "<init>", "()V");
    CHECK(gArrayListInfo.ctorId != NULL);

    gArrayListInfo.sizeId = env->GetMethodID(clazz.get(), "size", "()I");
    CHECK(gArrayListInfo.sizeId != NULL);
@@ -2960,6 +3119,19 @@ static void android_media_MediaCodec_native_init(JNIEnv *env, jclass) {

    gLinearBlockInfo.lockId = env->GetFieldID(clazz.get(), "mLock", "Ljava/lang/Object;");
    CHECK(gLinearBlockInfo.lockId != NULL);

    clazz.reset(env->FindClass("android/media/MediaCodec$ParameterDescriptor"));
    CHECK(clazz.get() != NULL);
    gDescriptorInfo.clazz = (jclass)env->NewGlobalRef(clazz.get());

    gDescriptorInfo.ctorId = env->GetMethodID(clazz.get(), "<init>", "()V");
    CHECK(gDescriptorInfo.ctorId != NULL);

    gDescriptorInfo.nameId = env->GetFieldID(clazz.get(), "mName", "Ljava/lang/String;");
    CHECK(gDescriptorInfo.nameId != NULL);

    gDescriptorInfo.typeId = env->GetFieldID(clazz.get(), "mType", "I");
    CHECK(gDescriptorInfo.typeId != NULL);
}

static void android_media_MediaCodec_native_setup(
@@ -3289,6 +3461,21 @@ static const JNINativeMethod gMethods[] = {
    { "native_setAudioPresentation", "(II)V",
      (void *)android_media_MediaCodec_setAudioPresentation },

    { "native_getSupportedVendorParameters", "()Ljava/util/List;",
      (void *)android_media_MediaCodec_getSupportedVendorParameters },

    { "native_getParameterDescriptor",
      "(Ljava/lang/String;)Landroid/media/MediaCodec$ParameterDescriptor;",
      (void *)android_media_MediaCodec_getParameterDescriptor },

    { "native_subscribeToVendorParameters",
      "(Ljava/util/List;)V",
      (void *)android_media_MediaCodec_subscribeToVendorParameters},

    { "native_unsubscribeFromVendorParameters",
      "(Ljava/util/List;)V",
      (void *)android_media_MediaCodec_unsubscribeFromVendorParameters},

    { "native_init", "()V", (void *)android_media_MediaCodec_native_init },

    { "native_setup", "(Ljava/lang/String;ZZ)V",
+8 −0
Original line number Diff line number Diff line
@@ -164,6 +164,14 @@ struct JMediaCodec : public AHandler {

    void selectAudioPresentation(const int32_t presentationId, const int32_t programId);

    status_t querySupportedVendorParameters(JNIEnv *env, jobject *names);

    status_t describeParameter(JNIEnv *env, jstring name, jobject *desc);

    status_t subscribeToVendorParameters(JNIEnv *env, jobject names);

    status_t unsubscribeFromVendorParameters(JNIEnv *env, jobject names);

    bool hasCryptoOrDescrambler() { return mHasCryptoOrDescrambler; }

    const sp<ICrypto> &getCrypto() { return mCrypto; }