Qt+mpg123+openal播放MP3流

时间:2021-04-28 00:04:11
#ifndef PLAYSTREAM_H
#define PLAYSTREAM_H

#include <QObject>
#include "../libMPG123/mpg123.h"
#include "../openal/include/al.h"
#include "../openal/include/alc.h"
#pragma comment (lib, "../openal/lib/OpenAL32.lib")
#pragma comment (lib, "../libMPG123/libmpg123.lib")

class PlayStream : public QObject
{
    Q_OBJECT

public:
    PlayStream(QObject *parent);
    ~PlayStream();
public:
    //打开流
    void OpenStream();
    //播放实时流,需先调用OpenStream()
    void Play(QByteArray datas);
    //停止播放
    void Stop();
    //暂停播放
    void Pasue();
private:
    void init();
    bool updataQueueBuffer();
    void mpgClose();

private:
    mpg123_handle *mh ;
    ALCdevice *pDevice;
    ALCcontext *pContext;
    ALuint outSourceID;
    long lRate;
};

#endif // PLAYSTREAM_H
#include "StdAfx.h"
#include "PlayStream.h"

PlayStream::PlayStream(QObject *parent)
    : QObject(parent)
{
    init();
}

PlayStream::~PlayStream()
{
    mpgClose();
    alcCloseDevice(pDevice);
    alcDestroyContext(pContext);
}

void PlayStream::init()
{
    int err;
    mpg123_init();
    mh = mpg123_new(NULL,&err);
    pDevice =alcOpenDevice(NULL);
    if (pDevice)
    {
        pContext=alcCreateContext(pDevice,NULL);
        alcMakeContextCurrent(pContext);
    }
    alGenSources(1, &outSourceID);
    alSourcei(outSourceID, AL_LOOPING, AL_FALSE);
    alSourcef(outSourceID, AL_SOURCE_TYPE, AL_STREAMING);
}

void PlayStream::Play(QByteArray datas)
{
    updataQueueBuffer();
    ALuint bufferID = 0;
    alGenBuffers(1, &bufferID);
    size_t done=0;
    size_t bufferSize=1638400;
    void *buffer=malloc(bufferSize);
    ALuint ulFormat= alGetEnumValue("AL_FORMAT_STEREO16");
    mpg123_decode(mh,(const unsigned char*)datas.constData(),datas.size(),(unsigned char *)buffer,bufferSize,&done);
    if (done)
    {
        alBufferData(bufferID, ulFormat, buffer,done, 44100);
        alSourceQueueBuffers(outSourceID, 1, &bufferID);
    }
    ALint values;
    alGetSourcei(outSourceID,AL_SOURCE_STATE,&values);
    if (values != AL_PLAYING)
    {
        alSourcePlay(outSourceID);
    }
    alDeleteBuffers(1, &bufferID);
    free(buffer);
    buffer=NULL;
}

bool PlayStream::updataQueueBuffer()
{
    ALint stateVaue;
    int processed, queued;
    alGetSourcei(outSourceID, AL_SOURCE_STATE, &stateVaue);
    if (stateVaue == AL_STOPPED) 
    {
        return false;
    }
    alGetSourcei(outSourceID, AL_BUFFERS_PROCESSED, &processed);
    alGetSourcei(outSourceID, AL_BUFFERS_QUEUED, &queued);
    while(processed--)
    {
        ALuint buff;
        alSourceUnqueueBuffers(outSourceID, 1, &buff);
        alDeleteBuffers(1, &buff);
    }
    return true;
}

void PlayStream::mpgClose()
{
    alSourceStop(outSourceID);
    alSourcei(outSourceID, AL_BUFFER, 0);
    int err=mpg123_close(mh);
}

void PlayStream::OpenStream()
{
    int err=mpg123_open_feed(mh);
}

void PlayStream::Stop()
{
    mpgClose();
    alcCloseDevice(pDevice);
    alcDestroyContext(pContext);
}

void PlayStream::Pasue()
{
    alSourcePause(outSourceID);
}