SDL_AMediaCodec* SDL_AMediaCodecJava_createDecoderByType(JNIEnv *env, const char *mime_type) { SDLTRACE("%s", __func__); jstring jmime_type = (*env)->NewStringUTF(env, mime_type); if (SDL_JNI_CatchException(env) || !jmime_type) { return NULL; } jobject local_android_media_codec = (*env)->CallStaticObjectMethod(env, g_clazz.clazz, g_clazz.jmid_createDecoderByType, jmime_type); SDL_JNI_DeleteLocalRefP(env, &jmime_type); if (SDL_JNI_CatchException(env) || !local_android_media_codec) { return NULL; } SDL_AMediaCodec* acodec = SDL_AMediaCodecJava_init(env, local_android_media_codec); SDL_JNI_DeleteLocalRefP(env, &local_android_media_codec); return acodec; }
static bool mediacodec_select_callback(void *opaque, ijkmp_mediacodecinfo_context *mcc) { JNIEnv *env = NULL; jobject jmime = NULL; jstring jcodec_name = NULL; jobject weak_this = (jobject) opaque; const char *codec_name = NULL; bool found_codec = false; if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) { ALOGE("%s: SetupThreadEnv failed\n", __func__); return -1; } jmime = (*env)->NewStringUTF(env, mcc->mime_type); if (SDL_JNI_CatchException(env) || !jmime) { goto fail; } jcodec_name = (*env)->CallStaticObjectMethod(env, g_clazz.clazz, g_clazz.jmid_onSelectCodec, weak_this, jmime, mcc->profile, mcc->level); if (SDL_JNI_CatchException(env) || !jcodec_name) { goto fail; } codec_name = (*env)->GetStringUTFChars(env, jcodec_name, NULL ); if (!codec_name || !*codec_name) { goto fail; } strncpy(mcc->codec_name, codec_name, sizeof(mcc->codec_name) / sizeof(*mcc->codec_name)); mcc->codec_name[sizeof(mcc->codec_name) / sizeof(*mcc->codec_name) - 1] = 0; found_codec = true; fail: if (codec_name) { (*env)->ReleaseStringUTFChars(env, jcodec_name, codec_name); codec_name = NULL; } SDL_JNI_DeleteLocalRefP(env, &jcodec_name); SDL_JNI_DeleteLocalRefP(env, &jmime); return found_codec; }
SDL_AMediaCodec* SDL_AMediaCodecJava_createByCodecName(JNIEnv *env, const char *codec_name) { SDLTRACE("%s", __func__); jstring jcodec_name = (*env)->NewStringUTF(env, codec_name); if (SDL_JNI_CatchException(env) || !jcodec_name) { return NULL; } jobject local_android_media_codec = (*env)->CallStaticObjectMethod(env, g_clazz.clazz, g_clazz.jmid_createByCodecName, jcodec_name); SDL_JNI_DeleteLocalRefP(env, &jcodec_name); if (SDL_JNI_CatchException(env) || !local_android_media_codec) { return NULL; } SDL_AMediaCodec* acodec = SDL_AMediaCodecJava_init(env, local_android_media_codec); acodec->object_serial = SDL_AMediaCodec_create_object_serial(); SDL_JNI_DeleteLocalRefP(env, &local_android_media_codec); return acodec; }
// NOTE: support to be called from read_thread static int inject_callback(void *opaque, int what, void *data, size_t data_size) { JNIEnv *env = NULL; jobject jbundle = NULL; int ret = -1; int is_handled = 0; SDL_JNI_SetupThreadEnv(&env); jobject weak_thiz = (jobject) opaque; if (weak_thiz == NULL ) goto fail; switch (what) { case AIRSTASHAVINJECT_CONCAT_RESOLVE_SEGMENT: case AIRSTASHAVINJECT_ON_TCP_OPEN: case AIRSTASHAVINJECT_ON_HTTP_OPEN: case AIRSTASHAVINJECT_ON_HTTP_RETRY: case AIRSTASHAVINJECT_ON_LIVE_RETRY: { AirStashAVInject_OnUrlOpenData *real_data = (AirStashAVInject_OnUrlOpenData *) data; real_data->is_handled = 0; jbundle = AirStashC_Bundle__Bundle__catchAll(env); if (!jbundle) { ALOGE("%s: ASDK_Bundle__init failed\n", __func__); goto fail; } AirStashC_Bundle__putString__withCString__catchAll(env, jbundle, "url", real_data->url); AirStashC_Bundle__putInt__withCString__catchAll(env, jbundle, "segment_index", real_data->segment_index); AirStashC_Bundle__putInt__withCString__catchAll(env, jbundle, "retry_counter", real_data->retry_counter); is_handled = AirStashC_AirStashMediaPlayer__onNativeInvoke__catchAll(env, weak_thiz, what, jbundle); if (AirStash_ExceptionCheck__catchAll(env)) goto fail; AirStashC_Bundle__getString__withCString__asCBuffer(env, jbundle, "url", real_data->url, sizeof(real_data->url)); if (AirStash_ExceptionCheck__catchAll(env)) goto fail; real_data->is_handled = is_handled; ret = 0; break; } default: { goto fail; } } fail: SDL_JNI_DeleteLocalRefP(env, &jbundle); return ret; }
// NOTE: support to be called from read_thread static int inject_callback(void *opaque, int what, void *data, size_t data_size) { JNIEnv *env = NULL; jobject jbundle = NULL; int ret = -1; SDL_JNI_SetupThreadEnv(&env); jobject weak_thiz = (jobject) opaque; if (weak_thiz == NULL ) goto fail; switch (what) { case IJKAVINJECT_CONCAT_RESOLVE_SEGMENT: { ret = _onNativeControlResolveSegment(env, weak_thiz, what, data, data_size); break; } case IJKAVINJECT_ON_TCP_OPEN: case IJKAVINJECT_ON_HTTP_OPEN: case IJKAVINJECT_ON_HTTP_RETRY: case IJKAVINJECT_ON_LIVE_RETRY: { IJKAVInject_OnUrlOpenData *real_data = (IJKAVInject_OnUrlOpenData *) data; jbundle = ASDK_Bundle__init(env); if (SDL_JNI_CatchException(env) || !jbundle) { ALOGE("%s: ASDK_Bundle__init failed\n", __func__); goto fail; } ASDK_Bundle__putString_c(env, jbundle, "url", real_data->url); ASDK_Bundle__putInt_c(env, jbundle, "segment_index", real_data->segment_index); ASDK_Bundle__putInt_c(env, jbundle, "retry_counter", real_data->retry_counter); if (!(*env)->CallStaticBooleanMethod(env, g_clazz.clazz, g_clazz.jmid_onNativeInvoke, weak_thiz, what, jbundle)) goto fail; ASDK_Bundle__getString_cbuf(env, jbundle, "url", real_data->url, sizeof(real_data->url)); ret = 0; break; } default: { goto fail; } } fail: SDL_JNI_CatchException(env); SDL_JNI_DeleteLocalRefP(env, &jbundle); return ret; }
static uint8_t* SDL_AMediaCodecJava_getInputBuffer(SDL_AMediaCodec* acodec, size_t idx, size_t *out_size) { AMCTRACE("%s", __func__); JNIEnv *env = NULL; if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) { ALOGE("%s: SetupThreadEnv failed", __func__); return NULL; } SDL_AMediaCodec_Opaque *opaque = (SDL_AMediaCodec_Opaque *)acodec->opaque; if (0 != getInputBuffers(env, acodec)) return NULL; assert(opaque->input_buffer_array); int buffer_count = (*env)->GetArrayLength(env, opaque->input_buffer_array); if (SDL_JNI_CatchException(env) || idx < 0 || idx >= buffer_count) { ALOGE("%s: idx(%d) < count(%d)\n", __func__, (int)idx, (int)buffer_count); return NULL; } SDL_JNI_DeleteGlobalRefP(env, &opaque->input_buffer); jobject local_input_buffer = (*env)->GetObjectArrayElement(env, opaque->input_buffer_array, idx); if (SDL_JNI_CatchException(env) || !local_input_buffer) { ALOGE("%s: GetObjectArrayElement failed\n", __func__); return NULL; } opaque->input_buffer = (*env)->NewGlobalRef(env, local_input_buffer); SDL_JNI_DeleteLocalRefP(env, &local_input_buffer); if (SDL_JNI_CatchException(env) || !opaque->input_buffer) { ALOGE("%s: GetObjectArrayElement.NewGlobalRef failed\n", __func__); return NULL; } jlong size = (*env)->GetDirectBufferCapacity(env, opaque->input_buffer); void *ptr = (*env)->GetDirectBufferAddress(env, opaque->input_buffer); if (out_size) *out_size = size; return ptr; }
SDL_AMediaFormat *SDL_AMediaCodecJava_getOutputFormat(SDL_AMediaCodec *thiz) { if (!thiz || !thiz->opaque) return NULL; JNIEnv *env = NULL; if (JNI_OK != SDL_JNI_SetupThreadEnv(&env)) { ALOGE("%s: SetupThreadEnv failed", __func__); return NULL; } SDL_AMediaCodec_Opaque *opaque = (SDL_AMediaCodec_Opaque *)thiz->opaque; jobject android_format = (*env)->CallObjectMethod(env, opaque->android_media_codec, g_clazz.jmid_getOutputFormat); if (SDL_JNI_CatchException(env) || !android_format) { return NULL; } SDL_AMediaFormat *aformat = SDL_AMediaFormatJava_init(env, android_format); SDL_JNI_DeleteLocalRefP(env, &android_format); return aformat; }
inline static int getOutputBuffers(JNIEnv *env, SDL_AMediaCodec* acodec) { SDL_AMediaCodec_Opaque *opaque = (SDL_AMediaCodec_Opaque *)acodec->opaque; jobject android_media_codec = opaque->android_media_codec; SDL_JNI_DeleteGlobalRefP(env, &opaque->output_buffer_array); if (opaque->output_buffer_array) return 0; jobjectArray local_output_buffer_array = (*env)->CallObjectMethod(env, android_media_codec, g_clazz.jmid_getOutputBuffers); if (SDL_JNI_CatchException(env) || !local_output_buffer_array) { ALOGE("%s: getInputBuffers failed\n", __func__); return -1; } opaque->output_buffer_array = (*env)->NewGlobalRef(env, local_output_buffer_array); SDL_JNI_DeleteLocalRefP(env, &local_output_buffer_array); if (SDL_JNI_CatchException(env) || !opaque->output_buffer_array) { ALOGE("%s: getOutputBuffers.NewGlobalRef failed\n", __func__); return -1; } return 0; }
static jobject IjkMediaPlayer_getMediaMeta(JNIEnv *env, jobject thiz) { MPTRACE("%s", __func__); bool is_locked = false; jobject jret_bundle = NULL; jobject jlocal_bundle = NULL; jobject jstream_bundle = NULL; jobject jarray_list = NULL; IjkMediaMeta *meta = NULL; IjkMediaPlayer *mp = jni_get_media_player(env, thiz); JNI_CHECK_GOTO(mp, env, "java/lang/IllegalStateException", "mpjni: getMediaMeta: null mp", LABEL_RETURN); meta = ijkmp_get_meta_l(mp); if (!meta) goto LABEL_RETURN; ijkmeta_lock(meta); is_locked = true; jlocal_bundle = ASDK_Bundle__init(env); if (SDL_JNI_RethrowException(env)) { goto LABEL_RETURN; } fillMetaInternal(env, jlocal_bundle, meta, IJKM_KEY_FORMAT, NULL ); fillMetaInternal(env, jlocal_bundle, meta, IJKM_KEY_DURATION_US, NULL ); fillMetaInternal(env, jlocal_bundle, meta, IJKM_KEY_START_US, NULL ); fillMetaInternal(env, jlocal_bundle, meta, IJKM_KEY_START_US, NULL ); fillMetaInternal(env, jlocal_bundle, meta, IJKM_KEY_VIDEO_STREAM, "-1"); fillMetaInternal(env, jlocal_bundle, meta, IJKM_KEY_AUDIO_STREAM, "-1"); jarray_list = ASDK_ArrayList__init(env); if (SDL_JNI_RethrowException(env)) { goto LABEL_RETURN; } size_t count = ijkmeta_get_children_count_l(meta); for (size_t i = 0; i < count; ++i) { IjkMediaMeta *streamRawMeta = ijkmeta_get_child_l(meta, i); if (streamRawMeta) { jstream_bundle = ASDK_Bundle__init(env); if (SDL_JNI_RethrowException(env)) { goto LABEL_RETURN; } fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_TYPE, IJKM_VAL_TYPE__UNKNOWN); const char *type = ijkmeta_get_string_l(streamRawMeta, IJKM_KEY_TYPE); if (type) { fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_CODEC_NAME, NULL ); fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_CODEC_PROFILE, NULL ); fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_CODEC_LONG_NAME, NULL ); fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_BITRATE, NULL ); if (0 == strcmp(type, IJKM_VAL_TYPE__VIDEO)) { fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_WIDTH, NULL ); fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_HEIGHT, NULL ); fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_FPS_NUM, NULL ); fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_FPS_DEN, NULL ); fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_TBR_NUM, NULL ); fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_TBR_DEN, NULL ); fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_SAR_NUM, NULL ); fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_SAR_DEN, NULL ); } else if (0 == strcmp(type, IJKM_VAL_TYPE__AUDIO)) { fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_SAMPLE_RATE, NULL ); fillMetaInternal(env, jstream_bundle, streamRawMeta, IJKM_KEY_CHANNEL_LAYOUT, NULL ); } ASDK_ArrayList__add(env, jarray_list, jstream_bundle); if (SDL_JNI_RethrowException(env)) { goto LABEL_RETURN; } } SDL_JNI_DeleteLocalRefP(env, &jstream_bundle); } } ASDK_Bundle__putParcelableArrayList_c(env, jlocal_bundle, IJKM_KEY_STREAMS, jarray_list); jret_bundle = jlocal_bundle; jlocal_bundle = NULL; LABEL_RETURN: if (is_locked && meta) ijkmeta_unlock(meta); SDL_JNI_DeleteLocalRefP(env, &jstream_bundle); SDL_JNI_DeleteLocalRefP(env, &jlocal_bundle); SDL_JNI_DeleteLocalRefP(env, &jarray_list); ijkmp_dec_ref_p(&mp); return jret_bundle; }
// NOTE: support to be called from read_thread static int inject_callback(void *opaque, int what, void *data, size_t data_size) { JNIEnv *env = NULL; jobject jbundle = NULL; int ret = -1; SDL_JNI_SetupThreadEnv(&env); jobject weak_thiz = (jobject) opaque; if (weak_thiz == NULL ) goto fail; switch (what) { case AVAPP_CTRL_WILL_HTTP_OPEN: case AVAPP_CTRL_WILL_LIVE_OPEN: case AVAPP_CTRL_WILL_CONCAT_SEGMENT_OPEN: { AVAppIOControl *real_data = (AVAppIOControl *)data; real_data->is_handled = 0; jbundle = J4AC_Bundle__Bundle__catchAll(env); if (!jbundle) { ALOGE("%s: J4AC_Bundle__Bundle__catchAll failed for case %d\n", __func__, what); goto fail; } J4AC_Bundle__putString__withCString__catchAll(env, jbundle, "url", real_data->url); J4AC_Bundle__putInt__withCString__catchAll(env, jbundle, "segment_index", real_data->segment_index); J4AC_Bundle__putInt__withCString__catchAll(env, jbundle, "retry_counter", real_data->retry_counter); real_data->is_handled = J4AC_IjkMediaPlayer__onNativeInvoke(env, weak_thiz, what, jbundle); if (J4A_ExceptionCheck__catchAll(env)) { goto fail; } J4AC_Bundle__getString__withCString__asCBuffer(env, jbundle, "url", real_data->url, sizeof(real_data->url)); if (J4A_ExceptionCheck__catchAll(env)) { goto fail; } ret = 0; break; } case AVAPP_EVENT_WILL_HTTP_OPEN: case AVAPP_EVENT_DID_HTTP_OPEN: case AVAPP_EVENT_WILL_HTTP_SEEK: case AVAPP_EVENT_DID_HTTP_SEEK: { AVAppHttpEvent *real_data = (AVAppHttpEvent *) data; jbundle = J4AC_Bundle__Bundle__catchAll(env); if (!jbundle) { ALOGE("%s: J4AC_Bundle__Bundle__catchAll failed for case %d\n", __func__, what); goto fail; } J4AC_Bundle__putString__withCString__catchAll(env, jbundle, "url", real_data->url); J4AC_Bundle__putLong__withCString__catchAll(env, jbundle, "offset", real_data->offset); J4AC_Bundle__putInt__withCString__catchAll(env, jbundle, "error", real_data->error); J4AC_Bundle__putInt__withCString__catchAll(env, jbundle, "http_code", real_data->http_code); J4AC_IjkMediaPlayer__onNativeInvoke(env, weak_thiz, what, jbundle); if (J4A_ExceptionCheck__catchAll(env)) goto fail; ret = 0; break; } case AVAPP_CTRL_DID_TCP_OPEN: case AVAPP_CTRL_WILL_TCP_OPEN: { AVAppTcpIOControl *real_data = (AVAppTcpIOControl *)data; jbundle = J4AC_Bundle__Bundle__catchAll(env); if (!jbundle) { ALOGE("%s: J4AC_Bundle__Bundle__catchAll failed for case %d\n", __func__, what); goto fail; } J4AC_Bundle__putInt__withCString__catchAll(env, jbundle, "error", real_data->error); J4AC_Bundle__putInt__withCString__catchAll(env, jbundle, "family", real_data->family); J4AC_Bundle__putString__withCString__catchAll(env, jbundle, "ip", real_data->ip); J4AC_Bundle__putInt__withCString__catchAll(env, jbundle, "port", real_data->port); J4AC_Bundle__putInt__withCString__catchAll(env, jbundle, "fd", real_data->fd); J4AC_IjkMediaPlayer__onNativeInvoke(env, weak_thiz, what, jbundle); if (J4A_ExceptionCheck__catchAll(env)) goto fail; ret = 0; break; } default: { ret = 0; } } fail: SDL_JNI_DeleteLocalRefP(env, &jbundle); return ret; }