メールの詳細(トピック表示)
初めまして、ごんぞーといいます。
現在、DirectShowのサンプル「synth」と「pushsource」を元に、自作デコードDLLから取得したビデオとオーディオを再生するソースフィルタを作成しています。
ソースフィルタはビデオ用とオーディオ用の出力ピンをそれぞれ持っています。
ビデオの再生については問題なく行えているのですが、オーディオの再生に問題が発生しています。
オーディオ側の出力ピンのFillBufferが、ビデオフレーム1秒分描画しているのに対して1回しか呼ばれません。(ビデオのフレームは29.97です。)
自作デコードDLLからは、ビデオもオーディオも1フレームづつの情報を取得してくるようになっているため、音がぶつ切りになってしまっています。
オーディオ側もビデオと同様に1フレームごとにFillBufferが発生されるようにするにはどうすればいいのでしょうか?
よろしくお願いいたします。
以下にオーディオ側のソースの抜粋を記載します。
GetMediaType
WAVEFORMATEX *pwfex;
pwfex = (WAVEFORMATEX *) pMediaType->AllocFormatBuffer(sizeof(WAVEFORMATEX));
pwfex->wFormatTag = WAVE_FORMAT_PCM;
pwfex->nChannels = 2;
pwfex->nSamplesPerSec = 48000;
pwfex->wBitsPerSample = (WORD)16;
pwfex->nBlockAlign = (WORD)4;
pwfex->nAvgBytesPerSec = 192000;
pwfex->cbSize = 0;
FillBuffer
BYTE *pData;
long cbData;
HRESULT hr;
// ロック
CAutoLock cAutoLockShared(&m_cSharedState);
// ピンのメディアタイプよりWAVEFORMATEXを取得
WAVEFORMATEX *pVih = (WAVEFORMATEX*)m_mt.pbFormat;
if (WAVE_FORMAT_PCM == pVih->wFormatTag)
{
// メディアサンプルのデータ格納先を取得
pSample->GetPointer(&pData);
// メディアサンプルのデータ格納先のサイズを取得
cbData = pSample->GetSize();
// オーディオフレームの取得
int ret = m_decoder->GetAudioFrame(m_rtSampleTime / UNITS , 0, pData);
hr = pSample->SetActualDataLength(pSample->GetSize());
//hr = pSample->SetActualDataLength(0);
if (FAILED(hr))
return hr;
}
m_iFrameNumber = m_rtSampleTime / UNITS;
CRefTime rtStart = m_rtSampleTime;
m_rtSampleTime = rtStart + (REFERENCE_TIME)(UNITS * pSample->GetActualDataLength()) / (REFERENCE_TIME)pVih->nAvgBytesPerSec;
hr = pSample->SetTime((REFERENCE_TIME*)&rtStart, (REFERENCE_TIME*)&m_rtSampleTime);
LONGLONG llMediaTimeStart = m_llSampleMediaTimeStart;
DWORD dwNumAudioSamplesInPacket = (pSample->GetActualDataLength() * BITS_PER_BYTE) / (pVih->nChannels * pVih->wBitsPerSample);
LONGLONG llMediaTimeStop = m_llSampleMediaTimeStart + dwNumAudioSamplesInPacket;
hr = pSample->SetMediaTime(&llMediaTimeStart, &llMediaTimeStop);
if (FAILED(hr)) {
return hr;
}
m_llSampleMediaTimeStart = llMediaTimeStop;
m_fFirstSampleDelivered = TRUE;
//pSample->SetSyncPoint(TRUE);
return S_OK;