ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

avidec.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.