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

Legend:
Removed from v.1896  
changed lines
  Added in v.2022

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