- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# DiracSplitter.cpp

    00001 /*
    00002  *      Copyright (C) 2003-2005 Gabest
    00003  *      http://www.gabest.org
    00004  *
    00005  *  This Program is free software; you can redistribute it and/or modify
    00006  *  it under the terms of the GNU General Public License as published by
    00007  *  the Free Software Foundation; either version 2, or (at your option)
    00008  *  any later version.
    00009  *
    00010  *  This Program is distributed in the hope that it will be useful,
    00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00013  *  GNU General Public License for more details.
    00014  *
    00015  *  You should have received a copy of the GNU General Public License
    00016  *  along with GNU Make; see the file COPYING.  If not, write to
    00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00018  *  http://www.gnu.org/copyleft/gpl.html
    00019  *
    00020  */
    00021
    00022 #include "StdAfx.h"
    00023 #include <mmreg.h>
    00024 #include <initguid.h>
    00025 #include "DiracSplitter.h"
    00026 #include "..\..\..\..\include\moreuuids.h"
    00027
    00028 #ifdef REGISTER_FILTER
    00029
    00030 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
    00031 {
    00032         {&MEDIATYPE_Stream, &MEDIASUBTYPE_Dirac},
    00033         {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL}
    00034 };
    00035
    00036 const AMOVIESETUP_PIN sudpPins[] =
    00037 {
    00038         {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
    00039         {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 0, NULL}
    00040 };
    00041
    00042 const AMOVIESETUP_MEDIATYPE sudPinTypesIn2[] =
    00043 {
    00044         {&MEDIATYPE_Video, &MEDIASUBTYPE_DiracVideo},
    00045 };
    00046
    00047 const AMOVIESETUP_MEDIATYPE sudPinTypesOut2[] =
    00048 {
    00049         {&MEDIATYPE_Video, &MEDIASUBTYPE_NULL},
    00050 };
    00051
    00052 const AMOVIESETUP_PIN sudpPins2[] =
    00053 {
    00054     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn2), sudPinTypesIn2},
    00055     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut2), sudPinTypesOut2}
    00056 };
    00057
    00058 const AMOVIESETUP_FILTER sudFilter[] =
    00059 {
    00060         {&__uuidof(CDiracSplitterFilter), L"Dirac Splitter", MERIT_NORMAL, countof(sudpPins), sudpPins},
    00061         {&__uuidof(CDiracSourceFilter), L"Dirac Source", MERIT_NORMAL, 0, NULL},
    00062         {&__uuidof(CDiracVideoDecoder), L"Dirac Video Decoder", MERIT_UNLIKELY, countof(sudpPins2), sudpPins2},
    00063 };
    00064
    00065 CFactoryTemplate g_Templates[] =
    00066 {
    00067         {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CDiracSplitterFilter>, NULL, &sudFilter[0]},
    00068         {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CDiracSourceFilter>, NULL, &sudFilter[1]},
    00069     {sudFilter[2].strName, sudFilter[2].clsID, CreateInstance<CDiracVideoDecoder>, NULL, &sudFilter[2]},
    00070 };
    00071
    00072 int g_cTemplates = countof(g_Templates);
    00073
    00074 STDAPI DllRegisterServer()
    00075 {
    00076         RegisterSourceFilter(
    00077                 CLSID_AsyncReader,
    00078                 MEDIASUBTYPE_Dirac,
    00079                 _T("0,8,,4B572D4449524143"), // KW-DIRAC
    00080                 _T(".drc"), NULL);
    00081
    00082         return AMovieDllRegisterServer2(TRUE);
    00083 }
    00084
    00085 STDAPI DllUnregisterServer()
    00086 {
    00087         UnRegisterSourceFilter(MEDIASUBTYPE_Dirac);
    00088
    00089         return AMovieDllRegisterServer2(FALSE);
    00090 }
    00091
    00092 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
    00093
    00094 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
    00095 {
    00096         return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
    00097 }
    00098
    00099 #endif
    00100
    00101 //
    00102 // CDiracSplitterFilter
    00103 //
    00104
    00105 CDiracSplitterFilter::CDiracSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr)
    00106         : CBaseSplitterFilter(NAME("CDiracSplitterFilter"), pUnk, phr, __uuidof(this))
    00107 {
    00108 }
    00109
    00110 STDMETHODIMP CDiracSplitterFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
    00111 {
    00112     CheckPointer(ppv, E_POINTER);
    00113
    00114     return
    00115                 __super::NonDelegatingQueryInterface(riid, ppv);
    00116 }
    00117
    00118 HRESULT CDiracSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
    00119 {
    00120         CheckPointer(pAsyncReader, E_POINTER);
    00121
    00122         HRESULT hr = E_FAIL;
    00123
    00124         m_pFile.Free();
    00125
    00126         m_pFile.Attach(new CDiracSplitterFile(pAsyncReader, hr));
    00127         if(!m_pFile) return E_OUTOFMEMORY;
    00128         if(FAILED(hr)) {m_pFile.Free(); return hr;}
    00129
    00130         CArray<CMediaType> mts;
    00131         mts.Add(m_pFile->GetMediaType());
    00132
    00133         CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CBaseSplitterOutputPin(mts, L"Video", this, this, &hr));
    00134         AddOutputPin(0, pPinOut);
    00135
    00136         m_rtNewStart = m_rtCurrent = 0;
    00137         m_rtNewStop = m_rtStop = m_rtDuration = m_pFile->GetDuration();
    00138
    00139         return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
    00140 }
    00141
    00142 bool CDiracSplitterFilter::DemuxInit()
    00143 {
    00144         if(!m_pFile) return(false);
    00145
    00146         // TODO
    00147
    00148         return(true);
    00149 }
    00150
    00151 void CDiracSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
    00152 {
    00153         REFERENCE_TIME rtPreroll = 0; //10000000;
    00154
    00155         if(rt <= rtPreroll || m_rtDuration <= 0)
    00156         {
    00157                 m_pFile->Seek(8);
    00158         }
    00159         else
    00160         {
    00161                 // TODO
    00162
    00163                 __int64 len = m_pFile->GetLength();
    00164                 __int64 seekpos = (__int64)(1.0*rt/m_rtDuration*len);
    00165
    00166                 m_pFile->Seek(seekpos);
    00167                 seekpos = 8;
    00168
    00169                 REFERENCE_TIME rtmax = rt - rtPreroll;
    00170                 REFERENCE_TIME rtmin = rtmax - 5000000;
    00171
    00172                 REFERENCE_TIME pdt = _I64_MIN;
    00173
    00174                 for(int j = 0; j < 10; j++)
    00175                 {
    00176                         BYTE code = NOT_START_CODE;
    00177                         while(m_pFile->Next(code) && code != IFRAME_START_CODE);
    00178                         if(code != IFRAME_START_CODE) {m_pFile->Seek(seekpos >>= 1); continue;}
    00179
    00180                         __int64 pos = m_pFile->GetPos() - 5;
    00181
    00182                         REFERENCE_TIME rt = ((DIRACINFOHEADER*)m_pFile->GetMediaType().Format())->hdr.AvgTimePerFrame * m_pFile->UnsignedGolombDecode();
    00183                         REFERENCE_TIME dt = rt - rtmax;
    00184                         if(dt > 0 && dt == pdt) dt = 10000000i64;
    00185
    00186                         if(rtmin <= rt && rt <= rtmax || pdt > 0 && dt < 0)
    00187                         {
    00188                                 seekpos = pos;
    00189                                 break;
    00190                         }
    00191
    00192                         m_pFile->Seek(pos - (__int64)(1.0*dt/m_rtDuration*len));
    00193
    00194                         pdt = dt;
    00195                 }
    00196
    00197                 m_pFile->Seek(seekpos);
    00198         }
    00199 }
    00200
    00201 bool CDiracSplitterFilter::DemuxLoop()
    00202 {
    00203         HRESULT hr = S_OK;
    00204         REFERENCE_TIME rtAvgTimePerFrame = ((DIRACINFOHEADER*)m_pFile->GetMediaType().Format())->hdr.AvgTimePerFrame;
    00205
    00206         while(SUCCEEDED(hr) && !CheckRequest(NULL))
    00207         {
    00208                 BYTE code = NOT_START_CODE;
    00209                 int size = 0, fnum = 0;
    00210                 const BYTE* pBuff = m_pFile->NextBlock(code, size, fnum);
    00211                 if(!pBuff || size < 5) break;
    00212
    00213                 if(isFrameStartCode(code))
    00214                 {
    00215                         CAutoPtr<Packet> p(new Packet());
    00216                         p->pData.SetSize(size);
    00217                         memcpy(p->pData.GetData(), pBuff, size);
    00218
    00219                         p->TrackNumber = 0;
    00220                         p->rtStart = rtAvgTimePerFrame*fnum;
    00221                         p->rtStop = p->rtStart + rtAvgTimePerFrame;
    00222                         p->bSyncPoint = code == IFRAME_START_CODE;
    00223
    00224                         hr = DeliverPacket(p);
    00225                 }
    00226
    00227                 if(code == SEQ_END_CODE)
    00228                         break;
    00229         }
    00230
    00231         return(true);
    00232 }
    00233
    00234 //
    00235 // CDiracSourceFilter
    00236 //
    00237
    00238 CDiracSourceFilter::CDiracSourceFilter(LPUNKNOWN pUnk, HRESULT* phr)
    00239         : CDiracSplitterFilter(pUnk, phr)
    00240 {
    00241         m_clsid = __uuidof(this);
    00242         m_pInput.Free();
    00243 }
    00244
    00245 //
    00246 // CDiracVideoDecoder
    00247 //
    00248
    00249 CDiracVideoDecoder::CDiracVideoDecoder(LPUNKNOWN lpunk, HRESULT* phr)
    00250         : CTransformFilter(NAME("CDiracVideoDecoder"), lpunk, __uuidof(this))
    00251 {
    00252         if(phr) *phr = S_OK;
    00253
    00254         m_decoder = NULL;
    00255         m_pYUV[0] = NULL;
    00256 }
    00257
    00258 CDiracVideoDecoder::~CDiracVideoDecoder()
    00259 {
    00260         delete [] m_pYUV[0];
    00261 }
    00262
    00263 void CDiracVideoDecoder::InitDecoder()
    00264 {
    00265         FreeDecoder();
    00266
    00267         dirac_decoder_t* decoder = dirac_decoder_init(0);
    00268
    00269         DIRACINFOHEADER* dvih = (DIRACINFOHEADER*)m_pInput->CurrentMediaType().Format();
    00270         dirac_buffer(decoder, (BYTE*)&dvih->dwSequenceHeader[0], (BYTE*)&dvih->dwSequenceHeader[0] + dvih->cbSequenceHeader);
    00271
    00272         m_decoder = decoder;
    00273 }
    00274
    00275 void CDiracVideoDecoder::FreeDecoder()
    00276 {
    00277         if(m_decoder)
    00278         {
    00279                 dirac_decoder_close((dirac_decoder_t*)m_decoder);
    00280                 m_decoder = NULL;
    00281                 delete [] m_pYUV[0]; m_pYUV[0] = NULL;
    00282         }
    00283 }
    00284
    00285 HRESULT CDiracVideoDecoder::Receive(IMediaSample* pIn)
    00286 {
    00287         CAutoLock cAutoLock(&m_csReceive);
    00288
    00289         HRESULT hr;
    00290
    00291     AM_SAMPLE2_PROPERTIES* const pProps = m_pInput->SampleProps();
    00292     if(pProps->dwStreamId != AM_STREAM_MEDIA)
    00293                 return m_pOutput->Deliver(pIn);
    00294
    00295         BYTE* pDataIn = NULL;
    00296         if(FAILED(hr = pIn->GetPointer(&pDataIn))) return hr;
    00297
    00298         long len = pIn->GetActualDataLength();
    00299         if(len <= 0) return S_OK; // nothing to do
    00300
    00301         if(pIn->IsDiscontinuity() == S_OK)
    00302                 InitDecoder();
    00303
    00304         dirac_decoder_t* decoder = (dirac_decoder_t*)m_decoder;
    00305
    00306         hr = S_OK;
    00307         while(SUCCEEDED(hr))
    00308         {
    00309         switch(dirac_parse(decoder))
    00310         {
    00311         case STATE_BUFFER:
    00312                         if(len == 0) return S_OK;
    00313                         dirac_buffer(decoder, pDataIn, pDataIn + len);
    00314                         len = 0;
    00315                         break;
    00316
    00317         case STATE_SEQUENCE:
    00318                         TRACE(_T("STATE_SEQUENCE\n"));
    00319
    00320                         {
    00321                                 DIRACINFOHEADER* dvih = (DIRACINFOHEADER*)m_pInput->CurrentMediaType().Format();
    00322                                 if(dvih->hdr.bmiHeader.biWidth != decoder->seq_params.width
    00323                                 || dvih->hdr.bmiHeader.biHeight != decoder->seq_params.height)
    00324                                         return E_FAIL; // hmm
    00325                         }
    00326
    00327                         if(!m_pYUV[0])
    00328                         {
    00329                                 int w = decoder->seq_params.width;
    00330                                 int h = decoder->seq_params.height;
    00331                                 int wc = decoder->seq_params.chroma_width;
    00332                                 int hc = decoder->seq_params.chroma_height;
    00333                                 delete [] m_pYUV[0]; m_pYUV[0] = NULL;
    00334                                 m_pYUV[0] = new BYTE[w*h + wc*hc*2 + w/2*h/2];
    00335                                 m_pYUV[1] = m_pYUV[0] + w*h;
    00336                                 m_pYUV[2] = m_pYUV[1] + wc*hc;
    00337                                 m_pYUV[3] = m_pYUV[2] + wc*hc;
    00338                                 memset(m_pYUV[3], 0x80, w/2*h/2);
    00339                                 m_rtAvgTimePerFrame = 10000000i64 * decoder->seq_params.frame_rate.denominator / decoder->seq_params.frame_rate.numerator;
    00340                                 dirac_set_buf(decoder, m_pYUV, NULL);
    00341                         }
    00342
    00343                         break;
    00344
    00345         case STATE_SEQUENCE_END:
    00346                         TRACE(_T("STATE_SEQUENCE_END\n"));
    00347             break;
    00348
    00349         case STATE_PICTURE_START:
    00350                         TRACE(_T("STATE_PICTURE_START, frame_type=%d frame_num=%d\n"), decoder->frame_params.ftype, decoder->frame_params.fnum);
    00351                         dirac_skip(decoder, (m_fDropFrames || decoder->frame_params.fnum * m_rtAvgTimePerFrame < m_tStart) && decoder->frame_params.ftype == L2_frame ? 1 : 0);
    00352                         if(m_fDropFrames && decoder->frame_params.ftype == L2_frame) return S_OK;
    00353             break;
    00354
    00355         case STATE_PICTURE_AVAIL:
    00356                         TRACE(_T("STATE_PICTURE_AVAIL, frame_type=%d frame_num=%d\n"), decoder->frame_params.ftype, decoder->frame_params.fnum);
    00357                         hr = Deliver(pIn, decoder->frame_params.fnum * m_rtAvgTimePerFrame - m_tStart, (decoder->frame_params.fnum + 1) * m_rtAvgTimePerFrame - m_tStart);
    00358                         break;
    00359
    00360         case STATE_INVALID:
    00361                         TRACE(_T("STATE_INVALID\n"));
    00362                         return E_FAIL; // TODO: can we recover from this state?
    00363                         // break;
    00364
    00365         default:
    00366                         TRACE(_T("unknown state\n"));
    00367             continue;
    00368         }
    00369     }
    00370
    00371         return hr;
    00372 }
    00373
    00374 HRESULT CDiracVideoDecoder::Deliver(IMediaSample* pIn, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop)
    00375 {
    00376         CheckPointer(pIn, E_POINTER);
    00377
    00378         HRESULT hr;
    00379
    00380         if(pIn->IsPreroll() == S_OK || rtStart < 0)
    00381                 return S_OK;
    00382
    00383     CComPtr<IMediaSample> pOut;
    00384         BYTE* pDataOut = NULL;
    00385         if(FAILED(hr = m_pOutput->GetDeliveryBuffer(&pOut, NULL, NULL, 0))
    00386         || FAILED(hr = pOut->GetPointer(&pDataOut)))
    00387                 return hr;
    00388
    00389         AM_MEDIA_TYPE* pmt;
    00390         if(SUCCEEDED(pOut->GetMediaType(&pmt)) && pmt)
    00391         {
    00392                 CMediaType mt(*pmt);
    00393                 m_pOutput->SetMediaType(&mt);
    00394                 DeleteMediaType(pmt);
    00395         }
    00396
    00397         TRACE(_T("CDiracVideoDecoder::Deliver(%I64d, %I64d)\n"), rtStart, rtStop);
    00398
    00399         pOut->SetTime(&rtStart, &rtStop);
    00400         pOut->SetMediaTime(NULL, NULL);
    00401
    00402         pOut->SetDiscontinuity(pIn->IsDiscontinuity() == S_OK);
    00403         pOut->SetSyncPoint(TRUE);
    00404
    00405         if(GetCLSID(m_pOutput->GetConnected()) == CLSID_OverlayMixer)
    00406                 pOut->SetDiscontinuity(TRUE);
    00407
    00408         Copy(pDataOut);
    00409
    00410         return m_pOutput->Deliver(pOut);
    00411 }
    00412
    00413 void CDiracVideoDecoder::Copy(BYTE* pOut)
    00414 {
    00415         // FIXME: modes other than I420 and Y-only
    00416
    00417         BITMAPINFOHEADER bihOut;
    00418         ExtractBIH(&m_pOutput->CurrentMediaType(), &bihOut);
    00419
    00420         dirac_decoder_t* decoder = (dirac_decoder_t*)m_decoder;
    00421
    00422         int w = decoder->seq_params.width;
    00423         int h = decoder->seq_params.height;
    00424         int wc = decoder->seq_params.chroma_width;
    00425         int hc = decoder->seq_params.chroma_height;
    00426
    00427         int pitchIn = w;
    00428
    00429         BYTE* pY = m_pYUV[0];
    00430         BYTE* pU = w/2 == wc && h/2 == hc ? m_pYUV[1] : m_pYUV[3]; // FIXME
    00431         BYTE* pV = w/2 == wc && h/2 == hc ? m_pYUV[2] : m_pYUV[3]; // FIXME
    00432
    00433         if(bihOut.biCompression == '2YUY')
    00434         {
    00435                 BitBltFromI420ToYUY2(w, h, pOut, bihOut.biWidth*2, pY, pU, pV, pitchIn);
    00436         }
    00437         else if(bihOut.biCompression == 'I420' || bihOut.biCompression == 'VUYI')
    00438         {
    00439                 BitBltFromI420ToI420(w, h, pOut, pOut + bihOut.biWidth*h, pOut + bihOut.biWidth*h*5/4, bihOut.biWidth, pY, pU, pV, pitchIn);
    00440         }
    00441         else if(bihOut.biCompression == '21VY')
    00442         {
    00443                 BitBltFromI420ToI420(w, h, pOut, pOut + bihOut.biWidth*h*5/4, pOut + bihOut.biWidth*h, bihOut.biWidth, pY, pU, pV, pitchIn);
    00444         }
    00445         else if(bihOut.biCompression == BI_RGB || bihOut.biCompression == BI_BITFIELDS)
    00446         {
    00447                 int pitchOut = bihOut.biWidth*bihOut.biBitCount>>3;
    00448
    00449                 if(bihOut.biHeight > 0)
    00450                 {
    00451                         pOut += pitchOut*(h-1);
    00452                         pitchOut = -pitchOut;
    00453                 }
    00454
    00455                 if(!BitBltFromI420ToRGB(w, h, pOut, pitchOut, bihOut.biBitCount, pY, pU, pV, pitchIn))
    00456                 {
    00457                         for(DWORD y = 0; y < h; y++, pOut += pitchOut)
    00458                                 memset(pOut, 0, pitchOut);
    00459                 }
    00460         }
    00461 }
    00462
    00463 HRESULT CDiracVideoDecoder::CheckInputType(const CMediaType* mtIn)
    00464 {
    00465         DIRACINFOHEADER* dvih = (DIRACINFOHEADER*)mtIn->Format();
    00466
    00467         if(mtIn->majortype != MEDIATYPE_Video
    00468         || mtIn->subtype != MEDIASUBTYPE_DiracVideo
    00469         || mtIn->formattype != FORMAT_DiracVideoInfo
    00470         || (dvih->hdr.bmiHeader.biWidth&1) || (dvih->hdr.bmiHeader.biHeight&1))
    00471                 return VFW_E_TYPE_NOT_ACCEPTED;
    00472
    00473         return S_OK;
    00474 }
    00475
    00476 HRESULT CDiracVideoDecoder::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
    00477 {
    00478         if(m_pOutput && m_pOutput->IsConnected())
    00479         {
    00480                 BITMAPINFOHEADER bih1, bih2;
    00481                 if(ExtractBIH(mtOut, &bih1) && ExtractBIH(&m_pOutput->CurrentMediaType(), &bih2)
    00482                 && abs(bih1.biHeight) != abs(bih2.biHeight))
    00483                         return VFW_E_TYPE_NOT_ACCEPTED;
    00484         }
    00485
    00486         return mtIn->majortype == MEDIATYPE_Video && mtIn->subtype == MEDIASUBTYPE_DiracVideo
    00487                 && mtOut->majortype == MEDIATYPE_Video && (mtOut->subtype == MEDIASUBTYPE_YUY2
    00488                                                                                                 || mtOut->subtype == MEDIASUBTYPE_YV12
    00489                                                                                                 || mtOut->subtype == MEDIASUBTYPE_I420
    00490                                                                                                 || mtOut->subtype == MEDIASUBTYPE_IYUV
    00491                                                                                                 || mtOut->subtype == MEDIASUBTYPE_ARGB32
    00492                                                                                                 || mtOut->subtype == MEDIASUBTYPE_RGB32
    00493                                                                                                 || mtOut->subtype == MEDIASUBTYPE_RGB24
    00494                                                                                                 || mtOut->subtype == MEDIASUBTYPE_RGB565
    00495                                                                                                 || mtOut->subtype == MEDIASUBTYPE_RGB555)
    00496                 ? S_OK
    00497                 : VFW_E_TYPE_NOT_ACCEPTED;
    00498 }
    00499
    00500 HRESULT CDiracVideoDecoder::DecideBufferSize(IMemAllocator* pAllocator, ALLOCATOR_PROPERTIES* pProperties)
    00501 {
    00502         if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
    00503
    00504         BITMAPINFOHEADER bih;
    00505         ExtractBIH(&m_pOutput->CurrentMediaType(), &bih);
    00506
    00507         pProperties->cBuffers = 1;
    00508         pProperties->cbBuffer = bih.biSizeImage;
    00509         pProperties->cbAlign = 1;
    00510         pProperties->cbPrefix = 0;
    00511
    00512         HRESULT hr;
    00513         ALLOCATOR_PROPERTIES Actual;
    00514     if(FAILED(hr = pAllocator->SetProperties(pProperties, &Actual)))
    00515                 return hr;
    00516
    00517     return(pProperties->cBuffers > Actual.cBuffers || pProperties->cbBuffer > Actual.cbBuffer
    00518                 ? E_FAIL
    00519                 : NOERROR);
    00520 }
    00521
    00522 HRESULT CDiracVideoDecoder::GetMediaType(int iPosition, CMediaType* pmt)
    00523 {
    00524     if(m_pInput->IsConnected() == FALSE) return E_UNEXPECTED;
    00525
    00526         struct {const GUID* subtype; WORD biPlanes, biBitCount; DWORD biCompression;} fmts[] =
    00527         {
    00528                 {&MEDIASUBTYPE_YV12, 3, 12, '21VY'},
    00529                 {&MEDIASUBTYPE_I420, 3, 12, '024I'},
    00530                 {&MEDIASUBTYPE_IYUV, 3, 12, 'VUYI'},
    00531                 {&MEDIASUBTYPE_YUY2, 1, 16, '2YUY'},
    00532                 {&MEDIASUBTYPE_ARGB32, 1, 32, BI_RGB},
    00533                 {&MEDIASUBTYPE_RGB32, 1, 32, BI_RGB},
    00534                 {&MEDIASUBTYPE_RGB24, 1, 24, BI_RGB},
    00535                 {&MEDIASUBTYPE_RGB565, 1, 16, BI_RGB},
    00536                 {&MEDIASUBTYPE_RGB555, 1, 16, BI_RGB},
    00537                 {&MEDIASUBTYPE_ARGB32, 1, 32, BI_BITFIELDS},
    00538                 {&MEDIASUBTYPE_RGB32, 1, 32, BI_BITFIELDS},
    00539                 {&MEDIASUBTYPE_RGB24, 1, 24, BI_BITFIELDS},
    00540                 {&MEDIASUBTYPE_RGB565, 1, 16, BI_BITFIELDS},
    00541                 {&MEDIASUBTYPE_RGB555, 1, 16, BI_BITFIELDS},
    00542         };
    00543
    00544         if(m_pInput->CurrentMediaType().formattype == FORMAT_VideoInfo)
    00545                 iPosition = iPosition*2 + 1;
    00546
    00547         if(iPosition < 0) return E_INVALIDARG;
    00548         if(iPosition >= 2*countof(fmts)) return VFW_S_NO_MORE_ITEMS;
    00549
    00550         BITMAPINFOHEADER bih;
    00551         ExtractBIH(&m_pInput->CurrentMediaType(), &bih);
    00552
    00553         pmt->majortype = MEDIATYPE_Video;
    00554         pmt->subtype = *fmts[iPosition/2].subtype;
    00555
    00556         BITMAPINFOHEADER bihOut;
    00557         memset(&bihOut, 0, sizeof(bihOut));
    00558         bihOut.biSize = sizeof(bihOut);
    00559         bihOut.biWidth = bih.biWidth;
    00560         bihOut.biHeight = bih.biHeight;
    00561         bihOut.biPlanes = fmts[iPosition/2].biPlanes;
    00562         bihOut.biBitCount = fmts[iPosition/2].biBitCount;
    00563         bihOut.biCompression = fmts[iPosition/2].biCompression;
    00564         bihOut.biSizeImage = bih.biWidth*bih.biHeight*bihOut.biBitCount>>3;
    00565
    00566         if(iPosition&1)
    00567         {
    00568                 pmt->formattype = FORMAT_VideoInfo;
    00569                 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
    00570                 memset(vih, 0, sizeof(VIDEOINFOHEADER));
    00571                 vih->bmiHeader = bihOut;
    00572
    00573                 if(m_pInput->CurrentMediaType().formattype == FORMAT_VideoInfo2)
    00574                 {
    00575                         vih->bmiHeader.biWidth = ((VIDEOINFOHEADER2*)m_pInput->CurrentMediaType().Format())->dwPictAspectRatioX;
    00576                         vih->bmiHeader.biHeight = ((VIDEOINFOHEADER2*)m_pInput->CurrentMediaType().Format())->dwPictAspectRatioY;
    00577                         vih->bmiHeader.biSizeImage = vih->bmiHeader.biWidth*vih->bmiHeader.biHeight*vih->bmiHeader.biBitCount>>3;
    00578                 }
    00579         }
    00580         else
    00581         {
    00582                 pmt->formattype = FORMAT_VideoInfo2;
    00583                 VIDEOINFOHEADER2* vih2 = (VIDEOINFOHEADER2*)pmt->AllocFormatBuffer(sizeof(VIDEOINFOHEADER2));
    00584                 memset(vih2, 0, sizeof(VIDEOINFOHEADER2));
    00585                 vih2->bmiHeader = bihOut;
    00586                 vih2->dwPictAspectRatioX = ((VIDEOINFOHEADER2*)m_pInput->CurrentMediaType().Format())->dwPictAspectRatioX;
    00587                 vih2->dwPictAspectRatioY = ((VIDEOINFOHEADER2*)m_pInput->CurrentMediaType().Format())->dwPictAspectRatioY;
    00588         }
    00589
    00590         CorrectMediaType(pmt);
    00591
    00592         return S_OK;
    00593 }
    00594
    00595 HRESULT CDiracVideoDecoder::StartStreaming()
    00596 {
    00597         InitDecoder();
    00598         return __super::StartStreaming();
    00599 }
    00600
    00601 HRESULT CDiracVideoDecoder::StopStreaming()
    00602 {
    00603         FreeDecoder();
    00604         return __super::StopStreaming();
    00605 }
    00606
    00607 HRESULT CDiracVideoDecoder::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
    00608 {
    00609         CAutoLock cAutoLock(&m_csReceive);
    00610
    00611         m_fDropFrames = false;
    00612         m_tStart = tStart;
    00613
    00614         return __super::NewSegment(tStart, tStop, dRate);
    00615 }
    00616
    00617 HRESULT CDiracVideoDecoder::AlterQuality(Quality q)
    00618 {
    00619         if(q.Late > 500*10000i64) m_fDropFrames = true;
    00620         if(q.Late <= 0) m_fDropFrames = false;
    00621         return E_NOTIMPL;
    00622 }