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

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

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