[svn] / branches / release-1_3-branch / xvidcore / dshow / src / CXvidDecoder.cpp Repository:
ViewVC logotype

Diff of /branches/release-1_3-branch/xvidcore/dshow/src/CXvidDecoder.cpp

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

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

Legend:
Removed from v.1558  
changed lines
  Added in v.1995

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