diff options
author | 2023-04-05 19:32:53 +0000 | |
---|---|---|
committer | 2023-04-05 19:32:53 +0000 | |
commit | c33f81fff5c3154ab83ee5402e2ec0384e1edbe4 (patch) | |
tree | 88c9d5c37bd92113af0305a2bb95f95615fb0beb | |
parent | 0573ebd94b15b5672fb6fa478d2f799f584bc728 (diff) | |
parent | d1a1b4e62adc17ca6561c723929e40c4673fd0a3 (diff) |
Merge "MediaCodec: report message from CodecErrorLog"
-rw-r--r-- | media/jni/android_media_MediaCodec.cpp | 263 | ||||
-rw-r--r-- | media/jni/android_media_MediaCodec.h | 2 |
2 files changed, 175 insertions, 90 deletions
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 5b0c2a203022..b878bcf5dfef 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -43,6 +43,8 @@ #include <android_runtime/android_hardware_HardwareBuffer.h> +#include <android-base/stringprintf.h> + #include <binder/MemoryDealer.h> #include <cutils/compiler.h> @@ -1099,7 +1101,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; } @@ -1121,7 +1124,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; } @@ -1134,7 +1138,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; } @@ -1166,7 +1172,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; } @@ -1187,7 +1194,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; } @@ -1198,6 +1206,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: @@ -1347,9 +1367,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; @@ -1364,23 +1392,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, @@ -1388,13 +1431,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( @@ -1404,13 +1447,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( @@ -1420,13 +1463,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( @@ -1440,7 +1483,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; } @@ -1478,7 +1521,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( @@ -1488,7 +1531,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; } @@ -1507,7 +1550,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( @@ -1611,7 +1654,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; } @@ -1625,7 +1668,7 @@ static void android_media_MediaCodec_setInputSurface( } status_t err = codec->setInputSurface(persistentSurface); if (err != NO_ERROR) { - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } } @@ -1635,7 +1678,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; } @@ -1643,7 +1686,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; } @@ -1658,13 +1701,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) { @@ -1673,13 +1716,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) { @@ -1688,7 +1731,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; } @@ -1701,7 +1744,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) { @@ -1710,13 +1753,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( @@ -1732,7 +1775,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; } @@ -1742,7 +1785,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 { @@ -1766,7 +1810,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; } @@ -1902,7 +1948,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; } @@ -1932,7 +1978,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; } @@ -2051,8 +2099,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) { @@ -2394,14 +2442,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; } @@ -2421,15 +2471,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 = @@ -2453,14 +2511,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( @@ -2471,14 +2537,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; } @@ -2503,7 +2571,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); @@ -2512,7 +2582,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( @@ -2522,13 +2594,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); } } @@ -2539,7 +2611,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; } @@ -2550,7 +2622,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( @@ -2560,7 +2632,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; } @@ -2572,7 +2644,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( @@ -2583,13 +2655,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, @@ -2598,13 +2670,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( @@ -2614,7 +2686,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; } @@ -2625,7 +2697,7 @@ static jobject android_media_MediaCodec_getFormatNative( return format; } - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); return NULL; } @@ -2637,7 +2709,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; } @@ -2648,7 +2720,7 @@ static jobject android_media_MediaCodec_getOutputFormatForIndexNative( return format; } - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); return NULL; } @@ -2660,7 +2732,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; } @@ -2673,7 +2745,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; @@ -2686,7 +2758,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; } @@ -2699,7 +2771,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; @@ -2712,7 +2784,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; } @@ -2725,7 +2797,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; @@ -2738,7 +2810,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; } @@ -2749,7 +2821,7 @@ static jobject android_media_MediaCodec_getName( return name; } - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); return NULL; } @@ -2761,7 +2833,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; } @@ -2772,7 +2844,7 @@ static jobject android_media_MediaCodec_getOwnCodecInfo( return codecInfoObj; } - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); return NULL; } @@ -2784,7 +2856,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; } @@ -2813,7 +2886,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; } @@ -2824,7 +2897,7 @@ static void android_media_MediaCodec_setParameters( err = codec->setParameters(params); } - throwExceptionAsNecessary(env, err); + throwExceptionAsNecessary(env, err, codec); } static void android_media_MediaCodec_setVideoScalingMode( @@ -2832,13 +2905,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; } @@ -2850,7 +2924,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; } @@ -2862,14 +2936,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; @@ -2880,7 +2954,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; } @@ -2897,13 +2971,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; } @@ -2913,13 +2987,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; } @@ -3310,11 +3384,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(); @@ -3362,7 +3440,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; } @@ -3385,7 +3465,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); @@ -3437,6 +3519,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; diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h index 616c31b29157..fbaf64fda572 100644 --- a/media/jni/android_media_MediaCodec.h +++ b/media/jni/android_media_MediaCodec.h @@ -176,6 +176,8 @@ struct JMediaCodec : public AHandler { const sp<ICrypto> &getCrypto() { return mCrypto; } + std::string getExceptionMessage(const char *msg) const; + protected: virtual ~JMediaCodec(); |