00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023
00024 #include "Shlwapi.h"
00025 #include <atlpath.h>
00026 #include <mmreg.h>
00027 #include <ks.h>
00028 #include <ksmedia.h>
00029 #include "AudioSwitcher.h"
00030 #include "Audio.h"
00031 #include "..\..\..\DSUtil\DSUtil.h"
00032
00033 #include <initguid.h>
00034 #include "..\..\..\..\include\Ogg\OggDS.h"
00035
00036
00037 #ifdef REGISTER_FILTER
00038
00039 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
00040 {
00041 {&MEDIATYPE_Audio, &MEDIASUBTYPE_NULL}
00042 };
00043
00044 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
00045 {
00046 {&MEDIATYPE_Audio, &MEDIASUBTYPE_NULL}
00047 };
00048
00049 const AMOVIESETUP_PIN sudpPins[] =
00050 {
00051 {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
00052 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
00053 };
00054
00055 const AMOVIESETUP_FILTER sudFilter[] =
00056 {
00057 {&__uuidof(CAudioSwitcherFilter), L"AudioSwitcher", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins}
00058 };
00059
00060 CFactoryTemplate g_Templates[] =
00061 {
00062 {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CAudioSwitcherFilter>, NULL, &sudFilter[0]}
00063 };
00064
00065 int g_cTemplates = countof(g_Templates);
00066
00067 STDAPI DllRegisterServer()
00068 {
00069 return AMovieDllRegisterServer2(TRUE);
00070 }
00071
00072 STDAPI DllUnregisterServer()
00073 {
00074 return AMovieDllRegisterServer2(FALSE);
00075 }
00076
00077 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00078
00079 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00080 {
00081 return DllEntryPoint((HINSTANCE)hModule, dwReason, 0);
00082 }
00083
00084 #endif
00085
00086
00087
00088
00089
00090 CAudioSwitcherFilter::CAudioSwitcherFilter(LPUNKNOWN lpunk, HRESULT* phr)
00091 : CStreamSwitcherFilter(lpunk, phr, __uuidof(this))
00092 {
00093 if(phr)
00094 {
00095 if(FAILED(*phr)) return;
00096 else *phr = S_OK;
00097 }
00098
00099 m_fCustomChannelMapping = false;
00100 memset(m_pSpeakerToChannelMap, 0, sizeof(m_pSpeakerToChannelMap));
00101 m_fDownSampleTo441 = false;
00102 m_rtAudioTimeShift = 0;
00103 m_rtNextStart = 0;
00104 m_rtNextStop = 1;
00105 }
00106
00107 STDMETHODIMP CAudioSwitcherFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00108 {
00109 return
00110 QI(IAudioSwitcherFilter)
00111 __super::NonDelegatingQueryInterface(riid, ppv);
00112 }
00113
00114 HRESULT CAudioSwitcherFilter::CheckMediaType(const CMediaType* pmt)
00115 {
00116 if(pmt->formattype == FORMAT_WaveFormatEx
00117 && ((WAVEFORMATEX*)pmt->pbFormat)->nChannels > 2
00118 && ((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag != WAVE_FORMAT_EXTENSIBLE)
00119 return VFW_E_INVALIDMEDIATYPE;
00120
00121 return (pmt->majortype == MEDIATYPE_Audio
00122 && pmt->formattype == FORMAT_WaveFormatEx
00123 && (((WAVEFORMATEX*)pmt->pbFormat)->wBitsPerSample == 8
00124 || ((WAVEFORMATEX*)pmt->pbFormat)->wBitsPerSample == 16
00125 || ((WAVEFORMATEX*)pmt->pbFormat)->wBitsPerSample == 24
00126 || ((WAVEFORMATEX*)pmt->pbFormat)->wBitsPerSample == 32)
00127 && (((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag == WAVE_FORMAT_PCM
00128 || ((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag == WAVE_FORMAT_IEEE_FLOAT
00129 || ((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag == WAVE_FORMAT_DOLBY_AC3_SPDIF
00130 || ((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag == WAVE_FORMAT_EXTENSIBLE))
00131 ? S_OK
00132 : VFW_E_TYPE_NOT_ACCEPTED;
00133 }
00134
00135 #define mixchannels(type, sumtype, mintype, maxtype) \
00136 sumtype sum = 0; \
00137 int num = 0; \
00138 for(int j = 0; j < 18 && j < wfe->nChannels; j++) \
00139 { \
00140 if(Channel&(1<<j)) \
00141 { \
00142 num++; \
00143 sum += *(type*)&pDataIn[bps*(j + wfe->nChannels*k)]; \
00144 } \
00145 } \
00146 sum = min(max(sum, mintype), maxtype); \
00147 *(type*)&pDataOut[bps*(i + wfeout->nChannels*k)] = (type)sum; \
00148
00149 HRESULT CAudioSwitcherFilter::Transform(IMediaSample* pIn, IMediaSample* pOut)
00150 {
00151 CStreamSwitcherInputPin* pInPin = GetInputPin();
00152 CStreamSwitcherOutputPin* pOutPin = GetOutputPin();
00153 if(!pInPin || !pOutPin)
00154 return __super::Transform(pIn, pOut);
00155
00156 WAVEFORMATEX* wfe = (WAVEFORMATEX*)pInPin->CurrentMediaType().pbFormat;
00157 WAVEFORMATEX* wfeout = (WAVEFORMATEX*)pOutPin->CurrentMediaType().pbFormat;
00158 WAVEFORMATEXTENSIBLE* wfex = (WAVEFORMATEXTENSIBLE*)wfe;
00159 WAVEFORMATEXTENSIBLE* wfexout = (WAVEFORMATEXTENSIBLE*)wfeout;
00160
00161 int bps = wfe->wBitsPerSample>>3;
00162
00163 int len = pIn->GetActualDataLength() / (bps*wfe->nChannels);
00164 int lenout = len * wfeout->nSamplesPerSec / wfe->nSamplesPerSec;
00165
00166 REFERENCE_TIME rtStart, rtStop;
00167 if(SUCCEEDED(pIn->GetTime(&rtStart, &rtStop)))
00168 {
00169 rtStart += m_rtAudioTimeShift;
00170 rtStop += m_rtAudioTimeShift;
00171 pOut->SetTime(&rtStart, &rtStop);
00172
00173 m_rtNextStart = rtStart;
00174 m_rtNextStop = rtStop;
00175 }
00176 else
00177 {
00178 pOut->SetTime(&m_rtNextStart, &m_rtNextStop);
00179 }
00180
00181 m_rtNextStart += 10000000i64*len/wfe->nSamplesPerSec;
00182 m_rtNextStop += 10000000i64*len/wfe->nSamplesPerSec;
00183
00184 bool fPCM = wfe->wFormatTag == WAVE_FORMAT_PCM
00185 || wfe->wFormatTag == WAVE_FORMAT_EXTENSIBLE && wfex->SubFormat == KSDATAFORMAT_SUBTYPE_PCM;
00186
00187 bool fFloat = wfe->wFormatTag == WAVE_FORMAT_IEEE_FLOAT
00188 || wfe->wFormatTag == WAVE_FORMAT_EXTENSIBLE && wfex->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
00189
00190 if(!fPCM && !fFloat)
00191 return __super::Transform(pIn, pOut);
00192
00193 BYTE* pDataIn = NULL;
00194 BYTE* pDataOut = NULL;
00195
00196 HRESULT hr;
00197 if(FAILED(hr = pIn->GetPointer(&pDataIn))) return hr;
00198 if(FAILED(hr = pOut->GetPointer(&pDataOut))) return hr;
00199
00200 if(!pDataIn || !pDataOut || len <= 0 || lenout <= 0) return S_FALSE;
00201
00202 memset(pDataOut, 0, pOut->GetSize());
00203
00204 if(m_fCustomChannelMapping)
00205 {
00206 if(m_chs[wfe->nChannels-1].GetCount() > 0)
00207 {
00208 for(int i = 0; i < wfeout->nChannels; i++)
00209 {
00210 DWORD Channel = m_chs[wfe->nChannels-1][i].Channel, nChannels = 0;
00211
00212 for(int k = 0; k < len; k++)
00213 {
00214 if(fPCM && wfe->wBitsPerSample == 8)
00215 {
00216 mixchannels(unsigned char, __int64, 0, UCHAR_MAX);
00217 }
00218 else if(fPCM && wfe->wBitsPerSample == 16)
00219 {
00220 mixchannels(short, __int64, SHRT_MIN, SHRT_MAX);
00221 }
00222 else if(fPCM && wfe->wBitsPerSample == 24)
00223 {
00224
00225
00226 __int64 sum = 0;
00227 int num = 0;
00228 for(int j = 0; j < 18 && j < wfe->nChannels; j++)
00229 {
00230 if(Channel&(1<<j))
00231 {
00232 num++;
00233 int tmp;
00234 memcpy((BYTE*)&tmp+1, &pDataIn[bps*(j + wfe->nChannels*k)], 3);
00235 tmp>>=8;
00236 sum += tmp;
00237 }
00238 }
00239 sum = min(max(sum, -(1<<24)), (1<<24)-1);
00240 memcpy(&pDataOut[bps*(i + wfeout->nChannels*k)], (BYTE*)&sum, 3);
00241 }
00242 else if(fPCM && wfe->wBitsPerSample == 32)
00243 {
00244 mixchannels(int, __int64, INT_MIN, INT_MAX);
00245 }
00246 else if(fFloat && wfe->wBitsPerSample == 32)
00247 {
00248 mixchannels(float, double, -1, 1);
00249 }
00250 else if(fFloat && wfe->wBitsPerSample == 64)
00251 {
00252 mixchannels(double, double, -1, 1);
00253 }
00254 }
00255 }
00256 }
00257 else
00258 {
00259 BYTE* pDataOut = NULL;
00260 HRESULT hr;
00261 if(FAILED(hr = pOut->GetPointer(&pDataOut)) || !pDataOut) return hr;
00262 memset(pDataOut, 0, pOut->GetSize());
00263 }
00264 }
00265 else
00266 {
00267 HRESULT hr;
00268 if(S_OK != (hr = __super::Transform(pIn, pOut)))
00269 return hr;
00270 }
00271
00272 if(m_fDownSampleTo441
00273 && wfe->nSamplesPerSec > 44100 && wfeout->nSamplesPerSec == 44100
00274 && wfe->wBitsPerSample <= 16 && fPCM)
00275 {
00276 if(BYTE* buff = new BYTE[len*bps])
00277 {
00278 for(int ch = 0; ch < wfeout->nChannels; ch++)
00279 {
00280 memset(buff, 0, len*bps);
00281
00282 for(int i = 0; i < len; i++)
00283 memcpy(buff + i*bps, (char*)pDataOut + (ch + i*wfeout->nChannels)*bps, bps);
00284
00285 m_pResamplers[ch]->Downsample(buff, len, buff, lenout);
00286
00287 for(int i = 0; i < lenout; i++)
00288 memcpy((char*)pDataOut + (ch + i*wfeout->nChannels)*bps, buff + i*bps, bps);
00289 }
00290
00291 delete [] buff;
00292 }
00293 }
00294
00295 pOut->SetActualDataLength(lenout*bps*wfeout->nChannels);
00296
00297 return S_OK;
00298 }
00299
00300 CMediaType CAudioSwitcherFilter::CreateNewOutputMediaType(CMediaType mt, long& cbBuffer)
00301 {
00302 CStreamSwitcherInputPin* pInPin = GetInputPin();
00303 CStreamSwitcherOutputPin* pOutPin = GetOutputPin();
00304 if(!pInPin || !pOutPin || ((WAVEFORMATEX*)mt.pbFormat)->wFormatTag == WAVE_FORMAT_DOLBY_AC3_SPDIF)
00305 return __super::CreateNewOutputMediaType(mt, cbBuffer);
00306
00307 WAVEFORMATEX* wfe = (WAVEFORMATEX*)pInPin->CurrentMediaType().pbFormat;
00308
00309 if(m_fCustomChannelMapping)
00310 {
00311 m_chs[wfe->nChannels-1].RemoveAll();
00312
00313 DWORD mask = DWORD((__int64(1)<<wfe->nChannels)-1);
00314 for(int i = 0; i < 18; i++)
00315 {
00316 if(m_pSpeakerToChannelMap[wfe->nChannels-1][i]&mask)
00317 {
00318 ChMap cm = {1<<i, m_pSpeakerToChannelMap[wfe->nChannels-1][i]};
00319 m_chs[wfe->nChannels-1].Add(cm);
00320 }
00321 }
00322
00323 if(m_chs[wfe->nChannels-1].GetCount() > 0)
00324 {
00325 mt.ReallocFormatBuffer(sizeof(WAVEFORMATEXTENSIBLE));
00326 WAVEFORMATEXTENSIBLE* wfex = (WAVEFORMATEXTENSIBLE*)mt.pbFormat;
00327 wfex->Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
00328 wfex->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
00329 wfex->Samples.wValidBitsPerSample = wfe->wBitsPerSample;
00330 wfex->SubFormat =
00331 wfe->wFormatTag == WAVE_FORMAT_PCM ? KSDATAFORMAT_SUBTYPE_PCM :
00332 wfe->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ? KSDATAFORMAT_SUBTYPE_IEEE_FLOAT :
00333 wfe->wFormatTag == WAVE_FORMAT_EXTENSIBLE ? ((WAVEFORMATEXTENSIBLE*)wfe)->SubFormat :
00334 KSDATAFORMAT_SUBTYPE_PCM;
00335
00336 wfex->dwChannelMask = 0;
00337 for(int i = 0; i < m_chs[wfe->nChannels-1].GetCount(); i++)
00338 wfex->dwChannelMask |= m_chs[wfe->nChannels-1][i].Speaker;
00339
00340 wfex->Format.nChannels = (WORD)m_chs[wfe->nChannels-1].GetCount();
00341 wfex->Format.nBlockAlign = wfex->Format.nChannels*wfex->Format.wBitsPerSample>>3;
00342 wfex->Format.nAvgBytesPerSec = wfex->Format.nBlockAlign*wfex->Format.nSamplesPerSec;
00343 }
00344 }
00345
00346 WAVEFORMATEX* wfeout = (WAVEFORMATEX*)mt.pbFormat;
00347
00348 if(m_fDownSampleTo441)
00349 {
00350 if(wfeout->nSamplesPerSec > 44100 && wfeout->wBitsPerSample <= 16)
00351 {
00352 wfeout->nSamplesPerSec = 44100;
00353 wfeout->nAvgBytesPerSec = wfeout->nBlockAlign*wfeout->nSamplesPerSec;
00354 }
00355 }
00356
00357 int bps = wfe->wBitsPerSample>>3;
00358 int len = cbBuffer / (bps*wfe->nChannels);
00359 int lenout = len * wfeout->nSamplesPerSec / wfe->nSamplesPerSec;
00360 cbBuffer = lenout*bps*wfeout->nChannels;
00361
00362
00363
00364
00365 return mt;
00366 }
00367
00368 void CAudioSwitcherFilter::OnNewOutputMediaType(const CMediaType& mtIn, const CMediaType& mtOut)
00369 {
00370 const WAVEFORMATEX* wfe = (WAVEFORMATEX*)mtIn.pbFormat;
00371 const WAVEFORMATEX* wfeout = (WAVEFORMATEX*)mtOut.pbFormat;
00372
00373 m_pResamplers.RemoveAll();
00374 for(int i = 0; i < wfeout->nChannels; i++)
00375 {
00376 CAutoPtr<AudioStreamResampler> pResampler;
00377 pResampler.Attach(new AudioStreamResampler(wfeout->wBitsPerSample>>3, wfe->nSamplesPerSec, wfeout->nSamplesPerSec, true));
00378 m_pResamplers.Add(pResampler);
00379 }
00380 }
00381
00382
00383
00384 STDMETHODIMP CAudioSwitcherFilter::GetInputSpeakerConfig(DWORD* pdwChannelMask)
00385 {
00386 if(!pdwChannelMask)
00387 return E_POINTER;
00388
00389 *pdwChannelMask = 0;
00390
00391 CStreamSwitcherInputPin* pInPin = GetInputPin();
00392 if(!pInPin || !pInPin->IsConnected())
00393 return E_UNEXPECTED;
00394
00395 WAVEFORMATEX* wfe = (WAVEFORMATEX*)pInPin->CurrentMediaType().pbFormat;
00396
00397 if(wfe->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
00398 {
00399 WAVEFORMATEXTENSIBLE* wfex = (WAVEFORMATEXTENSIBLE*)wfe;
00400 *pdwChannelMask = wfex->dwChannelMask;
00401 }
00402 else
00403 {
00404 *pdwChannelMask = 0;
00405 }
00406
00407 return S_OK;
00408 }
00409
00410 STDMETHODIMP CAudioSwitcherFilter::GetSpeakerConfig(bool* pfCustomChannelMapping, DWORD pSpeakerToChannelMap[18][18])
00411 {
00412 if(pfCustomChannelMapping) *pfCustomChannelMapping = m_fCustomChannelMapping;
00413 memcpy(pSpeakerToChannelMap, m_pSpeakerToChannelMap, sizeof(m_pSpeakerToChannelMap));
00414
00415 return S_OK;
00416 }
00417
00418 STDMETHODIMP CAudioSwitcherFilter::SetSpeakerConfig(bool fCustomChannelMapping, DWORD pSpeakerToChannelMap[18][18])
00419 {
00420 if(m_State == State_Stopped || m_fCustomChannelMapping != fCustomChannelMapping
00421 || memcmp(m_pSpeakerToChannelMap, pSpeakerToChannelMap, sizeof(m_pSpeakerToChannelMap)))
00422 {
00423 PauseGraph;
00424
00425 CStreamSwitcherInputPin* pInput = GetInputPin();
00426
00427 SelectInput(NULL);
00428
00429 m_fCustomChannelMapping = fCustomChannelMapping;
00430 memcpy(m_pSpeakerToChannelMap, pSpeakerToChannelMap, sizeof(m_pSpeakerToChannelMap));
00431
00432 SelectInput(pInput);
00433
00434 ResumeGraph;
00435 }
00436
00437 return S_OK;
00438 }
00439
00440 STDMETHODIMP_(int) CAudioSwitcherFilter::GetNumberOfInputChannels()
00441 {
00442 CStreamSwitcherInputPin* pInPin = GetInputPin();
00443 return pInPin ? ((WAVEFORMATEX*)pInPin->CurrentMediaType().pbFormat)->nChannels : 0;
00444 }
00445
00446 STDMETHODIMP_(bool) CAudioSwitcherFilter::IsDownSamplingTo441Enabled()
00447 {
00448 return(m_fDownSampleTo441);
00449 }
00450
00451 STDMETHODIMP CAudioSwitcherFilter::EnableDownSamplingTo441(bool fEnable)
00452 {
00453 if(m_fDownSampleTo441 != fEnable)
00454 {
00455 PauseGraph;
00456
00457 m_fDownSampleTo441 = fEnable;
00458
00459 ResumeGraph;
00460 }
00461
00462 return S_OK;
00463 }
00464
00465 STDMETHODIMP_(REFERENCE_TIME) CAudioSwitcherFilter::GetAudioTimeShift()
00466 {
00467 return(m_rtAudioTimeShift);
00468 }
00469
00470 STDMETHODIMP CAudioSwitcherFilter::SetAudioTimeShift(REFERENCE_TIME rtAudioTimeShift)
00471 {
00472 m_rtAudioTimeShift = rtAudioTimeShift;
00473 return S_OK;
00474 }