ijkplayer的实现流程

本文详述了ijkplayer的实现流程,从用户点击播放网络视频开始,深入到C语言底层,包括加载so库、设置URI、初始化播放器、分析网络视频源、C底层的函数调用和消息队列等关键步骤。ijkplayer使用了ffmpeg库,并在原基础上扩展,通过JNI调用实现了Android上的视频播放功能。
摘要由CSDN通过智能技术生成

ijkplayer阅读学习笔记之从代码上看播放流程


看了很久的ijkplayer的视频播放,其实还是没有怎么看懂,只是个人浅浅的笔记

关键部分就是联网获取数据那部分,还没有搞定其实

从用户点击一个已有地址的网络视频开始,从源码分析播放流程。

1.        // init player  加载native底层库

        IjkMediaPlayer.loadLibrariesOnce(null);

        IjkMediaPlayer.native_profileBegin("libijkplayer.so");

第一句话是加载三个重要的so文件

libLoader.loadLibrary("ijkffmpeg");

                libLoader.loadLibrary("ijksdl");

                libLoader.loadLibrary("ijkplayer");

第二句话调用了一个native方法public static native void native_profileBegin(String libName);

2.  设置uri,可以是rtmprtsphttp等,native ffplay代码中会根据该uri匹配不同的流媒体协议,具体参考ffplay 支持本地和网络视频。

if (mVideoPath != null)

            mVideoView.setVideoPath(mVideoPath);

        else if (mVideoUri != null)

            mVideoView.setVideoURI(mVideoUri);

3. 分析网络视频源:接着openVideo()

先创建播放器 mMediaPlayer = createPlayer(mSettings.getPlayer());接着是播放器的相关设置

诸如:       mMediaPlayer.setOnPreparedListener(mPreparedListener);

            mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);

            mMediaPlayer.setOnCompletionListener(mCompletionListener);

            mMediaPlayer.setOnErrorListener(mErrorListener);

            mMediaPlayer.setOnInfoListener(mInfoListener);

            mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);

当然,还需要设置播放源,会调用

tv.danmaku.ijk.media.player.IMediaPlayer#setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String,java.lang.String>)

开始播放mVideoView.start();调用tv.danmaku.ijk.media.player.IMediaPlayer#start,这里java层就结束了,进入c底层,其实从加载native底层库开始就进入c底层了

4. 分析c底层:/ijkmedia/ijkplayer/android/ijkplayer_jni.c这个文件里 static JNINativeMethod g_methods[] 一个数组,声明了全部的java层的native方法 ,而调用native的方法集中在类 tv.danmaku.ijk.media.player.IjkMediaPlayer

 

5. 没想到居然是c主动调用java,通过反射生成java端所需要的函数,这个地方不是我们正常JNI的调用思路

正常调用JNI的思路:是通过javah,获取一组带签名函数,然后实现这些函数。这种方法很常用,也是官方推荐的方法。

分析一下JNI运行时机制:

当在系统中调用System.loadLibrary函数时,该函数会找到对应的动态库,然后首先试图找到"JNI_OnLoad"函数,如果该函数存在,则调用它。
JNI_OnLoad可以和JNIEnvregisterNatives函数结合起来,实现动态的函数替换。很显然ijk的作者是使用的这种调用方式

在 ijkplayer-sample/src/main/jni/ijkmedia/ijkplayer/android/ijkplayer_jni.c

 


 

然后在JNI_OnLoad 初始化好多内容,比如上图三个 global 型的函数

这样就可以理解作者为什么一开始就先调用三个 so 文件了

ijkplayer-sample/src/main/jni/ijkmedia/ijksdl/android/ijksdl_android_jni.c里也有JNI_OnLoad

Ffmpeg的个人感觉是不需要,因为作者直接使用的ffmpeg的代码,只需要正常引入就好。

 

6. J4a里生成的两个java文件也是很重要的类

 

目前还不清楚作用

7. ijkplayer-sample/src/main/jni/ijkmedia/ijkplayer/ff_ffplay_def.h  这个定义了ijk播放器核心数据结构体的类,作者是直接使用的ffmpegijkplayer-sample/src/main/jni/ffmpeg/ffplay.cffmpeg的文件的基础上的扩展,里面引用了很多ffmpeg的源文件。基本上就不需要关心ffmpeg的源代码了。

8. 这里只分析libijkplayer.so

8.1  ijkmp_global_init 在 ijkplayer-sample/src/main/jni/ijkmedia/ijkplayer/ijkplayer.c

void ijkmp_global_init()

{

     ffp_global_init();

}

ffp_global_init() 

ijkplayer-sample/src/main/jni/ijkmedia/ijkplayer/ijkplayer_internal.hinclude

ijkplayer-sample/src/main/jni/ijkmedia/ijkplayer/ff_ffplay.h里,具体定义代码在

ijkplayer-sample/src/main/jni/ijkmedia/ijkplayer/ff_ffplay.c中,主要是ffmpeg的初始化工作。

8.2 ijkmp_global_set_inject_callback(inject_callback)是在

ijkplayer-sample/src/main/jni/ijkmedia/ijkplayer/ijkplayer.cinclude

ijkplayer-sample/src/main/jni/ijkmedia/ijkplayer/ijkavformat/ijkavformat.h里声明,

ijkplayer-sample/src/main/jni/ijkmedia/ijkplayer/ijkavformat/utils.c里定义

这里使用最多的是ijkavformat.h里的

typedef int (*IjkAVInjectCallback)(void *opaque, int message, void *data, size_t data_size);

这个声明引入了 IjkAVInjectCallback 类型作为函数指针的同义字,该函数有四个不同 类型的参数以及一个 int 类型的返回值

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值