MediaCodec: report message from CodecErrorLog

Bug: 267190033
Test: atest android.mediav2.cts.CodecUnitTest
Change-Id: Idd1adae38328ada955999a8cecb7ce14c75ea52e
This commit is contained in:
Wonsik Kim
2023-01-30 10:26:08 -08:00
parent 43957576a0
commit cc1fb7b1be
2 changed files with 175 additions and 90 deletions

View File

@@ -43,6 +43,8 @@
#include <android_runtime/android_hardware_HardwareBuffer.h>
#include <android-base/stringprintf.h>
#include <binder/MemoryDealer.h>
#include <cutils/compiler.h>
@@ -1276,7 +1278,8 @@ void JMediaCodec::handleCallback(const sp<AMessage> &msg) {
ALOGE("Could not create MediaCodec.BufferInfo.");
env->ExceptionClear();
}
jniThrowException(env, "java/lang/IllegalStateException", NULL);
jniThrowException(env, "java/lang/IllegalStateException",
"Fatal error: could not create MediaCodec.BufferInfo object");
return;
}
@@ -1309,7 +1312,8 @@ void JMediaCodec::handleCallback(const sp<AMessage> &msg) {
ALOGE("Could not create CodecException object.");
env->ExceptionClear();
}
jniThrowException(env, "java/lang/IllegalStateException", NULL);
jniThrowException(env, "java/lang/IllegalStateException",
"Fatal error: could not create CodecException object");
return;
}
@@ -1322,7 +1326,9 @@ void JMediaCodec::handleCallback(const sp<AMessage> &msg) {
CHECK(msg->findMessage("format", &format));
if (OK != ConvertMessageToMap(env, format, &obj)) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
jniThrowException(env, "java/lang/IllegalStateException",
"Fatal error: failed to convert format "
"from native to Java object");
return;
}
@@ -1353,7 +1359,8 @@ void JMediaCodec::handleFirstTunnelFrameReadyNotification(const sp<AMessage> &ms
status_t err = ConvertMessageToMap(env, data, &obj);
if (err != OK) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
jniThrowException(env, "java/lang/IllegalStateException",
"Fatal error: failed to convert format from native to Java object");
return;
}
@@ -1374,7 +1381,8 @@ void JMediaCodec::handleFrameRenderedNotification(const sp<AMessage> &msg) {
status_t err = ConvertMessageToMap(env, data, &obj);
if (err != OK) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
jniThrowException(env, "java/lang/IllegalStateException",
"Fatal error: failed to convert format from native to Java object");
return;
}
@@ -1385,6 +1393,18 @@ void JMediaCodec::handleFrameRenderedNotification(const sp<AMessage> &msg) {
env->DeleteLocalRef(obj);
}
std::string JMediaCodec::getExceptionMessage(const char *msg = nullptr) const {
if (mCodec == nullptr) {
return msg ?: "";
}
std::string prefix = "";
if (msg && msg[0] != '\0') {
prefix.append(msg);
prefix.append("\n");
}
return prefix + mCodec->getErrorLog().extract();
}
void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatCallbackNotify:
@@ -1471,9 +1491,17 @@ static void throwCryptoException(JNIEnv *env, status_t err, const char *msg,
env->Throw(exception);
}
static std::string GetExceptionMessage(const sp<JMediaCodec> &codec, const char *msg) {
if (codec == NULL) {
return msg ?: "codec is released already";
}
return codec->getExceptionMessage(msg);
}
static jint throwExceptionAsNecessary(
JNIEnv *env, status_t err, int32_t actionCode = ACTION_CODE_FATAL,
const char *msg = NULL, const sp<ICrypto>& crypto = NULL) {
const char *msg = NULL, const sp<ICrypto>& crypto = NULL,
const sp<JMediaCodec> &codec = NULL) {
switch (err) {
case OK:
return 0;
@@ -1488,23 +1516,38 @@ static jint throwExceptionAsNecessary(
return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
case INVALID_OPERATION:
jniThrowException(env, "java/lang/IllegalStateException", msg);
jniThrowException(
env, "java/lang/IllegalStateException",
GetExceptionMessage(codec, msg).c_str());
return 0;
case BAD_VALUE:
jniThrowException(env, "java/lang/IllegalArgumentException", msg);
jniThrowException(
env, "java/lang/IllegalArgumentException",
GetExceptionMessage(codec, msg).c_str());
return 0;
default:
if (isCryptoError(err)) {
throwCryptoException(env, err, msg, crypto);
throwCryptoException(
env, err,
GetExceptionMessage(codec, msg).c_str(),
crypto);
return 0;
}
throwCodecException(env, err, actionCode, msg);
throwCodecException(
env, err, actionCode,
GetExceptionMessage(codec, msg).c_str());
return 0;
}
}
static jint throwExceptionAsNecessary(
JNIEnv *env, status_t err, const sp<JMediaCodec> &codec,
int32_t actionCode = ACTION_CODE_FATAL) {
return throwExceptionAsNecessary(env, err, actionCode, NULL, NULL, codec);
}
static void android_media_MediaCodec_native_enableOnFirstTunnelFrameReadyListener(
JNIEnv *env,
jobject thiz,
@@ -1512,13 +1555,13 @@ static void android_media_MediaCodec_native_enableOnFirstTunnelFrameReadyListene
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->enableOnFirstTunnelFrameReadyListener(enabled);
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_native_enableOnFrameRenderedListener(
@@ -1528,13 +1571,13 @@ static void android_media_MediaCodec_native_enableOnFrameRenderedListener(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->enableOnFrameRenderedListener(enabled);
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_native_setCallback(
@@ -1544,13 +1587,13 @@ static void android_media_MediaCodec_native_setCallback(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->setCallback(cb);
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_native_configure(
@@ -1564,7 +1607,7 @@ static void android_media_MediaCodec_native_configure(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -1602,7 +1645,7 @@ static void android_media_MediaCodec_native_configure(
err = codec->configure(format, bufferProducer, crypto, descrambler, flags);
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_native_setSurface(
@@ -1612,7 +1655,7 @@ static void android_media_MediaCodec_native_setSurface(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -1631,7 +1674,7 @@ static void android_media_MediaCodec_native_setSurface(
}
status_t err = codec->setSurface(bufferProducer);
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
sp<PersistentSurface> android_media_MediaCodec_getPersistentInputSurface(
@@ -1735,7 +1778,7 @@ static void android_media_MediaCodec_setInputSurface(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -1749,7 +1792,7 @@ static void android_media_MediaCodec_setInputSurface(
}
status_t err = codec->setInputSurface(persistentSurface);
if (err != NO_ERROR) {
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
}
@@ -1759,7 +1802,7 @@ static jobject android_media_MediaCodec_createInputSurface(JNIEnv* env,
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -1767,7 +1810,7 @@ static jobject android_media_MediaCodec_createInputSurface(JNIEnv* env,
sp<IGraphicBufferProducer> bufferProducer;
status_t err = codec->createInputSurface(&bufferProducer);
if (err != NO_ERROR) {
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
return NULL;
}
@@ -1782,13 +1825,13 @@ static void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) {
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->start();
throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, "start failed");
throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
@@ -1797,13 +1840,13 @@ static void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->stop();
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) {
@@ -1812,7 +1855,7 @@ static void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) {
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -1825,7 +1868,7 @@ static void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) {
// trigger an IllegalStateException.
err = UNKNOWN_ERROR;
}
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
@@ -1834,13 +1877,13 @@ static void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->flush();
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_queueInputBuffer(
@@ -1856,7 +1899,7 @@ static void android_media_MediaCodec_queueInputBuffer(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -1866,7 +1909,8 @@ static void android_media_MediaCodec_queueInputBuffer(
index, offset, size, timestampUs, flags, &errorDetailMsg);
throwExceptionAsNecessary(
env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
env, err, ACTION_CODE_FATAL,
codec->getExceptionMessage(errorDetailMsg.c_str()).c_str());
}
struct NativeCryptoInfo {
@@ -1890,7 +1934,9 @@ struct NativeCryptoInfo {
} else if (jmode == gCryptoModes.AesCbc) {
mMode = CryptoPlugin::kMode_AES_CBC;
} else {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(
env, INVALID_OPERATION, ACTION_CODE_FATAL,
base::StringPrintf("unrecognized crypto mode: %d", jmode).c_str());
return;
}
@@ -2026,7 +2072,7 @@ static void android_media_MediaCodec_queueSecureInputBuffer(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -2056,7 +2102,9 @@ static void android_media_MediaCodec_queueSecureInputBuffer(
} else if (jmode == gCryptoModes.AesCbc) {
mode = CryptoPlugin::kMode_AES_CBC;
} else {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(
env, INVALID_OPERATION, ACTION_CODE_FATAL,
base::StringPrintf("Unrecognized crypto mode: %d", jmode).c_str());
return;
}
@@ -2175,8 +2223,8 @@ static void android_media_MediaCodec_queueSecureInputBuffer(
subSamples = NULL;
throwExceptionAsNecessary(
env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str(),
codec->getCrypto());
env, err, ACTION_CODE_FATAL,
codec->getExceptionMessage(errorDetailMsg.c_str()).c_str(), codec->getCrypto());
}
static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jclass, jobject bufferObj) {
@@ -2518,14 +2566,16 @@ static void android_media_MediaCodec_native_queueLinearBlock(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == nullptr || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
sp<AMessage> tunings;
status_t err = ConvertKeyValueListsToAMessage(env, keys, values, &tunings);
if (err != OK) {
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(
env, err, ACTION_CODE_FATAL,
"error occurred while converting tunings from Java to native");
return;
}
@@ -2545,15 +2595,23 @@ static void android_media_MediaCodec_native_queueLinearBlock(
}
env->MonitorExit(lock.get());
} else {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(
env, INVALID_OPERATION, ACTION_CODE_FATAL,
"Failed to grab lock for a LinearBlock object");
return;
}
AString errorDetailMsg;
if (codec->hasCryptoOrDescrambler()) {
if (!memory) {
// It means there was an unexpected failure in extractMemoryFromContext above
ALOGI("queueLinearBlock: no ashmem memory for encrypted content");
throwExceptionAsNecessary(env, BAD_VALUE);
throwExceptionAsNecessary(
env, BAD_VALUE, ACTION_CODE_FATAL,
"Unexpected error: the input buffer is not compatible with "
"the secure codec, and a fallback logic failed.\n"
"Suggestion: please try including the secure codec when calling "
"MediaCodec.LinearBlock#obtain method to obtain a compatible buffer.");
return;
}
auto cryptoInfo =
@@ -2577,14 +2635,22 @@ static void android_media_MediaCodec_native_queueLinearBlock(
ALOGI_IF(err != OK, "queueEncryptedLinearBlock returned err = %d", err);
} else {
if (!buffer) {
// It means there was an unexpected failure in extractBufferFromContext above
ALOGI("queueLinearBlock: no C2Buffer found");
throwExceptionAsNecessary(env, BAD_VALUE);
throwExceptionAsNecessary(
env, BAD_VALUE, ACTION_CODE_FATAL,
"Unexpected error: the input buffer is not compatible with "
"the non-secure codec, and a fallback logic failed.\n"
"Suggestion: please do not include the secure codec when calling "
"MediaCodec.LinearBlock#obtain method to obtain a compatible buffer.");
return;
}
err = codec->queueBuffer(
index, buffer, presentationTimeUs, flags, tunings, &errorDetailMsg);
}
throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, errorDetailMsg.c_str());
throwExceptionAsNecessary(
env, err, ACTION_CODE_FATAL,
codec->getExceptionMessage(errorDetailMsg.c_str()).c_str());
}
static void android_media_MediaCodec_native_queueHardwareBuffer(
@@ -2595,14 +2661,16 @@ static void android_media_MediaCodec_native_queueHardwareBuffer(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
sp<AMessage> tunings;
status_t err = ConvertKeyValueListsToAMessage(env, keys, values, &tunings);
if (err != OK) {
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(
env, err, ACTION_CODE_FATAL,
"error occurred while converting tunings from Java to native");
return;
}
@@ -2627,7 +2695,9 @@ static void android_media_MediaCodec_native_queueHardwareBuffer(
ALOGW("Failed to wrap AHardwareBuffer into C2GraphicAllocation");
native_handle_close(handle);
native_handle_delete(handle);
throwExceptionAsNecessary(env, BAD_VALUE);
throwExceptionAsNecessary(
env, BAD_VALUE, ACTION_CODE_FATAL,
"HardwareBuffer not recognized");
return;
}
std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
@@ -2636,7 +2706,9 @@ static void android_media_MediaCodec_native_queueHardwareBuffer(
AString errorDetailMsg;
err = codec->queueBuffer(
index, buffer, presentationTimeUs, flags, tunings, &errorDetailMsg);
throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, errorDetailMsg.c_str());
throwExceptionAsNecessary(
env, err, ACTION_CODE_FATAL,
codec->getExceptionMessage(errorDetailMsg.c_str()).c_str());
}
static void android_media_MediaCodec_native_getOutputFrame(
@@ -2646,13 +2718,13 @@ static void android_media_MediaCodec_native_getOutputFrame(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->getOutputFrame(env, frame, index);
if (err != OK) {
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
}
@@ -2663,7 +2735,7 @@ static jint android_media_MediaCodec_dequeueInputBuffer(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return -1;
}
@@ -2674,7 +2746,7 @@ static jint android_media_MediaCodec_dequeueInputBuffer(
return (jint) index;
}
return throwExceptionAsNecessary(env, err);
return throwExceptionAsNecessary(env, err, codec);
}
static jint android_media_MediaCodec_dequeueOutputBuffer(
@@ -2684,7 +2756,7 @@ static jint android_media_MediaCodec_dequeueOutputBuffer(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return 0;
}
@@ -2696,7 +2768,7 @@ static jint android_media_MediaCodec_dequeueOutputBuffer(
return (jint) index;
}
return throwExceptionAsNecessary(env, err);
return throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_releaseOutputBuffer(
@@ -2707,13 +2779,13 @@ static void android_media_MediaCodec_releaseOutputBuffer(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->releaseOutputBuffer(index, render, updatePTS, timestampNs);
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env,
@@ -2722,13 +2794,13 @@ static void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env,
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->signalEndOfInputStream();
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
static jobject android_media_MediaCodec_getFormatNative(
@@ -2738,7 +2810,7 @@ static jobject android_media_MediaCodec_getFormatNative(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2749,7 +2821,7 @@ static jobject android_media_MediaCodec_getFormatNative(
return format;
}
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
return NULL;
}
@@ -2761,7 +2833,7 @@ static jobject android_media_MediaCodec_getOutputFormatForIndexNative(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2772,7 +2844,7 @@ static jobject android_media_MediaCodec_getOutputFormatForIndexNative(
return format;
}
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
return NULL;
}
@@ -2784,7 +2856,7 @@ static jobjectArray android_media_MediaCodec_getBuffers(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2797,7 +2869,7 @@ static jobjectArray android_media_MediaCodec_getBuffers(
// if we're out of memory, an exception was already thrown
if (err != NO_MEMORY) {
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
return NULL;
@@ -2810,7 +2882,7 @@ static jobject android_media_MediaCodec_getBuffer(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2823,7 +2895,7 @@ static jobject android_media_MediaCodec_getBuffer(
// if we're out of memory, an exception was already thrown
if (err != NO_MEMORY) {
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
return NULL;
@@ -2836,7 +2908,7 @@ static jobject android_media_MediaCodec_getImage(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2849,7 +2921,7 @@ static jobject android_media_MediaCodec_getImage(
// if we're out of memory, an exception was already thrown
if (err != NO_MEMORY) {
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
return NULL;
@@ -2862,7 +2934,7 @@ static jobject android_media_MediaCodec_getName(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2873,7 +2945,7 @@ static jobject android_media_MediaCodec_getName(
return name;
}
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
return NULL;
}
@@ -2885,7 +2957,7 @@ static jobject android_media_MediaCodec_getOwnCodecInfo(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2896,7 +2968,7 @@ static jobject android_media_MediaCodec_getOwnCodecInfo(
return codecInfoObj;
}
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
return NULL;
}
@@ -2908,7 +2980,8 @@ android_media_MediaCodec_native_getMetrics(JNIEnv *env, jobject thiz)
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
jniThrowException(env, "java/lang/IllegalStateException",
GetExceptionMessage(codec, NULL).c_str());
return 0;
}
@@ -2937,7 +3010,7 @@ static void android_media_MediaCodec_setParameters(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -2948,7 +3021,7 @@ static void android_media_MediaCodec_setParameters(
err = codec->setParameters(params);
}
throwExceptionAsNecessary(env, err);
throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_setVideoScalingMode(
@@ -2956,13 +3029,14 @@ static void android_media_MediaCodec_setVideoScalingMode(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW
&& mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
jniThrowException(env, "java/lang/IllegalArgumentException",
String8::format("Unrecognized mode: %d", mode));
return;
}
@@ -2974,7 +3048,7 @@ static void android_media_MediaCodec_setAudioPresentation(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -2986,14 +3060,14 @@ static jobject android_media_MediaCodec_getSupportedVendorParameters(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
jobject ret = NULL;
status_t status = codec->querySupportedVendorParameters(env, &ret);
if (status != OK) {
throwExceptionAsNecessary(env, status);
throwExceptionAsNecessary(env, status, codec);
}
return ret;
@@ -3004,7 +3078,7 @@ static jobject android_media_MediaCodec_getParameterDescriptor(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -3021,13 +3095,13 @@ static void android_media_MediaCodec_subscribeToVendorParameters(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t status = codec->subscribeToVendorParameters(env, names);
if (status != OK) {
throwExceptionAsNecessary(env, status);
throwExceptionAsNecessary(env, status, codec);
}
return;
}
@@ -3037,13 +3111,13 @@ static void android_media_MediaCodec_unsubscribeFromVendorParameters(
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t status = codec->unsubscribeFromVendorParameters(env, names);
if (status != OK) {
throwExceptionAsNecessary(env, status);
throwExceptionAsNecessary(env, status, codec);
}
return;
}
@@ -3440,11 +3514,15 @@ static jobject android_media_MediaCodec_LinearBlock_native_map(
if (!context->mReadonlyMapping) {
const C2BufferData data = buffer->data();
if (data.type() != C2BufferData::LINEAR) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(
env, INVALID_OPERATION, ACTION_CODE_FATAL,
"Underlying buffer is not a linear buffer");
return nullptr;
}
if (data.linearBlocks().size() != 1u) {
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(
env, INVALID_OPERATION, ACTION_CODE_FATAL,
"Underlying buffer contains more than one block");
return nullptr;
}
C2ConstLinearBlock block = data.linearBlocks().front();
@@ -3492,7 +3570,9 @@ static jobject android_media_MediaCodec_LinearBlock_native_map(
false, // readOnly
true /* clearBuffer */);
}
throwExceptionAsNecessary(env, INVALID_OPERATION);
throwExceptionAsNecessary(
env, INVALID_OPERATION, ACTION_CODE_FATAL,
"Underlying buffer is empty");
return nullptr;
}
@@ -3515,7 +3595,9 @@ static void PopulateNamesVector(
}
const char *cstr = env->GetStringUTFChars(jstr, nullptr);
if (cstr == nullptr) {
throwExceptionAsNecessary(env, BAD_VALUE);
throwExceptionAsNecessary(
env, BAD_VALUE, ACTION_CODE_FATAL,
"Error converting Java string to native");
return;
}
names->emplace_back(cstr);
@@ -3567,6 +3649,7 @@ static jboolean android_media_MediaCodec_LinearBlock_checkCompatible(
}
status_t err = MediaCodec::CanFetchLinearBlock(names, &isCompatible);
if (err != OK) {
// TODO: CodecErrorLog
throwExceptionAsNecessary(env, err);
}
return isCompatible;

View File

@@ -176,6 +176,8 @@ struct JMediaCodec : public AHandler {
const sp<ICrypto> &getCrypto() { return mCrypto; }
std::string getExceptionMessage(const char *msg) const;
protected:
virtual ~JMediaCodec();