- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# 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 }