D2VSource.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *
00004  *  This Program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2, or (at your option)
00007  *  any later version.
00008  *   
00009  *  This Program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00012  *  GNU General Public License for more details.
00013  *   
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with GNU Make; see the file COPYING.  If not, write to
00016  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00017  *
00018  */
00019 
00020 #include "stdafx.h"
00021 #include "D2VSource.h"
00022 #include "mpeg2dec.h"
00023 #include "..\..\..\DSUtil\DSUtil.h"
00024 
00025 #ifdef REGISTER_FILTER
00026 
00027 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
00028 {
00029         {&MEDIATYPE_Video, &MEDIASUBTYPE_YUY2}
00030 };
00031 
00032 const AMOVIESETUP_PIN sudOpPin[] =
00033 {
00034         {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
00035 };
00036 
00037 const AMOVIESETUP_FILTER sudFilter[] =
00038 {
00039         {&__uuidof(CD2VSource), L"D2VSource", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin}
00040 };
00041 
00042 CFactoryTemplate g_Templates[] =
00043 {
00044         {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CD2VSource>, NULL, &sudFilter[0]}
00045 };
00046 
00047 int g_cTemplates = countof(g_Templates);
00048 
00049 STDAPI DllRegisterServer()
00050 {
00051         SetRegKeyValue(
00052                 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{47CE0591-C4D5-4b41-BED7-28F59AD76228}"), 
00053                 _T("0"), _T("0,18,,4456443241564950726F6A65637446696C65")); // "DVD2AVIProjectFile"
00054 
00055         SetRegKeyValue(
00056                 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{47CE0591-C4D5-4b41-BED7-28F59AD76228}"), 
00057                 _T("Source Filter"), _T("{47CE0591-C4D5-4b41-BED7-28F59AD76228}"));
00058 
00059         SetRegKeyValue(
00060                 _T("Media Type\\Extensions"), _T(".d2v"), 
00061                 _T("Source Filter"), _T("{47CE0591-C4D5-4b41-BED7-28F59AD76228}"));
00062 
00063         return AMovieDllRegisterServer2(TRUE);
00064 }
00065 
00066 STDAPI DllUnregisterServer()
00067 {
00068         DeleteRegKey(_T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{47CE0591-C4D5-4b41-BED7-28F59AD76228}"));
00069         DeleteRegKey(_T("Media Type\\Extensions"), _T(".d2v"));
00070 
00071         return AMovieDllRegisterServer2(FALSE);
00072 }
00073 
00074 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00075 
00076 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00077 {
00078     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
00079 }
00080 
00081 #endif
00082 
00083 //
00084 // CD2VSource
00085 //
00086 
00087 CD2VSource::CD2VSource(LPUNKNOWN lpunk, HRESULT* phr)
00088         : CBaseSource<CD2VStream>(NAME("CD2VSource"), lpunk, phr, __uuidof(this))
00089 {
00090         if(phr) *phr = S_OK;
00091 }
00092 
00093 CD2VSource::~CD2VSource()
00094 {
00095 }
00096 
00097 //
00098 // CD2VStream
00099 //
00100 
00101 CD2VStream::CD2VStream(const WCHAR* fn, CSource* pParent, HRESULT* phr) 
00102         : CBaseStream(NAME("D2VSourceStream"), pParent, phr)
00103         , m_pFrameBuffer(NULL)
00104 {
00105         CAutoLock cAutoLock(&m_cSharedState);
00106 
00107         m_pDecoder.Attach(new CMPEG2Dec());
00108         if(!m_pDecoder)
00109         {
00110                 if(phr) *phr = E_OUTOFMEMORY;
00111                 return;
00112         }
00113 
00114         if(!m_pDecoder->Open(CStringA(fn), CMPEG2Dec::YUY2))
00115         {
00116                 if(phr) *phr = E_FAIL;
00117                 return;
00118         }
00119 
00120         if(!m_pFrameBuffer.Allocate(m_pDecoder->Clip_Width*m_pDecoder->Clip_Height*4))
00121         {
00122                 if(phr) *phr = E_OUTOFMEMORY;
00123                 return;
00124         }
00125 
00126         m_AvgTimePerFrame = 10000000000i64/m_pDecoder->VF_FrameRate;
00127         m_rtDuration = m_rtStop = m_AvgTimePerFrame*m_pDecoder->VF_FrameLimit;
00128 
00129         if(phr) *phr = m_rtDuration > 0 ? S_OK : E_FAIL;
00130 }
00131 
00132 CD2VStream::~CD2VStream()
00133 {
00134         CAutoLock cAutoLock(&m_cSharedState);
00135 }
00136 
00137 HRESULT CD2VStream::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
00138 {
00139 //    CAutoLock cAutoLock(m_pFilter->pStateLock());
00140 
00141     ASSERT(pAlloc);
00142     ASSERT(pProperties);
00143 
00144     HRESULT hr = NOERROR;
00145 
00146         int w, h, bpp;
00147         if(!GetDim(w, h, bpp))
00148                 return E_FAIL;
00149 
00150         pProperties->cBuffers = 1;
00151         pProperties->cbBuffer = w*h*bpp>>3;
00152 
00153     ALLOCATOR_PROPERTIES Actual;
00154     if(FAILED(hr = pAlloc->SetProperties(pProperties, &Actual))) return hr;
00155 
00156     if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;
00157     ASSERT(Actual.cBuffers == pProperties->cBuffers);
00158 
00159     return NOERROR;
00160 }
00161 
00162 HRESULT CD2VStream::FillBuffer(IMediaSample* pSample, int nFrame, BYTE* pOut, long& len)
00163 {
00164         if(!m_pDecoder)
00165                 return S_FALSE;
00166 
00167         AM_MEDIA_TYPE* pmt;
00168         if(SUCCEEDED(pSample->GetMediaType(&pmt)) && pmt)
00169         {
00170                 CMediaType mt(*pmt);
00171                 SetMediaType(&mt);
00172 
00173                 DeleteMediaType(pmt);
00174         }
00175 
00176         int w, h, bpp;
00177         if(!GetDim(w, h, bpp))
00178                 return S_FALSE;
00179 
00180         BYTE* pIn = m_pFrameBuffer;
00181 
00182         int pitchIn, pitchOut = 0;
00183 
00184         pitchIn = m_pDecoder->Clip_Width*bpp>>3;
00185         pitchOut = w*bpp>>3;
00186 
00187         m_pDecoder->Decode(pIn, (unsigned long)(nFrame), pitchIn);
00188 
00189         for(int y = 0, p = min(pitchIn, pitchOut); 
00190                 y < h; 
00191                 y++, pIn += pitchIn, pOut += pitchOut)
00192         {
00193                 memcpy(pOut, pIn, p);
00194         }
00195 
00196         len = pitchOut*h;
00197 
00198         return S_OK;
00199 }
00200 
00201 HRESULT CD2VStream::GetMediaType(int iPosition, CMediaType* pmt)
00202 {
00203     CAutoLock cAutoLock(m_pFilter->pStateLock());
00204 
00205     if(iPosition < 0) return E_INVALIDARG;
00206     if(iPosition > 0) return VFW_S_NO_MORE_ITEMS;
00207 
00208     pmt->SetType(&MEDIATYPE_Video);
00209     pmt->SetSubtype(&MEDIASUBTYPE_YUY2);
00210     pmt->SetFormatType(&FORMAT_VideoInfo);
00211     pmt->SetTemporalCompression(FALSE);
00212 
00213         VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
00214         memset(vih, 0, sizeof(VIDEOINFOHEADER));
00215         vih->AvgTimePerFrame = m_AvgTimePerFrame;
00216         vih->bmiHeader.biSize = sizeof(vih->bmiHeader);
00217         vih->bmiHeader.biWidth = m_pDecoder->Clip_Width;
00218         vih->bmiHeader.biHeight = m_pDecoder->Clip_Height;
00219         vih->bmiHeader.biPlanes = 1;
00220         vih->bmiHeader.biBitCount = 16;
00221         vih->bmiHeader.biCompression = '2YUY';
00222         vih->bmiHeader.biSizeImage = vih->bmiHeader.biWidth*abs(vih->bmiHeader.biHeight)*vih->bmiHeader.biBitCount>>3;
00223 
00224         pmt->SetSampleSize(vih->bmiHeader.biSizeImage);
00225 
00226     return NOERROR;
00227 }
00228 
00229 HRESULT CD2VStream::SetMediaType(const CMediaType* pmt)
00230 {
00231         if(m_pDecoder)
00232         {
00233                 if(pmt->subtype == MEDIASUBTYPE_YUY2)
00234                         m_pDecoder->m_dstFormat = CMPEG2Dec::YUY2;
00235                 else
00236                         return E_FAIL;
00237         }
00238 
00239         return CSourceStream::SetMediaType(pmt);
00240 }
00241 
00242 HRESULT CD2VStream::CheckMediaType(const CMediaType* pmt)
00243 {
00244         return pmt->majortype == MEDIATYPE_Video
00245                 && pmt->subtype == MEDIASUBTYPE_YUY2
00246                 && pmt->formattype == FORMAT_VideoInfo
00247                 ? S_OK
00248                 : E_INVALIDARG;
00249 }
00250 
00251 STDMETHODIMP CD2VStream::Notify(IBaseFilter* pSender, Quality q)
00252 {
00253         if(q.Late > 0 && q.Late < 100000000)
00254         {
00255                 CAutoLock cAutoLockShared(&m_cSharedState);
00256 
00257         m_rtSampleTime += (q.Late/m_AvgTimePerFrame)*m_AvgTimePerFrame;
00258         m_rtPosition += (q.Late/m_AvgTimePerFrame)*m_AvgTimePerFrame;
00259         }
00260 
00261         return S_OK;
00262 }
00263 
00264 //
00265 
00266 bool CD2VStream::GetDim(int& w, int& h, int& bpp)
00267 {
00268         if(m_mt.formattype == FORMAT_VideoInfo)
00269         {
00270                 w = ((VIDEOINFOHEADER*)m_mt.pbFormat)->bmiHeader.biWidth;
00271                 h = abs(((VIDEOINFOHEADER*)m_mt.pbFormat)->bmiHeader.biHeight);
00272                 bpp = ((VIDEOINFOHEADER*)m_mt.pbFormat)->bmiHeader.biBitCount;
00273         }
00274         else if(m_mt.formattype == FORMAT_VideoInfo2)
00275         {
00276                 w = ((VIDEOINFOHEADER2*)m_mt.pbFormat)->bmiHeader.biWidth;
00277                 h = abs(((VIDEOINFOHEADER2*)m_mt.pbFormat)->bmiHeader.biHeight);
00278                 bpp = ((VIDEOINFOHEADER2*)m_mt.pbFormat)->bmiHeader.biBitCount;
00279         }
00280         else
00281         {
00282                 return(false);
00283         }
00284 
00285         return(true);
00286 }

Generated on Tue Dec 13 14:47:23 2005 for guliverkli by  doxygen 1.4.5