完成XThread类
该播放器会启用多个线程包括解封装线程、音视频解码线程、播放线程等等,所以必须有一个统一的线程类来进行统一的管理
代码如下,代码解析请看注释
#ifndef BOPLAY_XTHREAD_H
#define BOPLAY_XTHREAD_H
//sleep 毫秒
void XSleep(int ms);
class XThread {
public:
//启动线程
virtual void start();
//通过isExit变量安全停止线程(不一定成功), 在开发中不应该操作线程句柄直接让其停止, 风险大, 因为不知道程序执行到哪
virtual void stop();
//入口主函数
virtual void main(){}
protected:
//退出标志位
bool isExit = false;
//线程运行标志位
bool isRunning = false;
private:
void threadMain();
};
#endif //BOPLAY_XTHREAD_H
#include "XThread.h"
//c++11 线程库
#include <thread>
#include "XLog.h"
//using namespace不要放在头文件中
using namespace std;
//休眠函数
void XSleep(int ms){
chrono::milliseconds sTime(ms);
this_thread::sleep_for(sTime);
}
//启动线程
void XThread::start() {
isExit = false;
thread th(&XThread::threadMain, this);
//当前线程放弃对新建线程的控制, 防止对象被清空时, 新建线程出错
th.detach();
}
void XThread::stop() {
isExit = true;
//延时200ms等待线程结束运行,因为调用stop()时,目标线程未必运行到判断isExit的语句
for (int i = 0; i < 200; ++i) {
XSleep(1);
if (!isRunning){
XLOGI("停止线程成功");
return;
}
XSleep(1);
}
XLOGI("停止线程超时");
}
void XThread::threadMain() {
XLOGI("线程函数进入");
isRunning = true;
main();
isRunning = false;
XLOGI("线程函数退出");
}
解封装接口类IDemux继承XThread并实现线程主函数
#ifndef BOPLAY_IDEMUX_H
#define BOPLAY_IDEMUX_H
#include "XData.h"
#include "XThread.h"
//解封装接口类
class IDemux: public XThread {
public:
//打开文件或者流媒体 rtmp http rtsp
virtual bool Open(const char *url) = 0;
//读取一帧数据,数据由调用者清理
virtual XData Read() = 0;
//总时长(单位ms)
int totalMs = 0;
protected:
//不要让用户访问
virtual void main();
};
#endif //BOPLAY_IDEMUX_H
#include "IDemux.h"
#include "XLog.h"
void IDemux::main() {
while(!isExit){
//解封装线程的主函数主要是读取数据
XData xData = Read();
}
}