当前位置:网站首页>Player practice 19 xaudio turn on audio
Player practice 19 xaudio turn on audio
2022-06-12 14:10:00 【Sister Suo】
1.xaudio.h
#pragma once
class xaudioplay
{
public:
static xaudioplay* get();
xaudioplay();
// It must be a virtual destructor ,delete The destructions of inherited classes can only be completed through the parent class pointer
virtual ~xaudioplay();
virtual bool open()=0;
// If you open other media files for the second time, the following parameters will change , So you need to have close
virtual bool close() = 0;
// Pass parameters to ffmpeg Isolation , Therefore, it is passed through members ,QT The audio format object of requires these parameters
//channels And sampling rate demux Pass on , Sample size is fixed
int samplerate = 0;
int samplesize = 16;
int channels = 0;
// Audio
virtual bool write(const unsigned char* data, int datasize) = 0;
virtual int Getfree() = 0;
};
1. Pure virtual function (open(),close())
Just give the declaration in the base class , No virtual function implementation is defined , Instead, implement... In a derived class . This virtual function is called pure virtual function . If an ordinary function only gives its declaration and does not implement its function body , This can't be compiled . A pure virtual function has no body .
A pure virtual function needs to be declared with =0;
class < Base class name >
{
virtual < type >< Function name >(< Parameter table >)=0; …
};
2. abstract class (xaudioplay)
Classes with pure virtual functions are called abstract classes . Abstract classes can only be used as the base class of derived classes , Cannot define objects , But you can define pointers . After the derived class implements the pure virtual function , Define a pointer to an abstract class object , And point to or reference subclass objects .
1) In defining pure virtual functions , You can't define the implementation part of a virtual function ;
2) Before redefining this pure virtual function , You can't call this function .
The only purpose of an abstract class is to provide a base class for derived classes , Pure virtual functions are used as the basis of member functions in derived classes , And implement Dynamic polymorphism . If the derived class inherited from the abstract class cannot implement all the pure virtual functions in the base class , Then the derived class becomes an abstract class . Because it inherits the abstract functions of the base class , A class that contains pure virtual functions is an abstract class . The pure virtual function has defined the declaration of this method in the abstract class , Other classes can only implement according to this interface .
3. This kind (xaudioplay) Create objects as factories ( Define... In the header file ), Object specific (xaudio) The creation process is in its inherited class ( stay cpp In the definition of )
There may be several players : be based on QT, be based on DIRECXT, According to different needs, then return different inherited class objects
4.C++ Provide static This keyword declares static members , Static member functions are independent of class instantiation , For the same class , Static member functions are shared . Ordinary member functions need to be instantiated to call , For each instance , Ordinary member functions are unique to themselves
:static xaudioplay* get();
When using the class name to call , Instead of calling... Through the instantiated class name :
xaudioplay::get()->samplerate
2.xaudio.cpp
class audioplay :public xaudioplay
{
// Another advantage is that you can hide the details
// And qt Relevant members are placed in audioplay in
public:
QAudioOutput* output;
QIODevice* io;
// Because opening and closing may not be in the same thread , So lock it
std::mutex mux;
virtual bool open()
{
close();
QAudioFormat fmt;
fmt.setSampleRate(samplerate);
fmt.setSampleSize(samplesize);// Number of sampling bits
fmt.setChannelCount(channels);
fmt.setCodec("audio/pcm");
fmt.setByteOrder(QAudioFormat::LittleEndian);
fmt.setSampleType(QAudioFormat::UnSignedInt);
mux.lock();
output = new QAudioOutput(fmt);
io = output->start();// Start playing
mux.unlock();
if (io)
return true;
return false;
}
virtual bool close()
{
mux.lock();
if (io)
{
io->close();
//io Space is created by output Produced , So no need delete, When deleteoutput Will automatically delete this space
//“ Whoever produces it will release it ”
io = 0;
}
if (output)
{
output->stop();
delete output;
output = 0;
}
mux.unlock();
return true;
}
virtual bool write(const unsigned char* data, int datasize)
{
if (!data || datasize <= 0)return false;
mux.lock();
if (!output||!io)
{
mux.unlock();
return 0;
}
int size=io->write((char*)data, datasize);
if (size != datasize)
{
mux.unlock();
return false;
}
mux.unlock();
return true;
}
virtual int Getfree()
{
mux.lock();
if (!output)
{
mux.unlock();
return 0;
}
int free = output->bytesFree();
mux.unlock();
return free;
}
};
xaudioplay* xaudioplay::get()
{
static audioplay play;
return &play;
}
xaudioplay::xaudioplay()
{
}
xaudioplay::~xaudioplay()
{
}
In this case, there are only... In the parent class get() Not defined as a virtual function ,get Function as a bridge between parent class and child class , Conveyor belts in factories
By the parent class xxaudioplay Of get() Method defines a subclass , Set it to static, The will not be destroyed during the call , Ensure that multiple calls are the same object , usage :xaudioplay::get()->open()
3.main
Modify in the thread class
class testtread :public QThread
{
public:
void init()
{
const char* 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;
}
unsigned char *pcm = new unsigned char[1024 * 1024*1024];
void run()
{
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 size :"<<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() The parameters of are obtained by decoding , There is only one copy of the entire media file ,
resample.resample() The parameter is AVFrame, It is decoded in turn in the loop frame To deal with , Every time you get an audio from the decoding queue packet, That's it packet Resampling , And obtain the number of bits sampled each time for each audio channel after resampling , When used QAudioOutput Class Getfree() Determine the number of bits in the free space , When the current one is less than the latter, it will pcm( The resampled results are placed in pcm in ) Conduct write And play it
6 The sound channel media files are full of noise , Use ffmpeg Turn into 2 The sound channel can be played normally ( I don't know why )
边栏推荐
- Binary tree traversal
- Leetcode 2176. Count equal and divisible pairs in an array
- 【mysql进阶】查询优化原理与方案(六)
- 阿裏雲開發板HaaS510報送設備屬性
- Knowledge of wireless card driver
- SystemC time
- Transmission and response of events and use cases
- Summary of virtual box usage problems
- Lua callinfo structure, stkid structure resolution
- Why do Chinese programmers change jobs?
猜你喜欢

【mysql进阶】索引分类及索引优化方案(五)

If you want to build brand awareness, what bidding strategy can you choose?

Introduction to database system (Fifth Edition) notes Chapter 1 Introduction

对于跨境电商,更侧重收入的出价策略 —Google SEM

Shell脚本到底是什么高大上的技术吗?

Single bus temperature sensor 18B20 data on cloud (Alibaba cloud)

TestEngine with ID ‘junit-vintage‘ failed to discover tests

【mysql进阶】mysql索引数据结构的演变(四)
![[semidrive source code analysis] [x9 chip startup process] 25 - Introduction to mailbox inter core communication mechanism (code analysis) rpmsg-ipcc RTOS & QNX](/img/90/98faa5856fbc55ff7fda4a3adb3650.png)
[semidrive source code analysis] [x9 chip startup process] 25 - Introduction to mailbox inter core communication mechanism (code analysis) rpmsg-ipcc RTOS & QNX

阿里云开发板HaaS510将串口获取数据发送到物联网平台
随机推荐
Redis core configuration and advanced data types
对于跨境电商,更侧重收入的出价策略 —Google SEM
Player screen orientation scheme
单总线温度传感器18B20数据上云(阿里云)
Tree reconstruction (pre order + middle order or post order + middle order)
Create a slice slice pit using the make method
SystemC common errors
lua 常用内置函数
通信流量分析
Acwing: topology sequence
[MySQL advanced] index classification and index optimization scheme (V)
【视频课】android studio物联网APP设计制作全套教程--国庆期间全掌握
阿裏雲開發板HaaS510報送設備屬性
Getting started alicloud haas510 open board DTU (version 2.0) --510-as
Design of PLC intelligent slave station based on PROFIBUS DP protocol
Leetcode 2176. 统计数组中相等且可以被整除的数对
Cmake basic tutorial - 01 a-hello-cmake
Display logs in the database through loganalyzer
Talk about the top 10 classic MySQL errors
【mysql进阶】mysql索引数据结构的演变(四)