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;}


更多相关文章

  1. Android中工作线程与主线程同步方式
  2. android中调用系统功能 来显示本地相册图片 拍照 视频 音频功能
  3. Android事件分发和View绘制流程分析(三)
  4. Android自动化测试初探(四): 模拟键盘鼠标事件(Socket+Instrumentat
  5. Android手势检测简介
  6. Android调用getSimSerialNumber获取iccid不完整
  7. Android(安卓)Camera调用流程
  8. Android(安卓)无线启动过程分析 无线启动过程分析
  9. android中webView JS调用Android的方法、webView的下拉刷新(Swipe

随机推荐

  1. Android(安卓)USB OTG U盘读写相关使用最
  2. 自定义类似于listView中Item背景
  3. android webview 自定义404错误页面!
  4. 百度地图SDK for Android v2.1.2全新发布
  5. Android中attrs.xml
  6. android中无限循环滑动的gallery实例
  7. Android判断当前设备是否联网
  8. 蓝牙搜索显示结果到ListView(十分精简)
  9. 【Android】设备标识
  10. android插件化研究