【问题标题】:How to play audio buffer from IMFSourceReader using Media Foundation如何使用 Media Foundation 从 IMFSourceReader 播放音频缓冲区
【发布时间】:2014-07-17 04:11:48
【问题描述】:

我刚刚花了一整天的时间试图找到解决这个问题的方法,让我解释一下:

我正在使用 c++ 中的 Visual 2013、Qt、OpenGL 和 Media Foundation 在 Windows 上开发视频工具。 我有一个 IMFSourceReader,它正在抓取我在 QWindow 内使用 openGL 处理和显示的视频帧。

现在我想播放视频文件的音频流。 我知道如何获取音频样本(使用相同的源阅读器)。 我也知道如何枚举我所有的音频设备:

IMMDeviceEnumerator *pEnum = NULL;      // Audio device enumerator.
IMMDeviceCollection *pDevices = NULL;   // Audio device collection.
IMMDevice *pDevice = NULL;              // An audio device.
IMFAttributes *pAttributes = NULL;      // Attribute store.
IMFMediaSink *pSink = NULL;             // Streaming audio renderer (SAR)

LPWSTR wstrID = NULL;                   // Device ID.

// Create the device enumerator.
hr = CoCreateInstance(
    __uuidof(MMDeviceEnumerator),
    NULL,
    CLSCTX_ALL,
    __uuidof(IMMDeviceEnumerator),
    (void**)&pEnum
    );

// Enumerate the rendering devices.
if (SUCCEEDED(hr))
{
    hr = pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDevices);
}

// Get ID of the first device in the list.
if (SUCCEEDED(hr))
{
    hr = pDevices->Item(0, &pDevice);
}

if (SUCCEEDED(hr))
{
    hr = pDevice->GetId(&wstrID);
}

// Create an attribute store and set the device ID attribute.
if (SUCCEEDED(hr))
{
    hr = MFCreateAttributes(&pAttributes, 2);
}

if (SUCCEEDED(hr))
{
    hr = pAttributes->SetString(
        MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID,
        wstrID
        );
}

// Create the audio renderer.
if (SUCCEEDED(hr))
{
    hr = MFCreateAudioRenderer(pAttributes, &pSink);
}

SAFE_RELEASE(pEnum);
SAFE_RELEASE(pDevices);
SAFE_RELEASE(pDevice);
SAFE_RELEASE(pAttributes);
CoTaskMemFree(wstrID);
}

我想我必须选择a Streaming Audio Renderer,但仅此而已。我在网上找不到任何东西,我什至上了 Google 搜索的第 11 页...

你是我唯一的希望...

【问题讨论】:

    标签: c++ qt audio ms-media-foundation


    【解决方案1】:

    以防万一有些人可能需要一些帮助来解决这个问题,我自己找到了解决方案,它可能不是更优化的解决方案,但是嗯,这是我唯一的工作!

    标题:

    class                   AudioPlaybackRenderer : public QObject
    {
    
        Q_OBJECT
    
    private:
        SourceReader *      _sourceReader;
        QAudioOutput *      _audioOutput;
        QIODevice *         _output;
        QByteArray *        _buffer;
        bool                _isPaused;
        PreciseTimer        _deltaTimer;
        int                 _bufferDuration;
        QTimer              _nextRender;
    
    public:
        AudioPlaybackRenderer();
        ~AudioPlaybackRenderer();
    
    public:
        void                setSourceReader(SourceReader *);
    
    private:
        void                playBuffer();
    
    private slots:
        void                render();
    };
    

    实施:

    void                    AudioPlaybackRenderer::playBuffer()
    {
        if (this->_audioOutput && this->_audioOutput->state() != QAudio::StoppedState && this->_audioOutput->state() != QAudio::SuspendedState)
        {
            if (_buffer->size())
                this->_buffer->remove(0, _output->write(_buffer->data(), _buffer->size()));
            if (_buffer->size() <= 0)
            {
                delete this->_buffer;
                this->_buffer = NULL;
            }
        }
    }
    
    void                    AudioPlaybackRenderer::render()
    {
        this->_deltaTimer.stop();
        float lastLoop = this->_deltaTimer.getElapsedTimeinMilliSec();
        if (this->_isPaused == false)
        {
            if (this->_buffer == NULL)
                this->_buffer = this->_sourceReader->getNextAudioSample();
            if (this->_buffer != NULL)
            {
                this->playBuffer();
            }
        }
    
        if (this->_audioOutput->error() != QAudio::NoError)
            qDebug() << DEBUG_TAG << "ERROR:" << this->_audioOutput->error();
    
        this->_deltaTimer.start();
    
        //TODO: Add that as member
        float delta = this->_bufferDuration - lastLoop;
        if (delta < 0)
            delta = 0.f;
        this->_nextRender.start(delta);
    }
    

    【讨论】:

      猜你喜欢
      • 2011-10-31
      • 2017-12-15
      • 1970-01-01
      • 1970-01-01
      • 2019-07-21
      • 1970-01-01
      • 2018-10-07
      • 1970-01-01
      • 2013-11-22
      相关资源
      最近更新 更多