ijkplayer分析一:初始化

new IjkMediaPlayer();

IjkMediaPlayer.java中初始化方法:

public IjkMediaPlayer() {
   this(sLocalLibLoader);
}

調(diào)用

public IjkMediaPlayer(IjkLibLoader libLoader) {
    //初始化player
    initPlayer(libLoader);
}
private void initPlayer(IjkLibLoader libLoader) {
    loadLibrariesOnce(libLoader);//加載native庫划提,注冊靜態(tài)方法
    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:
當(dāng)去加載native庫時(shí)描焰,會調(diào)用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) );//注冊靜態(tài)方法
    ijkmp_global_init();//注冊編解碼器汁果,網(wǎng)絡(luò)一些初始化工作
    ijkmp_global_set_inject_callback(inject_callback);//設(shè)置回調(diào)
    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();//注冊設(shè)備
#endif
#if CONFIG_AVFILTER
    avfilter_register_all();//注冊濾鏡,用于圖像處理巫延,音頻重采樣處理等
#endif
    av_register_all();//注冊沟饥,包括編解碼器以及網(wǎng)絡(luò)其他等
    ijkav_register_all();//注冊網(wǎng)絡(luò)協(xié)議
    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);//創(chuàng)建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釋放掉珠叔,設(shè)置新的player
    ijkmp_set_weak_thiz(mp, (*env)->NewGlobalRef(env, weak_this));//設(shè)置全局弱引用player
    ijkmp_set_inject_opaque(mp, ijkmp_get_weak_thiz(mp));//設(shè)置AVApplication
    ijkmp_set_ijkio_inject_opaque(mp, ijkmp_get_weak_thiz(mp));//設(shè)置io
    ijkmp_android_set_mediacodec_select_callback(mp, mediacodec_select_callback, ijkmp_get_weak_thiz(mp));//設(shè)置編碼回調(diào)

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*))
{
    //創(chuàng)建播放器
    IjkMediaPlayer *mp = ijkmp_create(msg_loop);
    if (!mp)
        goto fail;
    //創(chuàng)建渲染輸出對象
    mp->ffplayer->vout = SDL_VoutAndroid_CreateForAndroidSurface();
    if (!mp->ffplayer->vout)
        goto fail;
    //創(chuàng)建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;
}

涉及到到結(jié)構(gòu)體:
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結(jié)構(gòu)體镶摘,在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;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市岳守,隨后出現(xiàn)的幾起案子凄敢,更是在濱河造成了極大的恐慌,老刑警劉巖湿痢,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涝缝,死亡現(xiàn)場離奇詭異,居然都是意外死亡譬重,警方通過查閱死者的電腦和手機(jī)拒逮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來臀规,“玉大人滩援,你說我怎么就攤上這事∫韵郑” “怎么了狠怨?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵约啊,是天一觀的道長邑遏。 經(jīng)常有香客問我,道長恰矩,這世上最難降的妖魔是什么记盒? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮外傅,結(jié)果婚禮上纪吮,老公的妹妹穿的比我還像新娘。我一直安慰自己萎胰,他們只是感情好碾盟,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著技竟,像睡著了一般冰肴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上榔组,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天熙尉,我揣著相機(jī)與錄音,去河邊找鬼搓扯。 笑死检痰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的锨推。 我是一名探鬼主播铅歼,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼公壤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谭贪?” 一聲冷哼從身側(cè)響起境钟,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎俭识,沒想到半個(gè)月后慨削,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡套媚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年缚态,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堤瘤。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡玫芦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出本辐,到底是詐尸還是另有隱情桥帆,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布慎皱,位于F島的核電站老虫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏茫多。R本人自食惡果不足惜祈匙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望天揖。 院中可真熱鬧夺欲,春花似錦、人聲如沸今膊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽斑唬。三九已至市埋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間赖钞,已是汗流浹背腰素。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留雪营,地道東北人弓千。 一個(gè)月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像献起,于是被迫代替她去往敵國和親洋访。 傳聞我的和親對象是個(gè)殘疾皇子镣陕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348