完成XThread類(lèi)
該播放器會(huì)啟用多個(gè)線程包括解封裝線程、音視頻解碼線程池凄、播放線程等等拼缝,所以必須有一個(gè)統(tǒng)一的線程類(lèi)來(lái)進(jìn)行統(tǒng)一的管理
代碼如下屿附,代碼解析請(qǐng)看注釋
#ifndef BOPLAY_XTHREAD_H
#define BOPLAY_XTHREAD_H
//sleep 毫秒
void XSleep(int ms);
class XThread {
public:
//啟動(dòng)線程
virtual void start();
//通過(guò)isExit變量安全停止線程(不一定成功), 在開(kāi)發(fā)中不應(yīng)該操作線程句柄直接讓其停止, 風(fēng)險(xiǎn)大, 因?yàn)椴恢莱绦驁?zhí)行到哪
virtual void stop();
//入口主函數(shù)
virtual void main(){}
protected:
//退出標(biāo)志位
bool isExit = false;
//線程運(yùn)行標(biāo)志位
bool isRunning = false;
private:
void threadMain();
};
#endif //BOPLAY_XTHREAD_H
#include "XThread.h"
//c++11 線程庫(kù)
#include <thread>
#include "XLog.h"
//using namespace不要放在頭文件中
using namespace std;
//休眠函數(shù)
void XSleep(int ms){
chrono::milliseconds sTime(ms);
this_thread::sleep_for(sTime);
}
//啟動(dòng)線程
void XThread::start() {
isExit = false;
thread th(&XThread::threadMain, this);
//當(dāng)前線程放棄對(duì)新建線程的控制, 防止對(duì)象被清空時(shí), 新建線程出錯(cuò)
th.detach();
}
void XThread::stop() {
isExit = true;
//延時(shí)200ms等待線程結(jié)束運(yùn)行斑芜,因?yàn)檎{(diào)用stop()時(shí),目標(biāo)線程未必運(yùn)行到判斷isExit的語(yǔ)句
for (int i = 0; i < 200; ++i) {
XSleep(1);
if (!isRunning){
XLOGI("停止線程成功");
return;
}
XSleep(1);
}
XLOGI("停止線程超時(shí)");
}
void XThread::threadMain() {
XLOGI("線程函數(shù)進(jìn)入");
isRunning = true;
main();
isRunning = false;
XLOGI("線程函數(shù)退出");
}
解封裝接口類(lèi)IDemux繼承XThread并實(shí)現(xiàn)線程主函數(shù)
#ifndef BOPLAY_IDEMUX_H
#define BOPLAY_IDEMUX_H
#include "XData.h"
#include "XThread.h"
//解封裝接口類(lèi)
class IDemux: public XThread {
public:
//打開(kāi)文件或者流媒體 rtmp http rtsp
virtual bool Open(const char *url) = 0;
//讀取一幀數(shù)據(jù),數(shù)據(jù)由調(diào)用者清理
virtual XData Read() = 0;
//總時(shí)長(zhǎng)(單位ms)
int totalMs = 0;
protected:
//不要讓用戶訪問(wèn)
virtual void main();
};
#endif //BOPLAY_IDEMUX_H
#include "IDemux.h"
#include "XLog.h"
void IDemux::main() {
while(!isExit){
//解封裝線程的主函數(shù)主要是讀取數(shù)據(jù)
XData xData = Read();
}
}