BiliBili-IJKPlayer播放器源码分析(一)

首先给大家推荐一下我老师大神的人工智能教学网站。教学不仅零基础,通俗易懂,而且非常风趣幽默,还时不时有内涵黄段子!点这里可以跳转到网站 IJKPlayer是一款基于ffmpeg/ffplay的开源播放器,可支持rtmp/rtsp/hls等多种媒体协议,支持Android/IOS等移动平台。项目地址:https://github.com/Bilibili/ijkplayer,项目地址有可供参考的编译方式。 “Android/iOS video player based on FFmpeg n3.1, with MediaCodec, VideoToolbox support.” IJKPlayer(Android)主要由Java层和JNI层组成,Java层主要负责业务控制,JNI部分主要功能是完成音视频的播放。JNI层向Java层提供接口调用,形成事件任务,同时以回调的形式向Java层推送事件完成的状态通知。 Java层主要包括ijkplayer-exo和ijkplayer-java两个类库,分别代表两个不同的播放器。jikplayer-java里面有IMediaPlayer接口和AbstractMediaPlayer抽象类。所以ijkplayer-exo依赖于ijkplayer-java。 ijkplayer-java的底层JNI基于ffplay。在ffplay里面,通过事件循环来实现流程的控制,ijkplayer-java不同于ffplay的事件循环,采用的是消息队列,但在本质上是一样的。 调用流程图:

JNI提供接口形式:

static JNINativeMethod g_methods[] = {    {        "_setDataSource",        "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V",        (void *) IjkMediaPlayer_setDataSourceAndHeaders    },    { "_setDataSourceFd",       "(I)V",     (void *) IjkMediaPlayer_setDataSourceFd },    { "_setDataSource",         "(Ltv/danmaku/ijk/media/player/misc/IMediaDataSource;)V", (void *)IjkMediaPlayer_setDataSourceCallback },     { "_setVideoSurface",       "(Landroid/view/Surface;)V", (void *) IjkMediaPlayer_setVideoSurface },    { "_prepareAsync",          "()V",      (void *) IjkMediaPlayer_prepareAsync },    { "_start",                 "()V",      (void *) IjkMediaPlayer_start },    { "_stop",                  "()V",      (void *) IjkMediaPlayer_stop },    { "seekTo",                 "(J)V",     (void *) IjkMediaPlayer_seekTo },    { "_pause",                 "()V",      (void *) IjkMediaPlayer_pause },    { "isPlaying",              "()Z",      (void *) IjkMediaPlayer_isPlaying },    { "getCurrentPosition",     "()J",      (void *) IjkMediaPlayer_getCurrentPosition },    { "getDuration",            "()J",      (void *) IjkMediaPlayer_getDuration },    { "_release",               "()V",      (void *) IjkMediaPlayer_release },    { "_reset",                 "()V",      (void *) IjkMediaPlayer_reset },    { "setVolume",              "(FF)V",    (void *) IjkMediaPlayer_setVolume },    { "getAudioSessionId",      "()I",      (void *) IjkMediaPlayer_getAudioSessionId },    { "native_init",            "()V",      (void *) IjkMediaPlayer_native_init },    { "native_setup",           "(Ljava/lang/Object;)V", (void *) IjkMediaPlayer_native_setup },    { "native_finalize",        "()V",      (void *) IjkMediaPlayer_native_finalize },     { "_setOption",             "(ILjava/lang/String;Ljava/lang/String;)V", (void *) IjkMediaPlayer_setOption },    { "_setOption",             "(ILjava/lang/String;J)V",                  (void *) IjkMediaPlayer_setOptionLong },     { "_getColorFormatName",    "(I)Ljava/lang/String;",    (void *) IjkMediaPlayer_getColorFormatName },    { "_getVideoCodecInfo",     "()Ljava/lang/String;",     (void *) IjkMediaPlayer_getVideoCodecInfo },    { "_getAudioCodecInfo",     "()Ljava/lang/String;",     (void *) IjkMediaPlayer_getAudioCodecInfo },    { "_getMediaMeta",          "()Landroid/os/Bundle;",    (void *) IjkMediaPlayer_getMediaMeta },    { "_setLoopCount",          "(I)V",                     (void *) IjkMediaPlayer_setLoopCount },    { "_getLoopCount",          "()I",                      (void *) IjkMediaPlayer_getLoopCount },    { "_getPropertyFloat",      "(IF)F",                    (void *) ijkMediaPlayer_getPropertyFloat },    { "_setPropertyFloat",      "(IF)V",                    (void *) ijkMediaPlayer_setPropertyFloat },    { "_getPropertyLong",       "(IJ)J",                    (void *) ijkMediaPlayer_getPropertyLong },    { "_setPropertyLong",       "(IJ)V",                    (void *) ijkMediaPlayer_setPropertyLong },    { "_setStreamSelected",     "(IZ)V",                    (void *) ijkMediaPlayer_setStreamSelected },     { "native_profileBegin",    "(Ljava/lang/String;)V",    (void *) IjkMediaPlayer_native_profileBegin },    { "native_profileEnd",      "()V",                      (void *) IjkMediaPlayer_native_profileEnd },     { "native_setLogLevel",     "(I)V",                     (void *) IjkMediaPlayer_native_setLogLevel },}; 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);     return JNI_VERSION_1_4;}

点这里可以跳转到人工智能网站