ijkplayer分析一:初始化

2019-01-16  本文已影响0人  九流程序员_風
new IjkMediaPlayer();

IjkMediaPlayer.java中初始化方法:

public IjkMediaPlayer() {
   this(sLocalLibLoader);
}

调用

public IjkMediaPlayer(IjkLibLoader libLoader) {
    //初始化player
    initPlayer(libLoader);
}
private void initPlayer(IjkLibLoader libLoader) {
    loadLibrariesOnce(libLoader);//加载native库,注册静态方法
    initNativeOnce();
    Looper looper;
    if ((looper = Looper.myLooper()) !=null) {
        mEventHandler =new EventHandler(this, looper);
    }else if ((looper = Looper.getMainLooper()) !=null) {
        mEventHandler =new EventHandler(this, looper);
    }else {
        mEventHandler =null;
    }
    native_setup(new WeakReference<IjkMediaPlayer>(this));//弱引用给到native层用
}

加载native库

public static void loadLibrariesOnce(IjkLibLoader libLoader) {
    synchronized (IjkMediaPlayer.class) {
        if (!mIsLibLoaded) {
            if (libLoader ==null)
                libLoader =sLocalLibLoader;
                libLoader.loadLibrary("ijkffmpeg");
                libLoader.loadLibrary("ijksdl");
                libLoader.loadLibrary("ijkplayer");
                mIsLibLoaded =true;
        }
    }
}

ijkplayer_jni.c:
当去加载native库时,会调用JNI_OnLoad方法:

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved){
    JNIEnv* env = NULL;
    g_jvm = vm;
    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        return -1;
    }
    assert(env != NULL);
    pthread_mutex_init(&g_clazz.mutex, NULL );
    // FindClass returns LocalReference
    IJK_FIND_JAVA_CLASS(env, g_clazz.clazz, JNI_CLASS_IJKPLAYER);
    (*env)->RegisterNatives(env, g_clazz.clazz, g_methods, NELEM(g_methods) );//注册静态方法
    ijkmp_global_init();//注册编解码器,网络一些初始化工作
    ijkmp_global_set_inject_callback(inject_callback);//设置回调
    FFmpegApi_global_init(env);//注册base64编码方法
    return JNI_VERSION_1_4;
}

ijkplayer.c: ijkmp_global_init():

void ijkmp_global_init()
{
    ffp_global_init();
}

ff_ffplayer.c : ffp_global_init():

void ffp_global_init(){
    if (g_ffmpeg_global_inited)//如果初始过了,返回
        return;
    ALOGD("ijkmediaplayer version : %s", ijkmp_version());
    /* register all codecs, demux and protocols */
    avcodec_register_all();//注册编解码器
#if CONFIG_AVDEVICE
    avdevice_register_all();//注册设备
#endif
#if CONFIG_AVFILTER
    avfilter_register_all();//注册滤镜,用于图像处理,音频重采样处理等
#endif
    av_register_all();//注册,包括编解码器以及网络其他等
    ijkav_register_all();//注册网络协议
    avformat_network_init();
    av_lockmgr_register(lockmgr);
    av_log_set_callback(ffp_log_callback_brief);
    av_init_packet(&flush_pkt);
    flush_pkt.data = (uint8_t *)&flush_pkt;
    g_ffmpeg_global_inited =true;
}

native_setup(new WeakReference<IjkMediaPlayer>(this));
ijkplayer_jni.c:IjkMediaPlayer_native_setup();

static void IjkMediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
{
    MPTRACE("%s\n", __func__);
    IjkMediaPlayer *mp = ijkmp_android_create(message_loop);//创建IjkMediaPlayer指针
    JNI_CHECK_GOTO(mp, env, "java/lang/OutOfMemoryError", "mpjni: native_setup: ijkmp_create() failed", LABEL_RETURN);

    jni_set_media_player(env, thiz, mp);//把旧的player释放掉,设置新的player
    ijkmp_set_weak_thiz(mp, (*env)->NewGlobalRef(env, weak_this));//设置全局弱引用player
    ijkmp_set_inject_opaque(mp, ijkmp_get_weak_thiz(mp));//设置AVApplication
    ijkmp_set_ijkio_inject_opaque(mp, ijkmp_get_weak_thiz(mp));//设置io
    ijkmp_android_set_mediacodec_select_callback(mp, mediacodec_select_callback, ijkmp_get_weak_thiz(mp));//设置编码回调

LABEL_RETURN:
    ijkmp_dec_ref_p(&mp);
}

IjkMediaPlayer *mp = ijkmp_android_create(message_loop)
ijkplayer_android.c:

IjkMediaPlayer *ijkmp_android_create(int(*msg_loop)(void*))
{
    //创建播放器
    IjkMediaPlayer *mp = ijkmp_create(msg_loop);
    if (!mp)
        goto fail;
    //创建渲染输出对象
    mp->ffplayer->vout = SDL_VoutAndroid_CreateForAndroidSurface();
    if (!mp->ffplayer->vout)
        goto fail;
    //创建pipeline,视频编解码器,音频输出
    mp->ffplayer->pipeline = ffpipeline_create_from_android(mp->ffplayer);
    if (!mp->ffplayer->pipeline)
        goto fail;

    ffpipeline_set_vout(mp->ffplayer->pipeline, mp->ffplayer->vout);

    return mp;

fail:
    ijkmp_dec_ref_p(&mp);
    return NULL;
}

IjkMediaPlayer *mp = ijkmp_create(msg_loop);
ijkplayer.c

IjkMediaPlayer *ijkmp_create(int (*msg_loop)(void*))
{
    IjkMediaPlayer *mp = (IjkMediaPlayer *) mallocz(sizeof(IjkMediaPlayer));
    if (!mp)
        goto fail;
    mp->ffplayer = ffp_create();
    if (!mp->ffplayer)
        goto fail;

    mp->msg_loop = msg_loop;

    ijkmp_inc_ref(mp);
    pthread_mutex_init(&mp->mutex, NULL);

    return mp;

    fail:
    ijkmp_destroy_p(&mp);
    return NULL;
}

mp->ffplayer = ffp_create();
ff_ffplay.c:

FFPlayer *ffp_create()
{
    av_log(NULL, AV_LOG_INFO, "av_version_info: %s\n", av_version_info());
    av_log(NULL, AV_LOG_INFO, "ijk_version_info: %s\n", ijk_version_info());

    FFPlayer* ffp = (FFPlayer*) av_mallocz(sizeof(FFPlayer));
    if (!ffp)
        return NULL;

    msg_queue_init(&ffp->msg_queue);
    ffp->af_mutex = SDL_CreateMutex();
    ffp->vf_mutex = SDL_CreateMutex();

    ffp_reset_internal(ffp);
    ffp->av_class = &ffp_context_class;
    ffp->meta = ijkmeta_create();

    av_opt_set_defaults(ffp);

    return ffp;
}

涉及到到结构体:
IjkMediaPlayer,在ijkplayer_internal.h中:

struct IjkMediaPlayer {
    volatile int ref_count;
    pthread_mutex_t mutex;
    FFPlayer *ffplayer;

    int (*msg_loop)(void*);
    SDL_Thread *msg_thread;
    SDL_Thread _msg_thread;

    int mp_state;
    char *data_source;
    void *weak_thiz;

    int restart;
    int restart_from_beginning;
    int seek_req;
    long seek_msec;
};

FFPlayer结构体,在ff_ffplay_def.h中:

typedef struct FFPlayer {
    const AVClass *av_class;

    /* ffplay context */
    VideoState *is;

    /* format/codec options */
    AVDictionary *format_opts;
    AVDictionary *codec_opts;
    AVDictionary *sws_dict;
    AVDictionary *player_opts;
    AVDictionary *swr_opts;
    AVDictionary *swr_preset_opts;

    /* ffplay options specified by the user */
#ifdef FFP_MERGE
    AVInputFormat *file_iformat;
#endif
    char *input_filename;
#ifdef FFP_MERGE
    const char *window_title;
    int fs_screen_width;
    int fs_screen_height;
    int default_width;
    int default_height;
    int screen_width;
    int screen_height;
#endif
    int audio_disable;
    int video_disable;
    int subtitle_disable;
    const char* wanted_stream_spec[AVMEDIA_TYPE_NB];
    int seek_by_bytes;
    int display_disable;
    int show_status;
    int av_sync_type;
    int64_t start_time;
    int64_t duration;
    int fast;
    int genpts;
    int lowres;
    int decoder_reorder_pts;
    int autoexit;
#ifdef FFP_MERGE
    int exit_on_keydown;
    int exit_on_mousedown;
#endif
    int loop;
    int framedrop;
    int64_t seek_at_start;
    int subtitle;
    int infinite_buffer;
    enum ShowMode show_mode;
    char *audio_codec_name;
    char *subtitle_codec_name;
    char *video_codec_name;
    double rdftspeed;
#ifdef FFP_MERGE
    int64_t cursor_last_shown;
    int cursor_hidden;
#endif
#if CONFIG_AVFILTER
    const char **vfilters_list;
    int nb_vfilters;
    char *afilters;
    char *vfilter0;
#endif
    int autorotate;
    int find_stream_info;
    unsigned sws_flags;

    /* current context */
#ifdef FFP_MERGE
    int is_full_screen;
#endif
    int64_t audio_callback_time;
#ifdef FFP_MERGE
    SDL_Surface *screen;
#endif

    /* extra fields */
    SDL_Aout *aout;
    SDL_Vout *vout;
    struct IJKFF_Pipeline *pipeline;
    struct IJKFF_Pipenode *node_vdec;
    int sar_num;
    int sar_den;

    char *video_codec_info;
    char *audio_codec_info;
    char *subtitle_codec_info;
    Uint32 overlay_format;

    int last_error;
    int prepared;
    int auto_resume;
    int error;
    int error_count;
    int start_on_prepared;
    int first_video_frame_rendered;
    int first_audio_frame_rendered;
    int sync_av_start;

    MessageQueue msg_queue;

    int64_t playable_duration_ms;

    int packet_buffering;
    int pictq_size;
    int max_fps;
    int startup_volume;

    int videotoolbox;
    int vtb_max_frame_width;
    int vtb_async;
    int vtb_wait_async;
    int vtb_handle_resolution_change;

    int mediacodec_all_videos;
    int mediacodec_avc;
    int mediacodec_hevc;
    int mediacodec_mpeg2;
    int mediacodec_mpeg4;
    int mediacodec_handle_resolution_change;
    int mediacodec_auto_rotate;

    int opensles;
    int soundtouch_enable;

    char *iformat_name;

    int no_time_adjust;
    double preset_5_1_center_mix_level;

    struct IjkMediaMeta *meta;

    SDL_SpeedSampler vfps_sampler;
    SDL_SpeedSampler vdps_sampler;

    /* filters */
    SDL_mutex  *vf_mutex;
    SDL_mutex  *af_mutex;
    int         vf_changed;
    int         af_changed;
    float       pf_playback_rate;
    int         pf_playback_rate_changed;
    float       pf_playback_volume;
    int         pf_playback_volume_changed;

    void               *inject_opaque;
    void               *ijkio_inject_opaque;
    FFStatistic         stat;
    FFDemuxCacheControl dcc;

    AVApplicationContext *app_ctx;
    IjkIOManagerContext *ijkio_manager_ctx;

    int enable_accurate_seek;
    int accurate_seek_timeout;
    int mediacodec_sync;
    int skip_calc_frame_rate;
    int get_frame_mode;
    GetImgInfo *get_img_info;
    int async_init_decoder;
    char *video_mime_type;
    char *mediacodec_default_name;
    int ijkmeta_delay_init;
    int render_wait_start;
}
上一篇下一篇

猜你喜欢

热点阅读