我们在ff_ffplay_options.h中可以看到我们可以设置的选项
// Android only options
{ "mediacodec", "MediaCodec: enable H264 (deprecated by 'mediacodec-avc')",
OPTION_OFFSET(mediacodec_avc), OPTION_INT(0, 0, 1) },
{ "mediacodec-auto-rotate", "MediaCodec: auto rotate frame depending on meta",
OPTION_OFFSET(mediacodec_auto_rotate), OPTION_INT(0, 0, 1) },
{ "mediacodec-all-videos", "MediaCodec: enable all videos",
OPTION_OFFSET(mediacodec_all_videos), OPTION_INT(0, 0, 1) },
{ "mediacodec-avc", "MediaCodec: enable H264",
OPTION_OFFSET(mediacodec_avc), OPTION_INT(0, 0, 1) },
{ "mediacodec-hevc", "MediaCodec: enable HEVC",
OPTION_OFFSET(mediacodec_hevc), OPTION_INT(0, 0, 1) },
{ "mediacodec-mpeg2", "MediaCodec: enable MPEG2VIDEO",
OPTION_OFFSET(mediacodec_mpeg2), OPTION_INT(0, 0, 1) },
{ "mediacodec-mpeg4", "MediaCodec: enable MPEG4",
OPTION_OFFSET(mediacodec_mpeg4), OPTION_INT(0, 0, 1) },
{ "mediacodec-handle-resolution-change", "MediaCodec: handle resolution change automatically",
OPTION_OFFSET(mediacodec_handle_resolution_change), OPTION_INT(0, 0, 1) },
{ "opensles", "OpenSL ES: enable",
OPTION_OFFSET(opensles), OPTION_INT(0, 0, 1) },
{ "soundtouch", "SoundTouch: enable",
OPTION_OFFSET(soundtouch_enable), OPTION_INT(0, 0, 1) },
{ "mediacodec-sync", "mediacodec: use msg_queue for synchronise",
OPTION_OFFSET(mediacodec_sync), OPTION_INT(0, 0, 1) },
{ "mediacodec-default-name", "mediacodec default name",
OPTION_OFFSET(mediacodec_default_name), OPTION_STR(NULL) },
{ "ijkmeta-delay-init", "ijkmeta delay init",
OPTION_OFFSET(ijkmeta_delay_init), OPTION_INT(0, 0, 1) },
{ "render-wait-start", "render wait start",
OPTION_OFFSET(render_wait_start), OPTION_INT(0, 0, 1) },
{ NULL }
比如我们要对所有的视频实行硬解码
我们去设置
{ "mediacodec-all-videos", "MediaCodec: enable all videos", OPTION_OFFSET(mediacodec_all_videos), OPTION_INT(0, 0, 1) },
我们这样设置
mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-all-videos", 1);
private native void _setOption(int category, String name, String value);
private native void _setOption(int category, String name, long value);
ijkplayer_jni.c
{ "_setOption", "(ILjava/lang/String;Ljava/lang/String;)V", (void *) IjkMediaPlayer_setOption },
{ "_setOption", "(ILjava/lang/String;J)V", (void *) IjkMediaPlayer_setOptionLong },
static void
IjkMediaPlayer_setOption(JNIEnv *env, jobject thiz, jint category, jobject name, jobject value)
{
MPTRACE("%s\n", __func__);
IjkMediaPlayer *mp = jni_get_media_player(env, thiz);
const char *c_name = NULL;
const char *c_value = NULL;
JNI_CHECK_GOTO(mp, env, "java/lang/IllegalStateException", "mpjni: setOption: null mp", LABEL_RETURN);
if (!name) {
goto LABEL_RETURN;
}
c_name = (*env)->GetStringUTFChars(env, name, NULL );
JNI_CHECK_GOTO(c_name, env, "java/lang/OutOfMemoryError", "mpjni: setOption: name.string oom", LABEL_RETURN);
JNI_CHECK_GOTO(mp, env, NULL, "mpjni: IjkMediaPlayer_setOption: null name", LABEL_RETURN);
if (value) {
c_value = (*env)->GetStringUTFChars(env, value, NULL );
JNI_CHECK_GOTO(c_name, env, "java/lang/OutOfMemoryError", "mpjni: setOption: name.string oom", LABEL_RETURN);
}
ijkmp_set_option(mp, category, c_name, c_value);
LABEL_RETURN:
if (c_name)
(*env)->ReleaseStringUTFChars(env, name, c_name);
if (c_value)
(*env)->ReleaseStringUTFChars(env, value, c_value);
ijkmp_dec_ref_p(&mp);
}
static void
IjkMediaPlayer_setOptionLong(JNIEnv *env, jobject thiz, jint category, jobject name, jlong value)
{
MPTRACE("%s\n", __func__);
IjkMediaPlayer *mp = jni_get_media_player(env, thiz);
const char *c_name = NULL;
JNI_CHECK_GOTO(mp, env, "java/lang/IllegalStateException", "mpjni: setOptionLong: null mp", LABEL_RETURN);
c_name = (*env)->GetStringUTFChars(env, name, NULL );
JNI_CHECK_GOTO(c_name, env, "java/lang/OutOfMemoryError", "mpjni: setOptionLong: name.string oom", LABEL_RETURN);
av_log(NULL, AV_LOG_ERROR, "yuanxuzhen IjkMediaPlayer_setOptionLong category=%d, name=%s, value=%lu", category, c_name, value);
ijkmp_set_option_int(mp, category, c_name, value);
LABEL_RETURN:
if (c_name)
(*env)->ReleaseStringUTFChars(env, name, c_name);
ijkmp_dec_ref_p(&mp);
}
void ijkmp_set_option_int(IjkMediaPlayer *mp, int opt_category, const char *name, int64_t value)
{
assert(mp);
// MPTRACE("%s(%s, %"PRId64")\n", __func__, name, value);
pthread_mutex_lock(&mp->mutex);
ffp_set_option_int(mp->ffplayer, opt_category, name, value);
pthread_mutex_unlock(&mp->mutex);
// MPTRACE("%s()=void\n", __func__);
}
void ffp_set_option_int(FFPlayer *ffp, int opt_category, const char *name, int64_t value)
{
if (!ffp)
return;
AVDictionary **dict = ffp_get_opt_dict(ffp, opt_category);
av_dict_set_int(dict, name, value, 0);
av_log(NULL, AV_LOG_ERROR, "yuanxuzhen ffp_set_option_int name=%s ffp->mediacodec_all_videos=%d",name, ffp->mediacodec_all_videos);
}
static AVDictionary **ffp_get_opt_dict(FFPlayer *ffp, int opt_category)
{
assert(ffp);
switch (opt_category) {
case FFP_OPT_CATEGORY_FORMAT: return &ffp->format_opts;
case FFP_OPT_CATEGORY_CODEC: return &ffp->codec_opts;
case FFP_OPT_CATEGORY_SWS: return &ffp->sws_dict;
case FFP_OPT_CATEGORY_PLAYER: return &ffp->player_opts;
case FFP_OPT_CATEGORY_SWR: return &ffp->swr_opts;
default:
av_log(ffp, AV_LOG_ERROR, "unknown option category %d\n", opt_category);
return NULL;
}
}
我们设置语句是setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-all-videos", 1);
可以知道最后设置到了FFPlayer中的player_opts
那么player_opts什么时候又设置到了FFPlayer
int ffp_prepare_async_l(FFPlayer *ffp, const char *file_name)
{
av_opt_set_dict(ffp, &ffp->player_opts);
}
av_opt_set_dict就将player_opts设置到了FFPlayer中了,将
{ "mediacodec-all-videos", "MediaCodec: enable all videos", OPTION_OFFSET(mediacodec_all_videos), OPTION_INT(0, 0, 1) },
mediacodec_all_videos设置为了1.
这里要注意下面的设置语句是相等的
setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-all-videos", 1);
setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-all-videos", "1");