可以切换音轨的SourseFilter开发。

多音轨wma格式音频选择音轨问题

在大部分播放器中,包括暴风影音和千千静听等都不能对多语言音轨的wma格式音频进行音轨选择操作。windows media player可以进行音轨选择。

在使用directshow做自己的播放器时,有时会有特殊需求需要选择音轨,但又同时不能用wmplayer时,就需要自己实现音轨选择功能了。

实现方案

dshow的WMASFReader Filter提供了IWMReaderAdvanced, IWMReaderAdvanced2接口,但并未提供SetStreamsSelected等wmfsdk的用于选择音轨的接口,所以,WMASFReader 是用不了了,只能自己写过一个sourcefilter。关于sourceFilter的列子可以参考directshow实务精选里的Appendix_D/FilterQQSource。可以直接在上面改,然后在里面使用WMFormat的IWMReaderAdvanced接口来进行wma文件的读取和音轨的选择。关于使用wmformat读取文件可以参考sdk里的sample,也可参考里的samples/Players例子,可以直接使用例子提供的一个wmreader类来进行读文件。

如有改进建议或意见,或有应用需求,请联系QQ:22154912

HRESULT CASFOutPin::FillBuffer(IMediaSample * pSample)

{

//=================================================================

if (g_pWMReader->mIsEOF)//&&g_pWMReader->m_nUsedBufferCount<1)

{

return S_FALSE;

}

// CAutoLock lock(&mSharedState);

// lock(&mSharedState);

if (m_bChangeStart)

{

Sleep(30);

// while (g_pWMReader->m_nUsedBufferCount<2)

// {

// Sleep(5);

// }

m_bChangeStart = FALSE;

}

while (g_pWMReader->m_nUsedBufferCount<1)

{

Sleep(5);

continue;

}

WriteLog("FillBuffer/n");

CheckPointer(pSample,E_POINTER);

// ASSERT(m_Ball);

BYTE *pData;

long lDataLen;

pSample->GetPointer(&pData);//得到Sample的地址指针

lDataLen = pSample->GetSize();//得到Sample的大小

ZeroMemory(pData, lDataLen);//清零

{

// CAutoLock cAutoLockShared(&m_cSharedState);

CopyMemory(pData,g_pWMReader->m_pBufferNodeFillBuffer->pBuffer, g_pWMReader->m_pBufferNodeFillBuffer->nBufferLen);

ZeroMemory(g_pWMReader->m_pSampleData,g_pWMReader->m_pBufferNodeFillBuffer->nBufferLen);

// The current time is the sample's start

CRefTime rtStart,rtSampleTime;// = m_rtSampleTime;

rtStart = g_pWMReader->m_pBufferNodeFillBuffer->nSampleTime-m_rtStart;

rtSampleTime = g_pWMReader->m_pBufferNodeFillBuffer->nSampleTime+(long)((float)lDataLen/176400*10000000);//这个数只是针对44.1kHz16bit的数值。

// Increment to find the finish time

pSample->SetActualDataLength(g_pWMReader->m_pBufferNodeFillBuffer->nBufferLen);

pSample->SetTime((REFERENCE_TIME *) &rtStart,(REFERENCE_TIME *) &rtSampleTime);//(REFERENCE_TIME *) &m_rtSampleTime);

g_pWMReader->m_pBufferNodeFillBuffer = g_pWMReader->m_pBufferNodeFillBuffer->pNext;

g_pWMReader->m_nUsedBufferCount--;

g_pWMReader->Resume();

}

//=================================================================

pSample->SetSyncPoint(TRUE);

return NOERROR;

}

HRESULT CWMReader::OnSample( /* [in] */ DWORD dwOutputNum,

/* [in] */ QWORD cnsSampleTime,

/* [in] */ QWORD cnsSampleDuration,

/* [in] */ DWORD dwFlags,

/* [in] */ INSSBuffer __RPC_FAR *pSample,

/* [in] */ void __RPC_FAR *pvContext )

{

#ifdef _DEBUG

DWORD threadId = GetCurrentThreadId();

#endif

// Check the output number of the sample against the stored output number.

// Because only the first audio output is stored, all other outputs,

// regardless of type, will be ignored.

if (dwOutputNum != mOutputNum)

{

WriteLog("dwOutputNum != mOutputNum/n");

return S_OK;

}

BYTE *pData = NULL;

DWORD cbData = 0;

// Get the sample from the buffer object.

HRESULT hr = pSample->GetBufferAndLength(&pData, &cbData);

if (FAILED(hr))

{

return hr;

}

mTimeElapsed = cnsSampleTime;

//================================================================

g_Time2=cnsSampleTime;

while (m_nUsedBufferCount>2)

{

Sleep(5);

continue;

}

if (m_pSampleData == NULL)

{

m_pSampleData = ( BYTE * )new BYTE[ BUFFERSIZE ];

}

CopyMemory(m_pBufferNodeOnSample->pBuffer, pData, cbData);

WriteLog("CopyMemory(m_pBufferNodeOnSample->pBuffer, pData, cbData);/n");

m_pBufferNodeOnSample->nBufferLen = cbData;

m_pBufferNodeOnSample->nSampleTime = cnsSampleTime;

m_pBufferNodeOnSample = m_pBufferNodeOnSample->pNext;

m_nUsedBufferCount++;

if (m_nUsedBufferCount>2)

{

Pause();

}

CopyMemory(m_pSampleData,pData,cbData);

WriteLog("CopyMemory(m_pSampleData,pData,cbData);/n");

if( FAILED( hr ) )

{

return( hr );

}

// BOOL ret = mPlayer->Play(pData, cbData, cnsSampleTime);

return(S_OK);// ret ? S_OK : E_FAIL;

//==============================================================

}

你可能感兴趣的:(可以切换音轨的SourseFilter开发。)