在UI界面层中会存在一个关键的函数:
int message_loop(void *arg)
该函数用来处理接收到的消息并执行相应的操作
UI与播放器核心直接交互的方式有以下几种方式:
1.UI直接调用IjkMediaPlayer的接口
2.UI发送消息给消息循环线程,然后调用IjkMediaPlayer的接口
3.IjkMediaPlayer发消息给消息循环线程,线程调用UI的接口
之前提到过部分消息是UI和IjkMediaPlayer都有处理,部分消息只是IjkMediaPlayer要处理。例如:
本篇文章主要介绍IjkMediaPlayer的主要接口:
ijkmp_create
ijkmp_destroy
ijkmp_prepare_async
ijkmp_start
ijkmp_stop
首先当用户点下播放按钮的时候,之前提到过会调用IjkMediaPlayer的接口:
ijkmp_create,ijkmp_destroy,ijkmp_prepare_async
然后等待消息MP_STATE_PREPARED再调用ijkmp_start启动播放
用户点击停止
先调用ijkmp_stop
再调用ijkmp_destroy
下面介绍一下接口的主要作用:
ijkmp_create:
ijkmp_destroy:
在总多接口中最重要的就是ijkmp_prepare_async
下面详细介绍一下该接口:
1.状态设置为MP_STATE_ASYNC_PREPARING(正在准备中),那么什么时候状态会转化为MP_STATE_PREPARED(已经准备完成)
在之后讲到的FFPlayer类中会有一个read_thread线程,用来解复用分析完码流情况,初始化对应的解码器,音视频输出,先调用toggle_pause设置为暂停播放的状态,然后发送FFP_MSG_PREPARED。
在IjkMediaPlayer类中收到FFP_MSG_PREPARED这个消息后,会把状态转化为MP_STATE_PREPARED。
在UI收到FFP_MSG_PREPARED消息后,调用IjkMediaPlayer的start接口,开始正常的播放视频。
2.启动消息队列msg_queue_start
3.创建msg_loop线程
4.调用FFplayer类中prepare_async_l
在ffplayer类中该函数也是极为关键的函数,其主要流程如下
a.调用stream_open函数,该函数包含以下的流程:
分配VideoState
保存filename到VideoState
帧初始化和包初始化
创建continue_read_thread解复用读取线程条件变量
时钟初始化
设置音量
创建视频刷新线程video_refresh_thread
创建数据读取线程read_thread(读取线程等到ffplayer类中再讲)
b.保存filename
ijkmp_start
ijkmp_stop
下面实现IjkMediaPlayer类
IjkMediaPlayer类成员变量:
// 互斥量
std::mutex mutex_;
// 真正的播放器
FFPlayer *ffplayer_ = NULL;
//函数指针, 指向创建的message_loop,即消息循环函数
// int (*msg_loop)(void*);
std::function<int(void *)> msg_loop_ = NULL; // ui处理消息的循环
//消息机制线程
std::thread *msg_thread_; // 执⾏msg_loop
// SDL_Thread _msg_thread;
//字符串,就是⼀个播放url
char *data_source_;
//播放器状态,例如prepared,resumed,error,completed等
int mp_state_; // 播放状态
IjkMediaPlayer成员函数
主要函数以上有介绍,当然还有些其他函数,之后再介绍。