2 * Implements MPEG Audio Decoder(CLSID_CMpegAudioCodec)
4 * FIXME - what library can we use? SMPEG??
8 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
43 #include "quartz_private.h"
47 static const WCHAR CMPEGAudioDecoderImpl_FilterName[] =
48 {'M','P','E','G',' ','A','u','d','i','o',' ','D','e','c','o','d','e','r',0};
51 typedef struct CMPEGAudioDecoderImpl
59 } CMPEGAudioDecoderImpl;
62 /*****************************************************************************
64 * codec-dependent stuffs - no codec
70 static void Codec_OnConstruct(CMPEGAudioDecoderImpl* This)
74 static void Codec_OnCleanup(CMPEGAudioDecoderImpl* This)
78 static HRESULT Codec_BeginTransform(CTransformBaseImpl* pImpl,CMPEGAudioDecoderImpl* This)
84 static HRESULT Codec_ProcessReceive(CTransformBaseImpl* pImpl,CMPEGAudioDecoderImpl* This,IMediaSample* pSampIn)
90 static HRESULT Codec_EndTransform(CTransformBaseImpl* pImpl,CMPEGAudioDecoderImpl* This)
98 /***************************************************************************
100 * CMPEGAudioDecoderImpl methods
104 static void CMPEGAudioDecoderImpl_CleanupOutTypes(CMPEGAudioDecoderImpl* This)
108 if ( This->pmt != NULL )
110 for ( i = 0; i < This->cmt; i++ )
112 QUARTZ_MediaType_Free(&This->pmt[i]);
114 QUARTZ_FreeMem(This->pmt);
120 static HRESULT CMPEGAudioDecoderImpl_Init( CTransformBaseImpl* pImpl )
122 CMPEGAudioDecoderImpl* This = (CMPEGAudioDecoderImpl*)pImpl->m_pUserData;
124 TRACE("(%p)\n",This);
129 This = (CMPEGAudioDecoderImpl*)QUARTZ_AllocMem( sizeof(CMPEGAudioDecoderImpl) );
131 return E_OUTOFMEMORY;
132 ZeroMemory( This, sizeof(CMPEGAudioDecoderImpl) );
133 pImpl->m_pUserData = This;
138 Codec_OnConstruct(This);
143 static HRESULT CMPEGAudioDecoderImpl_Cleanup( CTransformBaseImpl* pImpl )
145 CMPEGAudioDecoderImpl* This = (CMPEGAudioDecoderImpl*)pImpl->m_pUserData;
147 TRACE("(%p)\n",This);
153 Codec_OnCleanup(This);
154 CMPEGAudioDecoderImpl_CleanupOutTypes(This);
156 QUARTZ_FreeMem( This );
157 pImpl->m_pUserData = NULL;
162 static HRESULT CMPEGAudioDecoderImpl_CheckMediaType( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut )
164 CMPEGAudioDecoderImpl* This = (CMPEGAudioDecoderImpl*)pImpl->m_pUserData;
165 const WAVEFORMATEX* pwfxIn;
166 const WAVEFORMATEX* pwfxOut;
168 TRACE("(%p)\n",This);
172 if ( !IsEqualGUID( &pmtIn->majortype, &MEDIATYPE_Audio ) )
174 if ( !IsEqualGUID( &pmtIn->formattype, &FORMAT_WaveFormatEx ) )
177 if ( pmtIn->pbFormat == NULL ||
178 pmtIn->cbFormat < sizeof(WAVEFORMATEX) )
180 pwfxIn = (const WAVEFORMATEX*)pmtIn->pbFormat;
181 if ( pwfxIn->wFormatTag != WAVE_FORMAT_MPEG &&
182 pwfxIn->wFormatTag != WAVE_FORMAT_MPEGLAYER3 )
184 if ( pwfxIn->nChannels != 1 && pwfxIn->nChannels != 2 )
186 if ( pwfxIn->nBlockAlign < 1 )
189 if ( pmtOut != NULL )
191 if ( !IsEqualGUID( &pmtOut->majortype, &MEDIATYPE_Audio ) )
193 if ( !IsEqualGUID( &pmtOut->formattype, &FORMAT_WaveFormatEx ) )
196 if ( pmtOut->pbFormat == NULL ||
197 pmtOut->cbFormat < sizeof(WAVEFORMATEX) )
199 pwfxOut = (const WAVEFORMATEX*)pmtOut->pbFormat;
201 if ( pwfxOut->wFormatTag != WAVE_FORMAT_PCM )
203 if ( pwfxOut->nChannels != pwfxIn->nChannels ||
204 pwfxOut->nSamplesPerSec != pwfxIn->nSamplesPerSec )
206 if ( pwfxOut->wBitsPerSample != 16 )
208 if ( pwfxOut->nBlockAlign != (pwfxOut->nChannels * pwfxOut->wBitsPerSample >> 3 ) )
213 WARN("no codec implementation\n");
220 static HRESULT CMPEGAudioDecoderImpl_GetOutputTypes( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE** ppmtAcceptTypes, ULONG* pcAcceptTypes )
222 CMPEGAudioDecoderImpl* This = (CMPEGAudioDecoderImpl*)pImpl->m_pUserData;
224 const WAVEFORMATEX* pwfxIn;
225 AM_MEDIA_TYPE* pmtOut;
226 WAVEFORMATEX* pwfxOut;
228 TRACE("(%p)\n",This);
232 hr = CMPEGAudioDecoderImpl_CheckMediaType( pImpl, pmtIn, NULL );
235 pwfxIn = (const WAVEFORMATEX*)pmtIn->pbFormat;
237 CMPEGAudioDecoderImpl_CleanupOutTypes(This);
240 This->pmt = (AM_MEDIA_TYPE*)QUARTZ_AllocMem(
241 sizeof(AM_MEDIA_TYPE) * This->cmt );
242 if ( This->pmt == NULL )
243 return E_OUTOFMEMORY;
244 ZeroMemory( This->pmt, sizeof(AM_MEDIA_TYPE) * This->cmt );
246 pmtOut = &This->pmt[0];
248 memcpy( &pmtOut->majortype, &MEDIATYPE_Audio, sizeof(GUID) );
249 memcpy( &pmtOut->subtype, &MEDIASUBTYPE_PCM, sizeof(GUID) );
250 memcpy( &pmtOut->formattype, &FORMAT_WaveFormatEx, sizeof(GUID) );
251 pmtOut->bFixedSizeSamples = 1;
252 pmtOut->bTemporalCompression = 0;
253 pmtOut->lSampleSize = pwfxIn->nChannels * 16 >> 3;
254 pmtOut->pbFormat = (BYTE*)CoTaskMemAlloc( sizeof(WAVEFORMATEX) );
255 if ( pmtOut->pbFormat == NULL )
256 return E_OUTOFMEMORY;
257 pwfxOut = (WAVEFORMATEX*)pmtOut->pbFormat;
258 pmtOut->cbFormat = sizeof(WAVEFORMATEX);
259 pwfxOut->wFormatTag = WAVE_FORMAT_PCM;
260 pwfxOut->nChannels = pwfxIn->nChannels;
261 pwfxOut->nSamplesPerSec = pwfxIn->nSamplesPerSec;
262 pwfxOut->nAvgBytesPerSec = pwfxOut->nSamplesPerSec * pmtOut->lSampleSize;
263 pwfxOut->nBlockAlign = pmtOut->lSampleSize;
264 pwfxOut->wBitsPerSample = 16;
267 *ppmtAcceptTypes = This->pmt;
268 *pcAcceptTypes = This->cmt;
273 static HRESULT CMPEGAudioDecoderImpl_GetAllocProp( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, ALLOCATOR_PROPERTIES* pProp, BOOL* pbTransInPlace, BOOL* pbTryToReuseSample )
275 CMPEGAudioDecoderImpl* This = (CMPEGAudioDecoderImpl*)pImpl->m_pUserData;
276 const WAVEFORMATEX* pwfxIn;
277 const WAVEFORMATEX* pwfxOut;
280 TRACE("(%p)\n",This);
284 hr = CMPEGAudioDecoderImpl_CheckMediaType( pImpl, pmtIn, pmtOut );
287 pwfxIn = (const WAVEFORMATEX*)pmtIn->pbFormat;
288 pwfxOut = (const WAVEFORMATEX*)pmtOut->pbFormat;
291 pProp->cbBuffer = pwfxOut->nAvgBytesPerSec;
293 TRACE("cbBuffer %ld\n",pProp->cbBuffer);
295 *pbTransInPlace = FALSE;
296 *pbTryToReuseSample = FALSE;
301 static HRESULT CMPEGAudioDecoderImpl_BeginTransform( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, BOOL bReuseSample )
303 CMPEGAudioDecoderImpl* This = (CMPEGAudioDecoderImpl*)pImpl->m_pUserData;
306 TRACE("(%p,%p,%p,%d)\n",This,pmtIn,pmtOut,bReuseSample);
310 hr = CMPEGAudioDecoderImpl_CheckMediaType( pImpl, pmtIn, pmtOut );
313 memcpy( &This->wfxOut, (const WAVEFORMATEX*)pmtOut->pbFormat, sizeof(WAVEFORMATEX) );
315 return Codec_BeginTransform(pImpl,This);
318 static HRESULT CMPEGAudioDecoderImpl_ProcessReceive( CTransformBaseImpl* pImpl, IMediaSample* pSampIn )
320 CMPEGAudioDecoderImpl* This = (CMPEGAudioDecoderImpl*)pImpl->m_pUserData;
322 TRACE("(%p,%p)\n",This,pSampIn);
326 return Codec_ProcessReceive(pImpl,This,pSampIn);
329 static HRESULT CMPEGAudioDecoderImpl_EndTransform( CTransformBaseImpl* pImpl )
331 CMPEGAudioDecoderImpl* This = (CMPEGAudioDecoderImpl*)pImpl->m_pUserData;
334 TRACE("(%p)\n",This);
338 hr = Codec_EndTransform(pImpl,This);
341 ZeroMemory( &This->wfxOut, sizeof(WAVEFORMATEX) );
347 static const TransformBaseHandlers transhandlers =
349 CMPEGAudioDecoderImpl_Init,
350 CMPEGAudioDecoderImpl_Cleanup,
351 CMPEGAudioDecoderImpl_CheckMediaType,
352 CMPEGAudioDecoderImpl_GetOutputTypes,
353 CMPEGAudioDecoderImpl_GetAllocProp,
354 CMPEGAudioDecoderImpl_BeginTransform,
355 CMPEGAudioDecoderImpl_ProcessReceive,
357 CMPEGAudioDecoderImpl_EndTransform,
360 HRESULT QUARTZ_CreateCMpegAudioCodec(IUnknown* punkOuter,void** ppobj)
362 return QUARTZ_CreateTransformBase(
364 &CLSID_CMpegAudioCodec,
365 CMPEGAudioDecoderImpl_FilterName,