Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenavidec.c
Go to the documentation of this file.
00001 /* 00002 * AVI Decompressor (VFW decompressors wrapper) 00003 * 00004 * Copyright 2004-2005 Christian Costa 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include "config.h" 00022 00023 #include "quartz_private.h" 00024 #include "pin.h" 00025 00026 #include "uuids.h" 00027 #include "amvideo.h" 00028 #include "windef.h" 00029 #include "winbase.h" 00030 #include "dshow.h" 00031 #include "strmif.h" 00032 #include "vfwmsgs.h" 00033 #include "vfw.h" 00034 #include "dvdmedia.h" 00035 00036 #include <assert.h> 00037 00038 #include "wine/unicode.h" 00039 #include "wine/debug.h" 00040 00041 #include "transform.h" 00042 00043 WINE_DEFAULT_DEBUG_CHANNEL(quartz); 00044 00045 typedef struct AVIDecImpl 00046 { 00047 TransformFilterImpl tf; 00048 HIC hvid; 00049 BITMAPINFOHEADER* pBihIn; 00050 BITMAPINFOHEADER* pBihOut; 00051 } AVIDecImpl; 00052 00053 static HRESULT AVIDec_ProcessBegin(TransformFilterImpl* pTransformFilter) 00054 { 00055 AVIDecImpl* This = (AVIDecImpl*)pTransformFilter; 00056 DWORD result; 00057 00058 TRACE("(%p)->()\n", This); 00059 00060 result = ICDecompressBegin(This->hvid, This->pBihIn, This->pBihOut); 00061 if (result != ICERR_OK) 00062 { 00063 ERR("Cannot start processing (%d)\n", result); 00064 return E_FAIL; 00065 } 00066 return S_OK; 00067 } 00068 00069 static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample) 00070 { 00071 AVIDecImpl* This = (AVIDecImpl *)pin->pin.pinInfo.pFilter; 00072 AM_MEDIA_TYPE amt; 00073 HRESULT hr; 00074 DWORD res; 00075 IMediaSample* pOutSample = NULL; 00076 DWORD cbDstStream; 00077 LPBYTE pbDstStream; 00078 DWORD cbSrcStream; 00079 LPBYTE pbSrcStream; 00080 LONGLONG tStart, tStop; 00081 00082 EnterCriticalSection(&This->tf.csFilter); 00083 if (This->tf.state == State_Stopped) 00084 { 00085 LeaveCriticalSection(&This->tf.csFilter); 00086 return VFW_E_WRONG_STATE; 00087 } 00088 00089 if (pin->end_of_stream || pin->flushing) 00090 { 00091 LeaveCriticalSection(&This->tf.csFilter); 00092 return S_FALSE; 00093 } 00094 00095 hr = IMediaSample_GetPointer(pSample, &pbSrcStream); 00096 if (FAILED(hr)) 00097 { 00098 ERR("Cannot get pointer to sample data (%x)\n", hr); 00099 goto error; 00100 } 00101 00102 cbSrcStream = IMediaSample_GetActualDataLength(pSample); 00103 00104 TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream, cbSrcStream); 00105 00106 hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt); 00107 if (FAILED(hr)) { 00108 ERR("Unable to retrieve media type\n"); 00109 goto error; 00110 } 00111 00112 /* Update input size to match sample size */ 00113 This->pBihIn->biSizeImage = cbSrcStream; 00114 00115 hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); 00116 if (FAILED(hr)) { 00117 ERR("Unable to get delivery buffer (%x)\n", hr); 00118 goto error; 00119 } 00120 00121 hr = IMediaSample_SetActualDataLength(pOutSample, 0); 00122 assert(hr == S_OK); 00123 00124 hr = IMediaSample_GetPointer(pOutSample, &pbDstStream); 00125 if (FAILED(hr)) { 00126 ERR("Unable to get pointer to buffer (%x)\n", hr); 00127 goto error; 00128 } 00129 cbDstStream = IMediaSample_GetSize(pOutSample); 00130 if (cbDstStream < This->pBihOut->biSizeImage) { 00131 ERR("Sample size is too small %d < %d\n", cbDstStream, This->pBihOut->biSizeImage); 00132 hr = E_FAIL; 00133 goto error; 00134 } 00135 00136 res = ICDecompress(This->hvid, 0, This->pBihIn, pbSrcStream, This->pBihOut, pbDstStream); 00137 if (res != ICERR_OK) 00138 ERR("Error occurred during the decompression (%x)\n", res); 00139 00140 IMediaSample_SetActualDataLength(pOutSample, This->pBihOut->biSizeImage); 00141 00142 IMediaSample_SetPreroll(pOutSample, (IMediaSample_IsPreroll(pSample) == S_OK)); 00143 IMediaSample_SetDiscontinuity(pOutSample, (IMediaSample_IsDiscontinuity(pSample) == S_OK)); 00144 IMediaSample_SetSyncPoint(pOutSample, (IMediaSample_IsSyncPoint(pSample) == S_OK)); 00145 00146 if (IMediaSample_GetTime(pSample, &tStart, &tStop) == S_OK) 00147 IMediaSample_SetTime(pOutSample, &tStart, &tStop); 00148 else 00149 IMediaSample_SetTime(pOutSample, NULL, NULL); 00150 00151 LeaveCriticalSection(&This->tf.csFilter); 00152 hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample); 00153 if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) 00154 ERR("Error sending sample (%x)\n", hr); 00155 IMediaSample_Release(pOutSample); 00156 return hr; 00157 00158 error: 00159 if (pOutSample) 00160 IMediaSample_Release(pOutSample); 00161 00162 LeaveCriticalSection(&This->tf.csFilter); 00163 return hr; 00164 } 00165 00166 static HRESULT AVIDec_ProcessEnd(TransformFilterImpl* pTransformFilter) 00167 { 00168 AVIDecImpl* This = (AVIDecImpl*)pTransformFilter; 00169 DWORD result; 00170 00171 TRACE("(%p)->()\n", This); 00172 00173 if (!This->hvid) 00174 return S_OK; 00175 00176 result = ICDecompressEnd(This->hvid); 00177 if (result != ICERR_OK) 00178 { 00179 ERR("Cannot stop processing (%d)\n", result); 00180 return E_FAIL; 00181 } 00182 return S_OK; 00183 } 00184 00185 static HRESULT AVIDec_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt) 00186 { 00187 AVIDecImpl* This = (AVIDecImpl*)pin->pin.pinInfo.pFilter; 00188 HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED; 00189 00190 TRACE("(%p)->(%p)\n", This, pmt); 00191 00192 /* Check root (GUID w/o FOURCC) */ 00193 if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) && 00194 (!memcmp(((const char *)&pmt->subtype)+4, ((const char *)&MEDIATYPE_Video)+4, sizeof(GUID)-4))) 00195 { 00196 VIDEOINFOHEADER *format1 = (VIDEOINFOHEADER *)pmt->pbFormat; 00197 VIDEOINFOHEADER2 *format2 = (VIDEOINFOHEADER2 *)pmt->pbFormat; 00198 BITMAPINFOHEADER *bmi; 00199 00200 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) 00201 bmi = &format1->bmiHeader; 00202 else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) 00203 bmi = &format2->bmiHeader; 00204 else 00205 goto failed; 00206 TRACE("Fourcc: %s\n", debugstr_an((const char *)&pmt->subtype.Data1, 4)); 00207 00208 This->hvid = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, bmi, NULL, ICMODE_DECOMPRESS); 00209 if (This->hvid) 00210 { 00211 AM_MEDIA_TYPE* outpmt = &This->tf.pmt; 00212 const CLSID* outsubtype; 00213 DWORD bih_size; 00214 DWORD output_depth = bmi->biBitCount; 00215 DWORD result; 00216 FreeMediaType(outpmt); 00217 00218 switch(bmi->biBitCount) 00219 { 00220 case 32: outsubtype = &MEDIASUBTYPE_RGB32; break; 00221 case 24: outsubtype = &MEDIASUBTYPE_RGB24; break; 00222 case 16: outsubtype = &MEDIASUBTYPE_RGB565; break; 00223 case 8: outsubtype = &MEDIASUBTYPE_RGB8; break; 00224 default: 00225 WARN("Non standard input depth %d, forced output depth to 32\n", bmi->biBitCount); 00226 outsubtype = &MEDIASUBTYPE_RGB32; 00227 output_depth = 32; 00228 break; 00229 } 00230 00231 /* Copy bitmap header from media type to 1 for input and 1 for output */ 00232 bih_size = bmi->biSize + bmi->biClrUsed * 4; 00233 This->pBihIn = CoTaskMemAlloc(bih_size); 00234 if (!This->pBihIn) 00235 { 00236 hr = E_OUTOFMEMORY; 00237 goto failed; 00238 } 00239 This->pBihOut = CoTaskMemAlloc(bih_size); 00240 if (!This->pBihOut) 00241 { 00242 hr = E_OUTOFMEMORY; 00243 goto failed; 00244 } 00245 memcpy(This->pBihIn, bmi, bih_size); 00246 memcpy(This->pBihOut, bmi, bih_size); 00247 00248 /* Update output format as non compressed bitmap */ 00249 This->pBihOut->biCompression = 0; 00250 This->pBihOut->biBitCount = output_depth; 00251 This->pBihOut->biSizeImage = This->pBihOut->biWidth * This->pBihOut->biHeight * This->pBihOut->biBitCount / 8; 00252 TRACE("Size: %u\n", This->pBihIn->biSize); 00253 result = ICDecompressQuery(This->hvid, This->pBihIn, This->pBihOut); 00254 if (result != ICERR_OK) 00255 { 00256 ERR("Unable to found a suitable output format (%d)\n", result); 00257 goto failed; 00258 } 00259 00260 /* Update output media type */ 00261 CopyMediaType(outpmt, pmt); 00262 outpmt->subtype = *outsubtype; 00263 00264 if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) 00265 memcpy(&(((VIDEOINFOHEADER *)outpmt->pbFormat)->bmiHeader), This->pBihOut, This->pBihOut->biSize); 00266 else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) 00267 memcpy(&(((VIDEOINFOHEADER2 *)outpmt->pbFormat)->bmiHeader), This->pBihOut, This->pBihOut->biSize); 00268 else 00269 assert(0); 00270 00271 /* Update buffer size of media samples in output */ 00272 ((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = This->pBihOut->biSizeImage; 00273 00274 TRACE("Connection accepted\n"); 00275 return S_OK; 00276 } 00277 TRACE("Unable to find a suitable VFW decompressor\n"); 00278 } 00279 00280 failed: 00281 00282 TRACE("Connection refused\n"); 00283 return hr; 00284 } 00285 00286 static HRESULT AVIDec_Cleanup(InputPin *pin) 00287 { 00288 AVIDecImpl *This = (AVIDecImpl *)pin->pin.pinInfo.pFilter; 00289 00290 TRACE("(%p)->()\n", This); 00291 00292 if (This->hvid) 00293 ICClose(This->hvid); 00294 if (This->pBihIn) 00295 CoTaskMemFree(This->pBihIn); 00296 if (This->pBihOut) 00297 CoTaskMemFree(This->pBihOut); 00298 00299 This->hvid = NULL; 00300 This->pBihIn = NULL; 00301 This->pBihOut = NULL; 00302 00303 return S_OK; 00304 } 00305 00306 static const TransformFuncsTable AVIDec_FuncsTable = { 00307 AVIDec_ProcessBegin, 00308 AVIDec_ProcessSampleData, 00309 AVIDec_ProcessEnd, 00310 NULL, 00311 AVIDec_ConnectInput, 00312 AVIDec_Cleanup 00313 }; 00314 00315 HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv) 00316 { 00317 HRESULT hr; 00318 AVIDecImpl * This; 00319 00320 TRACE("(%p, %p)\n", pUnkOuter, ppv); 00321 00322 *ppv = NULL; 00323 00324 if (pUnkOuter) 00325 return CLASS_E_NOAGGREGATION; 00326 00327 /* Note: This memory is managed by the transform filter once created */ 00328 This = CoTaskMemAlloc(sizeof(AVIDecImpl)); 00329 00330 This->hvid = NULL; 00331 This->pBihIn = NULL; 00332 This->pBihOut = NULL; 00333 00334 hr = TransformFilter_Create(&(This->tf), &CLSID_AVIDec, &AVIDec_FuncsTable, NULL, NULL, NULL); 00335 00336 if (FAILED(hr)) 00337 return hr; 00338 00339 *ppv = This; 00340 00341 return hr; 00342 } Generated on Sat May 26 2012 04:20:27 for ReactOS by
1.7.6.1
|