wavdest.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
00019  *
00020  */
00021 
00022 #include "stdafx.h"
00023 #include <streams.h>
00024 #include <aviriff.h>
00025 #include "wavdest.h"
00026 #include "..\..\..\DSUtil\DSUtil.h"
00027 
00028 #ifdef REGISTER_FILTER
00029 
00030 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
00031 {
00032         {&MEDIATYPE_Audio, &MEDIASUBTYPE_WAVE},
00033 };
00034 
00035 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
00036 {
00037         {&MEDIATYPE_Stream, &MEDIASUBTYPE_WAVE},
00038 };
00039 
00040 const AMOVIESETUP_PIN sudpPins[] =
00041 {
00042     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
00043     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
00044 };
00045 
00046 const AMOVIESETUP_FILTER sudFilter[] =
00047 {
00048         {&__uuidof(CWavDestFilter), L"WavDest", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins}
00049 };
00050 
00051 CFactoryTemplate g_Templates[] =
00052 {
00053     {L"WavDest", &__uuidof(CWavDestFilter), CreateInstance<CWavDestFilter>, NULL, &sudFilter[0]}
00054 };
00055 
00056 int g_cTemplates = countof(g_Templates);
00057 
00058 STDAPI DllRegisterServer()
00059 {
00060         return AMovieDllRegisterServer2(TRUE);
00061 }
00062 
00063 STDAPI DllUnregisterServer()
00064 {
00065         return AMovieDllRegisterServer2(FALSE);
00066 }
00067 
00068 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00069 
00070 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00071 {
00072     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
00073 }
00074 
00075 #endif
00076 
00077 //
00078 // CWavDestFilter
00079 //
00080 
00081 CWavDestFilter::CWavDestFilter(LPUNKNOWN pUnk, HRESULT* phr)
00082         : CTransformFilter(NAME("WavDest filter"), pUnk, __uuidof(this))
00083 {
00084     if(SUCCEEDED(*phr))
00085     {
00086         if(CWavDestOutputPin* pOut = new CWavDestOutputPin(this, phr))
00087         {
00088             if(SUCCEEDED(*phr)) m_pOutput = pOut;
00089             else delete pOut;
00090         }
00091         else
00092         {
00093             *phr = E_OUTOFMEMORY;
00094                         return;
00095         }
00096 
00097                 if(CTransformInputPin* pIn = new CTransformInputPin(NAME("Transform input pin"), this, phr, L"In"))
00098         {
00099             if(SUCCEEDED(*phr)) m_pInput = pIn;
00100             else delete pIn;
00101         }
00102         else
00103         {
00104             *phr = E_OUTOFMEMORY;
00105                         return;
00106         }
00107     }
00108 }
00109 
00110 CWavDestFilter::~CWavDestFilter()
00111 {
00112 }
00113 
00114 HRESULT CWavDestFilter::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
00115 {
00116     return CheckInputType(mtIn);
00117 }
00118 
00119 HRESULT CWavDestFilter::Receive(IMediaSample* pSample)
00120 {
00121     ULONG cbOld = m_cbWavData;
00122     HRESULT hr = CTransformFilter::Receive(pSample);
00123 
00124     // don't update the count if Deliver() downstream fails.
00125     if(hr != S_OK)
00126                 m_cbWavData = cbOld;
00127 
00128     return hr;
00129 }
00130 
00131 HRESULT CWavDestFilter::Transform(IMediaSample* pIn, IMediaSample* pOut)
00132 {
00133     REFERENCE_TIME rtStart, rtEnd;
00134     
00135     HRESULT hr = Copy(pIn, pOut);
00136     if(FAILED(hr))
00137                 return hr;
00138 
00139     // Prepare it for writing
00140     LONG lActual = pOut->GetActualDataLength();
00141 
00142     if(m_cbWavData + m_cbHeader + lActual < m_cbWavData + m_cbHeader ) // overflow
00143         return E_FAIL;
00144 
00145     rtStart = m_cbWavData + m_cbHeader;
00146     rtEnd = rtStart + lActual;
00147     m_cbWavData += lActual;
00148 
00149     EXECUTE_ASSERT(pOut->SetTime(&rtStart, &rtEnd) == S_OK);
00150     
00151     return S_OK;
00152 }
00153 
00154 HRESULT CWavDestFilter::Copy(IMediaSample* pSource, IMediaSample* pDest) const
00155 {
00156     BYTE* pSourceBuffer, * pDestBuffer;
00157     long lSourceSize = pSource->GetActualDataLength();
00158 
00159 #ifdef DEBUG
00160     long lDestSize      = pDest->GetSize();
00161     ASSERT(lDestSize >= lSourceSize);
00162 #endif
00163         
00164     pSource->GetPointer(&pSourceBuffer);
00165     pDest->GetPointer(&pDestBuffer);
00166 
00167     CopyMemory((PVOID)pDestBuffer, (PVOID)pSourceBuffer, lSourceSize);
00168 
00169     // Copy the sample times
00170 
00171     REFERENCE_TIME TimeStart, TimeEnd;
00172     if(NOERROR == pSource->GetTime(&TimeStart, &TimeEnd))
00173                 pDest->SetTime(&TimeStart, &TimeEnd);
00174 
00175     LONGLONG MediaStart, MediaEnd;
00176     if(pSource->GetMediaTime(&MediaStart, &MediaEnd) == NOERROR)
00177                 pDest->SetMediaTime(&MediaStart, &MediaEnd);
00178 
00179     // Copy the media type
00180     AM_MEDIA_TYPE* pMediaType;
00181     pSource->GetMediaType(&pMediaType);
00182     pDest->SetMediaType(pMediaType);
00183     DeleteMediaType(pMediaType);
00184 
00185     // Copy the actual data length
00186     long lDataLength = pSource->GetActualDataLength();
00187     pDest->SetActualDataLength(lDataLength);
00188 
00189         return NOERROR;
00190 }
00191 
00192 HRESULT CWavDestFilter::CheckInputType(const CMediaType* mtIn)
00193 {
00194         return mtIn->formattype == FORMAT_WaveFormatEx ? S_OK : S_FALSE;
00195 }
00196 
00197 HRESULT CWavDestFilter::GetMediaType(int iPosition, CMediaType* pMediaType)
00198 {
00199     ASSERT(iPosition == 0 || iPosition == 1);
00200 
00201         if(iPosition == 0)
00202         {
00203         pMediaType->SetType(&MEDIATYPE_Stream);
00204         pMediaType->SetSubtype(&MEDIASUBTYPE_WAVE);
00205         return S_OK;
00206     }
00207 
00208     return VFW_S_NO_MORE_ITEMS;
00209 }
00210 
00211 HRESULT CWavDestFilter::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
00212 {
00213     if(m_pInput->IsConnected() == FALSE)
00214                 return E_UNEXPECTED;
00215 
00216     ASSERT(pAlloc);
00217     ASSERT(pProperties);
00218 
00219         HRESULT hr = NOERROR;
00220 
00221     pProperties->cBuffers = 1;
00222     pProperties->cbAlign = 1;
00223     
00224     CComPtr<IMemAllocator> pInAlloc;
00225     ALLOCATOR_PROPERTIES InProps;
00226     if(SUCCEEDED(hr = m_pInput->GetAllocator(&pInAlloc))
00227         && SUCCEEDED(hr = pInAlloc->GetProperties(&InProps)))
00228     {
00229                 pProperties->cbBuffer = InProps.cbBuffer;
00230     }
00231         else
00232         {
00233                 return hr;
00234         }
00235 
00236     ASSERT(pProperties->cbBuffer);
00237 
00238     ALLOCATOR_PROPERTIES Actual;
00239     if(FAILED(hr = pAlloc->SetProperties(pProperties,&Actual)))
00240                 return hr;
00241 
00242     ASSERT(Actual.cBuffers == 1);
00243 
00244     if(pProperties->cBuffers > Actual.cBuffers
00245         || pProperties->cbBuffer > Actual.cbBuffer)
00246         {
00247                 return E_FAIL;
00248     }
00249 
00250     return NOERROR;
00251 }
00252 
00253 // Compute the header size to allow space for us to write it at the end.
00254 //
00255 // 00000000    RIFF (00568BFE) 'WAVE'
00256 // 0000000C        fmt  (00000010)
00257 // 00000024        data (00568700)
00258 // 0056872C
00259 //
00260 
00261 HRESULT CWavDestFilter::StartStreaming()
00262 {
00263     // leave space for the header
00264     m_cbHeader = sizeof(RIFFLIST) + 
00265                  sizeof(RIFFCHUNK) + 
00266                  m_pInput->CurrentMediaType().FormatLength() + 
00267                  sizeof(RIFFCHUNK);
00268                  
00269     m_cbWavData = 0;
00270 
00271     return S_OK;
00272 }
00273 
00274 HRESULT CWavDestFilter::StopStreaming()
00275 {
00276     IStream* pStream;
00277     if (m_pOutput->IsConnected() == FALSE)
00278         return E_FAIL;
00279 
00280     IPin* pDwnstrmInputPin = m_pOutput->GetConnected();
00281 
00282     if (!pDwnstrmInputPin)
00283         return E_FAIL;
00284 
00285     HRESULT hr = ((IMemInputPin *) pDwnstrmInputPin)->QueryInterface(IID_IStream, (void **)&pStream);
00286     if(SUCCEEDED(hr))
00287     {
00288         BYTE *pb = (BYTE *)_alloca(m_cbHeader);
00289 
00290         RIFFLIST *pRiffWave = (RIFFLIST *)pb;
00291         RIFFCHUNK *pRiffFmt = (RIFFCHUNK *)(pRiffWave + 1);
00292         RIFFCHUNK *pRiffData = (RIFFCHUNK *)(((BYTE *)(pRiffFmt + 1)) +  m_pInput->CurrentMediaType().FormatLength());;
00293 
00294         pRiffData->fcc = FCC('data');
00295         pRiffData->cb = m_cbWavData;
00296 
00297         pRiffFmt->fcc = FCC('fmt ');
00298         pRiffFmt->cb = m_pInput->CurrentMediaType().FormatLength();
00299         CopyMemory(pRiffFmt + 1, m_pInput->CurrentMediaType().Format(), pRiffFmt->cb);
00300 
00301         pRiffWave->fcc = FCC('RIFF');
00302         pRiffWave->cb = m_cbWavData + m_cbHeader - sizeof(RIFFCHUNK);
00303         pRiffWave->fccListType = FCC('WAVE');
00304 
00305         LARGE_INTEGER li;
00306         ZeroMemory(&li, sizeof(li));
00307         
00308         hr = pStream->Seek(li, STREAM_SEEK_SET, 0);
00309         if(SUCCEEDED(hr)) {
00310             hr = pStream->Write(pb, m_cbHeader, 0);
00311         }
00312         pStream->Release();
00313     }
00314 
00315     return hr;
00316 }
00317 
00318 CWavDestOutputPin::CWavDestOutputPin(CTransformFilter* pFilter, HRESULT* phr)
00319         : CTransformOutputPin(NAME("WavDest output pin"), pFilter, phr, L"Out")
00320 {
00321 }
00322 
00323 STDMETHODIMP CWavDestOutputPin::EnumMediaTypes(IEnumMediaTypes** ppEnum)
00324 {
00325     return CBaseOutputPin::EnumMediaTypes(ppEnum);
00326 }
00327 
00328 HRESULT CWavDestOutputPin::CheckMediaType(const CMediaType* pmt)
00329 {
00330     if(pmt->majortype == MEDIATYPE_Stream && pmt->subtype == MEDIASUBTYPE_WAVE)
00331         return S_OK;
00332     else
00333         return S_FALSE;
00334 }

Generated on Tue Dec 13 14:47:10 2005 for guliverkli by  doxygen 1.4.5