0
点赞
收藏
分享

微信扫一扫

播放器实战20 解封装线程

九月的栩 2022-02-19 阅读 65

在这里插入图片描述
要打开xvideothread(初始化播放控件需要将其抽象类传进来),xaudiothread,xedmux,
将testtread类封装到解封装线程中

1.xdemuxthread.h

#pragma once
#include<qthread.h>
#include<mutex>
#include"ivideocall.h"
#include"xdemux.h"
#include"xaudiothread.h"
#include"xvideothread.h"
class xdemuxthread:public QThread
{
public:
	virtual bool open(const char* url,ivideocall *call);
	//启动所有线程,创建对象并打开
	virtual void start();
	xdemuxthread();
	virtual ~xdemuxthread();
	void run();
protected:
	xdemux *demux=0;
	xvideothread *vt=0;
	xaudiothread *at=0;
	std::mutex mux;
	bool isexit = false;
};
#include "xdemuxthread.h"
#include<iostream>
using namespace std;
void xdemuxthread::run()
{
	while (!isexit)
	{
		mux.lock();
		if (!demux)
		{
			mux.unlock();//若demux未打开则解锁让其他线程进来,等待5秒盼望demux能打开,然后再进行下次判断,判断demux是否打开
			msleep(5);
			continue;
		}
		AVPacket* pkt = demux->readfz();
        if (!pkt)
		{
			//读到结尾了
			mux.unlock();
			msleep(5);
			continue;
		}
		if (demux->isvideo(pkt))
		{
			if (vt)vt->push(pkt);
		}
		else
		{
			if (at)at->push(pkt);
		}
		mux.unlock();
	}
}
xdemuxthread::xdemuxthread()
{

}
xdemuxthread::~xdemuxthread()
{
	isexit = false;//调用析构后才停止当前线程
	wait();
	cout << "解封装线程退出" << endl;
}
bool xdemuxthread::open(const char* url, ivideocall* call)
{
	mux.lock();
	if (!demux)demux = new xdemux();
	if (!vt)vt = new xvideothread();
	if (!at)at = new xaudiothread();
	
	bool re=demux->Open(url);
	if (!re)
	{
		cout << "demux->open(url) failed!";
		return false;
	}
	re = vt->open(demux->CopyVPara(),call,demux->width,demux->height);
	if (!re)
	{
		cout << "vt->open(url) failed!";
		re = false;
	}
	re = at->open(demux->CopyAPara(), demux->sampletrate, demux->channels);
	if (!re)
	{
		cout << "at->open(url) failed!";
		re = false;
	}
	mux.unlock();
	cout << "xdemuxopen open:(1成功0失败)" << re << endl;
	return true;
}
void xdemuxthread::start()
{
	mux.lock();
	QThread::start();//启动当前线程,调用当前类的run()
	
	if (at)at->start();
	if (vt)vt->start();
	mux.unlock();
}

1.在open中打开音频线程与视频线程
2.当主函数调用解码线程的run时会调用xdemuxthread::start(),在该函数中调用音频线程的run与视频线程的run
3.在run中通过读封装获得packet,判断其类型,若是视频则push给视频线程的队列,若是音频则push给音频线程的队列

此时的main()函数得到了大大的简化:

using namespace std;
int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    Xplay2 w;
    w.show();
    xdemuxthread dt;
    dt.open("E:\\ffmpeg\\test222.mp4",w.ui.openGLWidget);
    dt.start();
    return a.exec();
}
举报

相关推荐

0 条评论