wavdest.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:9k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "stdafx.h"
  22. #include <streams.h>
  23. #include <aviriff.h>
  24. #include "wavdest.h"
  25. #include "......DSUtilDSUtil.h"
  26. #ifdef REGISTER_FILTER
  27. const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
  28. {
  29. {&MEDIATYPE_Audio, &MEDIASUBTYPE_WAVE},
  30. };
  31. const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
  32. {
  33. {&MEDIATYPE_Stream, &MEDIASUBTYPE_WAVE},
  34. };
  35. const AMOVIESETUP_PIN sudpPins[] =
  36. {
  37.     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
  38.     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
  39. };
  40. const AMOVIESETUP_FILTER sudFilter[] =
  41. {
  42. {&__uuidof(CWavDestFilter), L"WavDest", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins}
  43. };
  44. CFactoryTemplate g_Templates[] =
  45. {
  46.     {L"WavDest", &__uuidof(CWavDestFilter), CreateInstance<CWavDestFilter>, NULL, &sudFilter[0]}
  47. };
  48. int g_cTemplates = countof(g_Templates);
  49. STDAPI DllRegisterServer()
  50. {
  51. return AMovieDllRegisterServer2(TRUE);
  52. }
  53. STDAPI DllUnregisterServer()
  54. {
  55. return AMovieDllRegisterServer2(FALSE);
  56. }
  57. extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
  58. BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
  59. {
  60.     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
  61. }
  62. #endif
  63. //
  64. // CWavDestFilter
  65. //
  66. CWavDestFilter::CWavDestFilter(LPUNKNOWN pUnk, HRESULT* phr)
  67. : CTransformFilter(NAME("WavDest filter"), pUnk, __uuidof(this))
  68. {
  69.     if(SUCCEEDED(*phr))
  70.     {
  71.         if(CWavDestOutputPin* pOut = new CWavDestOutputPin(this, phr))
  72.         {
  73.             if(SUCCEEDED(*phr)) m_pOutput = pOut;
  74.             else delete pOut;
  75.         }
  76.         else
  77.         {
  78.             *phr = E_OUTOFMEMORY;
  79. return;
  80.         }
  81. if(CTransformInputPin* pIn = new CTransformInputPin(NAME("Transform input pin"), this, phr, L"In"))
  82.         {
  83.             if(SUCCEEDED(*phr)) m_pInput = pIn;
  84.             else delete pIn;
  85.         }
  86.         else
  87.         {
  88.             *phr = E_OUTOFMEMORY;
  89. return;
  90.         }
  91.     }
  92. }
  93. CWavDestFilter::~CWavDestFilter()
  94. {
  95. }
  96. HRESULT CWavDestFilter::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
  97. {
  98.     return CheckInputType(mtIn);
  99. }
  100. HRESULT CWavDestFilter::Receive(IMediaSample* pSample)
  101. {
  102.     ULONG cbOld = m_cbWavData;
  103.     HRESULT hr = CTransformFilter::Receive(pSample);
  104.     // don't update the count if Deliver() downstream fails.
  105.     if(hr != S_OK)
  106. m_cbWavData = cbOld;
  107.     return hr;
  108. }
  109. HRESULT CWavDestFilter::Transform(IMediaSample* pIn, IMediaSample* pOut)
  110. {
  111.     REFERENCE_TIME rtStart, rtEnd;
  112.     
  113.     HRESULT hr = Copy(pIn, pOut);
  114.     if(FAILED(hr))
  115. return hr;
  116.     // Prepare it for writing
  117.     LONG lActual = pOut->GetActualDataLength();
  118.     if(m_cbWavData + m_cbHeader + lActual < m_cbWavData + m_cbHeader ) // overflow
  119.         return E_FAIL;
  120.     rtStart = m_cbWavData + m_cbHeader;
  121.     rtEnd = rtStart + lActual;
  122.     m_cbWavData += lActual;
  123.     EXECUTE_ASSERT(pOut->SetTime(&rtStart, &rtEnd) == S_OK);
  124.     
  125.     return S_OK;
  126. }
  127. HRESULT CWavDestFilter::Copy(IMediaSample* pSource, IMediaSample* pDest) const
  128. {
  129.     BYTE* pSourceBuffer, * pDestBuffer;
  130.     long lSourceSize = pSource->GetActualDataLength();
  131. #ifdef DEBUG
  132.     long lDestSize = pDest->GetSize();
  133.     ASSERT(lDestSize >= lSourceSize);
  134. #endif
  135.         
  136.     pSource->GetPointer(&pSourceBuffer);
  137.     pDest->GetPointer(&pDestBuffer);
  138.     CopyMemory((PVOID)pDestBuffer, (PVOID)pSourceBuffer, lSourceSize);
  139.     // Copy the sample times
  140.     REFERENCE_TIME TimeStart, TimeEnd;
  141.     if(NOERROR == pSource->GetTime(&TimeStart, &TimeEnd))
  142. pDest->SetTime(&TimeStart, &TimeEnd);
  143.     LONGLONG MediaStart, MediaEnd;
  144.     if(pSource->GetMediaTime(&MediaStart, &MediaEnd) == NOERROR)
  145. pDest->SetMediaTime(&MediaStart, &MediaEnd);
  146.     // Copy the media type
  147.     AM_MEDIA_TYPE* pMediaType;
  148.     pSource->GetMediaType(&pMediaType);
  149.     pDest->SetMediaType(pMediaType);
  150.     DeleteMediaType(pMediaType);
  151.     // Copy the actual data length
  152.     long lDataLength = pSource->GetActualDataLength();
  153.     pDest->SetActualDataLength(lDataLength);
  154. return NOERROR;
  155. }
  156. HRESULT CWavDestFilter::CheckInputType(const CMediaType* mtIn)
  157. {
  158. return mtIn->formattype == FORMAT_WaveFormatEx ? S_OK : S_FALSE;
  159. }
  160. HRESULT CWavDestFilter::GetMediaType(int iPosition, CMediaType* pMediaType)
  161. {
  162.     ASSERT(iPosition == 0 || iPosition == 1);
  163. if(iPosition == 0)
  164. {
  165.         pMediaType->SetType(&MEDIATYPE_Stream);
  166.         pMediaType->SetSubtype(&MEDIASUBTYPE_WAVE);
  167.         return S_OK;
  168.     }
  169.     return VFW_S_NO_MORE_ITEMS;
  170. }
  171. HRESULT CWavDestFilter::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
  172. {
  173.     if(m_pInput->IsConnected() == FALSE)
  174. return E_UNEXPECTED;
  175.     ASSERT(pAlloc);
  176.     ASSERT(pProperties);
  177. HRESULT hr = NOERROR;
  178.     pProperties->cBuffers = 1;
  179.     pProperties->cbAlign = 1;
  180.     
  181.     CComPtr<IMemAllocator> pInAlloc;
  182.     ALLOCATOR_PROPERTIES InProps;
  183.     if(SUCCEEDED(hr = m_pInput->GetAllocator(&pInAlloc))
  184. && SUCCEEDED(hr = pInAlloc->GetProperties(&InProps)))
  185.     {
  186. pProperties->cbBuffer = InProps.cbBuffer;
  187.     }
  188. else
  189. {
  190. return hr;
  191. }
  192.     ASSERT(pProperties->cbBuffer);
  193.     ALLOCATOR_PROPERTIES Actual;
  194.     if(FAILED(hr = pAlloc->SetProperties(pProperties,&Actual)))
  195. return hr;
  196.     ASSERT(Actual.cBuffers == 1);
  197.     if(pProperties->cBuffers > Actual.cBuffers
  198. || pProperties->cbBuffer > Actual.cbBuffer)
  199. {
  200. return E_FAIL;
  201.     }
  202.     return NOERROR;
  203. }
  204. // Compute the header size to allow space for us to write it at the end.
  205. //
  206. // 00000000    RIFF (00568BFE) 'WAVE'
  207. // 0000000C        fmt  (00000010)
  208. // 00000024        data (00568700)
  209. // 0056872C
  210. //
  211. HRESULT CWavDestFilter::StartStreaming()
  212. {
  213.     // leave space for the header
  214.     m_cbHeader = sizeof(RIFFLIST) + 
  215.                  sizeof(RIFFCHUNK) + 
  216.                  m_pInput->CurrentMediaType().FormatLength() + 
  217.                  sizeof(RIFFCHUNK);
  218.                  
  219.     m_cbWavData = 0;
  220.     return S_OK;
  221. }
  222. HRESULT CWavDestFilter::StopStreaming()
  223. {
  224.     IStream* pStream;
  225.     if (m_pOutput->IsConnected() == FALSE)
  226.         return E_FAIL;
  227.     IPin* pDwnstrmInputPin = m_pOutput->GetConnected();
  228.     if (!pDwnstrmInputPin)
  229.         return E_FAIL;
  230.     HRESULT hr = ((IMemInputPin *) pDwnstrmInputPin)->QueryInterface(IID_IStream, (void **)&pStream);
  231.     if(SUCCEEDED(hr))
  232.     {
  233.         BYTE *pb = (BYTE *)_alloca(m_cbHeader);
  234.         RIFFLIST *pRiffWave = (RIFFLIST *)pb;
  235.         RIFFCHUNK *pRiffFmt = (RIFFCHUNK *)(pRiffWave + 1);
  236.         RIFFCHUNK *pRiffData = (RIFFCHUNK *)(((BYTE *)(pRiffFmt + 1)) +  m_pInput->CurrentMediaType().FormatLength());;
  237.         pRiffData->fcc = FCC('data');
  238.         pRiffData->cb = m_cbWavData;
  239.         pRiffFmt->fcc = FCC('fmt ');
  240.         pRiffFmt->cb = m_pInput->CurrentMediaType().FormatLength();
  241.         CopyMemory(pRiffFmt + 1, m_pInput->CurrentMediaType().Format(), pRiffFmt->cb);
  242.         pRiffWave->fcc = FCC('RIFF');
  243.         pRiffWave->cb = m_cbWavData + m_cbHeader - sizeof(RIFFCHUNK);
  244.         pRiffWave->fccListType = FCC('WAVE');
  245.         LARGE_INTEGER li;
  246.         ZeroMemory(&li, sizeof(li));
  247.         
  248.         hr = pStream->Seek(li, STREAM_SEEK_SET, 0);
  249.         if(SUCCEEDED(hr)) {
  250.             hr = pStream->Write(pb, m_cbHeader, 0);
  251.         }
  252.         pStream->Release();
  253.     }
  254.     return hr;
  255. }
  256. CWavDestOutputPin::CWavDestOutputPin(CTransformFilter* pFilter, HRESULT* phr)
  257. : CTransformOutputPin(NAME("WavDest output pin"), pFilter, phr, L"Out")
  258. {
  259. }
  260. STDMETHODIMP CWavDestOutputPin::EnumMediaTypes(IEnumMediaTypes** ppEnum)
  261. {
  262.     return CBaseOutputPin::EnumMediaTypes(ppEnum);
  263. }
  264. HRESULT CWavDestOutputPin::CheckMediaType(const CMediaType* pmt)
  265. {
  266.     if(pmt->majortype == MEDIATYPE_Stream && pmt->subtype == MEDIASUBTYPE_WAVE)
  267.         return S_OK;
  268.     else
  269.         return S_FALSE;
  270. }