Merge "fix slow get caps -- DO NOT MERGE" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
991ae64ffe
@@ -1602,7 +1602,9 @@ final public class MediaCodec {
|
||||
private EventHandler mCallbackHandler;
|
||||
private Callback mCallback;
|
||||
private OnFrameRenderedListener mOnFrameRenderedListener;
|
||||
private Object mListenerLock = new Object();
|
||||
private final Object mListenerLock = new Object();
|
||||
private MediaCodecInfo mCodecInfo;
|
||||
private final Object mCodecInfoLock = new Object();
|
||||
|
||||
private static final int EVENT_CALLBACK = 1;
|
||||
private static final int EVENT_SET_CALLBACK = 2;
|
||||
@@ -3469,9 +3471,25 @@ final public class MediaCodec {
|
||||
*/
|
||||
@NonNull
|
||||
public MediaCodecInfo getCodecInfo() {
|
||||
return MediaCodecList.getInfoFor(getName());
|
||||
// Get the codec name first. If the codec is already released,
|
||||
// IllegalStateException will be thrown here.
|
||||
String name = getName();
|
||||
synchronized (mCodecInfoLock) {
|
||||
if (mCodecInfo == null) {
|
||||
// Get the codec info for this codec itself first. Only initialize
|
||||
// the full codec list if this somehow fails because it can be slow.
|
||||
mCodecInfo = getOwnCodecInfo();
|
||||
if (mCodecInfo == null) {
|
||||
mCodecInfo = MediaCodecList.getInfoFor(name);
|
||||
}
|
||||
}
|
||||
return mCodecInfo;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private native final MediaCodecInfo getOwnCodecInfo();
|
||||
|
||||
@NonNull
|
||||
private native final ByteBuffer[] getBuffers(boolean input);
|
||||
|
||||
|
||||
@@ -829,14 +829,24 @@ public final class MediaCodecInfo {
|
||||
|
||||
/** @hide */
|
||||
public CodecCapabilities dup() {
|
||||
return new CodecCapabilities(
|
||||
// clone writable arrays
|
||||
Arrays.copyOf(profileLevels, profileLevels.length),
|
||||
Arrays.copyOf(colorFormats, colorFormats.length),
|
||||
isEncoder(),
|
||||
mFlagsVerified,
|
||||
mDefaultFormat,
|
||||
mCapabilitiesInfo);
|
||||
CodecCapabilities caps = new CodecCapabilities();
|
||||
|
||||
// profileLevels and colorFormats may be modified by client.
|
||||
caps.profileLevels = Arrays.copyOf(profileLevels, profileLevels.length);
|
||||
caps.colorFormats = Arrays.copyOf(colorFormats, colorFormats.length);
|
||||
|
||||
caps.mMime = mMime;
|
||||
caps.mMaxSupportedInstances = mMaxSupportedInstances;
|
||||
caps.mFlagsRequired = mFlagsRequired;
|
||||
caps.mFlagsSupported = mFlagsSupported;
|
||||
caps.mFlagsVerified = mFlagsVerified;
|
||||
caps.mAudioCaps = mAudioCaps;
|
||||
caps.mVideoCaps = mVideoCaps;
|
||||
caps.mEncoderCaps = mEncoderCaps;
|
||||
caps.mDefaultFormat = mDefaultFormat;
|
||||
caps.mCapabilitiesInfo = mCapabilitiesInfo;
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -898,13 +908,13 @@ public final class MediaCodecInfo {
|
||||
|
||||
if (mMime.toLowerCase().startsWith("audio/")) {
|
||||
mAudioCaps = AudioCapabilities.create(info, this);
|
||||
mAudioCaps.setDefaultFormat(mDefaultFormat);
|
||||
mAudioCaps.getDefaultFormat(mDefaultFormat);
|
||||
} else if (mMime.toLowerCase().startsWith("video/")) {
|
||||
mVideoCaps = VideoCapabilities.create(info, this);
|
||||
}
|
||||
if (encoder) {
|
||||
mEncoderCaps = EncoderCapabilities.create(info, this);
|
||||
mEncoderCaps.setDefaultFormat(mDefaultFormat);
|
||||
mEncoderCaps.getDefaultFormat(mDefaultFormat);
|
||||
}
|
||||
|
||||
final Map<String, Object> global = MediaCodecList.getGlobalSettings();
|
||||
@@ -990,8 +1000,7 @@ public final class MediaCodecInfo {
|
||||
return caps;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void init(MediaFormat info, CodecCapabilities parent) {
|
||||
private void init(MediaFormat info, CodecCapabilities parent) {
|
||||
mParent = parent;
|
||||
initWithPlatformLimits();
|
||||
applyLevelLimits();
|
||||
@@ -1171,7 +1180,7 @@ public final class MediaCodecInfo {
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void setDefaultFormat(MediaFormat format) {
|
||||
public void getDefaultFormat(MediaFormat format) {
|
||||
// report settings that have only a single choice
|
||||
if (mBitrateRange.getLower().equals(mBitrateRange.getUpper())) {
|
||||
format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrateRange.getLower());
|
||||
@@ -1585,8 +1594,7 @@ public final class MediaCodecInfo {
|
||||
return caps;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void init(MediaFormat info, CodecCapabilities parent) {
|
||||
private void init(MediaFormat info, CodecCapabilities parent) {
|
||||
mParent = parent;
|
||||
initWithPlatformLimits();
|
||||
applyLevelLimits();
|
||||
@@ -2707,8 +2715,7 @@ public final class MediaCodecInfo {
|
||||
return caps;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void init(MediaFormat info, CodecCapabilities parent) {
|
||||
private void init(MediaFormat info, CodecCapabilities parent) {
|
||||
// no support for complexity or quality yet
|
||||
mParent = parent;
|
||||
mComplexityRange = Range.create(0, 0);
|
||||
@@ -2789,7 +2796,7 @@ public final class MediaCodecInfo {
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void setDefaultFormat(MediaFormat format) {
|
||||
public void getDefaultFormat(MediaFormat format) {
|
||||
// don't list trivial quality/complexity as default for now
|
||||
if (!mQualityRange.getUpper().equals(mQualityRange.getLower())
|
||||
&& mDefaultQuality != null) {
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "android_util_Binder.h"
|
||||
#include "jni.h"
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include <nativehelper/ScopedLocalRef.h>
|
||||
|
||||
#include <android/hardware/cas/native/1.0/IDescrambler.h>
|
||||
|
||||
@@ -98,6 +99,13 @@ static struct {
|
||||
jint AesCbc;
|
||||
} gCryptoModes;
|
||||
|
||||
static struct {
|
||||
jclass capsClazz;
|
||||
jmethodID capsCtorId;
|
||||
jclass profileLevelClazz;
|
||||
jfieldID profileField;
|
||||
jfieldID levelField;
|
||||
} gCodecInfo;
|
||||
|
||||
struct fields_t {
|
||||
jfieldID context;
|
||||
@@ -625,6 +633,103 @@ status_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
|
||||
return OK;
|
||||
}
|
||||
|
||||
static jobject getCodecCapabilitiesObject(
|
||||
JNIEnv *env, const char *mime, bool isEncoder,
|
||||
const sp<MediaCodecInfo::Capabilities> &capabilities) {
|
||||
Vector<MediaCodecInfo::ProfileLevel> profileLevels;
|
||||
Vector<uint32_t> colorFormats;
|
||||
|
||||
sp<AMessage> defaultFormat = new AMessage();
|
||||
defaultFormat->setString("mime", mime);
|
||||
|
||||
capabilities->getSupportedColorFormats(&colorFormats);
|
||||
capabilities->getSupportedProfileLevels(&profileLevels);
|
||||
uint32_t flags = capabilities->getFlags();
|
||||
sp<AMessage> details = capabilities->getDetails();
|
||||
|
||||
jobject defaultFormatObj = NULL;
|
||||
if (ConvertMessageToMap(env, defaultFormat, &defaultFormatObj)) {
|
||||
return NULL;
|
||||
}
|
||||
ScopedLocalRef<jobject> defaultFormatRef(env, defaultFormatObj);
|
||||
|
||||
jobject detailsObj = NULL;
|
||||
if (ConvertMessageToMap(env, details, &detailsObj)) {
|
||||
return NULL;
|
||||
}
|
||||
ScopedLocalRef<jobject> detailsRef(env, detailsObj);
|
||||
|
||||
ScopedLocalRef<jobjectArray> profileLevelArray(env, env->NewObjectArray(
|
||||
profileLevels.size(), gCodecInfo.profileLevelClazz, NULL));
|
||||
|
||||
for (size_t i = 0; i < profileLevels.size(); ++i) {
|
||||
const MediaCodecInfo::ProfileLevel &src = profileLevels.itemAt(i);
|
||||
|
||||
ScopedLocalRef<jobject> srcRef(env, env->AllocObject(
|
||||
gCodecInfo.profileLevelClazz));
|
||||
|
||||
env->SetIntField(srcRef.get(), gCodecInfo.profileField, src.mProfile);
|
||||
env->SetIntField(srcRef.get(), gCodecInfo.levelField, src.mLevel);
|
||||
|
||||
env->SetObjectArrayElement(profileLevelArray.get(), i, srcRef.get());
|
||||
}
|
||||
|
||||
ScopedLocalRef<jintArray> colorFormatsArray(
|
||||
env, env->NewIntArray(colorFormats.size()));
|
||||
for (size_t i = 0; i < colorFormats.size(); ++i) {
|
||||
jint val = colorFormats.itemAt(i);
|
||||
env->SetIntArrayRegion(colorFormatsArray.get(), i, 1, &val);
|
||||
}
|
||||
|
||||
return env->NewObject(
|
||||
gCodecInfo.capsClazz, gCodecInfo.capsCtorId,
|
||||
profileLevelArray.get(), colorFormatsArray.get(), isEncoder, flags,
|
||||
defaultFormatRef.get(), detailsRef.get());
|
||||
}
|
||||
|
||||
status_t JMediaCodec::getCodecInfo(JNIEnv *env, jobject *codecInfoObject) const {
|
||||
sp<MediaCodecInfo> codecInfo;
|
||||
|
||||
status_t err = mCodec->getCodecInfo(&codecInfo);
|
||||
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ScopedLocalRef<jstring> nameObject(env,
|
||||
env->NewStringUTF(codecInfo->getCodecName()));
|
||||
|
||||
bool isEncoder = codecInfo->isEncoder();
|
||||
|
||||
Vector<AString> mimes;
|
||||
codecInfo->getSupportedMimes(&mimes);
|
||||
|
||||
ScopedLocalRef<jobjectArray> capsArrayObj(env,
|
||||
env->NewObjectArray(mimes.size(), gCodecInfo.capsClazz, NULL));
|
||||
|
||||
for (size_t i = 0; i < mimes.size(); i++) {
|
||||
const sp<MediaCodecInfo::Capabilities> caps =
|
||||
codecInfo->getCapabilitiesFor(mimes[i].c_str());
|
||||
|
||||
ScopedLocalRef<jobject> capsObj(env, getCodecCapabilitiesObject(
|
||||
env, mimes[i].c_str(), isEncoder, caps));
|
||||
|
||||
env->SetObjectArrayElement(capsArrayObj.get(), i, capsObj.get());
|
||||
}
|
||||
|
||||
ScopedLocalRef<jclass> codecInfoClazz(env,
|
||||
env->FindClass("android/media/MediaCodecInfo"));
|
||||
CHECK(codecInfoClazz.get() != NULL);
|
||||
|
||||
jmethodID codecInfoCtorID = env->GetMethodID(codecInfoClazz.get(), "<init>",
|
||||
"(Ljava/lang/String;Z[Landroid/media/MediaCodecInfo$CodecCapabilities;)V");
|
||||
|
||||
*codecInfoObject = env->NewObject(codecInfoClazz.get(), codecInfoCtorID,
|
||||
nameObject.get(), isEncoder, capsArrayObj.get());
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t JMediaCodec::getMetrics(JNIEnv *, MediaAnalyticsItem * &reply) const {
|
||||
|
||||
status_t status = mCodec->getMetrics(reply);
|
||||
@@ -1665,6 +1770,29 @@ static jobject android_media_MediaCodec_getName(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static jobject android_media_MediaCodec_getOwnCodecInfo(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
ALOGV("android_media_MediaCodec_getOwnCodecInfo");
|
||||
|
||||
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
|
||||
|
||||
if (codec == NULL) {
|
||||
throwExceptionAsNecessary(env, INVALID_OPERATION);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jobject codecInfoObj;
|
||||
status_t err = codec->getCodecInfo(env, &codecInfoObj);
|
||||
|
||||
if (err == OK) {
|
||||
return codecInfoObj;
|
||||
}
|
||||
|
||||
throwExceptionAsNecessary(env, err);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static jobject
|
||||
android_media_MediaCodec_native_getMetrics(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
@@ -1877,6 +2005,28 @@ static void android_media_MediaCodec_native_init(JNIEnv *env) {
|
||||
field = env->GetFieldID(clazz.get(), "mPersistentObject", "J");
|
||||
CHECK(field != NULL);
|
||||
gPersistentSurfaceClassInfo.mPersistentObject = field;
|
||||
|
||||
clazz.reset(env->FindClass("android/media/MediaCodecInfo$CodecCapabilities"));
|
||||
CHECK(clazz.get() != NULL);
|
||||
gCodecInfo.capsClazz = (jclass)env->NewGlobalRef(clazz.get());
|
||||
|
||||
method = env->GetMethodID(clazz.get(), "<init>",
|
||||
"([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZI"
|
||||
"Ljava/util/Map;Ljava/util/Map;)V");
|
||||
CHECK(method != NULL);
|
||||
gCodecInfo.capsCtorId = method;
|
||||
|
||||
clazz.reset(env->FindClass("android/media/MediaCodecInfo$CodecProfileLevel"));
|
||||
CHECK(clazz.get() != NULL);
|
||||
gCodecInfo.profileLevelClazz = (jclass)env->NewGlobalRef(clazz.get());
|
||||
|
||||
field = env->GetFieldID(clazz.get(), "profile", "I");
|
||||
CHECK(field != NULL);
|
||||
gCodecInfo.profileField = field;
|
||||
|
||||
field = env->GetFieldID(clazz.get(), "level", "I");
|
||||
CHECK(field != NULL);
|
||||
gCodecInfo.levelField = field;
|
||||
}
|
||||
|
||||
static void android_media_MediaCodec_native_setup(
|
||||
@@ -2002,6 +2152,9 @@ static const JNINativeMethod gMethods[] = {
|
||||
{ "getName", "()Ljava/lang/String;",
|
||||
(void *)android_media_MediaCodec_getName },
|
||||
|
||||
{ "getOwnCodecInfo", "()Landroid/media/MediaCodecInfo;",
|
||||
(void *)android_media_MediaCodec_getOwnCodecInfo },
|
||||
|
||||
{ "native_getMetrics", "()Landroid/os/PersistableBundle;",
|
||||
(void *)android_media_MediaCodec_native_getMetrics},
|
||||
|
||||
|
||||
@@ -120,6 +120,8 @@ struct JMediaCodec : public AHandler {
|
||||
|
||||
status_t getName(JNIEnv *env, jstring *name) const;
|
||||
|
||||
status_t getCodecInfo(JNIEnv *env, jobject *codecInfo) const;
|
||||
|
||||
status_t getMetrics(JNIEnv *env, MediaAnalyticsItem * &reply) const;
|
||||
|
||||
status_t setParameters(const sp<AMessage> ¶ms);
|
||||
|
||||
Reference in New Issue
Block a user