struct IJKFF_Pipenode *node_vdec;
struct IJKFF_Pipenode {
SDL_mutex *mutex;
void *opaque;
void (*func_destroy) (IJKFF_Pipenode *node);
int (*func_run_sync)(IJKFF_Pipenode *node);
int (*func_flush) (IJKFF_Pipenode *node); // optional
};
通过ijkplayer源码---解码(decode)_qq_15255121的专栏-CSDN博客 我们大致了解到node_vdec就是解码器
static int stream_component_open(FFPlayer *ffp, int stream_index)
{
case AVMEDIA_TYPE_VIDEO:
is->video_stream = stream_index;
is->video_st = ic->streams[stream_index];
if (ffp->async_init_decoder) {
while (!is->initialized_decoder) {
SDL_Delay(5);
}
if (ffp->node_vdec) {
is->viddec.avctx = avctx;
ret = ffpipeline_config_video_decoder(ffp->pipeline, ffp);
}
if (ret || !ffp->node_vdec) {
decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread);
ffp->node_vdec = ffpipeline_open_video_decoder(ffp->pipeline, ffp);
if (!ffp->node_vdec)
goto fail;
}
} else {
decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread);
ffp->node_vdec = ffpipeline_open_video_decoder(ffp->pipeline, ffp);
if (!ffp->node_vdec)
goto fail;
}
}
通过上面我们知道ffp->node_vdec = ffpipeline_open_video_decoder(ffp->pipeline, ffp);
IJKFF_Pipenode* ffpipeline_open_video_decoder(IJKFF_Pipeline *pipeline, FFPlayer *ffp)
{
return pipeline->func_open_video_decoder(pipeline, ffp);
}
static IJKFF_Pipenode *func_open_video_decoder(IJKFF_Pipeline *pipeline, FFPlayer *ffp)
{
IJKFF_Pipeline_Opaque *opaque = pipeline->opaque;
IJKFF_Pipenode *node = NULL;
if (ffp->mediacodec_all_videos || ffp->mediacodec_avc || ffp->mediacodec_hevc || ffp->mediacodec_mpeg2)
node = ffpipenode_create_video_decoder_from_android_mediacodec(ffp, pipeline, opaque->weak_vout);
if (!node) {
node = ffpipenode_create_video_decoder_from_ffplay(ffp);
}
return node;
}
通过这篇文章ijkplayer源码---FFPlayer结构体5 IJKFF_Pipeline_qq_15255121的专栏-CSDN博客 我们可以知道node_vdec就是视频解码器
char *video_codec_info;
char *audio_codec_info;
char *subtitle_codec_info;
void ffp_set_video_codec_info(FFPlayer *ffp, const char *module, const char *codec)
{
av_freep(&ffp->video_codec_info);
ffp->video_codec_info = av_asprintf("%s, %s", module ? module : "", codec ? codec : "");
av_log(ffp, AV_LOG_INFO, "VideoCodec: %s\n", ffp->video_codec_info);
}
void ffp_set_audio_codec_info(FFPlayer *ffp, const char *module, const char *codec)
{
av_freep(&ffp->audio_codec_info);
ffp->audio_codec_info = av_asprintf("%s, %s", module ? module : "", codec ? codec : "");
av_log(ffp, AV_LOG_INFO, "AudioCodec: %s\n", ffp->audio_codec_info);
}
void ffp_set_subtitle_codec_info(FFPlayer *ffp, const char *module, const char *codec)
{
av_freep(&ffp->subtitle_codec_info);
ffp->subtitle_codec_info = av_asprintf("%s, %s", module ? module : "", codec ? codec : "");
av_log(ffp, AV_LOG_INFO, "SubtitleCodec: %s\n", ffp->subtitle_codec_info);
}
IJKFF_Pipenode *ffpipenode_create_video_decoder_from_android_mediacodec(FFPlayer *ffp, IJKFF_Pipeline *pipeline, SDL_Vout *vout){
.....
ffp_set_video_codec_info(ffp, MEDIACODEC_MODULE_NAME, opaque->mcc.codec_name);
.....
}
opaque->mcc.codec_name从哪里来的呢?
static IJKFF_Pipenode *func_open_video_decoder(IJKFF_Pipeline *pipeline, FFPlayer *ffp)
{
IJKFF_Pipeline_Opaque *opaque = pipeline->opaque;
IJKFF_Pipenode *node = NULL;
if (ffp->mediacodec_all_videos || ffp->mediacodec_avc || ffp->mediacodec_hevc || ffp->mediacodec_mpeg2)
node = ffpipenode_create_video_decoder_from_android_mediacodec(ffp, pipeline, opaque->weak_vout);
if (!node) {
node = ffpipenode_create_video_decoder_from_ffplay(ffp);
}
return node;
}
IJKFF_Pipenode *ffpipenode_create_video_decoder_from_android_mediacodec(FFPlayer *ffp, IJKFF_Pipeline *pipeline, SDL_Vout *vout)
{
IJKFF_Pipenode *node = ffpipenode_alloc(sizeof(IJKFF_Pipenode_Opaque));
opaque->mcc.profile = opaque->codecpar->profile;
opaque->mcc.level = opaque->codecpar->level;
if (!ffpipeline_select_mediacodec_l(pipeline, &opaque->mcc) || !opaque->mcc.codec_name[0]) {
ALOGE("amc: no suitable codec\n");
goto fail;
}
ffp_set_video_codec_info(ffp, MEDIACODEC_MODULE_NAME, opaque->mcc.codec_name);
}
bool ffpipeline_select_mediacodec_l(IJKFF_Pipeline* pipeline, ijkmp_mediacodecinfo_context *mcc)
{
ALOGD("%s\n", __func__);
if (!check_ffpipeline(pipeline, __func__))
return false;
if (!mcc || !pipeline->opaque->mediacodec_select_callback)
return false;
return pipeline->opaque->mediacodec_select_callback(pipeline->opaque->mediacodec_select_callback_opaque, mcc);
}
通过https://blog.csdn.net/qq_15255121/article/details/123280252?spm=1001.2014.3001.5502
我们知道上层调用了
public static class DefaultMediaCodecSelector implements OnMediaCodecSelectListener {
public static final DefaultMediaCodecSelector sInstance = new DefaultMediaCodecSelector();
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public String onMediaCodecSelect(IMediaPlayer mp, String mimeType, int profile, int level) {
以及下面的赋值代码
#define J4AC_IjkMediaPlayer__onSelectCodec__withCString__asCBuffer J4AC_tv_danmaku_ijk_media_player_IjkMediaPlayer__onSelectCodec__withCString__asCBuffer
const char *J4AC_tv_danmaku_ijk_media_player_IjkMediaPlayer__onSelectCodec__withCString__asCBuffer(JNIEnv *env, jobject weakThiz, const char *mimeType_cstr__, jint profile, jint level, char *out_buf, int out_len)
{
const char *ret_value = NULL;
const char *c_str = NULL;
jstring local_string = J4AC_tv_danmaku_ijk_media_player_IjkMediaPlayer__onSelectCodec__withCString(env, weakThiz, mimeType_cstr__, profile, level);
if (J4A_ExceptionCheck__throwAny(env) || !local_string) {
goto fail;
}
c_str = (*env)->GetStringUTFChars(env, local_string, NULL );
if (J4A_ExceptionCheck__throwAny(env) || !c_str) {
goto fail;
}
strlcpy(out_buf, c_str, out_len);
ret_value = out_buf;
fail:
J4A_ReleaseStringUTFChars__p(env, local_string, &c_str);
J4A_DeleteLocalRef__p(env, &local_string);
return ret_value;
}
out_buf就是我们我们的mcc.codec_name
audio和subtitle相对比较简单
#define AVCODEC_MODULE_NAME "avcodec"
ffp_set_audio_codec_info(ffp, AVCODEC_MODULE_NAME, avcodec_get_name(avctx->codec_id));
ffp_set_subtitle_codec_info(ffp, AVCODEC_MODULE_NAME, avcodec_get_name(avctx->codec_id));
|