Merge "fix slow get caps -- DO NOT MERGE" into pi-dev

This commit is contained in:
TreeHugger Robot
2018-03-15 21:40:32 +00:00
committed by Android (Google) Code Review
4 changed files with 200 additions and 20 deletions

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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},

View File

@@ -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> &params);