AudioSwitcher.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:14k
- /*
- * Copyright (C) 2003-2005 Gabest
- * http://www.gabest.org
- *
- * This Program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This Program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- */
- #include "StdAfx.h"
- #include "Shlwapi.h"
- #include <atlpath.h>
- #include <mmreg.h>
- #include <ks.h>
- #include <ksmedia.h>
- #include "AudioSwitcher.h"
- #include "Audio.h"
- #include "......DSUtilDSUtil.h"
- #include <initguid.h>
- #include "........includeOggOggDS.h"
- #ifdef REGISTER_FILTER
- const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
- {
- {&MEDIATYPE_Audio, &MEDIASUBTYPE_NULL}
- };
- const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
- {
- {&MEDIATYPE_Audio, &MEDIASUBTYPE_NULL}
- };
- const AMOVIESETUP_PIN sudpPins[] =
- {
- {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
- {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
- };
- const AMOVIESETUP_FILTER sudFilter[] =
- {
- {&__uuidof(CAudioSwitcherFilter), L"AudioSwitcher", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins}
- };
- CFactoryTemplate g_Templates[] =
- {
- {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CAudioSwitcherFilter>, NULL, &sudFilter[0]}
- };
- int g_cTemplates = countof(g_Templates);
- STDAPI DllRegisterServer()
- {
- return AMovieDllRegisterServer2(TRUE);
- }
- STDAPI DllUnregisterServer()
- {
- return AMovieDllRegisterServer2(FALSE);
- }
- extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
- BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
- {
- return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
- }
- #endif
- //
- // CAudioSwitcherFilter
- //
- CAudioSwitcherFilter::CAudioSwitcherFilter(LPUNKNOWN lpunk, HRESULT* phr)
- : CStreamSwitcherFilter(lpunk, phr, __uuidof(this))
- {
- if(phr)
- {
- if(FAILED(*phr)) return;
- else *phr = S_OK;
- }
- m_fCustomChannelMapping = false;
- memset(m_pSpeakerToChannelMap, 0, sizeof(m_pSpeakerToChannelMap));
- m_fDownSampleTo441 = false;
- m_rtAudioTimeShift = 0;
- m_rtNextStart = 0;
- m_rtNextStop = 1;
- }
- STDMETHODIMP CAudioSwitcherFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
- {
- return
- QI(IAudioSwitcherFilter)
- __super::NonDelegatingQueryInterface(riid, ppv);
- }
- HRESULT CAudioSwitcherFilter::CheckMediaType(const CMediaType* pmt)
- {
- if(pmt->formattype == FORMAT_WaveFormatEx
- && ((WAVEFORMATEX*)pmt->pbFormat)->nChannels > 2
- && ((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag != WAVE_FORMAT_EXTENSIBLE)
- return VFW_E_INVALIDMEDIATYPE; // stupid iviaudio tries to fool us
- return (pmt->majortype == MEDIATYPE_Audio
- && pmt->formattype == FORMAT_WaveFormatEx
- && (((WAVEFORMATEX*)pmt->pbFormat)->wBitsPerSample == 8
- || ((WAVEFORMATEX*)pmt->pbFormat)->wBitsPerSample == 16
- || ((WAVEFORMATEX*)pmt->pbFormat)->wBitsPerSample == 24
- || ((WAVEFORMATEX*)pmt->pbFormat)->wBitsPerSample == 32)
- && (((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag == WAVE_FORMAT_PCM
- || ((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag == WAVE_FORMAT_IEEE_FLOAT
- || ((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag == WAVE_FORMAT_DOLBY_AC3_SPDIF
- || ((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag == WAVE_FORMAT_EXTENSIBLE))
- ? S_OK
- : VFW_E_TYPE_NOT_ACCEPTED;
- }
- #define mixchannels(type, sumtype, mintype, maxtype)
- sumtype sum = 0;
- int num = 0;
- for(int j = 0; j < 18 && j < wfe->nChannels; j++)
- {
- if(Channel&(1<<j))
- {
- num++;
- sum += *(type*)&pDataIn[bps*(j + wfe->nChannels*k)];
- }
- }
- sum = min(max(sum, mintype), maxtype);
- *(type*)&pDataOut[bps*(i + wfeout->nChannels*k)] = (type)sum;
- HRESULT CAudioSwitcherFilter::Transform(IMediaSample* pIn, IMediaSample* pOut)
- {
- CStreamSwitcherInputPin* pInPin = GetInputPin();
- CStreamSwitcherOutputPin* pOutPin = GetOutputPin();
- if(!pInPin || !pOutPin)
- return __super::Transform(pIn, pOut);
- WAVEFORMATEX* wfe = (WAVEFORMATEX*)pInPin->CurrentMediaType().pbFormat;
- WAVEFORMATEX* wfeout = (WAVEFORMATEX*)pOutPin->CurrentMediaType().pbFormat;
- WAVEFORMATEXTENSIBLE* wfex = (WAVEFORMATEXTENSIBLE*)wfe;
- WAVEFORMATEXTENSIBLE* wfexout = (WAVEFORMATEXTENSIBLE*)wfeout;
- int bps = wfe->wBitsPerSample>>3;
- int len = pIn->GetActualDataLength() / (bps*wfe->nChannels);
- int lenout = len * wfeout->nSamplesPerSec / wfe->nSamplesPerSec;
- REFERENCE_TIME rtStart, rtStop;
- if(SUCCEEDED(pIn->GetTime(&rtStart, &rtStop)))
- {
- rtStart += m_rtAudioTimeShift;
- rtStop += m_rtAudioTimeShift;
- pOut->SetTime(&rtStart, &rtStop);
- m_rtNextStart = rtStart;
- m_rtNextStop = rtStop;
- }
- else
- {
- pOut->SetTime(&m_rtNextStart, &m_rtNextStop);
- }
- m_rtNextStart += 10000000i64*len/wfe->nSamplesPerSec;
- m_rtNextStop += 10000000i64*len/wfe->nSamplesPerSec;
- bool fPCM = wfe->wFormatTag == WAVE_FORMAT_PCM
- || wfe->wFormatTag == WAVE_FORMAT_EXTENSIBLE && wfex->SubFormat == KSDATAFORMAT_SUBTYPE_PCM;
- bool fFloat = wfe->wFormatTag == WAVE_FORMAT_IEEE_FLOAT
- || wfe->wFormatTag == WAVE_FORMAT_EXTENSIBLE && wfex->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
- if(!fPCM && !fFloat)
- return __super::Transform(pIn, pOut);
- BYTE* pDataIn = NULL;
- BYTE* pDataOut = NULL;
- HRESULT hr;
- if(FAILED(hr = pIn->GetPointer(&pDataIn))) return hr;
- if(FAILED(hr = pOut->GetPointer(&pDataOut))) return hr;
- if(!pDataIn || !pDataOut || len <= 0 || lenout <= 0) return S_FALSE;
- memset(pDataOut, 0, pOut->GetSize());
- if(m_fCustomChannelMapping)
- {
- if(m_chs[wfe->nChannels-1].GetCount() > 0)
- {
- for(int i = 0; i < wfeout->nChannels; i++)
- {
- DWORD Channel = m_chs[wfe->nChannels-1][i].Channel, nChannels = 0;
- for(int k = 0; k < len; k++)
- {
- if(fPCM && wfe->wBitsPerSample == 8)
- {
- mixchannels(unsigned char, __int64, 0, UCHAR_MAX);
- }
- else if(fPCM && wfe->wBitsPerSample == 16)
- {
- mixchannels(short, __int64, SHRT_MIN, SHRT_MAX);
- }
- else if(fPCM && wfe->wBitsPerSample == 24)
- {
- // mixchannels(_int24, __int64, _INT24_MIN, _INT24_MAX);
- __int64 sum = 0;
- int num = 0;
- for(int j = 0; j < 18 && j < wfe->nChannels; j++)
- {
- if(Channel&(1<<j))
- {
- num++;
- int tmp;
- memcpy((BYTE*)&tmp+1, &pDataIn[bps*(j + wfe->nChannels*k)], 3);
- tmp>>=8;
- sum += tmp;
- }
- }
- sum = min(max(sum, -(1<<24)), (1<<24)-1);
- memcpy(&pDataOut[bps*(i + wfeout->nChannels*k)], (BYTE*)&sum, 3);
- }
- else if(fPCM && wfe->wBitsPerSample == 32)
- {
- mixchannels(int, __int64, INT_MIN, INT_MAX);
- }
- else if(fFloat && wfe->wBitsPerSample == 32)
- {
- mixchannels(float, double, -1, 1);
- }
- else if(fFloat && wfe->wBitsPerSample == 64)
- {
- mixchannels(double, double, -1, 1);
- }
- }
- }
- }
- else
- {
- BYTE* pDataOut = NULL;
- HRESULT hr;
- if(FAILED(hr = pOut->GetPointer(&pDataOut)) || !pDataOut) return hr;
- memset(pDataOut, 0, pOut->GetSize());
- }
- }
- else
- {
- HRESULT hr;
- if(S_OK != (hr = __super::Transform(pIn, pOut)))
- return hr;
- }
- if(m_fDownSampleTo441
- && wfe->nSamplesPerSec > 44100 && wfeout->nSamplesPerSec == 44100
- && wfe->wBitsPerSample <= 16 && fPCM)
- {
- if(BYTE* buff = new BYTE[len*bps])
- {
- for(int ch = 0; ch < wfeout->nChannels; ch++)
- {
- memset(buff, 0, len*bps);
- for(int i = 0; i < len; i++)
- memcpy(buff + i*bps, (char*)pDataOut + (ch + i*wfeout->nChannels)*bps, bps);
- m_pResamplers[ch]->Downsample(buff, len, buff, lenout);
- for(int i = 0; i < lenout; i++)
- memcpy((char*)pDataOut + (ch + i*wfeout->nChannels)*bps, buff + i*bps, bps);
- }
- delete [] buff;
- }
- }
- pOut->SetActualDataLength(lenout*bps*wfeout->nChannels);
- return S_OK;
- }
- CMediaType CAudioSwitcherFilter::CreateNewOutputMediaType(CMediaType mt, long& cbBuffer)
- {
- CStreamSwitcherInputPin* pInPin = GetInputPin();
- CStreamSwitcherOutputPin* pOutPin = GetOutputPin();
- if(!pInPin || !pOutPin || ((WAVEFORMATEX*)mt.pbFormat)->wFormatTag == WAVE_FORMAT_DOLBY_AC3_SPDIF)
- return __super::CreateNewOutputMediaType(mt, cbBuffer);
- WAVEFORMATEX* wfe = (WAVEFORMATEX*)pInPin->CurrentMediaType().pbFormat;
- if(m_fCustomChannelMapping)
- {
- m_chs[wfe->nChannels-1].RemoveAll();
- DWORD mask = DWORD((__int64(1)<<wfe->nChannels)-1);
- for(int i = 0; i < 18; i++)
- {
- if(m_pSpeakerToChannelMap[wfe->nChannels-1][i]&mask)
- {
- ChMap cm = {1<<i, m_pSpeakerToChannelMap[wfe->nChannels-1][i]};
- m_chs[wfe->nChannels-1].Add(cm);
- }
- }
- if(m_chs[wfe->nChannels-1].GetCount() > 0)
- {
- mt.ReallocFormatBuffer(sizeof(WAVEFORMATEXTENSIBLE));
- WAVEFORMATEXTENSIBLE* wfex = (WAVEFORMATEXTENSIBLE*)mt.pbFormat;
- wfex->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
- wfex->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- wfex->Samples.wValidBitsPerSample = wfe->wBitsPerSample;
- wfex->SubFormat =
- wfe->wFormatTag == WAVE_FORMAT_PCM ? KSDATAFORMAT_SUBTYPE_PCM :
- wfe->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ? KSDATAFORMAT_SUBTYPE_IEEE_FLOAT :
- wfe->wFormatTag == WAVE_FORMAT_EXTENSIBLE ? ((WAVEFORMATEXTENSIBLE*)wfe)->SubFormat :
- KSDATAFORMAT_SUBTYPE_PCM; // can't happen
- wfex->dwChannelMask = 0;
- for(int i = 0; i < m_chs[wfe->nChannels-1].GetCount(); i++)
- wfex->dwChannelMask |= m_chs[wfe->nChannels-1][i].Speaker;
- wfex->Format.nChannels = (WORD)m_chs[wfe->nChannels-1].GetCount();
- wfex->Format.nBlockAlign = wfex->Format.nChannels*wfex->Format.wBitsPerSample>>3;
- wfex->Format.nAvgBytesPerSec = wfex->Format.nBlockAlign*wfex->Format.nSamplesPerSec;
- }
- }
- WAVEFORMATEX* wfeout = (WAVEFORMATEX*)mt.pbFormat;
- if(m_fDownSampleTo441)
- {
- if(wfeout->nSamplesPerSec > 44100 && wfeout->wBitsPerSample <= 16)
- {
- wfeout->nSamplesPerSec = 44100;
- wfeout->nAvgBytesPerSec = wfeout->nBlockAlign*wfeout->nSamplesPerSec;
- }
- }
- int bps = wfe->wBitsPerSample>>3;
- int len = cbBuffer / (bps*wfe->nChannels);
- int lenout = len * wfeout->nSamplesPerSec / wfe->nSamplesPerSec;
- cbBuffer = lenout*bps*wfeout->nChannels;
- // mt.lSampleSize = (ULONG)max(mt.lSampleSize, wfe->nAvgBytesPerSec * rtLen / 10000000i64);
- // mt.lSampleSize = (mt.lSampleSize + (wfe->nBlockAlign-1)) & ~(wfe->nBlockAlign-1);
- return mt;
- }
- void CAudioSwitcherFilter::OnNewOutputMediaType(const CMediaType& mtIn, const CMediaType& mtOut)
- {
- const WAVEFORMATEX* wfe = (WAVEFORMATEX*)mtIn.pbFormat;
- const WAVEFORMATEX* wfeout = (WAVEFORMATEX*)mtOut.pbFormat;
- m_pResamplers.RemoveAll();
- for(int i = 0; i < wfeout->nChannels; i++)
- {
- CAutoPtr<AudioStreamResampler> pResampler;
- pResampler.Attach(new AudioStreamResampler(wfeout->wBitsPerSample>>3, wfe->nSamplesPerSec, wfeout->nSamplesPerSec, true));
- m_pResamplers.Add(pResampler);
- }
- }
- // IAudioSwitcherFilter
- STDMETHODIMP CAudioSwitcherFilter::GetInputSpeakerConfig(DWORD* pdwChannelMask)
- {
- if(!pdwChannelMask)
- return E_POINTER;
- *pdwChannelMask = 0;
- CStreamSwitcherInputPin* pInPin = GetInputPin();
- if(!pInPin || !pInPin->IsConnected())
- return E_UNEXPECTED;
- WAVEFORMATEX* wfe = (WAVEFORMATEX*)pInPin->CurrentMediaType().pbFormat;
- if(wfe->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
- {
- WAVEFORMATEXTENSIBLE* wfex = (WAVEFORMATEXTENSIBLE*)wfe;
- *pdwChannelMask = wfex->dwChannelMask;
- }
- else
- {
- *pdwChannelMask = 0/*wfe->nChannels == 1 ? 4 : wfe->nChannels == 2 ? 3 : 0*/;
- }
- return S_OK;
- }
- STDMETHODIMP CAudioSwitcherFilter::GetSpeakerConfig(bool* pfCustomChannelMapping, DWORD pSpeakerToChannelMap[18][18])
- {
- if(pfCustomChannelMapping) *pfCustomChannelMapping = m_fCustomChannelMapping;
- memcpy(pSpeakerToChannelMap, m_pSpeakerToChannelMap, sizeof(m_pSpeakerToChannelMap));
- return S_OK;
- }
- STDMETHODIMP CAudioSwitcherFilter::SetSpeakerConfig(bool fCustomChannelMapping, DWORD pSpeakerToChannelMap[18][18])
- {
- if(m_State == State_Stopped || m_fCustomChannelMapping != fCustomChannelMapping
- || memcmp(m_pSpeakerToChannelMap, pSpeakerToChannelMap, sizeof(m_pSpeakerToChannelMap)))
- {
- PauseGraph;
-
- CStreamSwitcherInputPin* pInput = GetInputPin();
- SelectInput(NULL);
- m_fCustomChannelMapping = fCustomChannelMapping;
- memcpy(m_pSpeakerToChannelMap, pSpeakerToChannelMap, sizeof(m_pSpeakerToChannelMap));
- SelectInput(pInput);
- ResumeGraph;
- }
- return S_OK;
- }
- STDMETHODIMP_(int) CAudioSwitcherFilter::GetNumberOfInputChannels()
- {
- CStreamSwitcherInputPin* pInPin = GetInputPin();
- return pInPin ? ((WAVEFORMATEX*)pInPin->CurrentMediaType().pbFormat)->nChannels : 0;
- }
- STDMETHODIMP_(bool) CAudioSwitcherFilter::IsDownSamplingTo441Enabled()
- {
- return(m_fDownSampleTo441);
- }
- STDMETHODIMP CAudioSwitcherFilter::EnableDownSamplingTo441(bool fEnable)
- {
- if(m_fDownSampleTo441 != fEnable)
- {
- PauseGraph;
- m_fDownSampleTo441 = fEnable;
- ResumeGraph;
- }
- return S_OK;
- }
- STDMETHODIMP_(REFERENCE_TIME) CAudioSwitcherFilter::GetAudioTimeShift()
- {
- return(m_rtAudioTimeShift);
- }
- STDMETHODIMP CAudioSwitcherFilter::SetAudioTimeShift(REFERENCE_TIME rtAudioTimeShift)
- {
- m_rtAudioTimeShift = rtAudioTimeShift;
- return S_OK;
- }