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

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

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

revision 1428, Wed Apr 14 03:25:41 2004 UTC revision 2018, Wed Jun 15 19:09:17 2011 UTC
# Line 1  Line 1 
1  /*****************************************************************************  /*****************************************************************************
2   *   *
3   *  XVID MPEG-4 VIDEO CODEC   *  XVID MPEG-4 VIDEO CODEC
4   *  - XviD Decoder part of the DShow Filter  -   *  - Xvid Decoder part of the DShow Filter  -
5   *   *
6   *  Copyright(C) 2002-2004 Peter Ross <pross@xvid.org>   *  Copyright(C) 2002-2011 Peter Ross <pross@xvid.org>
7     *               2003-2011 Michael Militzer <michael@xvid.org>
8   *   *
9   *  This program is free software ; you can redistribute it and/or modify   *  This program is free software ; you can redistribute it and/or modify
10   *  it under the terms of the GNU General Public License as published by   *  it under the terms of the GNU General Public License as published by
# Line 19  Line 20 
20   *  along with this program ; if not, write to the Free Software   *  along with this program ; if not, write to the Free Software
21   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22   *   *
23   * $Id: CXvidDecoder.cpp,v 1.5 2004-04-14 03:25:41 syskin Exp $   * $Id$
  *  
  ****************************************************************************/  
   
 /****************************************************************************  
  *  
  * 2003/12/11 - added some additional options, mainly to make the deblocking  
  *              code from xvidcore available. Most of the new code is taken  
  *              from Nic's dshow filter, (C) Nic, http://nic.dnsalias.com  
24   *   *
25   ****************************************************************************/   ****************************************************************************/
26    
# Line 36  Line 29 
29          place these paths at the top of the Tools|Options|Directories list          place these paths at the top of the Tools|Options|Directories list
30    
31          headers:          headers:
32          C:\DXVCSDK\include          C:\DX90SDK\Include
33          C:\DXVCSDK\samples\Multimedia\DirectShow\BaseClasses          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses
34    
35          libraries (optional):          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Release
36          C:\DXVCSDK\samples\Multimedia\DirectShow\BaseClasses\Release          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Debug
37  */  */
38    
39    #ifdef ENABLE_MFT
40    #define XVID_USE_MFT
41    #endif
42    
43    #define XVID_USE_TRAYICON
44    
45  #include <windows.h>  #include <windows.h>
46    
# Line 55  Line 52 
52  #endif  #endif
53  #include <dvdmedia.h>   // VIDEOINFOHEADER2  #include <dvdmedia.h>   // VIDEOINFOHEADER2
54    
55  #include <xvid.h>               // XviD API  #if defined(XVID_USE_MFT)
56    #define MFT_UNIQUE_METHOD_NAMES
57    #include <mftransform.h>
58    #include <mfapi.h>
59    #include <mferror.h>
60    #include <shlwapi.h>
61    #endif
62    
63    #include <shellapi.h>
64    
65    #include <xvid.h>               // Xvid API
66    
67    #include "resource.h"
68    
69  #include "IXvidDecoder.h"  #include "IXvidDecoder.h"
70  #include "CXvidDecoder.h"  #include "CXvidDecoder.h"
# Line 81  Line 90 
90          { &MEDIATYPE_Video, &CLSID_DIVX_UC },          { &MEDIATYPE_Video, &CLSID_DIVX_UC },
91          { &MEDIATYPE_Video, &CLSID_DX50 },          { &MEDIATYPE_Video, &CLSID_DX50 },
92          { &MEDIATYPE_Video, &CLSID_DX50_UC },          { &MEDIATYPE_Video, &CLSID_DX50_UC },
93            { &MEDIATYPE_Video, &CLSID_3IVX },
94            { &MEDIATYPE_Video, &CLSID_3IVX_UC },
95            { &MEDIATYPE_Video, &CLSID_3IV0 },
96            { &MEDIATYPE_Video, &CLSID_3IV0_UC },
97            { &MEDIATYPE_Video, &CLSID_3IV1 },
98            { &MEDIATYPE_Video, &CLSID_3IV1_UC },
99            { &MEDIATYPE_Video, &CLSID_3IV2 },
100            { &MEDIATYPE_Video, &CLSID_3IV2_UC },
101            { &MEDIATYPE_Video, &CLSID_LMP4 },
102            { &MEDIATYPE_Video, &CLSID_LMP4_UC },
103            { &MEDIATYPE_Video, &CLSID_RMP4 },
104            { &MEDIATYPE_Video, &CLSID_RMP4_UC },
105            { &MEDIATYPE_Video, &CLSID_SMP4 },
106            { &MEDIATYPE_Video, &CLSID_SMP4_UC },
107            { &MEDIATYPE_Video, &CLSID_HDX4 },
108            { &MEDIATYPE_Video, &CLSID_HDX4_UC },
109          { &MEDIATYPE_Video, &CLSID_MP4V },          { &MEDIATYPE_Video, &CLSID_MP4V },
110      { &MEDIATYPE_Video, &CLSID_MP4V_UC },
111  };  };
112    
113  const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] =  const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] =
# Line 121  Line 147 
147  {  {
148          &CLSID_XVID,                    // Filter CLSID          &CLSID_XVID,                    // Filter CLSID
149          XVID_NAME_L,                    // Filter name          XVID_NAME_L,                    // Filter name
150          MERIT_PREFERRED,                // Its merit          MERIT_PREFERRED+2,              // Its merit
151          sizeof(psudPins) / sizeof(AMOVIESETUP_PIN),     // Number of pins          sizeof(psudPins) / sizeof(AMOVIESETUP_PIN),     // Number of pins
152          psudPins                                // Pin details          psudPins                                // Pin details
153  };  };
# Line 148  Line 174 
174    
175  };  };
176    
   
177  /* note: g_cTemplates must be global; used by strmbase.lib(dllentry.cpp,dllsetup.cpp) */  /* note: g_cTemplates must be global; used by strmbase.lib(dllentry.cpp,dllsetup.cpp) */
178  int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate);  int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate);
179    
180    #ifdef XVID_USE_TRAYICON
181    extern HINSTANCE g_xvid_hInst;
182    
183    static int GUI_Page = 0;
184    static int Tray_Icon = 0;
185    extern "C" void CALLBACK Configure(HWND hWndParent, HINSTANCE hInstParent, LPSTR lpCmdLine, int nCmdShow );
186    
187    LRESULT CALLBACK msg_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
188    {
189            switch ( uMsg )
190            {
191            case WM_ICONMESSAGE:
192                    switch(lParam)
193                    {
194                    case WM_LBUTTONDBLCLK:
195                            if (!GUI_Page) {
196                                    GUI_Page = 1;
197                                    Configure(hwnd, g_xvid_hInst, "", 1);
198                                    GUI_Page = 0;
199                            }
200                            break;
201                    default:
202                            return DefWindowProc(hwnd, uMsg, wParam, lParam);
203                    };
204                    break;
205    
206            case WM_DESTROY:
207                    NOTIFYICONDATA nid;
208                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
209    
210                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
211                    nid.hWnd = hwnd;
212                    nid.uID = 1456;
213    
214                    Shell_NotifyIcon(NIM_DELETE, &nid);
215                    Tray_Icon = 0;
216            default:
217                    return DefWindowProc(hwnd, uMsg, wParam, lParam);
218            }
219    
220            return TRUE; /* ok */
221    }
222    #endif
223    
224  STDAPI DllRegisterServer()  STDAPI DllRegisterServer()
225  {  {
226    #if defined(XVID_USE_MFT)
227            int inputs_num = sizeof(sudInputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE);
228            int outputs_num = sizeof(sudOutputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE);
229            MFT_REGISTER_TYPE_INFO * mft_bs = new MFT_REGISTER_TYPE_INFO[inputs_num];
230            MFT_REGISTER_TYPE_INFO * mft_csp = new MFT_REGISTER_TYPE_INFO[outputs_num];
231    
232            {
233                    int i;
234                    for(i=0;i<inputs_num;i++) {
235                            mft_bs[i].guidMajorType = *sudInputPinTypes[i].clsMajorType;
236                            mft_bs[i].guidSubtype = *sudInputPinTypes[i].clsMinorType;
237                    }
238                    for(i=0;i<outputs_num;i++) {
239                            mft_csp[i].guidMajorType = *sudOutputPinTypes[i].clsMajorType;
240                            mft_csp[i].guidSubtype = *sudOutputPinTypes[i].clsMinorType; // MFT and AM GUIDs really the same?
241                    }
242            }
243    
244            /* Register the MFT decoder */
245            MFTRegister(CLSID_XVID,                          // CLSID
246                            MFT_CATEGORY_VIDEO_DECODER,          // Category
247                            const_cast<LPWSTR>(XVID_NAME_L),     // Friendly name
248                            0,                                   // Flags
249                            inputs_num,                          // Number of input types
250                            mft_bs,                              // Input types
251                            outputs_num,                         // Number of output types
252                            mft_csp,                             // Output types
253                            NULL                                 // Attributes (optional)
254                            );
255    
256            delete[] mft_bs;
257            delete[] mft_csp;
258    #endif /* XVID_USE_MFT */
259    
260      return AMovieDllRegisterServer2( TRUE );      return AMovieDllRegisterServer2( TRUE );
261  }  }
262    
263    
264  STDAPI DllUnregisterServer()  STDAPI DllUnregisterServer()
265  {  {
266    #if defined(XVID_USE_MFT)
267            MFTUnregister(CLSID_XVID);
268    #endif
269      return AMovieDllRegisterServer2( FALSE );      return AMovieDllRegisterServer2( FALSE );
270  }  }
271    
# Line 194  Line 299 
299          return GetInterface((ISpecifyPropertyPages *) this, ppv);          return GetInterface((ISpecifyPropertyPages *) this, ppv);
300          }          }
301    
302    #if defined(XVID_USE_MFT)
303            if (riid == IID_IMFTransform)
304            {
305                    return GetInterface((IMFTransform *) this, ppv);
306            }
307    #endif
308    
309          return CVideoTransformFilter::NonDelegatingQueryInterface(riid, ppv);          return CVideoTransformFilter::NonDelegatingQueryInterface(riid, ppv);
310  }  }
311    
# Line 201  Line 313 
313    
314  /* constructor */  /* constructor */
315    
 #define XVID_DLL_NAME "xvidcore.dll"  
   
316  CXvidDecoder::CXvidDecoder(LPUNKNOWN punk, HRESULT *phr) :  CXvidDecoder::CXvidDecoder(LPUNKNOWN punk, HRESULT *phr) :
317      CVideoTransformFilter(NAME("CXvidDecoder"), punk, CLSID_XVID)      CVideoTransformFilter(TEXT("CXvidDecoder"), punk, CLSID_XVID), m_hdll (NULL)
318  {  {
319          DPRINTF("Constructor");          DPRINTF("Constructor");
320    
321        xvid_decore_func = NULL; // Hmm, some strange errors appearing if I try to initialize...
322        xvid_global_func = NULL; // ...this in constructor's init-list. So, they assigned here.
323    
324    #if defined(XVID_USE_MFT)
325            InitializeCriticalSection(&m_mft_lock);
326            m_pInputType = NULL;
327            m_pOutputType = NULL;
328            m_rtFrame = 0;
329            m_duration = 0;
330            m_discont = 0;
331            m_frameRate.Denominator = 1;
332            m_frameRate.Numerator = 1;
333    #endif
334    
335        LoadRegistryInfo();
336    
337        *phr = OpenLib();
338    }
339    
340    HRESULT CXvidDecoder::OpenLib()
341    {
342        DPRINTF("OpenLib");
343    
344        if (m_hdll != NULL)
345                    return E_UNEXPECTED; // Seems, that library already opened.
346    
347          xvid_gbl_init_t init;          xvid_gbl_init_t init;
348          memset(&init, 0, sizeof(init));          memset(&init, 0, sizeof(init));
349          init.version = XVID_VERSION;          init.version = XVID_VERSION;
350            init.cpu_flags = g_config.cpu;
351    
352          ar_x = ar_y = 0;          xvid_gbl_info_t info;
353            memset(&info, 0, sizeof(info));
354            info.version = XVID_VERSION;
355    
356          m_hdll = LoadLibrary(XVID_DLL_NAME);          m_hdll = LoadLibrary(XVID_DLL_NAME);
357          if (m_hdll == NULL) {          if (m_hdll == NULL) {
358                  DPRINTF("dll load failed");                  DPRINTF("dll load failed");
359                  MessageBox(0, XVID_DLL_NAME " not found","Error", 0);                  MessageBox(0, XVID_DLL_NAME TEXT(" not found"), TEXT("Error"), MB_TOPMOST);
360                  return;                  return E_FAIL;
361          }          }
362    
363          xvid_global_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_global");          xvid_global_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_global");
364          if (xvid_global_func == NULL) {          if (xvid_global_func == NULL) {
365                  MessageBox(0, "xvid_global() not found", "Error", 0);          FreeLibrary(m_hdll);
366                  return;          m_hdll = NULL;
367                    MessageBox(0, TEXT("xvid_global() not found"), TEXT("Error"), MB_TOPMOST);
368                    return E_FAIL;
369          }          }
370    
371          xvid_decore_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_decore");          xvid_decore_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_decore");
372          if (xvid_decore_func == NULL) {          if (xvid_decore_func == NULL) {
373                  MessageBox(0, "xvid_decore() not found", "Error", 0);          xvid_global_func = NULL;
374                  return;          FreeLibrary(m_hdll);
375            m_hdll = NULL;
376                    MessageBox(0, TEXT("xvid_decore() not found"), TEXT("Error"), MB_TOPMOST);
377                    return E_FAIL;
378          }          }
379    
380          if (xvid_global_func(0, XVID_GBL_INIT, &init, NULL) < 0)          if (xvid_global_func(0, XVID_GBL_INIT, &init, NULL) < 0)
381          {          {
382                  MessageBox(0, "xvid_global() failed", "Error", 0);          xvid_global_func = NULL;
383                  return;          xvid_decore_func = NULL;
384            FreeLibrary(m_hdll);
385            m_hdll = NULL;
386                    MessageBox(0, TEXT("xvid_global() failed"), TEXT("Error"), MB_TOPMOST);
387                    return E_FAIL;
388            }
389    
390            if (xvid_global_func(0, XVID_GBL_INFO, &info, NULL) < 0)
391            {
392            xvid_global_func = NULL;
393            xvid_decore_func = NULL;
394            FreeLibrary(m_hdll);
395            m_hdll = NULL;
396                    MessageBox(0, TEXT("xvid_global() failed"), TEXT("Error"), MB_TOPMOST);
397                    return E_FAIL;
398          }          }
399    
400          memset(&m_create, 0, sizeof(m_create));          memset(&m_create, 0, sizeof(m_create));
401          m_create.version = XVID_VERSION;          m_create.version = XVID_VERSION;
402          m_create.handle = NULL;          m_create.handle = NULL;
403        /* Decoder threads */
404        if (g_config.cpu & XVID_CPU_FORCE) {
405                    m_create.num_threads = g_config.num_threads;
406            }
407            else {
408            m_create.num_threads = info.num_threads; /* Autodetect */
409                    g_config.num_threads = info.num_threads;
410            }
411    
412          memset(&m_frame, 0, sizeof(m_frame));          memset(&m_frame, 0, sizeof(m_frame));
413          m_frame.version = XVID_VERSION;          m_frame.version = XVID_VERSION;
414    
         LoadRegistryInfo();  
   
415          USE_IYUV = false;          USE_IYUV = false;
416          USE_YV12 = false;          USE_YV12 = false;
417          USE_YUY2 = false;          USE_YUY2 = false;
# Line 285  Line 449 
449                  USE_RGB32 = true;                  USE_RGB32 = true;
450                  break;                  break;
451          }          }
452    
453            switch (g_config.aspect_ratio)
454            {
455            case 0:
456            case 1:
457                    break;
458            case 2:
459                    ar_x = 4;
460                    ar_y = 3;
461                    break;
462            case 3:
463                    ar_x = 16;
464                    ar_y = 9;
465                    break;
466            case 4:
467                    ar_x = 47;
468                    ar_y = 20;
469                    break;
470            }
471    
472            return S_OK;
473  }  }
474    
475  void CXvidDecoder::CloseLib()  void CXvidDecoder::CloseLib()
476  {  {
477          DPRINTF("Destructor");          DPRINTF("CloseLib");
478    
479          if (m_create.handle != NULL) {          if ((m_create.handle != NULL) && (xvid_decore_func != NULL))
480            {
481                  xvid_decore_func(m_create.handle, XVID_DEC_DESTROY, 0, 0);                  xvid_decore_func(m_create.handle, XVID_DEC_DESTROY, 0, 0);
482                  m_create.handle = NULL;                  m_create.handle = NULL;
483          }          }
# Line 300  Line 486 
486                  FreeLibrary(m_hdll);                  FreeLibrary(m_hdll);
487                  m_hdll = NULL;                  m_hdll = NULL;
488          }          }
489        xvid_decore_func = NULL;
490        xvid_global_func = NULL;
491  }  }
492    
493  /* destructor */  /* destructor */
494    
495  CXvidDecoder::~CXvidDecoder()  CXvidDecoder::~CXvidDecoder()
496  {  {
497        DPRINTF("Destructor");
498    
499    #ifdef XVID_USE_TRAYICON
500            if (Tray_Icon) { /* Destroy tray icon */
501                    NOTIFYICONDATA nid;
502                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
503    
504                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
505                    nid.hWnd = MSG_hwnd;
506                    nid.uID = 1456;
507    
508                    Shell_NotifyIcon(NIM_DELETE, &nid);
509                    Tray_Icon = 0;
510            }
511    #endif
512    
513            /* Close xvidcore library */
514          CloseLib();          CloseLib();
515    
516    #if defined(XVID_USE_MFT)
517            DeleteCriticalSection(&m_mft_lock);
518    #endif
519  }  }
520    
521    
# Line 318  Line 527 
527          DPRINTF("CheckInputType");          DPRINTF("CheckInputType");
528          BITMAPINFOHEADER * hdr;          BITMAPINFOHEADER * hdr;
529    
530            ar_x = ar_y = 0;
531    
532          if (*mtIn->Type() != MEDIATYPE_Video)          if (*mtIn->Type() != MEDIATYPE_Video)
533          {          {
534                  DPRINTF("Error: Unknown Type");                  DPRINTF("Error: Unknown Type");
# Line 325  Line 536 
536                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
537          }          }
538    
539        if (m_hdll == NULL)
540        {
541                    HRESULT hr = OpenLib();
542    
543            if (FAILED(hr) || (m_hdll == NULL)) // Paranoid checks.
544                            return VFW_E_TYPE_NOT_ACCEPTED;
545        }
546    
547          if (*mtIn->FormatType() == FORMAT_VideoInfo)          if (*mtIn->FormatType() == FORMAT_VideoInfo)
548          {          {
549                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtIn->Format();                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtIn->Format();
550                  hdr = &vih->bmiHeader;                  hdr = &vih->bmiHeader;
                 /* PAR (x:y) is (1/ppm_X):(1/ppm_Y) where ppm is pixels-per-meter  
                    which is equal to ppm_Y:ppm_X */  
                 ar_x = vih->bmiHeader.biYPelsPerMeter * abs(hdr->biWidth);  
                 ar_y = vih->bmiHeader.biXPelsPerMeter * abs(hdr->biHeight);  
                 DPRINTF("VIDEOINFOHEADER PAR: %d:%d -> AR %d:%d",  
                         vih->bmiHeader.biYPelsPerMeter,vih->bmiHeader.biXPelsPerMeter, ar_x, ar_y);  
551          }          }
552          else if (*mtIn->FormatType() == FORMAT_VideoInfo2)          else if (*mtIn->FormatType() == FORMAT_VideoInfo2)
553          {          {
554                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 *) mtIn->Format();                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 *) mtIn->Format();
555                  hdr = &vih2->bmiHeader;                  hdr = &vih2->bmiHeader;
556                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
557                            ar_x = vih2->dwPictAspectRatioX;
558                            ar_y = vih2->dwPictAspectRatioY;
559                    }
560                    DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);
561            }
562      else if (*mtIn->FormatType() == FORMAT_MPEG2Video) {
563        MPEG2VIDEOINFO * mpgvi = (MPEG2VIDEOINFO*)mtIn->Format();
564        VIDEOINFOHEADER2 * vih2 = &mpgvi->hdr;
565                    hdr = &vih2->bmiHeader;
566                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
567                  ar_x = vih2->dwPictAspectRatioX;                  ar_x = vih2->dwPictAspectRatioX;
568                  ar_y = vih2->dwPictAspectRatioY;                  ar_y = vih2->dwPictAspectRatioY;
569                    }
570                  DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);                  DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);
571    
572        /* haali media splitter reports VOL information in the format header */
573    
574        if (mpgvi->cbSequenceHeader>0) {
575    
576          xvid_dec_stats_t stats;
577                memset(&stats, 0, sizeof(stats));
578                stats.version = XVID_VERSION;
579    
580                if (m_create.handle == NULL) {
581                        if (xvid_decore_func == NULL)
582                                return E_FAIL;
583                        if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
584              DPRINTF("*** XVID_DEC_CREATE error");
585                                return E_FAIL;
586                        }
587                }
588    
589          m_frame.general = 0;
590          m_frame.bitstream = (void*)mpgvi->dwSequenceHeader;
591          m_frame.length = mpgvi->cbSequenceHeader;
592          m_frame.output.csp = XVID_CSP_NULL;
593    
594          int ret = 0;
595          if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
596            /* honour video dimensions reported in VOL header */
597                  if (stats.type == XVID_TYPE_VOL) {
598              hdr->biWidth = stats.data.vol.width;
599              hdr->biHeight = stats.data.vol.height;
600                      }
601              }
602          if (ret == XVID_ERR_MEMORY) return E_FAIL;
603            }
604          }          }
605          else          else
606          {          {
# Line 350  Line 608 
608                  CloseLib();                  CloseLib();
609                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
610          }          }
   
611          if (hdr->biHeight < 0)          if (hdr->biHeight < 0)
612          {          {
613                  DPRINTF("colorspace: inverted input format not supported");                  DPRINTF("colorspace: inverted input format not supported");
# Line 361  Line 618 
618    
619          switch(hdr->biCompression)          switch(hdr->biCompression)
620          {          {
621            case FOURCC_mp4v :
622          case FOURCC_MP4V:          case FOURCC_MP4V:
623            case FOURCC_lmp4 :
624            case FOURCC_LMP4 :
625            case FOURCC_rmp4 :
626            case FOURCC_RMP4 :
627            case FOURCC_smp4 :
628            case FOURCC_SMP4 :
629            case FOURCC_hdx4 :
630            case FOURCC_HDX4 :
631                  if (!(g_config.supported_4cc & SUPPORT_MP4V)) {                  if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
632                          CloseLib();                          CloseLib();
633                          return VFW_E_TYPE_NOT_ACCEPTED;                          return VFW_E_TYPE_NOT_ACCEPTED;
634                  }                  }
635                  break;                  break;
636            case FOURCC_divx :
637          case FOURCC_DIVX :          case FOURCC_DIVX :
638            case FOURCC_dx50 :
639            case FOURCC_DX50 :
640                  if (!(g_config.supported_4cc & SUPPORT_DIVX)) {                  if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
641                          CloseLib();                          CloseLib();
642                          return VFW_E_TYPE_NOT_ACCEPTED;                          return VFW_E_TYPE_NOT_ACCEPTED;
643                  }                  }
644                  break;                  break;
645          case FOURCC_DX50 :          case FOURCC_3ivx :
646                  if (!(g_config.supported_4cc & SUPPORT_DX50)) {          case FOURCC_3IVX :
647            case FOURCC_3iv0 :
648            case FOURCC_3IV0 :
649            case FOURCC_3iv1 :
650            case FOURCC_3IV1 :
651            case FOURCC_3iv2 :
652            case FOURCC_3IV2 :
653                    if (!(g_config.supported_4cc & SUPPORT_3IVX)) {
654                          CloseLib();                          CloseLib();
655                          return VFW_E_TYPE_NOT_ACCEPTED;                          return VFW_E_TYPE_NOT_ACCEPTED;
656                  }                  }
657            case FOURCC_xvid :
658          case FOURCC_XVID :          case FOURCC_XVID :
659                  break;                  break;
660    
# Line 393  Line 669 
669                  CloseLib();                  CloseLib();
670                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
671          }          }
672    
673            m_create.fourcc = hdr->biCompression;
674    
675          return S_OK;          return S_OK;
676  }  }
677    
# Line 421  Line 700 
700                  if (ar_x != 0 && ar_y != 0) {                  if (ar_x != 0 && ar_y != 0) {
701                          vih->dwPictAspectRatioX = ar_x;                          vih->dwPictAspectRatioX = ar_x;
702                          vih->dwPictAspectRatioY = ar_y;                          vih->dwPictAspectRatioY = ar_y;
703                            forced_ar = true;
704                  } else { // just to be safe                  } else { // just to be safe
705                          vih->dwPictAspectRatioX = m_create.width;                          vih->dwPictAspectRatioX = m_create.width;
706                          vih->dwPictAspectRatioY = abs(m_create.height);                          vih->dwPictAspectRatioY = abs(m_create.height);
707                            forced_ar = false;
708                  }                  }
   
709          } else {          } else {
710    
711                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER));                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER));
# Line 533  Line 813 
813    
814    
815  /* (internal function) change colorspace */  /* (internal function) change colorspace */
816    #define CALC_BI_STRIDE(width,bitcount)  ((((width * bitcount) + 31) & ~31) >> 3)
817    
818  HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format)  HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format, int noflip)
819  {  {
820            DWORD biWidth;
821    
822          if (formattype == FORMAT_VideoInfo)          if (formattype == FORMAT_VideoInfo)
823          {          {
824                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;
825                  m_frame.output.stride[0] = (((vih->bmiHeader.biWidth * vih->bmiHeader.biBitCount) + 31) & ~31) >> 3;                  biWidth = vih->bmiHeader.biWidth;
826                    out_stride = CALC_BI_STRIDE(vih->bmiHeader.biWidth, vih->bmiHeader.biBitCount);
827                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
828          }          }
829          else if (formattype == FORMAT_VideoInfo2)          else if (formattype == FORMAT_VideoInfo2)
830          {          {
831                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;
832                  m_frame.output.stride[0] = (((vih2->bmiHeader.biWidth * vih2->bmiHeader.biBitCount) + 31) & ~31) >> 3;                  biWidth = vih2->bmiHeader.biWidth;
833                    out_stride = CALC_BI_STRIDE(vih2->bmiHeader.biWidth, vih2->bmiHeader.biBitCount);
834                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
835          }          }
836          else          else
# Line 553  Line 838 
838                  return S_FALSE;                  return S_FALSE;
839          }          }
840    
841            if (noflip) rgb_flip = 0;
842    
843          if (subtype == CLSID_MEDIASUBTYPE_IYUV)          if (subtype == CLSID_MEDIASUBTYPE_IYUV)
844          {          {
845                  DPRINTF("IYUV");                  DPRINTF("IYUV");
846                  rgb_flip = 0;                  rgb_flip = 0;
847                  m_frame.output.csp = XVID_CSP_I420;                  m_frame.output.csp = XVID_CSP_I420;
848                  m_frame.output.stride[0] = (m_frame.output.stride[0] * 2) / 3;  /* planar format fix */                  out_stride = CALC_BI_STRIDE(biWidth, 8);        /* planar format fix */
849          }          }
850          else if (subtype == MEDIASUBTYPE_YV12)          else if (subtype == MEDIASUBTYPE_YV12)
851          {          {
852                  DPRINTF("YV12");                  DPRINTF("YV12");
853                  rgb_flip = 0;                  rgb_flip = 0;
854                  m_frame.output.csp = XVID_CSP_YV12;                  m_frame.output.csp = XVID_CSP_YV12;
855                  m_frame.output.stride[0] = (m_frame.output.stride[0] * 2) / 3;  /* planar format fix */                  out_stride = CALC_BI_STRIDE(biWidth, 8);        /* planar format fix */
856          }          }
857          else if (subtype == MEDIASUBTYPE_YUY2)          else if (subtype == MEDIASUBTYPE_YUY2)
858          {          {
# Line 626  Line 913 
913    
914          if (direction == PINDIR_OUTPUT)          if (direction == PINDIR_OUTPUT)
915          {          {
916                  return ChangeColorspace(*pmt->Subtype(), *pmt->FormatType(), pmt->Format());                  return ChangeColorspace(*pmt->Subtype(), *pmt->FormatType(), pmt->Format(), 0);
917          }          }
918    
919          return S_OK;          return S_OK;
# Line 638  Line 925 
925  HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)  HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
926  {  {
927          DPRINTF("CheckTransform");          DPRINTF("CheckTransform");
928    
929            return S_OK;
930    }
931    
932    /* input/output pin connection complete */
933    
934    HRESULT CXvidDecoder::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin)
935    {
936            DPRINTF("CompleteConnect");
937    
938    #ifdef XVID_USE_TRAYICON
939            if ((direction == PINDIR_OUTPUT) && (Tray_Icon == 0))
940            {
941                    WNDCLASSEX wc;
942    
943                    wc.cbSize = sizeof(WNDCLASSEX);
944                    wc.lpfnWndProc = msg_proc;
945                    wc.style = CS_HREDRAW | CS_VREDRAW;
946                    wc.cbWndExtra = 0;
947                    wc.cbClsExtra = 0;
948                    wc.hInstance = (HINSTANCE) g_xvid_hInst;
949                    wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH);
950                    wc.lpszMenuName = NULL;
951                    wc.lpszClassName = TEXT("XVID_MSG_WINDOW");
952                    wc.hIcon = NULL;
953                    wc.hIconSm = NULL;
954                    wc.hCursor = NULL;
955                    RegisterClassEx(&wc);
956    
957                    MSG_hwnd = CreateWindowEx(0, TEXT("XVID_MSG_WINDOW"), NULL, 0, CW_USEDEFAULT,
958                            CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE) g_xvid_hInst, NULL);
959    
960                    /* display the tray icon */
961                    NOTIFYICONDATA nid;
962                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
963    
964                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
965                    nid.hWnd = MSG_hwnd;
966                    nid.uID = 1456;
967                    nid.uCallbackMessage = WM_ICONMESSAGE;
968                    nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
969                    lstrcpy(nid.szTip, TEXT("Xvid Video Decoder"));
970                    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
971    
972                    Shell_NotifyIcon(NIM_ADD, &nid);
973    
974                    DestroyIcon(nid.hIcon);
975                    Tray_Icon = 1;
976            }
977    #endif
978    
979          return S_OK;          return S_OK;
980  }  }
981    
982    /* input/output pin disconnected */
983    HRESULT CXvidDecoder::BreakConnect(PIN_DIRECTION direction)
984    {
985            DPRINTF("BreakConnect");
986    
987            return S_OK;
988    }
989    
990  /* alloc output buffer */  /* alloc output buffer */
991    
# Line 689  Line 1034 
1034    
1035          if (m_create.handle == NULL)          if (m_create.handle == NULL)
1036          {          {
1037                    if (xvid_decore_func == NULL)
1038                            return E_FAIL;
1039    
1040                  if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)                  if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
1041                  {                  {
1042              DPRINTF("*** XVID_DEC_CREATE error");              DPRINTF("*** XVID_DEC_CREATE error");
1043                          return S_FALSE;                          return E_FAIL;
1044                  }                  }
1045          }          }
1046    
# Line 702  Line 1050 
1050          {          {
1051                  HRESULT result;                  HRESULT result;
1052    
1053                  result = ChangeColorspace(mtOut->subtype, mtOut->formattype, mtOut->pbFormat);                  result = ChangeColorspace(mtOut->subtype, mtOut->formattype, mtOut->pbFormat, 0);
1054                  DeleteMediaType(mtOut);                  DeleteMediaType(mtOut);
1055    
1056                  if (result != S_OK)                  if (result != S_OK)
# Line 733  Line 1081 
1081    
1082          if (g_config.nDeblock_UV)          if (g_config.nDeblock_UV)
1083                  m_frame.general |= XVID_DEBLOCKUV;                  m_frame.general |= XVID_DEBLOCKUV;
1084  /*  
1085          if (g_config.nDering)          if (g_config.nDering_Y)
1086                  m_frame.general |= XVID_DERING;                  m_frame.general |= XVID_DERINGY;
1087  */  
1088            if (g_config.nDering_UV)
1089                    m_frame.general |= XVID_DERINGUV;
1090    
1091          if (g_config.nFilmEffect)          if (g_config.nFilmEffect)
1092                  m_frame.general |= XVID_FILMEFFECT;                  m_frame.general |= XVID_FILMEFFECT;
1093    
# Line 744  Line 1095 
1095    
1096          m_frame.output.csp &= ~XVID_CSP_VFLIP;          m_frame.output.csp &= ~XVID_CSP_VFLIP;
1097          m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0);          m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0);
1098            m_frame.output.stride[0] = out_stride;
1099    
1100        // Paranoid check.
1101        if (xvid_decore_func == NULL)
1102                    return E_FAIL;
1103    
1104    
1105  repeat :  repeat :
1106    
# Line 751  Line 1108 
1108          {          {
1109                  length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);                  length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1110    
1111                  if (length < 0)                  if (length == XVID_ERR_MEMORY)
1112                            return E_FAIL;
1113                    else if (length < 0)
1114                  {                  {
1115              DPRINTF("*** XVID_DEC_DECODE");              DPRINTF("*** XVID_DEC_DECODE");
1116                          return S_FALSE;                          return S_FALSE;
1117                    } else
1118                            if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1 && forced_ar == false) {
1119    
1120          if (stats.type != XVID_TYPE_NOTHING) {  /* dont attempt to set vmr aspect ratio if no frame was returned by decoder */
1121                            // inspired by minolta! works for VMR 7 + 9
1122                            IMediaSample2 *pOut2 = NULL;
1123                            AM_SAMPLE2_PROPERTIES outProp2;
1124                            if (SUCCEEDED(pOut->QueryInterface(IID_IMediaSample2, (void **)&pOut2)) &&
1125                                    SUCCEEDED(pOut2->GetProperties(FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, tStart), (PBYTE)&outProp2)))
1126                            {
1127                                    CMediaType mtOut2 = m_pOutput->CurrentMediaType();
1128                                    VIDEOINFOHEADER2* vihOut2 = (VIDEOINFOHEADER2*)mtOut2.Format();
1129    
1130                                    if (*mtOut2.FormatType() == FORMAT_VideoInfo2 &&
1131                                            vihOut2->dwPictAspectRatioX != ar_x && vihOut2->dwPictAspectRatioY != ar_y)
1132                                    {
1133                                            vihOut2->dwPictAspectRatioX = ar_x;
1134                                            vihOut2->dwPictAspectRatioY = ar_y;
1135                                            pOut2->SetMediaType(&mtOut2);
1136                                            m_pOutput->SetMediaType(&mtOut2);
1137                                    }
1138                                    pOut2->Release();
1139                            }
1140          }
1141                  }                  }
1142          }          }
1143          else          else
# Line 771  Line 1154 
1154                  m_frame.general &= ~XVID_FILMEFFECT;                  m_frame.general &= ~XVID_FILMEFFECT;
1155    
1156                  length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);                  length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1157                  if (length < 0)                  if (length == XVID_ERR_MEMORY)
1158                            return E_FAIL;
1159                    else if (length < 0)
1160                  {                  {
1161              DPRINTF("*** XVID_DEC_DECODE");              DPRINTF("*** XVID_DEC_DECODE");
1162                          return S_FALSE;                          return S_FALSE;
# Line 796  Line 1181 
1181                          return S_FALSE;                          return S_FALSE;
1182                  }                  }
1183    
 //              pOut->SetDiscontinuity(TRUE);  
1184                  pOut->SetSyncPoint(TRUE);                  pOut->SetSyncPoint(TRUE);
1185    
1186                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) { /* auto */
1187                            int par_x, par_y;
1188                            if (stats.data.vol.par == XVID_PAR_EXT) {
1189                                    par_x = stats.data.vol.par_width;
1190                                    par_y = stats.data.vol.par_height;
1191                            } else {
1192                                    par_x = PARS[stats.data.vol.par-1][0];
1193                                    par_y = PARS[stats.data.vol.par-1][1];
1194                            }
1195    
1196                            ar_x = par_x * stats.data.vol.width;
1197                            ar_y = par_y * stats.data.vol.height;
1198                    }
1199    
1200                  m_frame.bitstream = (BYTE*)m_frame.bitstream + length;                  m_frame.bitstream = (BYTE*)m_frame.bitstream + length;
1201                  m_frame.length -= length;                  m_frame.length -= length;
1202                  goto repeat;                  goto repeat;
# Line 838  Line 1236 
1236          CoTaskMemFree(pPages->pElems);          CoTaskMemFree(pPages->pElems);
1237          return S_OK;          return S_OK;
1238  }  }
1239    
1240    /*===============================================================================
1241    // MFT Interface
1242    //=============================================================================*/
1243    #if defined(XVID_USE_MFT)
1244    #include <limits.h> // _I64_MAX
1245    #define INVALID_TIME  _I64_MAX
1246    
1247    HRESULT CXvidDecoder::MFTGetStreamLimits(DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum)
1248    {
1249            DPRINTF("(MFT)GetStreamLimits");
1250    
1251            if ((pdwInputMinimum == NULL) || (pdwInputMaximum == NULL) || (pdwOutputMinimum == NULL) || (pdwOutputMaximum == NULL))
1252                    return E_POINTER;
1253    
1254            /* Just a fixed number of streams allowed */
1255            *pdwInputMinimum = *pdwInputMaximum = 1;
1256            *pdwOutputMinimum = *pdwOutputMaximum = 1;
1257    
1258            return S_OK;
1259    }
1260    
1261    HRESULT CXvidDecoder::MFTGetStreamCount(DWORD *pcInputStreams, DWORD *pcOutputStreams)
1262    {
1263            DPRINTF("(MFT)GetStreamCount");
1264    
1265            if ((pcInputStreams == NULL) || (pcOutputStreams == NULL))
1266                    return E_POINTER;
1267    
1268            /* We have a fixed number of streams */
1269            *pcInputStreams = 1;
1270            *pcOutputStreams = 1;
1271    
1272            return S_OK;
1273    }
1274    
1275    HRESULT CXvidDecoder::MFTGetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs)
1276    {
1277            DPRINTF("(MFT)GetStreamIDs");
1278            return E_NOTIMPL; /* We have fixed number of streams, so stream ID match stream index */
1279    }
1280    
1281    HRESULT CXvidDecoder::MFTGetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo)
1282    {
1283            DPRINTF("(MFT)GetInputStreamInfo");
1284    
1285            if (pStreamInfo == NULL)
1286                    return E_POINTER;
1287    
1288            if (dwInputStreamID != 0)
1289                    return MF_E_INVALIDSTREAMNUMBER;
1290    
1291            EnterCriticalSection(&m_mft_lock);
1292    
1293            pStreamInfo->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER;
1294            pStreamInfo->hnsMaxLatency = 0;
1295    
1296            pStreamInfo->cbSize = 1; /* Need atleast 1 byte input */
1297            pStreamInfo->cbMaxLookahead = 0;
1298            pStreamInfo->cbAlignment = 1;
1299    
1300            LeaveCriticalSection(&m_mft_lock);
1301            return S_OK;
1302    }
1303    
1304    HRESULT CXvidDecoder::MFTGetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo)
1305    {
1306            DPRINTF("(MFT)GetOutputStreamInfo");
1307    
1308            if (pStreamInfo == NULL)
1309                    return E_POINTER;
1310    
1311            if (dwOutputStreamID != 0)
1312                    return MF_E_INVALIDSTREAMNUMBER;
1313    
1314            EnterCriticalSection(&m_mft_lock);
1315    
1316            pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_DISCARDABLE;
1317    
1318            if (m_pOutputType == NULL) {
1319                    pStreamInfo->cbSize = 0;
1320                    pStreamInfo->cbAlignment = 0;
1321            }
1322            else {
1323                    pStreamInfo->cbSize = m_create.width * abs(m_create.height) * 4; // XXX
1324                    pStreamInfo->cbAlignment = 1;
1325            }
1326    
1327            LeaveCriticalSection(&m_mft_lock);
1328            return S_OK;
1329    }
1330    
1331    HRESULT CXvidDecoder::GetAttributes(IMFAttributes** pAttributes)
1332    {
1333            DPRINTF("(MFT)GetAttributes");
1334            return E_NOTIMPL; /* We don't support any attributes */
1335    }
1336    
1337    HRESULT CXvidDecoder::GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes **ppAttributes)
1338    {
1339            DPRINTF("(MFT)GetInputStreamAttributes");
1340            return E_NOTIMPL; /* We don't support any attributes */
1341    }
1342    
1343    HRESULT CXvidDecoder::GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes **ppAttributes)
1344    {
1345            DPRINTF("(MFT)GetOutputStreamAttributes");
1346            return E_NOTIMPL; /* We don't support any attributes */
1347    }
1348    
1349    HRESULT CXvidDecoder::MFTDeleteInputStream(DWORD dwStreamID)
1350    {
1351            DPRINTF("(MFT)DeleteInputStream");
1352            return E_NOTIMPL; /* We have a fixed number of streams */
1353    }
1354    
1355    HRESULT CXvidDecoder::MFTAddInputStreams(DWORD cStreams, DWORD *adwStreamIDs)
1356    {
1357            DPRINTF("(MFT)AddInputStreams");
1358            return E_NOTIMPL; /* We have a fixed number of streams */
1359    }
1360    
1361    HRESULT CXvidDecoder::MFTGetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1362    {
1363            DPRINTF("(MFT)GetInputAvailableType");
1364    
1365            if (dwInputStreamID != 0)
1366                    return MF_E_INVALIDSTREAMNUMBER;
1367    
1368            DWORD i = 0;
1369            GUID *bs_guid_table[8];
1370    
1371            bs_guid_table[i++] = (GUID *)&CLSID_XVID;
1372            bs_guid_table[i++] = (GUID *)&CLSID_XVID_UC;
1373    
1374            if (g_config.supported_4cc & SUPPORT_3IVX) {
1375                    bs_guid_table[i++] = (GUID *)&CLSID_3IVX;
1376                    bs_guid_table[i++] = (GUID *)&CLSID_3IVX_UC;
1377                    bs_guid_table[i++] = (GUID *)&CLSID_3IV0;
1378                    bs_guid_table[i++] = (GUID *)&CLSID_3IV0_UC;
1379                    bs_guid_table[i++] = (GUID *)&CLSID_3IV1;
1380                    bs_guid_table[i++] = (GUID *)&CLSID_3IV1_UC;
1381                    bs_guid_table[i++] = (GUID *)&CLSID_3IV2;
1382                    bs_guid_table[i++] = (GUID *)&CLSID_3IV2_UC;
1383            }
1384            if (g_config.supported_4cc & SUPPORT_DIVX) {
1385                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX;
1386                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX_UC;
1387                    bs_guid_table[i++] = (GUID *)&CLSID_DX50;
1388                    bs_guid_table[i++] = (GUID *)&CLSID_DX50_UC;
1389            }
1390            if (g_config.supported_4cc & SUPPORT_MP4V) {
1391                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V;
1392                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V_UC;
1393                    bs_guid_table[i++] = (GUID *)&CLSID_LMP4;
1394                    bs_guid_table[i++] = (GUID *)&CLSID_LMP4_UC;
1395                    bs_guid_table[i++] = (GUID *)&CLSID_RMP4;
1396                    bs_guid_table[i++] = (GUID *)&CLSID_RMP4_UC;
1397                    bs_guid_table[i++] = (GUID *)&CLSID_SMP4;
1398                    bs_guid_table[i++] = (GUID *)&CLSID_SMP4_UC;
1399                    bs_guid_table[i++] = (GUID *)&CLSID_HDX4;
1400                    bs_guid_table[i++] = (GUID *)&CLSID_HDX4_UC;
1401            }
1402    
1403            const GUID *subtype;
1404            if (dwTypeIndex < i) {
1405                    subtype = bs_guid_table[dwTypeIndex];
1406            }
1407            else {
1408                    return MF_E_NO_MORE_TYPES;
1409            }
1410    
1411            EnterCriticalSection(&m_mft_lock);
1412    
1413            HRESULT hr = S_OK;
1414    
1415            if (ppType) {
1416                    IMFMediaType *pInputType = NULL;
1417                    hr = MFCreateMediaType(&pInputType);
1418    
1419                    if (SUCCEEDED(hr))
1420                            hr = pInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1421    
1422                    if (SUCCEEDED(hr))
1423                            hr = pInputType->SetGUID(MF_MT_SUBTYPE, *subtype);
1424    
1425                    if (SUCCEEDED(hr)) {
1426                            *ppType = pInputType;
1427                            (*ppType)->AddRef();
1428                    }
1429                    if (pInputType) pInputType->Release();
1430            }
1431    
1432            LeaveCriticalSection(&m_mft_lock);
1433    
1434            return hr;
1435    }
1436    
1437    HRESULT CXvidDecoder::MFTGetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1438    {
1439            DPRINTF("(MFT)GetOutputAvailableType");
1440    
1441            if (ppType == NULL)
1442                    return E_INVALIDARG;
1443    
1444            if (dwOutputStreamID != 0)
1445                    return MF_E_INVALIDSTREAMNUMBER;
1446    
1447            if (dwTypeIndex < 0) return E_INVALIDARG;
1448    
1449            GUID csp;
1450            int bitdepth = 8;
1451            switch(dwTypeIndex)
1452            {
1453            case 0:
1454    if ( USE_YUY2 )
1455    {
1456                    csp = MFVideoFormat_YUY2;
1457                    bitdepth = 4;
1458                    break;
1459    }
1460            case 1 :
1461    if ( USE_UYVY )
1462    {
1463                    csp = MFVideoFormat_UYVY;
1464                    bitdepth = 4;
1465                    break;
1466    }
1467            case 2  :
1468                    if ( USE_IYUV )
1469    {
1470                    csp = MFVideoFormat_IYUV;
1471                    bitdepth = 3;
1472                    break;
1473    }
1474            case 3  :
1475    if ( USE_YV12 )
1476    {
1477                    csp = MFVideoFormat_YV12;
1478                    bitdepth = 3;
1479                    break;
1480    }
1481            case 4 :
1482    if ( USE_RGB32 )
1483    {
1484                    csp = MFVideoFormat_RGB32;
1485                    bitdepth = 8;
1486                    break;
1487    }
1488            case 5 :
1489    if ( USE_RGB24 )
1490    {
1491                    csp = MFVideoFormat_RGB24;
1492                    bitdepth = 6;
1493                    break;
1494    }
1495            case 6 :
1496    if ( USE_RG555 )
1497    {
1498                    csp = MFVideoFormat_RGB555;
1499                    bitdepth = 4;
1500                    break;
1501    }
1502            case 7 :
1503    if ( USE_RG565 )
1504    {
1505                    csp = MFVideoFormat_RGB565;
1506                    bitdepth = 4;
1507                    break;
1508    }
1509            default :
1510                    return MF_E_NO_MORE_TYPES;
1511            }
1512    
1513            if (m_pInputType == NULL)
1514                    return MF_E_TRANSFORM_TYPE_NOT_SET;
1515    
1516            EnterCriticalSection(&m_mft_lock);
1517    
1518            HRESULT hr = S_OK;
1519    
1520            IMFMediaType *pOutputType = NULL;
1521            hr = MFCreateMediaType(&pOutputType);
1522    
1523            if (SUCCEEDED(hr)) {
1524                    hr = pOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1525            }
1526    
1527            if (SUCCEEDED(hr)) {
1528                    hr = pOutputType->SetGUID(MF_MT_SUBTYPE, csp);
1529        }
1530    
1531            if (SUCCEEDED(hr)) {
1532                    hr = pOutputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE);
1533            }
1534    
1535            if (SUCCEEDED(hr)) {
1536                    hr = pOutputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
1537            }
1538    
1539            if (SUCCEEDED(hr)) {
1540                    hr = pOutputType->SetUINT32(MF_MT_SAMPLE_SIZE, (m_create.height * m_create.width * bitdepth)>>1);
1541            }
1542    
1543            if (SUCCEEDED(hr)) {
1544                    hr = MFSetAttributeSize(pOutputType, MF_MT_FRAME_SIZE, m_create.width, m_create.height);
1545            }
1546    
1547            if (SUCCEEDED(hr)) {
1548                    hr = MFSetAttributeRatio(pOutputType, MF_MT_FRAME_RATE, m_frameRate.Numerator, m_frameRate.Denominator);
1549            }
1550    
1551            if (SUCCEEDED(hr)) {
1552                    hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
1553            }
1554    
1555            if (SUCCEEDED(hr)) {
1556                    hr = MFSetAttributeRatio(pOutputType, MF_MT_PIXEL_ASPECT_RATIO, ar_x, ar_y);
1557            }
1558    
1559            if (SUCCEEDED(hr)) {
1560                    *ppType = pOutputType;
1561                    (*ppType)->AddRef();
1562            }
1563    
1564            if (pOutputType) pOutputType->Release();
1565    
1566            LeaveCriticalSection(&m_mft_lock);
1567            return hr;
1568    }
1569    
1570    HRESULT CXvidDecoder::MFTSetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags)
1571    {
1572            DPRINTF("(MFT)SetInputType");
1573    
1574            if (dwInputStreamID != 0)
1575                    return MF_E_INVALIDSTREAMNUMBER;
1576    
1577            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1578                    return E_INVALIDARG;
1579    
1580            EnterCriticalSection(&m_mft_lock);
1581    
1582            HRESULT hr = S_OK;
1583    
1584            /* Actually set the type or just test it? */
1585            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1586    
1587            /* If we have samples pending the type can't be changed right now */
1588            if (HasPendingOutput())
1589                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1590    
1591            if (SUCCEEDED(hr)) {
1592            if (pType) { // /* Check the type */
1593                hr = OnCheckInputType(pType);
1594            }
1595            }
1596    
1597            if (SUCCEEDED(hr)) {
1598                    if (bReallySet) { /* Set the type if needed */
1599                            hr = OnSetInputType(pType);
1600                    }
1601            }
1602    
1603            LeaveCriticalSection(&m_mft_lock);
1604            return hr;
1605    }
1606    
1607    HRESULT CXvidDecoder::MFTSetOutputType(DWORD dwOutputStreamID, IMFMediaType *pType, DWORD dwFlags)
1608    {
1609            DPRINTF("(MFT)SetOutputType");
1610    
1611            if (dwOutputStreamID != 0)
1612                    return MF_E_INVALIDSTREAMNUMBER;
1613    
1614            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1615                    return E_INVALIDARG;
1616    
1617            HRESULT hr = S_OK;
1618    
1619            EnterCriticalSection(&m_mft_lock);
1620    
1621            /* Actually set the type or just test it? */
1622            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1623    
1624            /* If we have samples pending the type can't be changed right now */
1625            if (HasPendingOutput())
1626                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1627    
1628            if (SUCCEEDED(hr)) {
1629                    if (pType) { /* Check the type */
1630                            AM_MEDIA_TYPE *am;
1631                            hr = MFCreateAMMediaTypeFromMFMediaType(pType, GUID_NULL, &am);
1632    
1633                            if (SUCCEEDED(hr)) {
1634                                    if (FAILED(ChangeColorspace(am->subtype, am->formattype, am->pbFormat, 1))) {
1635                                            DPRINTF("(MFT)InternalCheckOutputType (MF_E_INVALIDTYPE)");
1636                                            return MF_E_INVALIDTYPE;
1637                                    }
1638    
1639                            CoTaskMemFree(am->pbFormat);
1640                            CoTaskMemFree(am);
1641                            }
1642                    }
1643            }
1644    
1645            if (SUCCEEDED(hr)) {
1646                    if (bReallySet) { /* Set the type if needed */
1647                            hr = OnSetOutputType(pType);
1648                    }
1649            }
1650    #ifdef XVID_USE_TRAYICON
1651            if (SUCCEEDED(hr) && Tray_Icon == 0) /* Create message passing window */
1652            {
1653                    WNDCLASSEX wc;
1654    
1655                    wc.cbSize = sizeof(WNDCLASSEX);
1656                    wc.lpfnWndProc = msg_proc;
1657                    wc.style = CS_HREDRAW | CS_VREDRAW;
1658                    wc.cbWndExtra = 0;
1659                    wc.cbClsExtra = 0;
1660                    wc.hInstance = (HINSTANCE) g_xvid_hInst;
1661                    wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH);
1662                    wc.lpszMenuName = NULL;
1663                    wc.lpszClassName = TEXT("XVID_MSG_WINDOW");
1664                    wc.hIcon = NULL;
1665                    wc.hIconSm = NULL;
1666                    wc.hCursor = NULL;
1667                    RegisterClassEx(&wc);
1668    
1669                    MSG_hwnd = CreateWindowEx(0, TEXT("XVID_MSG_WINDOW"), NULL, 0, CW_USEDEFAULT,
1670                                      CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE) g_xvid_hInst, NULL);
1671    
1672                    /* display the tray icon */
1673                    NOTIFYICONDATA nid;
1674                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
1675    
1676                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
1677                    nid.hWnd = MSG_hwnd;
1678                    nid.uID = 1456;
1679                    nid.uCallbackMessage = WM_ICONMESSAGE;
1680                    nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
1681                    lstrcpy(nid.szTip, TEXT("Xvid Video Decoder"));
1682                    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
1683    
1684                    Shell_NotifyIcon(NIM_ADD, &nid);
1685    
1686                    DestroyIcon(nid.hIcon);
1687                    Tray_Icon = 1;
1688            }
1689    #endif
1690    
1691            LeaveCriticalSection(&m_mft_lock);
1692            return hr;
1693    }
1694    
1695    HRESULT CXvidDecoder::MFTGetInputCurrentType(DWORD dwInputStreamID, IMFMediaType **ppType)
1696    {
1697            DPRINTF("(MFT)GetInputCurrentType");
1698    
1699            if (ppType == NULL)
1700                    return E_POINTER;
1701    
1702            if (dwInputStreamID != 0)
1703                    return MF_E_INVALIDSTREAMNUMBER;
1704    
1705            EnterCriticalSection(&m_mft_lock);
1706    
1707            HRESULT hr = S_OK;
1708    
1709            if (!m_pInputType)
1710                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1711    
1712            if (SUCCEEDED(hr)) {
1713                    *ppType = m_pInputType;
1714                    (*ppType)->AddRef();
1715            }
1716    
1717            LeaveCriticalSection(&m_mft_lock);
1718            return hr;
1719    }
1720    
1721    HRESULT CXvidDecoder::MFTGetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType)
1722    {
1723            DPRINTF("(MFT)GetOutputCurrentType");
1724    
1725            if (ppType == NULL)
1726                    return E_POINTER;
1727    
1728            if (dwOutputStreamID != 0)
1729                    return MF_E_INVALIDSTREAMNUMBER;
1730    
1731            EnterCriticalSection(&m_mft_lock);
1732    
1733            HRESULT hr = S_OK;
1734    
1735            if (!m_pOutputType)
1736                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1737    
1738            if (SUCCEEDED(hr)) {
1739                    *ppType = m_pOutputType;
1740                    (*ppType)->AddRef();
1741            }
1742    
1743            LeaveCriticalSection(&m_mft_lock);
1744            return hr;
1745    }
1746    
1747    HRESULT CXvidDecoder::MFTGetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags)
1748    {
1749            DPRINTF("(MFT)GetInputStatus");
1750    
1751            if (pdwFlags == NULL)
1752                    return E_POINTER;
1753    
1754            if (dwInputStreamID != 0)
1755                    return MF_E_INVALIDSTREAMNUMBER;
1756    
1757            EnterCriticalSection(&m_mft_lock);
1758    
1759            /* If there's pending output sampels we don't accept new
1760               input data until ProcessOutput() or Flush() was called */
1761            if (!HasPendingOutput()) {
1762                    *pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
1763            }
1764            else {
1765                    *pdwFlags = 0;
1766            }
1767    
1768            LeaveCriticalSection(&m_mft_lock);
1769    
1770            return S_OK;
1771    }
1772    
1773    HRESULT CXvidDecoder::MFTGetOutputStatus(DWORD *pdwFlags)
1774    {
1775            DPRINTF("(MFT)GetOutputStatus");
1776    
1777            if (pdwFlags == NULL)
1778                    return E_POINTER;
1779    
1780            EnterCriticalSection(&m_mft_lock);
1781    
1782            /* We can render an output sample only after we
1783               have decoded one */
1784            if (HasPendingOutput()) {
1785                    *pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
1786            }
1787            else {
1788                    *pdwFlags = 0;
1789            }
1790    
1791            LeaveCriticalSection(&m_mft_lock);
1792    
1793            return S_OK;
1794    }
1795    
1796    HRESULT CXvidDecoder::MFTSetOutputBounds(LONGLONG hnsLowerBound, LONGLONG hnsUpperBound)
1797    {
1798            DPRINTF("(MFT)SetOutputBounds");
1799            return E_NOTIMPL;
1800    }
1801    
1802    HRESULT CXvidDecoder::MFTProcessEvent(DWORD dwInputStreamID, IMFMediaEvent *pEvent)
1803    {
1804            DPRINTF("(MFT)ProcessEvent");
1805            return E_NOTIMPL; /* We don't handle any stream events */
1806    }
1807    
1808    HRESULT CXvidDecoder::MFTProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
1809    {
1810            DPRINTF("(MFT)ProcessMessage");
1811            HRESULT hr = S_OK;
1812    
1813            EnterCriticalSection(&m_mft_lock);
1814    
1815            switch (eMessage)
1816            {
1817            case MFT_MESSAGE_COMMAND_FLUSH:
1818                    if (m_create.handle != NULL) {
1819                            DPRINTF("(MFT)CommandFlush");
1820    
1821                            xvid_dec_stats_t stats;
1822                            int used_bytes;
1823    
1824                            memset(&stats, 0, sizeof(stats));
1825                            stats.version = XVID_VERSION;
1826    
1827                            int csp = m_frame.output.csp;
1828    
1829                            m_frame.output.csp = XVID_CSP_INTERNAL;
1830                            m_frame.bitstream = NULL;
1831                            m_frame.length = -1;
1832                            m_frame.general = XVID_LOWDELAY;
1833    
1834                            do {
1835                                    used_bytes = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1836                            } while(used_bytes>=0 && stats.type <= 0);
1837    
1838                            m_frame.output.csp = csp;
1839                            m_frame.output.plane[1] = NULL; /* Don't display flushed samples */
1840    
1841                            //m_timestamp = INVALID_TIME;
1842                            //m_timelength = INVALID_TIME;
1843                            //m_rtFrame = 0;
1844            }
1845        break;
1846    
1847            case MFT_MESSAGE_COMMAND_DRAIN:
1848                    m_discont = 1; /* Set discontinuity flag */
1849                    m_rtFrame = 0;
1850                    break;
1851    
1852            case MFT_MESSAGE_SET_D3D_MANAGER:
1853                    hr = E_NOTIMPL;
1854                    break;
1855    
1856            case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
1857            case MFT_MESSAGE_NOTIFY_END_STREAMING:
1858                    break;
1859    
1860            case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
1861            case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
1862                    break;
1863            }
1864    
1865            LeaveCriticalSection(&m_mft_lock);
1866    
1867            return hr;
1868    }
1869    
1870    HRESULT CXvidDecoder::MFTProcessInput(DWORD dwInputStreamID, IMFSample *pSample, DWORD dwFlags)
1871    {
1872            DPRINTF("(MFT)ProcessInput");
1873    
1874            if (pSample == NULL)
1875                    return E_POINTER;
1876    
1877            if (dwInputStreamID != 0)
1878                    return MF_E_INVALIDSTREAMNUMBER;
1879    
1880            if (dwFlags != 0)
1881                    return E_INVALIDARG;
1882    
1883            if (!m_pInputType || !m_pOutputType) {
1884                    return MF_E_NOTACCEPTING;   /* Must have set input and output types */
1885            }
1886            else if (HasPendingOutput()) {
1887                    return MF_E_NOTACCEPTING;   /* We still have output samples to render */
1888            }
1889    
1890            xvid_dec_stats_t stats;
1891            int length;
1892    
1893            memset(&stats, 0, sizeof(stats));
1894            stats.version = XVID_VERSION;
1895    
1896            if (m_create.handle == NULL)
1897            {
1898                    if (xvid_decore_func == NULL)
1899                            return E_FAIL;
1900                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
1901                    {
1902                            DPRINTF("*** XVID_DEC_CREATE error");
1903                            return E_FAIL;
1904                    }
1905            }
1906    
1907            EnterCriticalSection(&m_mft_lock);
1908    
1909            HRESULT hr = S_OK;
1910            IMFMediaBuffer *pBuffer = NULL;
1911    
1912            if (SUCCEEDED(hr)) {
1913                    hr = pSample->ConvertToContiguousBuffer(&pBuffer);
1914            }
1915    
1916            if (SUCCEEDED(hr)) {
1917                    hr = pBuffer->Lock((BYTE**)&m_frame.bitstream, NULL, (DWORD *)&m_frame.length);
1918            }
1919    
1920            m_frame.general = XVID_LOWDELAY;
1921    
1922            if (m_discont == 1) {
1923                    m_frame.general |= XVID_DISCONTINUITY;
1924                    m_discont = 0;
1925            }
1926    
1927            if (g_config.nDeblock_Y)
1928                    m_frame.general |= XVID_DEBLOCKY;
1929    
1930            if (g_config.nDeblock_UV)
1931                    m_frame.general |= XVID_DEBLOCKUV;
1932    
1933            if (g_config.nDering_Y)
1934                    m_frame.general |= XVID_DERINGY;
1935    
1936            if (g_config.nDering_UV)
1937                    m_frame.general |= XVID_DERINGUV;
1938    
1939            if (g_config.nFilmEffect)
1940                    m_frame.general |= XVID_FILMEFFECT;
1941    
1942            m_frame.brightness = g_config.nBrightness;
1943    
1944            m_frame.output.csp &= ~XVID_CSP_VFLIP;
1945            m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0);
1946    
1947            int csp = m_frame.output.csp;
1948            m_frame.output.csp = XVID_CSP_INTERNAL;
1949    
1950        // Paranoid check.
1951            if (xvid_decore_func == NULL) {
1952                    hr = E_FAIL;
1953                    goto END_LOOP;
1954            }
1955    
1956    repeat :
1957            length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1958    
1959            if (length == XVID_ERR_MEMORY) {
1960                    hr = E_FAIL;
1961                    goto END_LOOP;
1962            }
1963            else if (length < 0)
1964            {
1965                    DPRINTF("*** XVID_DEC_DECODE");
1966                    goto END_LOOP;
1967            }
1968    
1969            if (stats.type == XVID_TYPE_NOTHING && length > 0) {
1970                    DPRINTF(" B-Frame decoder lag");
1971                    m_frame.output.plane[1] = NULL;
1972                    goto END_LOOP;
1973            }
1974    
1975            if (stats.type == XVID_TYPE_VOL)
1976            {
1977                    if (stats.data.vol.width != m_create.width ||
1978                            stats.data.vol.height != m_create.height)
1979                    {
1980                            DPRINTF("TODO: auto-resize");
1981                            m_frame.output.plane[1] = NULL;
1982                            hr = E_FAIL;
1983                    }
1984    
1985                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) { /* auto */
1986                            int par_x, par_y;
1987                            if (stats.data.vol.par == XVID_PAR_EXT) {
1988                                    par_x = stats.data.vol.par_width;
1989                                    par_y = stats.data.vol.par_height;
1990                            } else {
1991                                    par_x = PARS[stats.data.vol.par-1][0];
1992                                    par_y = PARS[stats.data.vol.par-1][1];
1993                            }
1994    
1995                            ar_x = par_x * stats.data.vol.width;
1996                            ar_y = par_y * stats.data.vol.height;
1997                    }
1998    
1999                    m_frame.bitstream = (BYTE*)m_frame.bitstream + length;
2000                    m_frame.length -= length;
2001                    goto repeat;
2002            }
2003    
2004    END_LOOP:
2005            m_frame.output.csp = csp;
2006    
2007            if (pBuffer) {
2008                    pBuffer->Unlock();
2009                    pBuffer->Release();
2010            }
2011    
2012            if (SUCCEEDED(hr)) {
2013                    /* Try to get a timestamp */
2014                    if (FAILED(pSample->GetSampleTime(&m_timestamp)))
2015                            m_timestamp = INVALID_TIME;
2016    
2017                    if (FAILED(pSample->GetSampleDuration(&m_timelength))) {
2018                            m_timelength = INVALID_TIME;
2019                    }
2020                    if (m_timestamp != INVALID_TIME && stats.type == XVID_TYPE_IVOP) {
2021                            m_rtFrame = m_timestamp;
2022                    }
2023            }
2024    
2025            LeaveCriticalSection(&m_mft_lock);
2026    
2027            return hr;
2028    }
2029    
2030    HRESULT CXvidDecoder::MFTProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus)
2031    {
2032            DPRINTF("(MFT)ProcessOutput");
2033    
2034            /* Preroll in MFT ??
2035               Flags ?? -> TODO... */
2036            if (dwFlags != 0)
2037                    return E_INVALIDARG;
2038    
2039            if (pOutputSamples == NULL || pdwStatus == NULL)
2040                    return E_POINTER;
2041    
2042            if (cOutputBufferCount != 1) /* Must be exactly one output buffer */
2043                    return E_INVALIDARG;
2044    
2045            if (pOutputSamples[0].pSample == NULL) /* Must have a sample */
2046                    return E_INVALIDARG;
2047    
2048            if (!HasPendingOutput()) { /* If there's no sample we need to decode one first */
2049                    return MF_E_TRANSFORM_NEED_MORE_INPUT;
2050            }
2051    
2052            EnterCriticalSection(&m_mft_lock);
2053    
2054            HRESULT hr = S_OK;
2055    
2056            BYTE *Dst = NULL;
2057            DWORD buffer_size;
2058    
2059            IMFMediaBuffer *pOutput = NULL;
2060    
2061            if (SUCCEEDED(hr)) {
2062                    hr = pOutputSamples[0].pSample->GetBufferByIndex(0, &pOutput); /* Get output buffer */
2063            }
2064    
2065            if (SUCCEEDED(hr)) {
2066                    hr = pOutput->GetMaxLength(&buffer_size);
2067            }
2068    
2069            if (SUCCEEDED(hr))
2070                    hr = pOutput->Lock(&Dst, NULL, NULL);
2071    
2072            if (SUCCEEDED(hr)) {
2073                    xvid_gbl_convert_t convert;
2074    
2075                    memset(&convert, 0, sizeof(convert));
2076                    convert.version = XVID_VERSION;
2077    
2078                    convert.input.csp = XVID_CSP_INTERNAL;
2079                    convert.input.plane[0] = m_frame.output.plane[0];
2080                    convert.input.plane[1] = m_frame.output.plane[1];
2081                    convert.input.plane[2] = m_frame.output.plane[2];
2082                    convert.input.stride[0] = m_frame.output.stride[0];
2083                    convert.input.stride[1] = m_frame.output.stride[1];
2084                    convert.input.stride[2] = m_frame.output.stride[2];
2085    
2086                    convert.output.csp = m_frame.output.csp;
2087                    convert.output.plane[0] = Dst;
2088                    convert.output.stride[0] = out_stride;
2089    
2090                    convert.width = m_create.width;
2091                    convert.height = m_create.height;
2092                    convert.interlacing = 0;
2093    
2094                    if (m_frame.output.plane[1] != NULL && Dst != NULL && xvid_global_func != NULL)
2095                            if (xvid_global_func(0, XVID_GBL_CONVERT, &convert, NULL) < 0) /* CSP convert into output buffer */
2096                                    hr = E_FAIL;
2097    
2098                    m_frame.output.plane[1] = NULL;
2099            }
2100    
2101            *pdwStatus = 0;
2102    
2103            if (SUCCEEDED(hr)) {
2104                    if (SUCCEEDED(hr))
2105                            hr = pOutputSamples[0].pSample->SetUINT32(MFSampleExtension_CleanPoint, TRUE); // key frame
2106    
2107                    if (SUCCEEDED(hr)) { /* Set timestamp of output sample */
2108                            if (m_timestamp != INVALID_TIME)
2109                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_timestamp);
2110                            else
2111                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_rtFrame);
2112    
2113                            if (m_timelength != INVALID_TIME)
2114                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_timelength);
2115                            else
2116                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_duration);
2117    
2118                            m_rtFrame += m_duration;
2119                    }
2120    
2121                    if (SUCCEEDED(hr))
2122                            hr = pOutput->SetCurrentLength(m_create.width * abs(m_create.height) * 4); // XXX
2123            }
2124    
2125            if (pOutput) {
2126                    pOutput->Unlock();
2127                    pOutput->Release();
2128            }
2129    
2130            LeaveCriticalSection(&m_mft_lock);
2131    
2132            return hr;
2133    }
2134    
2135    HRESULT CXvidDecoder::OnCheckInputType(IMFMediaType *pmt)
2136    {
2137            DPRINTF("(MFT)CheckInputType");
2138    
2139            HRESULT hr = S_OK;
2140    
2141            /*  Check if input type is already set. Reject any type that is not identical */
2142            if (m_pInputType) {
2143                    DWORD dwFlags = 0;
2144                    if (S_OK == m_pInputType->IsEqual(pmt, &dwFlags)) {
2145                            return S_OK;
2146                    }
2147                    else {
2148                            return MF_E_INVALIDTYPE;
2149                    }
2150            }
2151    
2152            GUID majortype = {0}, subtype = {0};
2153            UINT32 width = 0, height = 0;
2154    
2155            hr = pmt->GetMajorType(&majortype);
2156    
2157            if (SUCCEEDED(hr)) {
2158                    if (majortype != MFMediaType_Video) { /* Must be Video */
2159                            hr = MF_E_INVALIDTYPE;
2160                    }
2161            }
2162    
2163            if (m_hdll == NULL) {
2164                    HRESULT hr2 = OpenLib();
2165    
2166                    if (FAILED(hr2) || (m_hdll == NULL)) // Paranoid checks.
2167                            hr = MF_E_INVALIDTYPE;
2168            }
2169    
2170            if (SUCCEEDED(hr)) {
2171                    hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &width, &height);
2172            }
2173    
2174            /* Check the frame size */
2175            if (SUCCEEDED(hr)) {
2176                    if (width > 4096 || height > 4096) {
2177                            hr = MF_E_INVALIDTYPE;
2178                    }
2179            }
2180            m_create.width = width;
2181            m_create.height = height;
2182    
2183            if (SUCCEEDED(hr)) {
2184                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
2185                            hr = MFGetAttributeRatio(pmt, MF_MT_PIXEL_ASPECT_RATIO, (UINT32*)&ar_x, (UINT32*)&ar_y);
2186                    }
2187            }
2188    
2189            /* TODO1: Make sure there really is a frame rate after all!
2190               TODO2: Use the framerate for something! */
2191            MFRatio fps = {0};
2192            if (SUCCEEDED(hr)) {
2193                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&fps.Numerator, (UINT32*)&fps.Denominator);
2194            }
2195    
2196            if (SUCCEEDED(hr)) {
2197                    hr = pmt->GetGUID(MF_MT_SUBTYPE, &subtype);
2198            }
2199    
2200            if (subtype == CLSID_MP4V || subtype == CLSID_MP4V_UC ||
2201                subtype == CLSID_LMP4 || subtype == CLSID_LMP4_UC ||
2202                subtype == CLSID_RMP4 || subtype == CLSID_RMP4_UC ||
2203                subtype == CLSID_SMP4 || subtype == CLSID_SMP4_UC ||
2204                subtype == CLSID_HDX4 || subtype == CLSID_HDX4_UC) {
2205                    if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
2206                            CloseLib();
2207                            hr = MF_E_INVALIDTYPE;
2208                    }
2209                    else m_create.fourcc = FOURCC_MP4V;
2210            }
2211            else if (subtype == CLSID_DIVX || subtype == CLSID_DIVX_UC) {
2212                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2213                            CloseLib();
2214                            hr = MF_E_INVALIDTYPE;
2215                    }
2216                    else m_create.fourcc = FOURCC_DIVX;
2217            }
2218            else if (subtype == CLSID_DX50 || subtype == CLSID_DX50_UC) {
2219                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2220                            CloseLib();
2221                            hr = MF_E_INVALIDTYPE;
2222                    }
2223                    else m_create.fourcc = FOURCC_DX50;
2224            }
2225            else if (subtype == CLSID_3IVX || subtype == CLSID_3IVX_UC ||
2226                     subtype == CLSID_3IV0 || subtype == CLSID_3IV0_UC ||
2227                     subtype == CLSID_3IV1 || subtype == CLSID_3IV1_UC ||
2228                     subtype == CLSID_3IV2 || subtype == CLSID_3IV2_UC) {
2229                    if (!(g_config.supported_4cc & SUPPORT_3IVX)) {
2230                            CloseLib();
2231                            hr = MF_E_INVALIDTYPE;
2232                    }
2233                    else m_create.fourcc = FOURCC_3IVX;
2234            }
2235            else if (subtype == CLSID_XVID || subtype == CLSID_XVID_UC) {
2236                    m_create.fourcc = FOURCC_XVID;
2237            }
2238            else {
2239                    DPRINTF("Unknown subtype!");
2240                    CloseLib();
2241                    hr = MF_E_INVALIDTYPE;
2242            }
2243    
2244            /* haali media splitter reports VOL information in the format header */
2245            if (SUCCEEDED(hr))
2246            {
2247                    UINT32 cbSeqHeader = 0;
2248    
2249                    (void)pmt->GetBlobSize(MF_MT_MPEG_SEQUENCE_HEADER, &cbSeqHeader);
2250    
2251                    if (cbSeqHeader>0) {
2252                            xvid_dec_stats_t stats;
2253                            memset(&stats, 0, sizeof(stats));
2254                            stats.version = XVID_VERSION;
2255    
2256                            if (m_create.handle == NULL) {
2257                                    if (xvid_decore_func == NULL)
2258                                            hr = E_FAIL;
2259                                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
2260                                            DPRINTF("*** XVID_DEC_CREATE error");
2261                                            hr = E_FAIL;
2262                                    }
2263                            }
2264    
2265                            if (SUCCEEDED(hr)) {
2266                                    (void)pmt->GetAllocatedBlob(MF_MT_MPEG_SEQUENCE_HEADER, (UINT8 **)&m_frame.bitstream, (UINT32 *)&m_frame.length);
2267                                    m_frame.general = 0;
2268                                    m_frame.output.csp = XVID_CSP_NULL;
2269    
2270                                    int ret = 0;
2271                                    if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
2272                                            /* honour video dimensions reported in VOL header */
2273                                            if (stats.type == XVID_TYPE_VOL) {
2274                                                    m_create.width = stats.data.vol.width;
2275                                                    m_create.height = stats.data.vol.height;
2276                                            }
2277                                    }
2278    
2279                                    if (ret == XVID_ERR_MEMORY) hr = E_FAIL;
2280                                    CoTaskMemFree(m_frame.bitstream);
2281                            }
2282                    }
2283            }
2284    
2285            return hr;
2286    }
2287    
2288    HRESULT CXvidDecoder::OnSetInputType(IMFMediaType *pmt)
2289    {
2290            HRESULT hr = S_OK;
2291            UINT32 w, h;
2292    
2293            if (m_pInputType) m_pInputType->Release();
2294    
2295            hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &w, &h);
2296            m_create.width = w; m_create.height = h;
2297    
2298            if (SUCCEEDED(hr))
2299                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&m_frameRate.Numerator, (UINT32*)&m_frameRate.Denominator);
2300    
2301            if (SUCCEEDED(hr)) { /* Store frame duration, derived from the frame rate */
2302                    hr = MFFrameRateToAverageTimePerFrame(m_frameRate.Numerator, m_frameRate.Denominator, &m_duration);
2303            }
2304    
2305            if (SUCCEEDED(hr)) {
2306                    m_pInputType = pmt;
2307                    m_pInputType->AddRef();
2308            }
2309    
2310            return hr;
2311    }
2312    
2313    HRESULT CXvidDecoder::OnSetOutputType(IMFMediaType *pmt)
2314    {
2315            if (m_pOutputType) m_pOutputType->Release();
2316    
2317            m_pOutputType = pmt;
2318            m_pOutputType->AddRef();
2319    
2320            return S_OK;
2321    }
2322    
2323    #endif /* XVID_USE_MFT */

Legend:
Removed from v.1428  
changed lines
  Added in v.2018

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