美文网首页
从demo分析ijk源码三:IjkMediaPlayer的jni

从demo分析ijk源码三:IjkMediaPlayer的jni

作者: DON_1007 | 来源:发表于2019-12-21 17:44 被阅读0次

    回顾 mac系统 ijk(Android)编译ijk的整个编译过程大致分为下载编译ffmpeg编译ijk编译ffmpeg我们可以得到libijkffmpeg.so编译ijk可以得到libijksdl.solibijkplayer.so,编译ijk的时候需要依赖libijkffmpeg.so,这就是在ijk加载这三个so库的时候,为什么要先加载libijkffmpeg.so的原因。
    下面以moudle ijkplayer-armv7a中的源码学习ijk中的jni实现,ijk c源码位于ijkplayer-armv7a/src/main/jni/目录下

    如上图,jni目录下是c源码,obj目录下存放的是编译之后生成的文件,Android.mk 是提供给NDK编译的脚本。

    一、Android.mk

    LOCAL_PATH := $(call my-dir)
    
    MY_APP_JNI_ROOT := $(realpath $(LOCAL_PATH))
    MY_APP_PRJ_ROOT := $(realpath $(MY_APP_JNI_ROOT)/..)
    MY_APP_ANDROID_ROOT := $(realpath $(MY_APP_PRJ_ROOT)/../../../..)
    
    ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
    MY_APP_FFMPEG_OUTPUT_PATH := $(realpath $(MY_APP_ANDROID_ROOT)/contrib/build/ffmpeg-armv7a/output)
    MY_APP_FFMPEG_INCLUDE_PATH := $(realpath $(MY_APP_FFMPEG_OUTPUT_PATH)/include)
    endif
    ifeq ($(TARGET_ARCH_ABI),armeabi)
    MY_APP_FFMPEG_OUTPUT_PATH := $(realpath $(MY_APP_ANDROID_ROOT)/contrib/build/ffmpeg-armv5/output)
    MY_APP_FFMPEG_INCLUDE_PATH := $(realpath $(MY_APP_FFMPEG_OUTPUT_PATH)/include)
    endif
    ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
    MY_APP_FFMPEG_OUTPUT_PATH := $(realpath $(MY_APP_ANDROID_ROOT)/contrib/build/ffmpeg-arm64/output)
    MY_APP_FFMPEG_INCLUDE_PATH := $(realpath $(MY_APP_FFMPEG_OUTPUT_PATH)/include)
    endif
    ifeq ($(TARGET_ARCH_ABI),x86)
    MY_APP_FFMPEG_OUTPUT_PATH := $(realpath $(MY_APP_ANDROID_ROOT)/contrib/build/ffmpeg-x86/output)
    MY_APP_FFMPEG_INCLUDE_PATH := $(realpath $(MY_APP_FFMPEG_OUTPUT_PATH)/include)
    endif
    ifeq ($(TARGET_ARCH_ABI),x86_64)
    MY_APP_FFMPEG_OUTPUT_PATH := $(realpath $(MY_APP_ANDROID_ROOT)/contrib/build/ffmpeg-x86_64/output)
    MY_APP_FFMPEG_INCLUDE_PATH := $(realpath $(MY_APP_FFMPEG_OUTPUT_PATH)/include)
    endif
    
    include $(call all-subdir-makefiles)
    

    Android.mk通过 include $(call all-subdir-makefiles)调用编译所有子目录的mk文件

    二、ijkplayer_jni.c

    ijkplayer_jni.cAndroid Studio中的路径是
    ijkplayer-android/android/ijkplayer/ijkplayer-armv7a/src/main/jni/ijkmedia/ijkplayer/android/ijkplayer_jni.c,这个路径其实是个软链,其真实存放路径为 ijkplayer-android/ijkmedia/ijkplayer/android/ijkplayer_jni.c

    ijkplayer_jni.c文件中包含所有的在IjkMediaPlayer中定义的native方法的c实现。

    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 },
        { "_setAndroidIOCallback",  "(Ltv/danmaku/ijk/media/player/misc/IAndroidIO;)V", (void *)IjkMediaPlayer_setAndroidIOCallback },
    
        { "_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 },
        { "_setFrameAtTime",        "(Ljava/lang/String;JJII)V", (void *) IjkMediaPlayer_setFrameAtTime },
    };
    
    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;
    }
    
    JNIEXPORT void JNI_OnUnload(JavaVM *jvm, void *reserved)
    {
        ijkmp_global_uninit();
    
        pthread_mutex_destroy(&g_clazz.mutex);
    }
    

    我们可以从这里入手学习ijk是如何调用ffplay实现播放的。

    相关文章

      网友评论

          本文标题:从demo分析ijk源码三:IjkMediaPlayer的jni

          本文链接:https://www.haomeiwen.com/subject/sircnctx.html