[cvs] / xvidcore / dshow / src / CXvidDecoder.cpp Repository:
ViewVC logotype

Diff of /xvidcore/dshow/src/CXvidDecoder.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1, Sat Feb 22 08:22:03 2003 UTC revision 1.1.2.1, Sat Feb 22 08:22:03 2003 UTC
# Line 0  Line 1 
1    /**************************************************************************
2     *
3     *      XVID DIRECTSHOW FRONTEND -- decoder fitler
4     *      Copyright (c) 2002 Peter Ross <pross@xvid.org>
5     *
6     *      This program is free software; you can redistribute it and/or modify
7     *      it under the terms of the GNU General Public License as published by
8     *      the Free Software Foundation; either version 2 of the License, or
9     *      (at your option) any later version.
10     *
11     *      This program is distributed in the hope that it will be useful,
12     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     *      GNU General Public License for more details.
15     *
16     *      You should have received a copy of the GNU General Public License
17     *      along with this program; if not, write to the Free Software
18     *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     *
20     *************************************************************************/
21    
22     /*
23            this requires the directx sdk
24            place these paths at the top of the Tools|Options|Directories list
25    
26            headers:
27            C:\DXVCSDK\include
28            C:\DXVCSDK\samples\Multimedia\DirectShow\BaseClasses
29    
30            libraries (optional):
31            C:\DXVCSDK\samples\Multimedia\DirectShow\BaseClasses\Release
32    */
33    
34    
35    
36    #include <windows.h>
37    
38    #include <streams.h>
39    #include <initguid.h>
40    #include <olectl.h>
41    #if (1100 > _MSC_VER)
42    #include <olectlid.h>
43    #endif
44    #include <dvdmedia.h>   // VIDEOINFOHEADER2
45    
46    #include <xvid.h>               // XviD API
47    
48    #include "IXvidDecoder.h"
49    #include "CXvidDecoder.h"
50    #include "CAbout.h"
51    
52    
53    const AMOVIESETUP_MEDIATYPE sudInputPinTypes[] =
54    {
55        { &MEDIATYPE_Video, &CLSID_XVID },
56            { &MEDIATYPE_Video, &CLSID_XVID_UC },
57            { &MEDIATYPE_Video, &CLSID_DIVX },
58            { &MEDIATYPE_Video, &CLSID_DIVX_UC },
59            { &MEDIATYPE_Video, &CLSID_DX50 },
60            { &MEDIATYPE_Video, &CLSID_DX50_UC },
61    };
62    
63    const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] =
64    {
65        { &MEDIATYPE_Video, &MEDIASUBTYPE_NULL }
66    };
67    
68    
69    const AMOVIESETUP_PIN psudPins[] =
70    {
71            {
72                    L"Input",           // String pin name
73                    FALSE,              // Is it rendered
74                    FALSE,              // Is it an output
75                    FALSE,              // Allowed none
76                    FALSE,              // Allowed many
77                    &CLSID_NULL,        // Connects to filter
78                    L"Output",          // Connects to pin
79                    sizeof(sudInputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE), // Number of types
80                    &sudInputPinTypes[0]    // The pin details
81            },
82            {
83                    L"Output",          // String pin name
84                    FALSE,              // Is it rendered
85                    TRUE,               // Is it an output
86                    FALSE,              // Allowed none
87                    FALSE,              // Allowed many
88                    &CLSID_NULL,        // Connects to filter
89                    L"Input",           // Connects to pin
90                    sizeof(sudOutputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE),      // Number of types
91                    sudOutputPinTypes       // The pin details
92            }
93    };
94    
95    
96    const AMOVIESETUP_FILTER sudXvidDecoder =
97    {
98            &CLSID_XVID,                    // Filter CLSID
99            XVID_NAME_L,                    // Filter name
100            MERIT_PREFERRED,                // Its merit
101            sizeof(psudPins) / sizeof(AMOVIESETUP_PIN),     // Number of pins
102            psudPins                                // Pin details
103    };
104    
105    
106    // List of class IDs and creator functions for the class factory. This
107    // provides the link between the OLE entry point in the DLL and an object
108    // being created. The class factory will call the static CreateInstance
109    
110    CFactoryTemplate g_Templates[] =
111    {
112            {
113                    XVID_NAME_L,
114                    &CLSID_XVID,
115                    CXvidDecoder::CreateInstance,
116                    NULL,
117                    &sudXvidDecoder
118            },
119            {
120                    XVID_NAME_L L"About",
121                    &CLSID_CABOUT,
122                    CAbout::CreateInstance
123            }
124    
125    };
126    
127    int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate);
128    
129    
130    
131    
132    STDAPI DllRegisterServer()
133    {
134        return AMovieDllRegisterServer2( TRUE );
135    }
136    
137    
138    STDAPI DllUnregisterServer()
139    {
140        return AMovieDllRegisterServer2( FALSE );
141    }
142    
143    
144    /* create instance */
145    
146    CUnknown * WINAPI CXvidDecoder::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
147    {
148        CXvidDecoder * pNewObject = new CXvidDecoder(punk, phr);
149        if (pNewObject == NULL)
150            {
151            *phr = E_OUTOFMEMORY;
152        }
153        return pNewObject;
154    }
155    
156    
157    /* query interfaces */
158    
159    STDMETHODIMP CXvidDecoder::NonDelegatingQueryInterface(REFIID riid, void **ppv)
160    {
161            CheckPointer(ppv, E_POINTER);
162    
163            if (riid == IID_IXvidDecoder)
164            {
165                    return GetInterface((IXvidDecoder *) this, ppv);
166            }
167    
168            if (riid == IID_ISpecifyPropertyPages)
169            {
170            return GetInterface((ISpecifyPropertyPages *) this, ppv);
171            }
172    
173            return CVideoTransformFilter::NonDelegatingQueryInterface(riid, ppv);
174    }
175    
176    
177    
178    /* dummy decore() */
179    
180    static int dummy_xvid_decore(void * handle, int opt, void * param1, void * param2)
181    {
182            return XVID_ERR_FAIL;
183    }
184    
185    
186    
187    /* constructor */
188    
189    #define XVID_DLL_NAME           "xvid.dll"
190    #define XVID_GLOBAL_NAME        "xvid_global"
191    #define XVID_DECORE_NAME        "xvid_decore"
192    
193    CXvidDecoder::CXvidDecoder(LPUNKNOWN punk, HRESULT *phr) :
194        CVideoTransformFilter(NAME("CXvidDecoder"), punk, CLSID_XVID)
195    {
196            DPRINTF("Constructor");
197    
198            m_xvid_decore = dummy_xvid_decore;
199    
200            m_hdll = LoadLibrary(XVID_DLL_NAME);
201            if (m_hdll == NULL) {
202                    DPRINTF("dll load failed");
203                    MessageBox(0, XVID_DLL_NAME " not found","Error", 0);
204                    return;
205            }
206    
207            m_xvid_global = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, XVID_GLOBAL_NAME);
208            if (m_xvid_global == NULL) {
209                    MessageBox(0, XVID_GLOBAL_NAME "() not found", "Error", 0);
210                    return;
211            }
212    
213            m_xvid_decore = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, XVID_DECORE_NAME);
214            if (m_xvid_decore == NULL) {
215                    MessageBox(0, XVID_DECORE_NAME "() not found", "Error", 0);
216                    return;
217            }
218    
219            xvid_gbl_init_t init;
220            memset(&init, 0, sizeof(init));
221            init.version = XVID_VERSION;
222            if (m_xvid_global(0, XVID_GBL_INIT, &init, NULL) < 0)
223            {
224                    MessageBox(0, XVID_GLOBAL_NAME "() failed", "Error", 0);
225                    return;
226            }
227    
228            memset(&m_create, 0, sizeof(m_create));
229            m_create.version = XVID_VERSION;
230            m_create.handle = NULL;
231    
232            memset(&m_frame, 0, sizeof(m_frame));
233            m_frame.version = XVID_VERSION;
234    }
235    
236    
237    
238    /* destructor */
239    
240    CXvidDecoder::~CXvidDecoder()
241    {
242            DPRINTF("Destructor");
243    
244            if (m_create.handle != NULL)
245            {
246                    m_xvid_decore(m_create.handle, XVID_DEC_DESTROY, 0, 0);
247                    m_create.handle = NULL;
248            }
249    
250            if (m_hdll != NULL)
251            {
252                    FreeLibrary(m_hdll);
253                    m_hdll = NULL;
254            }
255    }
256    
257    
258    
259    /* check input type */
260    
261    HRESULT CXvidDecoder::CheckInputType(const CMediaType * mtIn)
262    {
263            DPRINTF("CheckInputType");
264            BITMAPINFOHEADER * hdr;
265    
266            if (*mtIn->Type() != MEDIATYPE_Video)
267            {
268                    DPRINTF("Error: Unknown Type");
269                    return VFW_E_TYPE_NOT_ACCEPTED;
270            }
271    
272            if (*mtIn->FormatType() == FORMAT_VideoInfo)
273            {
274                    VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtIn->Format();
275                    hdr = &vih->bmiHeader;
276            }
277            else if (*mtIn->FormatType() == FORMAT_VideoInfo2)
278            {
279                    VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 *) mtIn->Format();
280                    hdr = &vih2->bmiHeader;
281            }
282            else
283            {
284                    DPRINTF("Error: Unknown FormatType");
285                    return VFW_E_TYPE_NOT_ACCEPTED;
286            }
287    
288            if (hdr->biHeight < 0)
289            {
290                    DPRINTF("colorspace: inverted input format not supported");
291            }
292    
293            m_create.width = hdr->biWidth;
294            m_create.height = hdr->biHeight;
295    
296            switch(hdr->biCompression)
297            {
298            case FOURCC_XVID :
299    //      case FOURCC_DIVX :
300    //      case FOURCC_DX50 :
301                    break;
302    
303            default :
304                    DPRINTF("Unknown fourcc: 0x%08x (%c%c%c%c)",
305                            hdr->biCompression,
306                            (hdr->biCompression)&0xff,
307                            (hdr->biCompression>>8)&0xff,
308                            (hdr->biCompression>>16)&0xff,
309                            (hdr->biCompression>>24)&0xff);
310                    return VFW_E_TYPE_NOT_ACCEPTED;
311            }
312    
313            return S_OK;
314    }
315    
316    
317    #define USE_IYUV
318    #define USE_YV12
319    #define USE_YUY2
320    #define USE_YVYU
321    #define USE_UYVY
322    #define USE_RGB32
323    #define USE_RGB24
324    #define USE_RG555
325    #define USE_RG565
326    
327    /* get list of supported output colorspaces */
328    
329    HRESULT CXvidDecoder::GetMediaType(int iPosition, CMediaType *mtOut)
330    {
331            DPRINTF("GetMediaType");
332    
333            if (m_pInput->IsConnected() == FALSE)
334            {
335                    return E_UNEXPECTED;
336            }
337    
338            VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER));
339            if (vih == NULL)
340            {
341                    return E_OUTOFMEMORY;
342            }
343    
344            ZeroMemory(vih, sizeof (VIDEOINFOHEADER));
345            vih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
346            vih->bmiHeader.biWidth  = m_create.width;
347            vih->bmiHeader.biHeight = m_create.height;
348            vih->bmiHeader.biPlanes = 1;
349    
350            if (iPosition < 0)
351            {
352                    return E_INVALIDARG;
353            }
354    
355            switch(iPosition)
356            {
357            case 0  :
358    #ifdef USE_IYUV
359                    vih->bmiHeader.biCompression = MEDIASUBTYPE_IYUV.Data1;
360                    vih->bmiHeader.biBitCount = 12;
361                    mtOut->SetSubtype(&MEDIASUBTYPE_IYUV);
362                    break;
363    #endif
364            case 1  :
365    #ifdef USE_YV12
366                    vih->bmiHeader.biCompression = MEDIASUBTYPE_YV12.Data1;
367                    vih->bmiHeader.biBitCount = 12;
368                    mtOut->SetSubtype(&MEDIASUBTYPE_YV12);
369                    break;
370    #endif
371            case 2:
372    #ifdef USE_YUY2
373                    vih->bmiHeader.biCompression = MEDIASUBTYPE_YUY2.Data1;
374                    vih->bmiHeader.biBitCount = 16;
375                    mtOut->SetSubtype(&MEDIASUBTYPE_YUY2);
376                    break;
377    #endif
378            case 3 :
379    #ifdef USE_YVYU
380                    vih->bmiHeader.biCompression = MEDIASUBTYPE_YVYU.Data1;
381                    vih->bmiHeader.biBitCount = 16;
382                    mtOut->SetSubtype(&MEDIASUBTYPE_YVYU);
383                    break;
384    #endif
385            case 4 :
386    #ifdef USE_UYVY
387                    vih->bmiHeader.biCompression = MEDIASUBTYPE_UYVY.Data1;
388                    vih->bmiHeader.biBitCount = 16;
389                    mtOut->SetSubtype(&MEDIASUBTYPE_UYVY);
390                    break;
391    #endif
392            case 5 :
393    #ifdef USE_RGB32
394                    vih->bmiHeader.biCompression = BI_RGB;
395                    vih->bmiHeader.biBitCount = 32;
396                    mtOut->SetSubtype(&MEDIASUBTYPE_RGB32);
397                    break;
398    #endif
399            case 6 :
400    #ifdef USE_RGB24
401                    vih->bmiHeader.biCompression = BI_RGB;
402                    vih->bmiHeader.biBitCount = 24;
403                    mtOut->SetSubtype(&MEDIASUBTYPE_RGB24);
404                    break;
405    #endif
406            case 7 :
407    #ifdef USE_RG555
408                    vih->bmiHeader.biCompression = BI_RGB;
409                    vih->bmiHeader.biBitCount = 16;
410                    mtOut->SetSubtype(&MEDIASUBTYPE_RGB555);
411                    break;
412    #endif
413            case 8 :
414    #ifdef USE_RG565
415                    vih->bmiHeader.biCompression = BI_RGB;
416                    vih->bmiHeader.biBitCount = 16;
417                    mtOut->SetSubtype(&MEDIASUBTYPE_RGB565);
418                    break;
419    #endif
420            default :
421                    return VFW_S_NO_MORE_ITEMS;
422            }
423    
424            vih->bmiHeader.biSizeImage = GetBitmapSize(&vih->bmiHeader);
425    
426            mtOut->SetType(&MEDIATYPE_Video);
427            mtOut->SetFormatType(&FORMAT_VideoInfo);
428            mtOut->SetTemporalCompression(FALSE);
429            mtOut->SetSampleSize(vih->bmiHeader.biSizeImage);
430    
431            return S_OK;
432    }
433    
434    
435    /* (internal function) change colorspace */
436    
437    HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format)
438    {
439            int rgb_flip;
440    
441            if (formattype == FORMAT_VideoInfo)
442            {
443                    VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;
444                    m_frame.output.stride[0] = (((vih->bmiHeader.biWidth * vih->bmiHeader.biBitCount) + 31) & ~31) >> 3;
445                    rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
446            }
447            else if (formattype == FORMAT_VideoInfo2)
448            {
449                    VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;
450                    m_frame.output.stride[0] = (((vih2->bmiHeader.biWidth * vih2->bmiHeader.biBitCount) + 31) & ~31) >> 3;
451                    rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
452            }
453            else
454            {
455                    return S_FALSE;
456            }
457    
458            if (subtype == MEDIASUBTYPE_IYUV)
459            {
460                    DPRINTF("IYUV");
461                    m_frame.output.csp = XVID_CSP_I420;
462                    m_frame.output.stride[0] = (m_frame.output.stride[0] * 2) / 3;  /* planar format fix */
463            }
464            else if (subtype == MEDIASUBTYPE_YV12)
465            {
466                    DPRINTF("YV12");
467                    m_frame.output.csp = XVID_CSP_YV12;
468                    m_frame.output.stride[0] = (m_frame.output.stride[0] * 2) / 3;  /* planar format fix */
469            }
470            else if (subtype == MEDIASUBTYPE_YUY2)
471            {
472                    DPRINTF("YUY2");
473                    m_frame.output.csp = XVID_CSP_YUY2;
474            }
475            else if (subtype == MEDIASUBTYPE_YVYU)
476            {
477                    DPRINTF("YVYU");
478                    m_frame.output.csp = XVID_CSP_YVYU;
479            }
480            else if (subtype == MEDIASUBTYPE_UYVY)
481            {
482                    DPRINTF("UYVY");
483                    m_frame.output.csp = XVID_CSP_UYVY;
484            }
485            else if (subtype == MEDIASUBTYPE_RGB32)
486            {
487                    DPRINTF("RGB32");
488                    m_frame.output.csp = rgb_flip | XVID_CSP_BGRA;
489            }
490            else if (subtype == MEDIASUBTYPE_RGB24)
491            {
492                    DPRINTF("RGB24");
493                    m_frame.output.csp = rgb_flip | XVID_CSP_BGR;
494            }
495            else if (subtype == MEDIASUBTYPE_RGB555)
496            {
497                    DPRINTF("RGB555");
498                    m_frame.output.csp = rgb_flip | XVID_CSP_RGB555;
499            }
500            else if (subtype == MEDIASUBTYPE_RGB565)
501            {
502                    DPRINTF("RGB565");
503                    m_frame.output.csp = rgb_flip | XVID_CSP_RGB565;
504            }
505            else if (subtype == GUID_NULL)
506            {
507                    m_frame.output.csp = XVID_CSP_NULL;
508            }
509            else
510            {
511                    return S_FALSE;
512            }
513    
514            return S_OK;
515    }
516    
517    
518    /* set output colorspace */
519    
520    HRESULT CXvidDecoder::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt)
521    {
522            DPRINTF("SetMediaType");
523    
524            if (direction == PINDIR_OUTPUT)
525            {
526                    return ChangeColorspace(*pmt->Subtype(), *pmt->FormatType(), pmt->Format());
527            }
528    
529            return S_OK;
530    }
531    
532    
533    /* check input<->output compatiblity */
534    
535    HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
536    {
537            DPRINTF("CheckTransform");
538            return S_OK;
539    }
540    
541    
542    /* alloc output buffer */
543    
544    HRESULT CXvidDecoder::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest)
545    {
546            DPRINTF("DecideBufferSize");
547            HRESULT result;
548            ALLOCATOR_PROPERTIES ppropActual;
549    
550            if (m_pInput->IsConnected() == FALSE)
551            {
552                    return E_UNEXPECTED;
553            }
554    
555            ppropInputRequest->cBuffers = 1;
556            ppropInputRequest->cbBuffer = m_create.width * m_create.height * 4;
557            // cbAlign causes problems with the resize filter */
558            // ppropInputRequest->cbAlign = 16;
559            ppropInputRequest->cbPrefix = 0;
560    
561            result = pAlloc->SetProperties(ppropInputRequest, &ppropActual);
562            if (result != S_OK)
563            {
564                    return result;
565            }
566    
567            if (ppropActual.cbBuffer < ppropInputRequest->cbBuffer)
568            {
569                    return E_FAIL;
570            }
571    
572            return S_OK;
573    }
574    
575    
576    /* decode frame */
577    
578    HRESULT CXvidDecoder::Transform(IMediaSample *pIn, IMediaSample *pOut)
579    {
580            DPRINTF("Transform");
581            xvid_dec_stats_t stats;
582        int length;
583    
584            memset(&stats, 0, sizeof(stats));
585            stats.version = XVID_VERSION;
586    
587            if (m_create.handle == NULL)
588            {
589                    if (m_xvid_decore(0, XVID_DEC_CREATE, &m_create, 0) < 0)
590                    {
591                DPRINTF("*** XVID_DEC_CREATE error");
592                            return S_FALSE;
593                    }
594            }
595    
596            AM_MEDIA_TYPE * mtOut;
597            pOut->GetMediaType(&mtOut);
598            if (mtOut != NULL)
599            {
600                    HRESULT result;
601    
602                    result = ChangeColorspace(mtOut->subtype, mtOut->formattype, mtOut->pbFormat);
603                    DeleteMediaType(mtOut);
604    
605                    if (result != S_OK)
606                    {
607                DPRINTF("*** ChangeColorspace error");
608                            return result;
609                    }
610            }
611    
612            m_frame.length = pIn->GetActualDataLength();
613            if (pIn->GetPointer((BYTE**)&m_frame.bitstream) != S_OK)
614            {
615                    return S_FALSE;
616            }
617    
618            if (pOut->GetPointer((BYTE**)&m_frame.output.plane[0]) != S_OK)
619            {
620                    return S_FALSE;
621            }
622    
623            m_frame.general = XVID_LOWDELAY;
624            if (pIn->IsDiscontinuity() == S_OK)
625                    m_frame.general = XVID_DISCONTINUITY;
626    
627    repeat :
628    
629            if (pIn->IsPreroll() != S_OK)
630            {
631                    length = m_xvid_decore(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
632                    if (length < 0)
633                    {
634                DPRINTF("*** XVID_DEC_DECODE");
635                            return S_FALSE;
636                    }
637            }
638            else
639            {
640                    int tmp = m_frame.output.csp;
641                    m_frame.output.csp = XVID_CSP_NULL;
642    
643                    length = m_xvid_decore(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
644                    if (length < 0)
645                    {
646                DPRINTF("*** XVID_DEC_DECODE");
647                            return S_FALSE;
648                    }
649    
650                    m_frame.output.csp = tmp;
651            }
652    
653            if (stats.type == XVID_TYPE_VOL)
654            {
655                    if (stats.data.vol.width != m_create.width ||
656                            stats.data.vol.height != m_create.height)
657                    {
658                            DPRINTF("TODO: auto-resize");
659                            return S_FALSE;
660                    }
661    
662                    m_frame.bitstream = (BYTE*)m_frame.bitstream + length;
663                    m_frame.length -= length;
664                    goto repeat;
665            }
666    
667            return S_OK;
668    }
669    
670    
671    /* get property page list */
672    
673    STDMETHODIMP CXvidDecoder::GetPages(CAUUID * pPages)
674    {
675            DPRINTF("GetPages");
676    
677            pPages->cElems = 1;
678            pPages->pElems = (GUID *)CoTaskMemAlloc(pPages->cElems * sizeof(GUID));
679            if (pPages->pElems == NULL)
680            {
681                    return E_OUTOFMEMORY;
682            }
683            pPages->pElems[0] = CLSID_CABOUT;
684    
685            return S_OK;
686    }
687    
688    
689    /* cleanup pages */
690    
691    STDMETHODIMP CXvidDecoder::FreePages(CAUUID * pPages)
692    {
693            DPRINTF("FreePages");
694            CoTaskMemFree(pPages->pElems);
695            return S_OK;
696    }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.1.2.1

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4