admin 管理员组文章数量: 1184232
1.xaudio.h
#pragma onceclassxaudioplay{public:static xaudioplay*get();xaudioplay();//一定得是虚析构函数,delete时才可以通过父类指针完成继承类的析构virtual~xaudioplay();virtualboolopen()=0;//第二次打开如果是其他媒体文件的话下面这些参数就要变,因此需要有closevirtualboolclose()=0;//将参数传递与ffmpeg隔离,故通过成员传递,QT的音频格式对象需要这些参数//channels和采样率通过demux传递,采样大小固定int samplerate =0;int samplesize =16;int channels =0;//音频virtualboolwrite(constunsignedchar* data,int datasize)=0;virtualintGetfree()=0;};1.纯虚函数(open(),close())
在基类中仅仅给出声明,不对虚函数实现定义,而是在派生类中实现。这个虚函数称为纯虚函数。普通函数如果仅仅给出它的声明而没有实现它的函数体,这是编译不过的。纯虚函数没有函数体。
纯虚函数需要在声明之后加个=0;
class <基类名>
{
virtual <类型><函数名>(<参数表>)=0; …
};
2.抽象类 (xaudioplay)
含有纯虚函数的类被称为抽象类。抽象类只能作为派生类的基类,不能定义对象,但可以定义指针。在派生类实现该纯虚函数后,定义抽象类对象的指针,并指向或引用子类对象。
1)在定义纯虚函数时,不能定义虚函数的实现部分;
2)在没有重新定义这种纯虚函数之前,是不能调用这种函数的。
抽象类的唯一用途是为派生类提供基类,纯虚函数的作用是作为派生类中的成员函数的基础,并实现 动态多态性 。继承于抽象类的派生类如果不能实现基类中所有的纯虚函数,那么这个派生类也就成了抽象类。因为它继承了基类的抽象函数,只要含有纯虚函数的类就是抽象类。纯虚函数已经在抽象类中定义了这个方法的声明,其它类中只能按照这个接口去实现。
3.该类(xaudioplay)做为工厂来创建对象(在头文件中定义),对象具体(xaudio)创建过程在其继承类中(在cpp中定义)
可能会几种播放器:基于QT,基于DIRECXT,根据不同的需要然后返回不同的继承类对象
4.C++提供static这个关键词对静态成员进行声明,静态成员函数和类的实例化无关,对于同一类来说,静态成员函数是共享的。而普通成员函数需要实例化才能调用,对于每一个实例来说,普通成员函数是自己独有的
:static xaudioplay* get();
在使用使通过类名来调用,而不是通过实例化后的类名来调用:
xaudioplay::get()->samplerate
2.xaudio.cpp
classaudioplay:public xaudioplay
{//还有个好处是可以将细节隐藏起来//与qt相关的成员放在audioplay中public:
QAudioOutput* output;
QIODevice* io;//因为打开与关闭可能不在一个线程,所以要加锁
std::mutex mux;virtualboolopen(){close();
QAudioFormat fmt;
fmt.setSampleRate(samplerate);
fmt.setSampleSize(samplesize);//采样位数
fmt.setChannelCount(channels);
fmt.setCodec("audio/pcm");
fmt.setByteOrder(QAudioFormat::LittleEndian);
fmt.setSampleType(QAudioFormat::UnSignedInt);
mux.lock();
output =newQAudioOutput(fmt);
io = output->start();//开始播放
mux.unlock();if(io)returntrue;returnfalse;}virtualboolclose(){
mux.lock();if(io){
io->close();//io空间是由output产生的,所以不需要delete,当deleteoutput时会自动删除这块空间//“由谁产生就谁释放”
io =0;}if(output){
output->stop();delete output;
output =0;}
mux.unlock();returntrue;}virtualboolwrite(constunsignedchar* data,int datasize){if(!data || datasize <=0)returnfalse;
mux.lock();if(!output||!io){
mux.unlock();return0;}int size=io->write((char*)data, datasize);if(size != datasize){
mux.unlock();returnfalse;}
mux.unlock();returntrue;}virtualintGetfree(){
mux.lock();if(!output){
mux.unlock();return0;}int free = output->bytesFree();
mux.unlock();return free;}};xaudioplay* xaudioplay::get(){static audioplay play;return&play;}
xaudioplay::xaudioplay(){}
xaudioplay::~xaudioplay(){}本例中父类中只有get()没有定义为虚函数,get函数做为父类与子类的桥梁,工厂中的传送带
通过父类xxaudioplay的get()方法定义一个其子类,将其设为static,调用期间该不会销毁,保证多次调用都是同一个对象,用法:xaudioplay::get()->open()
3.main
在线程类中修改
classtesttread:public QThread
{public:voidinit(){constchar* path ="E:\\ffmpeg\\test222.mp4";
cout <<"demux.Open = "<< demux.Open(path)<< endl;
cout <<"vdecode.open()"<< vdecode.open(demux.CopyVPara())<< endl;
cout <<"adecode.open()"<< adecode.open(demux.CopyAPara())<< endl;
cout <<"reasmple.open()"<< resample.Open(demux.CopyAPara())<< endl;
xaudioplay::get()->channels = demux.channels;
xaudioplay::get()->samplerate = demux.sampletrate;
cout <<"xaudioplay::get()->open()"<< xaudioplay::get()->open()<<endl;}unsignedchar*pcm =newunsignedchar[1024*1024*1024];voidrun(){for(;;){
AVPacket* pkt = demux.readfz();if(demux.isvideo(pkt)==true){
vdecode.send(pkt);
AVFrame* frame = vdecode.receive();
video->Repaint(frame);}else{
adecode.send(pkt);
AVFrame* frame = adecode.receive();int len = resample.Resample(frame, pcm);
cout<<"resample大小:"<<len<<endl;while(len >0){if(xaudioplay::get()->Getfree()>= len){
xaudioplay::get()->write(pcm, len);break;}msleep(5);}}if(!pkt)break;}}
xdemux demux;
xvideowidget* video;
xresample resample;protected:
xdecode vdecode;
xdecode adecode;};
resample.open()的参数是解码获得的,整个媒体文件只有一份,
resample.resample()的参数是AVFrame,是在循环里依次对解码得到的frame进行处理,每从解码队列里获得一个音频packet,就对这个packet进行重采样,并获得重采样后每个音频通道每次采样的比特数,当用QAudioOutput类的方法成员Getfree()判断空余空间中比特数,当前者小于后者时便将pcm(重采样后的结果放在pcm中)进行write并播放
6声道媒体文件播放全是杂音,使用ffmpeg转成2声道就可以正常播放(暂时不知道为什么)
版权声明:本文标题:播放器实战19 Xaudio打开音频_x aoiio 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1774170189a3568644.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论