2 * Implements AVI MJPG Decompressor.
6 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
41 #include "quartz_private.h"
45 static const WCHAR MJPGDec_FilterName[] =
46 {'M','J','P','G',' ','D','e','c','o','m','p','r','e','s','s','o','r',0};
48 typedef struct CMJPGDecImpl
50 AM_MEDIA_TYPE* m_pmtConv;
52 BITMAPINFOHEADER m_biOut;
55 static const BYTE jpeg_standard_dht_data[0x1f+0xb5+0x1f+0xb5+2*4] =
57 0xff, 0xc4, 0x00, 0x1f, 0x00,
58 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
59 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
61 0x08, 0x09, 0x0a, 0x0b,
63 0xff, 0xc4, 0x00, 0xb5, 0x10,
64 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
65 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
66 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
67 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
68 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
69 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
70 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
71 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
72 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
73 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
74 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
75 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
76 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
77 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
78 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
79 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
80 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
81 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
82 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
83 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
84 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
85 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
88 0xff, 0xc4, 0x00, 0x1f, 0x01,
89 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
90 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
92 0x08, 0x09, 0x0a, 0x0b,
94 0xff, 0xc4, 0x00, 0xb5, 0x11,
95 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
96 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
97 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
98 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
99 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
100 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
101 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
102 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
103 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
104 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
105 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
106 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
107 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
108 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
109 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
110 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
111 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
112 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
113 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
114 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
115 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
116 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
120 /***************************************************************************
122 * CMJPGDecImpl methods
126 static void MJPGDec_FreeOutTypes(CMJPGDecImpl* This)
130 if ( This->m_pmtConv == NULL )
133 TRACE("cConv = %lu\n",This->m_cConv);
134 for ( i = 0; i < This->m_cConv; i++ )
136 QUARTZ_MediaType_Free(&This->m_pmtConv[i]);
138 QUARTZ_FreeMem(This->m_pmtConv);
139 This->m_pmtConv = NULL;
144 static HRESULT MJPGDec_Init( CTransformBaseImpl* pImpl )
146 CMJPGDecImpl* This = pImpl->m_pUserData;
151 This = (CMJPGDecImpl*)QUARTZ_AllocMem( sizeof(CMJPGDecImpl) );
153 return E_OUTOFMEMORY;
154 ZeroMemory( This, sizeof(CMJPGDecImpl) );
155 pImpl->m_pUserData = This;
157 This->m_pmtConv = NULL;
163 static HRESULT MJPGDec_Cleanup( CTransformBaseImpl* pImpl )
165 CMJPGDecImpl* This = pImpl->m_pUserData;
170 MJPGDec_FreeOutTypes(This);
172 QUARTZ_FreeMem( This );
173 pImpl->m_pUserData = NULL;
178 static HRESULT MJPGDec_CheckMediaType( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut )
180 CMJPGDecImpl* This = pImpl->m_pUserData;
181 const BITMAPINFOHEADER* pbiIn = NULL;
182 const BITMAPINFOHEADER* pbiOut = NULL;
184 TRACE("(%p)\n",This);
189 if ( !IsEqualGUID( &pmtIn->majortype, &MEDIATYPE_Video ) )
191 if ( !IsEqualGUID( &pmtIn->formattype, &FORMAT_VideoInfo ) )
193 pbiIn = (&((const VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
194 if ( pbiIn->biCompression != mmioFOURCC('M','J','P','G') &&
195 pbiIn->biCompression != mmioFOURCC('m','j','p','g') )
197 if ( pbiIn->biBitCount != 24 )
200 if ( pmtOut != NULL )
202 if ( !IsEqualGUID( &pmtOut->majortype, &MEDIATYPE_Video ) )
204 if ( !IsEqualGUID( &pmtOut->formattype, &FORMAT_VideoInfo ) )
206 if ( !IsEqualGUID( &pmtOut->subtype, &MEDIASUBTYPE_RGB24 ) )
208 pbiOut = (&((const VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
209 if ( pbiOut->biCompression != 0 )
211 if ( pbiIn->biWidth != pbiOut->biWidth ||
212 pbiIn->biHeight != pbiOut->biHeight ||
213 pbiIn->biPlanes != 1 || pbiOut->biPlanes != 1 ||
214 pbiOut->biBitCount != pbiIn->biBitCount )
221 static HRESULT MJPGDec_GetOutputTypes( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE** ppmtAcceptTypes, ULONG* pcAcceptTypes )
223 CMJPGDecImpl* This = pImpl->m_pUserData;
226 const BITMAPINFOHEADER* pbiIn = NULL;
227 BITMAPINFOHEADER* pbiOut = NULL;
229 TRACE("(%p)\n",This);
234 hr = MJPGDec_CheckMediaType( pImpl, pmtIn, NULL );
237 pbiIn = (&((const VIDEOINFOHEADER*)pmtIn->pbFormat)->bmiHeader);
239 MJPGDec_FreeOutTypes(This);
242 This->m_pmtConv = (AM_MEDIA_TYPE*)QUARTZ_AllocMem( sizeof(AM_MEDIA_TYPE) );
243 if ( This->m_pmtConv == NULL )
244 return E_OUTOFMEMORY;
245 ZeroMemory( This->m_pmtConv, sizeof(AM_MEDIA_TYPE) * 1 );
249 memcpy( &This->m_pmtConv[dwIndex].majortype, &MEDIATYPE_Video, sizeof(GUID) );
250 memcpy( &This->m_pmtConv[dwIndex].subtype, &MEDIASUBTYPE_RGB24, sizeof(GUID) );
251 This->m_pmtConv[dwIndex].bFixedSizeSamples = 1;
252 This->m_pmtConv[dwIndex].bTemporalCompression = 0;
253 This->m_pmtConv[dwIndex].lSampleSize = DIBSIZE(*pbiIn);
254 memcpy( &This->m_pmtConv[dwIndex].formattype, &FORMAT_VideoInfo, sizeof(GUID) );
255 This->m_pmtConv[dwIndex].cbFormat = sizeof(VIDEOINFO);
256 This->m_pmtConv[dwIndex].pbFormat = (BYTE*)CoTaskMemAlloc( This->m_pmtConv[dwIndex].cbFormat );
257 if ( This->m_pmtConv[dwIndex].pbFormat == NULL )
258 return E_OUTOFMEMORY;
259 ZeroMemory( This->m_pmtConv[dwIndex].pbFormat, This->m_pmtConv[dwIndex].cbFormat );
260 pbiOut = &(((VIDEOINFOHEADER*)(This->m_pmtConv[dwIndex].pbFormat))->bmiHeader);
261 pbiOut->biSize = sizeof(BITMAPINFOHEADER);
262 pbiOut->biWidth = pbiIn->biWidth;
263 pbiOut->biHeight = pbiIn->biHeight;
264 pbiOut->biPlanes = 1;
265 pbiOut->biBitCount = pbiIn->biBitCount;
267 *ppmtAcceptTypes = This->m_pmtConv;
268 *pcAcceptTypes = This->m_cConv;
273 static HRESULT MJPGDec_GetAllocProp( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, ALLOCATOR_PROPERTIES* pProp, BOOL* pbTransInPlace, BOOL* pbTryToReuseSample )
275 CMJPGDecImpl* This = pImpl->m_pUserData;
277 const BITMAPINFOHEADER* pbiOut = NULL;
279 TRACE("(%p)\n",This);
284 hr = MJPGDec_CheckMediaType( pImpl, pmtIn, NULL );
287 pbiOut = (&((const VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
290 pProp->cbBuffer = DIBSIZE(*pbiOut);
295 static HRESULT MJPGDec_BeginTransform( CTransformBaseImpl* pImpl, const AM_MEDIA_TYPE* pmtIn, const AM_MEDIA_TYPE* pmtOut, BOOL bReuseSample )
297 CMJPGDecImpl* This = pImpl->m_pUserData;
299 const BITMAPINFOHEADER* pbiOut = NULL;
301 TRACE("(%p)\n",This);
306 hr = MJPGDec_CheckMediaType( pImpl, pmtIn, NULL );
310 ZeroMemory( &This->m_biOut, sizeof(BITMAPINFOHEADER) );
312 pbiOut = (&((const VIDEOINFOHEADER*)pmtOut->pbFormat)->bmiHeader);
313 memcpy( &This->m_biOut, pbiOut, sizeof(BITMAPINFOHEADER) );
318 static HRESULT MJPGDec_Transform( CTransformBaseImpl* pImpl, IMediaSample* pSampIn, IMediaSample* pSampOut )
320 CMJPGDecImpl* This = pImpl->m_pUserData;
321 BYTE* pDataIn = NULL;
322 BYTE* pDataOut = NULL;
326 const char* psrcs[3];
329 TRACE("(%p)\n",This);
334 hr = IMediaSample_GetPointer( pSampIn, &pDataIn );
337 lDataInLen = IMediaSample_GetActualDataLength( pSampIn );
338 if ( lDataInLen < 4 )
340 hr = IMediaSample_GetPointer( pSampOut, &pDataOut );
343 IMediaSample_SetActualDataLength( pSampOut, DIBSIZE(This->m_biOut) );
345 if ( pDataIn[0] != 0xff || pDataIn[1] != 0xd8 )
348 psrcs[0] = (const char*)&pDataIn[0];
349 psrcs[1] = (const char*)jpeg_standard_dht_data;
350 psrcs[2] = (const char*)&pDataIn[2];
352 lenofsrcs[1] = sizeof(jpeg_standard_dht_data);
353 lenofsrcs[2] = lDataInLen - 2;
355 outpitch = DIBWIDTHBYTES(This->m_biOut);
356 if ( 0 > IJGDEC_Decode(
357 pDataOut + (This->m_biOut.biHeight-1) * outpitch, - outpitch,
358 This->m_biOut.biWidth, This->m_biOut.biHeight,
359 This->m_biOut.biBitCount,
360 &psrcs[0], &lenofsrcs[0], 3 ) )
368 static HRESULT MJPGDec_EndTransform( CTransformBaseImpl* pImpl )
370 CMJPGDecImpl* This = pImpl->m_pUserData;
372 TRACE("(%p)\n",This);
377 ZeroMemory( &This->m_biOut, sizeof(BITMAPINFOHEADER) );
383 static const TransformBaseHandlers transhandlers =
387 MJPGDec_CheckMediaType,
388 MJPGDec_GetOutputTypes,
389 MJPGDec_GetAllocProp,
390 MJPGDec_BeginTransform,
393 MJPGDec_EndTransform,
396 HRESULT QUARTZ_CreateMJPGDecompressor(IUnknown* punkOuter,void** ppobj)
398 return QUARTZ_CreateTransformBase(
400 &CLSID_quartzMJPGDecompressor,