当前位置:网站首页>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 )

原网站

版权声明
本文为[Sister Suo]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/03/202203010513446685.html