我花了一整天的时间试图找到解决这个问题的方法,让我解释一下:
我正在使用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一起去,但就是这样。我在网上找不到任何东西,我甚至进入了谷歌搜索的第11页......
你是我唯一的希望......
答案 0 :(得分:0)
为了防止某些人可能需要一些帮助解决这个问题,我自己找到了解决方案,它可能不是更优化的解决方案,但呃,这是我唯一的工作!
部首:
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);
}