[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

revision 1502, Sun Jul 18 00:58:14 2004 UTC revision 1916, Wed Dec 22 15:21:13 2010 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-2010 Peter Ross <pross@xvid.org>
7     *               2003-2010 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.10 2004-07-18 00:58:14 suxen_drol Exp $   * $Id: CXvidDecoder.cpp,v 1.25 2010-12-22 15:21:13 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 36  Line 29 
29          place these paths at the top of the Tools|Options|Directories list          place these paths at the top of the Tools|Options|Directories list
30    
31          headers:          headers:
32          C:\DXVCSDK\include          C:\DX90SDK\Include
33          C:\DXVCSDK\samples\Multimedia\DirectShow\BaseClasses          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses
34    
35          libraries (optional):          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Release
36          C:\DXVCSDK\samples\Multimedia\DirectShow\BaseClasses\Release          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Debug
37  */  */
38    
39    #define XVID_USE_MFT
40    #define XVID_USE_TRAYICON
41    
42  #include <windows.h>  #include <windows.h>
43    
# Line 55  Line 49 
49  #endif  #endif
50  #include <dvdmedia.h>   // VIDEOINFOHEADER2  #include <dvdmedia.h>   // VIDEOINFOHEADER2
51    
52  #include <xvid.h>               // XviD API  #if defined(XVID_USE_MFT)
53    #define MFT_UNIQUE_METHOD_NAMES
54    #include <mftransform.h>
55    #include <mfapi.h>
56    #include <mferror.h>
57    #include <shlwapi.h>
58    #endif
59    
60    #include <shellapi.h>
61    
62    #include <xvid.h>               // Xvid API
63    
64    #include "resource.h"
65    
66  #include "IXvidDecoder.h"  #include "IXvidDecoder.h"
67  #include "CXvidDecoder.h"  #include "CXvidDecoder.h"
# Line 82  Line 88 
88          { &MEDIATYPE_Video, &CLSID_DX50 },          { &MEDIATYPE_Video, &CLSID_DX50 },
89          { &MEDIATYPE_Video, &CLSID_DX50_UC },          { &MEDIATYPE_Video, &CLSID_DX50_UC },
90          { &MEDIATYPE_Video, &CLSID_MP4V },          { &MEDIATYPE_Video, &CLSID_MP4V },
91      { &MEDIATYPE_Video, &CLSID_MP4V_UC },
92  };  };
93    
94  const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] =  const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] =
# Line 148  Line 155 
155    
156  };  };
157    
   
158  /* 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) */
159  int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate);  int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate);
160    
161    #ifdef XVID_USE_TRAYICON
162    extern HINSTANCE g_xvid_hInst;
163    
164    static int GUI_Page = 0;
165    static int Tray_Icon = 0;
166    extern "C" void CALLBACK Configure(HWND hWndParent, HINSTANCE hInstParent, LPSTR lpCmdLine, int nCmdShow );
167    
168    LRESULT CALLBACK msg_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
169    {
170            switch ( uMsg )
171            {
172            case WM_ICONMESSAGE:
173                    switch(lParam)
174                    {
175                    case WM_LBUTTONDBLCLK:
176                            if (!GUI_Page) {
177                                    GUI_Page = 1;
178                                    Configure(hwnd, g_xvid_hInst, "", 1);
179                                    GUI_Page = 0;
180                            }
181                            break;
182                    default:
183                            return DefWindowProc(hwnd, uMsg, wParam, lParam);
184                    };
185                    break;
186    
187            case WM_DESTROY:
188                    NOTIFYICONDATA nid;
189                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
190    
191                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
192                    nid.hWnd = hwnd;
193                    nid.uID = 1456;
194    
195                    Shell_NotifyIcon(NIM_DELETE, &nid);
196                    Tray_Icon = 0;
197            default:
198                    return DefWindowProc(hwnd, uMsg, wParam, lParam);
199            }
200    
201            return TRUE; /* ok */
202    }
203    #endif
204    
205  STDAPI DllRegisterServer()  STDAPI DllRegisterServer()
206  {  {
207    #if defined(XVID_USE_MFT)
208            int inputs_num = sizeof(sudInputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE);
209            int outputs_num = sizeof(sudOutputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE);
210            MFT_REGISTER_TYPE_INFO * mft_bs = new MFT_REGISTER_TYPE_INFO[inputs_num];
211            MFT_REGISTER_TYPE_INFO * mft_csp = new MFT_REGISTER_TYPE_INFO[outputs_num];
212    
213            {
214                    int i;
215                    for(i=0;i<inputs_num;i++) {
216                            mft_bs[i].guidMajorType = *sudInputPinTypes[i].clsMajorType;
217                            mft_bs[i].guidSubtype = *sudInputPinTypes[i].clsMinorType;
218                    }
219                    for(i=0;i<outputs_num;i++) {
220                            mft_csp[i].guidMajorType = *sudOutputPinTypes[i].clsMajorType;
221                            mft_csp[i].guidSubtype = *sudOutputPinTypes[i].clsMinorType; // MFT and AM GUIDs really the same?
222                    }
223            }
224    
225            /* Register the MFT decoder */
226            MFTRegister(CLSID_XVID,                          // CLSID
227                            MFT_CATEGORY_VIDEO_DECODER,          // Category
228                            const_cast<LPWSTR>(XVID_NAME_L),     // Friendly name
229                            0,                                   // Flags
230                            inputs_num,                          // Number of input types
231                            mft_bs,                              // Input types
232                            outputs_num,                         // Number of output types
233                            mft_csp,                             // Output types
234                            NULL                                 // Attributes (optional)
235                            );
236    
237            delete[] mft_bs;
238            delete[] mft_csp;
239    #endif /* XVID_USE_MFT */
240    
241      return AMovieDllRegisterServer2( TRUE );      return AMovieDllRegisterServer2( TRUE );
242  }  }
243    
244    
245  STDAPI DllUnregisterServer()  STDAPI DllUnregisterServer()
246  {  {
247    #if defined(XVID_USE_MFT)
248            MFTUnregister(CLSID_XVID);
249    #endif
250      return AMovieDllRegisterServer2( FALSE );      return AMovieDllRegisterServer2( FALSE );
251  }  }
252    
# Line 194  Line 280 
280          return GetInterface((ISpecifyPropertyPages *) this, ppv);          return GetInterface((ISpecifyPropertyPages *) this, ppv);
281          }          }
282    
283    #if defined(XVID_USE_MFT)
284            if (riid == IID_IMFTransform)
285            {
286                    return GetInterface((IMFTransform *) this, ppv);
287            }
288    #endif
289    
290          return CVideoTransformFilter::NonDelegatingQueryInterface(riid, ppv);          return CVideoTransformFilter::NonDelegatingQueryInterface(riid, ppv);
291  }  }
292    
# Line 204  Line 297 
297  #define XVID_DLL_NAME "xvidcore.dll"  #define XVID_DLL_NAME "xvidcore.dll"
298    
299  CXvidDecoder::CXvidDecoder(LPUNKNOWN punk, HRESULT *phr) :  CXvidDecoder::CXvidDecoder(LPUNKNOWN punk, HRESULT *phr) :
300      CVideoTransformFilter(NAME("CXvidDecoder"), punk, CLSID_XVID)      CVideoTransformFilter(NAME("CXvidDecoder"), punk, CLSID_XVID), m_hdll (NULL)
301  {  {
302          DPRINTF("Constructor");          DPRINTF("Constructor");
303    
304        xvid_decore_func = NULL; // Hmm, some strange errors appearing if I try to initialize...
305        xvid_global_func = NULL; // ...this in constructor's init-list. So, they assigned here.
306    
307    #if defined(XVID_USE_MFT)
308            InitializeCriticalSection(&m_mft_lock);
309            m_pInputType = NULL;
310            m_pOutputType = NULL;
311            m_rtFrame = 0;
312            m_duration = 0;
313            m_discont = 0;
314            m_frameRate.Denominator = 1;
315            m_frameRate.Numerator = 1;
316    #endif
317    
318        LoadRegistryInfo();
319    
320        *phr = OpenLib();
321    }
322    
323    HRESULT CXvidDecoder::OpenLib()
324    {
325        DPRINTF("OpenLib");
326    
327        if (m_hdll != NULL)
328                    return E_UNEXPECTED; // Seems, that library already opened.
329    
330          xvid_gbl_init_t init;          xvid_gbl_init_t init;
331          memset(&init, 0, sizeof(init));          memset(&init, 0, sizeof(init));
332          init.version = XVID_VERSION;          init.version = XVID_VERSION;
333            init.cpu_flags = g_config.cpu;
334    
335            xvid_gbl_info_t info;
336            memset(&info, 0, sizeof(info));
337            info.version = XVID_VERSION;
338    
339          m_hdll = LoadLibrary(XVID_DLL_NAME);          m_hdll = LoadLibrary(XVID_DLL_NAME);
340          if (m_hdll == NULL) {          if (m_hdll == NULL) {
341                  DPRINTF("dll load failed");                  DPRINTF("dll load failed");
342                  MessageBox(0, XVID_DLL_NAME " not found","Error", MB_TOPMOST);                  MessageBox(0, XVID_DLL_NAME " not found","Error", MB_TOPMOST);
343                  return;                  return E_FAIL;
344          }          }
345    
346          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");
347          if (xvid_global_func == NULL) {          if (xvid_global_func == NULL) {
348            FreeLibrary(m_hdll);
349            m_hdll = NULL;
350                  MessageBox(0, "xvid_global() not found", "Error", MB_TOPMOST);                  MessageBox(0, "xvid_global() not found", "Error", MB_TOPMOST);
351                  return;                  return E_FAIL;
352          }          }
353    
354          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");
355          if (xvid_decore_func == NULL) {          if (xvid_decore_func == NULL) {
356            xvid_global_func = NULL;
357            FreeLibrary(m_hdll);
358            m_hdll = NULL;
359                  MessageBox(0, "xvid_decore() not found", "Error", MB_TOPMOST);                  MessageBox(0, "xvid_decore() not found", "Error", MB_TOPMOST);
360                  return;                  return E_FAIL;
361          }          }
362    
363          if (xvid_global_func(0, XVID_GBL_INIT, &init, NULL) < 0)          if (xvid_global_func(0, XVID_GBL_INIT, &init, NULL) < 0)
364          {          {
365            xvid_global_func = NULL;
366            xvid_decore_func = NULL;
367            FreeLibrary(m_hdll);
368            m_hdll = NULL;
369                    MessageBox(0, "xvid_global() failed", "Error", MB_TOPMOST);
370                    return E_FAIL;
371            }
372    
373            if (xvid_global_func(0, XVID_GBL_INFO, &info, NULL) < 0)
374            {
375            xvid_global_func = NULL;
376            xvid_decore_func = NULL;
377            FreeLibrary(m_hdll);
378            m_hdll = NULL;
379                  MessageBox(0, "xvid_global() failed", "Error", MB_TOPMOST);                  MessageBox(0, "xvid_global() failed", "Error", MB_TOPMOST);
380                  return;                  return E_FAIL;
381          }          }
382    
383          memset(&m_create, 0, sizeof(m_create));          memset(&m_create, 0, sizeof(m_create));
384          m_create.version = XVID_VERSION;          m_create.version = XVID_VERSION;
385          m_create.handle = NULL;          m_create.handle = NULL;
386        /* Decoder threads */
387        if (g_config.cpu & XVID_CPU_FORCE) {
388                    m_create.num_threads = g_config.num_threads;
389            }
390            else {
391            m_create.num_threads = info.num_threads; /* Autodetect */
392                    g_config.num_threads = info.num_threads;
393            }
394    
395          memset(&m_frame, 0, sizeof(m_frame));          memset(&m_frame, 0, sizeof(m_frame));
396          m_frame.version = XVID_VERSION;          m_frame.version = XVID_VERSION;
397    
         LoadRegistryInfo();  
   
398          USE_IYUV = false;          USE_IYUV = false;
399          USE_YV12 = false;          USE_YV12 = false;
400          USE_YUY2 = false;          USE_YUY2 = false;
# Line 302  Line 451 
451                  ar_y = 20;                  ar_y = 20;
452                  break;                  break;
453          }          }
454    
455            return S_OK;
456  }  }
457    
458  void CXvidDecoder::CloseLib()  void CXvidDecoder::CloseLib()
459  {  {
460          DPRINTF("Destructor");          DPRINTF("CloseLib");
461    
462          if (m_create.handle != NULL) {          if ((m_create.handle != NULL) && (xvid_decore_func != NULL))
463            {
464                  xvid_decore_func(m_create.handle, XVID_DEC_DESTROY, 0, 0);                  xvid_decore_func(m_create.handle, XVID_DEC_DESTROY, 0, 0);
465                  m_create.handle = NULL;                  m_create.handle = NULL;
466          }          }
# Line 317  Line 469 
469                  FreeLibrary(m_hdll);                  FreeLibrary(m_hdll);
470                  m_hdll = NULL;                  m_hdll = NULL;
471          }          }
472        xvid_decore_func = NULL;
473        xvid_global_func = NULL;
474  }  }
475    
476  /* destructor */  /* destructor */
477    
478  CXvidDecoder::~CXvidDecoder()  CXvidDecoder::~CXvidDecoder()
479  {  {
480        DPRINTF("Destructor");
481    
482    #ifdef XVID_USE_TRAYICON
483            if (Tray_Icon) { /* Destroy tray icon */
484                    NOTIFYICONDATA nid;
485                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
486    
487                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
488                    nid.hWnd = MSG_hwnd;
489                    nid.uID = 1456;
490    
491                    Shell_NotifyIcon(NIM_DELETE, &nid);
492                    Tray_Icon = 0;
493            }
494    #endif
495    
496            /* Close xvidcore library */
497          CloseLib();          CloseLib();
498    
499    #if defined(XVID_USE_MFT)
500            DeleteCriticalSection(&m_mft_lock);
501    #endif
502  }  }
503    
504    
# Line 344  Line 519 
519                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
520          }          }
521    
522        if (m_hdll == NULL)
523        {
524                    HRESULT hr = OpenLib();
525    
526            if (FAILED(hr) || (m_hdll == NULL)) // Paranoid checks.
527                            return VFW_E_TYPE_NOT_ACCEPTED;
528        }
529    
530          if (*mtIn->FormatType() == FORMAT_VideoInfo)          if (*mtIn->FormatType() == FORMAT_VideoInfo)
531          {          {
532                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtIn->Format();                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtIn->Format();
# Line 359  Line 542 
542                  }                  }
543                  DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);                  DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);
544          }          }
545      else if (*mtIn->FormatType() == FORMAT_MPEG2Video) {
546        MPEG2VIDEOINFO * mpgvi = (MPEG2VIDEOINFO*)mtIn->Format();
547        VIDEOINFOHEADER2 * vih2 = &mpgvi->hdr;
548                    hdr = &vih2->bmiHeader;
549                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
550                            ar_x = vih2->dwPictAspectRatioX;
551                            ar_y = vih2->dwPictAspectRatioY;
552                    }
553                    DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);
554    
555        /* haali media splitter reports VOL information in the format header */
556    
557        if (mpgvi->cbSequenceHeader>0) {
558    
559          xvid_dec_stats_t stats;
560                memset(&stats, 0, sizeof(stats));
561                stats.version = XVID_VERSION;
562    
563                if (m_create.handle == NULL) {
564                        if (xvid_decore_func == NULL)
565                                return E_FAIL;
566                        if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
567              DPRINTF("*** XVID_DEC_CREATE error");
568                                return E_FAIL;
569                        }
570                }
571    
572          m_frame.general = 0;
573          m_frame.bitstream = (void*)mpgvi->dwSequenceHeader;
574          m_frame.length = mpgvi->cbSequenceHeader;
575          m_frame.output.csp = XVID_CSP_NULL;
576    
577          int ret = 0;
578          if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
579            /* honour video dimensions reported in VOL header */
580                  if (stats.type == XVID_TYPE_VOL) {
581              hdr->biWidth = stats.data.vol.width;
582              hdr->biHeight = stats.data.vol.height;
583                      }
584              }
585          if (ret == XVID_ERR_MEMORY) return E_FAIL;
586            }
587      }
588          else          else
589          {          {
590                  DPRINTF("Error: Unknown FormatType");                  DPRINTF("Error: Unknown FormatType");
591                  CloseLib();                  CloseLib();
592                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
593          }          }
   
594          if (hdr->biHeight < 0)          if (hdr->biHeight < 0)
595          {          {
596                  DPRINTF("colorspace: inverted input format not supported");                  DPRINTF("colorspace: inverted input format not supported");
# Line 376  Line 601 
601    
602          switch(hdr->biCompression)          switch(hdr->biCompression)
603          {          {
604      case FOURCC_mp4v:
605          case FOURCC_MP4V:          case FOURCC_MP4V:
606                  if (!(g_config.supported_4cc & SUPPORT_MP4V)) {                  if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
607                          CloseLib();                          CloseLib();
# Line 408  Line 633 
633                  CloseLib();                  CloseLib();
634                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
635          }          }
636    
637            m_create.fourcc = hdr->biCompression;
638    
639          return S_OK;          return S_OK;
640  }  }
641    
# Line 549  Line 777 
777    
778    
779  /* (internal function) change colorspace */  /* (internal function) change colorspace */
780    #define CALC_BI_STRIDE(width,bitcount)  ((((width * bitcount) + 31) & ~31) >> 3)
781    
782  HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format)  HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format)
783  {  {
784            DWORD biWidth;
785    
786          if (formattype == FORMAT_VideoInfo)          if (formattype == FORMAT_VideoInfo)
787          {          {
788                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;
789                  m_frame.output.stride[0] = (((vih->bmiHeader.biWidth * vih->bmiHeader.biBitCount) + 31) & ~31) >> 3;                  biWidth = vih->bmiHeader.biWidth;
790                    out_stride = CALC_BI_STRIDE(vih->bmiHeader.biWidth, vih->bmiHeader.biBitCount);
791                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
792          }          }
793          else if (formattype == FORMAT_VideoInfo2)          else if (formattype == FORMAT_VideoInfo2)
794          {          {
795                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;
796                  m_frame.output.stride[0] = (((vih2->bmiHeader.biWidth * vih2->bmiHeader.biBitCount) + 31) & ~31) >> 3;                  biWidth = vih2->bmiHeader.biWidth;
797                    out_stride = CALC_BI_STRIDE(vih2->bmiHeader.biWidth, vih2->bmiHeader.biBitCount);
798                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
799          }          }
800          else          else
# Line 574  Line 807 
807                  DPRINTF("IYUV");                  DPRINTF("IYUV");
808                  rgb_flip = 0;                  rgb_flip = 0;
809                  m_frame.output.csp = XVID_CSP_I420;                  m_frame.output.csp = XVID_CSP_I420;
810                  m_frame.output.stride[0] = (m_frame.output.stride[0] * 2) / 3;  /* planar format fix */                  out_stride = CALC_BI_STRIDE(biWidth, 8);        /* planar format fix */
811          }          }
812          else if (subtype == MEDIASUBTYPE_YV12)          else if (subtype == MEDIASUBTYPE_YV12)
813          {          {
814                  DPRINTF("YV12");                  DPRINTF("YV12");
815                  rgb_flip = 0;                  rgb_flip = 0;
816                  m_frame.output.csp = XVID_CSP_YV12;                  m_frame.output.csp = XVID_CSP_YV12;
817                  m_frame.output.stride[0] = (m_frame.output.stride[0] * 2) / 3;  /* planar format fix */                  out_stride = CALC_BI_STRIDE(biWidth, 8);        /* planar format fix */
818          }          }
819          else if (subtype == MEDIASUBTYPE_YUY2)          else if (subtype == MEDIASUBTYPE_YUY2)
820          {          {
# Line 654  Line 887 
887  HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)  HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
888  {  {
889          DPRINTF("CheckTransform");          DPRINTF("CheckTransform");
890    
891            return S_OK;
892    }
893    
894    /* input/output pin connection complete */
895    
896    HRESULT CXvidDecoder::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin)
897    {
898            DPRINTF("CompleteConnect");
899    
900    #ifdef XVID_USE_TRAYICON
901            if ((direction == PINDIR_OUTPUT) && (Tray_Icon == 0))
902            {
903                    WNDCLASSEX wc;
904    
905                    wc.cbSize = sizeof(WNDCLASSEX);
906                    wc.lpfnWndProc = msg_proc;
907                    wc.style = CS_HREDRAW | CS_VREDRAW;
908                    wc.cbWndExtra = 0;
909                    wc.cbClsExtra = 0;
910                    wc.hInstance = (HINSTANCE) g_xvid_hInst;
911                    wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH);
912                    wc.lpszMenuName = NULL;
913                    wc.lpszClassName = "XVID_MSG_WINDOW";
914                    wc.hIcon = NULL;
915                    wc.hIconSm = NULL;
916                    wc.hCursor = NULL;
917                    RegisterClassEx(&wc);
918    
919                    MSG_hwnd = CreateWindowEx(0, "XVID_MSG_WINDOW", NULL, 0, CW_USEDEFAULT,
920                                      CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE) g_xvid_hInst, NULL);
921    
922                    /* display the tray icon */
923                    NOTIFYICONDATA nid;
924                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
925    
926                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
927                    nid.hWnd = MSG_hwnd;
928                    nid.uID = 1456;
929                    nid.uCallbackMessage = WM_ICONMESSAGE;
930                    nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
931                    strcpy_s(nid.szTip, 19, "Xvid Video Decoder");
932                    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
933    
934                    Shell_NotifyIcon(NIM_ADD, &nid);
935    
936                    DestroyIcon(nid.hIcon);
937                    Tray_Icon = 1;
938            }
939    #endif
940    
941          return S_OK;          return S_OK;
942  }  }
943    
944    /* input/output pin disconnected */
945    HRESULT CXvidDecoder::BreakConnect(PIN_DIRECTION direction)
946    {
947            DPRINTF("BreakConnect");
948    
949            return S_OK;
950    }
951    
952  /* alloc output buffer */  /* alloc output buffer */
953    
# Line 705  Line 996 
996    
997          if (m_create.handle == NULL)          if (m_create.handle == NULL)
998          {          {
999                    if (xvid_decore_func == NULL)
1000                            return E_FAIL;
1001    
1002                  if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)                  if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
1003                  {                  {
1004              DPRINTF("*** XVID_DEC_CREATE error");              DPRINTF("*** XVID_DEC_CREATE error");
1005                          return S_FALSE;                          return E_FAIL;
1006                  }                  }
1007          }          }
1008    
# Line 763  Line 1057 
1057    
1058          m_frame.output.csp &= ~XVID_CSP_VFLIP;          m_frame.output.csp &= ~XVID_CSP_VFLIP;
1059          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);
1060            m_frame.output.stride[0] = out_stride;
1061    
1062        // Paranoid check.
1063        if (xvid_decore_func == NULL)
1064                    return E_FAIL;
1065    
1066    
1067  repeat :  repeat :
# Line 773  Line 1070 
1070          {          {
1071                  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);
1072    
1073                  if (length < 0)                  if (length == XVID_ERR_MEMORY)
1074                            return E_FAIL;
1075                    else if (length < 0)
1076                  {                  {
1077              DPRINTF("*** XVID_DEC_DECODE");              DPRINTF("*** XVID_DEC_DECODE");
1078                          return S_FALSE;                          return S_FALSE;
1079                  } else                  } else
1080                          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  
1081    
1082          if (stats.type != XVID_TYPE_NOTHING) {  /* dont attempt to set vmr aspect ratio if no frame was returned by decoder */
1083                            // inspired by minolta! works for VMR 7 + 9
1084                          IMediaSample2 *pOut2 = NULL;                          IMediaSample2 *pOut2 = NULL;
1085                          AM_SAMPLE2_PROPERTIES outProp2;                          AM_SAMPLE2_PROPERTIES outProp2;
1086                          if (SUCCEEDED(pOut->QueryInterface(IID_IMediaSample2, (void **)&pOut2)) &&                          if (SUCCEEDED(pOut->QueryInterface(IID_IMediaSample2, (void **)&pOut2)) &&
# Line 801  Line 1101 
1101                          }                          }
1102                  }                  }
1103          }          }
1104            }
1105          else          else
1106          {       /* Preroll frame - won't be displayed */          {       /* Preroll frame - won't be displayed */
1107                  int tmp = m_frame.output.csp;                  int tmp = m_frame.output.csp;
# Line 815  Line 1116 
1116                  m_frame.general &= ~XVID_FILMEFFECT;                  m_frame.general &= ~XVID_FILMEFFECT;
1117    
1118                  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);
1119                  if (length < 0)                  if (length == XVID_ERR_MEMORY)
1120                            return E_FAIL;
1121                    else if (length < 0)
1122                  {                  {
1123              DPRINTF("*** XVID_DEC_DECODE");              DPRINTF("*** XVID_DEC_DECODE");
1124                          return S_FALSE;                          return S_FALSE;
# Line 848  Line 1151 
1151                                  par_x = stats.data.vol.par_width;                                  par_x = stats.data.vol.par_width;
1152                                  par_y = stats.data.vol.par_height;                                  par_y = stats.data.vol.par_height;
1153                          } else {                          } else {
1154                                  par_x = PARS[stats.data.vol.par][0];                                  par_x = PARS[stats.data.vol.par-1][0];
1155                                  par_y = PARS[stats.data.vol.par][1];                                  par_y = PARS[stats.data.vol.par-1][1];
1156                          }                          }
1157    
1158                          ar_x = par_x * stats.data.vol.width;                          ar_x = par_x * stats.data.vol.width;
# Line 895  Line 1198 
1198          CoTaskMemFree(pPages->pElems);          CoTaskMemFree(pPages->pElems);
1199          return S_OK;          return S_OK;
1200  }  }
1201    
1202    /*===============================================================================
1203    // MFT Interface
1204    //=============================================================================*/
1205    #if defined(XVID_USE_MFT)
1206    #include <limits.h> // _I64_MAX
1207    #define INVALID_TIME  _I64_MAX
1208    
1209    HRESULT CXvidDecoder::MFTGetStreamLimits(DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum)
1210    {
1211            DPRINTF("(MFT)GetStreamLimits");
1212    
1213            if ((pdwInputMinimum == NULL) || (pdwInputMaximum == NULL) || (pdwOutputMinimum == NULL) || (pdwOutputMaximum == NULL))
1214                    return E_POINTER;
1215    
1216            /* Just a fixed number of streams allowed */
1217            *pdwInputMinimum = *pdwInputMaximum = 1;
1218            *pdwOutputMinimum = *pdwOutputMaximum = 1;
1219    
1220            return S_OK;
1221    }
1222    
1223    HRESULT CXvidDecoder::MFTGetStreamCount(DWORD *pcInputStreams, DWORD *pcOutputStreams)
1224    {
1225            DPRINTF("(MFT)GetStreamCount");
1226    
1227            if ((pcInputStreams == NULL) || (pcOutputStreams == NULL))
1228                    return E_POINTER;
1229    
1230            /* We have a fixed number of streams */
1231            *pcInputStreams = 1;
1232            *pcOutputStreams = 1;
1233    
1234            return S_OK;
1235    }
1236    
1237    HRESULT CXvidDecoder::MFTGetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs)
1238    {
1239            DPRINTF("(MFT)GetStreamIDs");
1240            return E_NOTIMPL; /* We have fixed number of streams, so stream ID match stream index */
1241    }
1242    
1243    HRESULT CXvidDecoder::MFTGetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo)
1244    {
1245            DPRINTF("(MFT)GetInputStreamInfo");
1246    
1247            if (pStreamInfo == NULL)
1248                    return E_POINTER;
1249    
1250            if (dwInputStreamID != 0)
1251                    return MF_E_INVALIDSTREAMNUMBER;
1252    
1253            EnterCriticalSection(&m_mft_lock);
1254    
1255            pStreamInfo->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER;
1256            pStreamInfo->hnsMaxLatency = 0;
1257    
1258            pStreamInfo->cbSize = 1; /* Need atleast 1 byte input */
1259            pStreamInfo->cbMaxLookahead = 0;
1260            pStreamInfo->cbAlignment = 1;
1261    
1262            LeaveCriticalSection(&m_mft_lock);
1263            return S_OK;
1264    }
1265    
1266    HRESULT CXvidDecoder::MFTGetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo)
1267    {
1268            DPRINTF("(MFT)GetOutputStreamInfo");
1269    
1270            if (pStreamInfo == NULL)
1271                    return E_POINTER;
1272    
1273            if (dwOutputStreamID != 0)
1274                    return MF_E_INVALIDSTREAMNUMBER;
1275    
1276            EnterCriticalSection(&m_mft_lock);
1277    
1278            pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_DISCARDABLE;
1279    
1280            if (m_pOutputType == NULL) {
1281                    pStreamInfo->cbSize = 0;
1282                    pStreamInfo->cbAlignment = 0;
1283            }
1284            else {
1285                    pStreamInfo->cbSize = m_create.width * abs(m_create.height) * 4; // XXX
1286                    pStreamInfo->cbAlignment = 1;
1287            }
1288    
1289            LeaveCriticalSection(&m_mft_lock);
1290            return S_OK;
1291    }
1292    
1293    HRESULT CXvidDecoder::GetAttributes(IMFAttributes** pAttributes)
1294    {
1295            DPRINTF("(MFT)GetAttributes");
1296            return E_NOTIMPL; /* We don't support any attributes */
1297    }
1298    
1299    HRESULT CXvidDecoder::GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes **ppAttributes)
1300    {
1301            DPRINTF("(MFT)GetInputStreamAttributes");
1302            return E_NOTIMPL; /* We don't support any attributes */
1303    }
1304    
1305    HRESULT CXvidDecoder::GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes **ppAttributes)
1306    {
1307            DPRINTF("(MFT)GetOutputStreamAttributes");
1308            return E_NOTIMPL; /* We don't support any attributes */
1309    }
1310    
1311    HRESULT CXvidDecoder::MFTDeleteInputStream(DWORD dwStreamID)
1312    {
1313            DPRINTF("(MFT)DeleteInputStream");
1314            return E_NOTIMPL; /* We have a fixed number of streams */
1315    }
1316    
1317    HRESULT CXvidDecoder::MFTAddInputStreams(DWORD cStreams, DWORD *adwStreamIDs)
1318    {
1319            DPRINTF("(MFT)AddInputStreams");
1320            return E_NOTIMPL; /* We have a fixed number of streams */
1321    }
1322    
1323    HRESULT CXvidDecoder::MFTGetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1324    {
1325            DPRINTF("(MFT)GetInputAvailableType");
1326    
1327            if (dwInputStreamID != 0)
1328                    return MF_E_INVALIDSTREAMNUMBER;
1329    
1330            DWORD i = 0;
1331            GUID *bs_guid_table[8];
1332    
1333            bs_guid_table[i++] = (GUID *)&CLSID_XVID;
1334            bs_guid_table[i++] = (GUID *)&CLSID_XVID_UC;
1335    
1336            if (g_config.supported_4cc & SUPPORT_DX50) {
1337                    bs_guid_table[i++] = (GUID *)&CLSID_DX50;
1338                    bs_guid_table[i++] = (GUID *)&CLSID_DX50_UC;
1339            }
1340            if (g_config.supported_4cc & SUPPORT_DIVX) {
1341                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX;
1342                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX_UC;
1343            }
1344            if (g_config.supported_4cc & SUPPORT_MP4V) {
1345                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V;
1346                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V_UC;
1347            }
1348    
1349            const GUID *subtype;
1350            if (dwTypeIndex < i) {
1351                    subtype = bs_guid_table[dwTypeIndex];
1352            }
1353            else {
1354                    return MF_E_NO_MORE_TYPES;
1355            }
1356    
1357            EnterCriticalSection(&m_mft_lock);
1358    
1359            HRESULT hr = S_OK;
1360    
1361            if (ppType) {
1362                    IMFMediaType *pInputType = NULL;
1363                    hr = MFCreateMediaType(&pInputType);
1364    
1365                    if (SUCCEEDED(hr))
1366                            hr = pInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1367    
1368                    if (SUCCEEDED(hr))
1369                            hr = pInputType->SetGUID(MF_MT_SUBTYPE, *subtype);
1370    
1371                    if (SUCCEEDED(hr)) {
1372                            *ppType = pInputType;
1373                            (*ppType)->AddRef();
1374                    }
1375                    if (pInputType) pInputType->Release();
1376            }
1377    
1378            LeaveCriticalSection(&m_mft_lock);
1379    
1380            return hr;
1381    }
1382    
1383    HRESULT CXvidDecoder::MFTGetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1384    {
1385            DPRINTF("(MFT)GetOutputAvailableType");
1386    
1387            if (ppType == NULL)
1388                    return E_INVALIDARG;
1389    
1390            if (dwOutputStreamID != 0)
1391                    return MF_E_INVALIDSTREAMNUMBER;
1392    
1393            if (dwTypeIndex < 0) return E_INVALIDARG;
1394    
1395            GUID csp;
1396            int bitdepth = 8;
1397            switch(dwTypeIndex)
1398            {
1399            case 0:
1400    if ( USE_YUY2 )
1401    {
1402                    csp = MFVideoFormat_YUY2;
1403                    bitdepth = 4;
1404                    break;
1405    }
1406            case 1 :
1407    if ( USE_UYVY )
1408    {
1409                    csp = MFVideoFormat_UYVY;
1410                    bitdepth = 4;
1411                    break;
1412    }
1413            case 2  :
1414                    if ( USE_IYUV )
1415    {
1416                    csp = MFVideoFormat_IYUV;
1417                    bitdepth = 3;
1418                    break;
1419    }
1420            case 3  :
1421    if ( USE_YV12 )
1422    {
1423                    csp = MFVideoFormat_YV12;
1424                    bitdepth = 3;
1425                    break;
1426    }
1427            case 4 :
1428    if ( USE_RGB32 )
1429    {
1430                    csp = MFVideoFormat_RGB32;
1431                    bitdepth = 8;
1432                    break;
1433    }
1434            case 5 :
1435    if ( USE_RGB24 )
1436    {
1437                    csp = MFVideoFormat_RGB24;
1438                    bitdepth = 6;
1439                    break;
1440    }
1441            case 6 :
1442    if ( USE_RG555 )
1443    {
1444                    csp = MFVideoFormat_RGB555;
1445                    bitdepth = 4;
1446                    break;
1447    }
1448            case 7 :
1449    if ( USE_RG565 )
1450    {
1451                    csp = MFVideoFormat_RGB565;
1452                    bitdepth = 4;
1453                    break;
1454    }
1455            default :
1456                    return MF_E_NO_MORE_TYPES;
1457            }
1458    
1459            if (m_pInputType == NULL)
1460                    return MF_E_TRANSFORM_TYPE_NOT_SET;
1461    
1462            EnterCriticalSection(&m_mft_lock);
1463    
1464            HRESULT hr = S_OK;
1465    
1466            IMFMediaType *pOutputType = NULL;
1467            hr = MFCreateMediaType(&pOutputType);
1468    
1469            if (SUCCEEDED(hr)) {
1470                    hr = pOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1471            }
1472    
1473            if (SUCCEEDED(hr)) {
1474                    hr = pOutputType->SetGUID(MF_MT_SUBTYPE, csp);
1475        }
1476    
1477            if (SUCCEEDED(hr)) {
1478                    hr = pOutputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE);
1479            }
1480    
1481            if (SUCCEEDED(hr)) {
1482                    hr = pOutputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
1483            }
1484    
1485            if (SUCCEEDED(hr)) {
1486                    hr = pOutputType->SetUINT32(MF_MT_SAMPLE_SIZE, (m_create.height * m_create.width * bitdepth)>>1);
1487            }
1488    
1489            if (SUCCEEDED(hr)) {
1490                    hr = MFSetAttributeSize(pOutputType, MF_MT_FRAME_SIZE, m_create.width, m_create.height);
1491            }
1492    
1493            if (SUCCEEDED(hr)) {
1494                    hr = MFSetAttributeRatio(pOutputType, MF_MT_FRAME_RATE, m_frameRate.Numerator, m_frameRate.Denominator);
1495            }
1496    
1497            if (SUCCEEDED(hr)) {
1498                    hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
1499            }
1500    
1501            if (SUCCEEDED(hr)) {
1502                    hr = MFSetAttributeRatio(pOutputType, MF_MT_PIXEL_ASPECT_RATIO, ar_x, ar_y);
1503            }
1504    
1505            if (SUCCEEDED(hr)) {
1506                    *ppType = pOutputType;
1507                    (*ppType)->AddRef();
1508            }
1509    
1510            if (pOutputType) pOutputType->Release();
1511    
1512            LeaveCriticalSection(&m_mft_lock);
1513            return hr;
1514    }
1515    
1516    HRESULT CXvidDecoder::MFTSetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags)
1517    {
1518            DPRINTF("(MFT)SetInputType");
1519    
1520            if (dwInputStreamID != 0)
1521                    return MF_E_INVALIDSTREAMNUMBER;
1522    
1523            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1524                    return E_INVALIDARG;
1525    
1526            EnterCriticalSection(&m_mft_lock);
1527    
1528            HRESULT hr = S_OK;
1529    
1530            /* Actually set the type or just test it? */
1531            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1532    
1533            /* If we have samples pending the type can't be changed right now */
1534            if (HasPendingOutput())
1535                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1536    
1537            if (SUCCEEDED(hr)) {
1538            if (pType) { // /* Check the type */
1539                hr = OnCheckInputType(pType);
1540            }
1541            }
1542    
1543            if (SUCCEEDED(hr)) {
1544                    if (bReallySet) { /* Set the type if needed */
1545                            hr = OnSetInputType(pType);
1546                    }
1547            }
1548    
1549            LeaveCriticalSection(&m_mft_lock);
1550            return hr;
1551    }
1552    
1553    HRESULT CXvidDecoder::MFTSetOutputType(DWORD dwOutputStreamID, IMFMediaType *pType, DWORD dwFlags)
1554    {
1555            DPRINTF("(MFT)SetOutputType");
1556    
1557            if (dwOutputStreamID != 0)
1558                    return MF_E_INVALIDSTREAMNUMBER;
1559    
1560            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1561                    return E_INVALIDARG;
1562    
1563            HRESULT hr = S_OK;
1564    
1565            EnterCriticalSection(&m_mft_lock);
1566    
1567            /* Actually set the type or just test it? */
1568            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1569    
1570            /* If we have samples pending the type can't be changed right now */
1571            if (HasPendingOutput())
1572                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1573    
1574            if (SUCCEEDED(hr)) {
1575                    if (pType) { /* Check the type */
1576                            AM_MEDIA_TYPE *am;
1577                            hr = MFCreateAMMediaTypeFromMFMediaType(pType, GUID_NULL, &am);
1578    
1579                            if (SUCCEEDED(hr)) {
1580                                    if (FAILED(ChangeColorspace(am->subtype, am->formattype, am->pbFormat))) {
1581                                            DPRINTF("(MFT)InternalCheckOutputType (MF_E_INVALIDTYPE)");
1582                                            return MF_E_INVALIDTYPE;
1583                                    }
1584    
1585                            CoTaskMemFree(am->pbFormat);
1586                            CoTaskMemFree(am);
1587                            }
1588                    }
1589            }
1590    
1591            if (SUCCEEDED(hr)) {
1592                    if (bReallySet) { /* Set the type if needed */
1593                            hr = OnSetOutputType(pType);
1594                    }
1595            }
1596    #ifdef XVID_USE_TRAYICON
1597            if (SUCCEEDED(hr) && Tray_Icon == 0) /* Create message passing window */
1598            {
1599                    WNDCLASSEX wc;
1600    
1601                    wc.cbSize = sizeof(WNDCLASSEX);
1602                    wc.lpfnWndProc = msg_proc;
1603                    wc.style = CS_HREDRAW | CS_VREDRAW;
1604                    wc.cbWndExtra = 0;
1605                    wc.cbClsExtra = 0;
1606                    wc.hInstance = (HINSTANCE) g_xvid_hInst;
1607                    wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH);
1608                    wc.lpszMenuName = NULL;
1609                    wc.lpszClassName = "XVID_MSG_WINDOW";
1610                    wc.hIcon = NULL;
1611                    wc.hIconSm = NULL;
1612                    wc.hCursor = NULL;
1613                    RegisterClassEx(&wc);
1614    
1615                    MSG_hwnd = CreateWindowEx(0, "XVID_MSG_WINDOW", NULL, 0, CW_USEDEFAULT,
1616                                      CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE) g_xvid_hInst, NULL);
1617    
1618                    /* display the tray icon */
1619                    NOTIFYICONDATA nid;
1620                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
1621    
1622                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
1623                    nid.hWnd = MSG_hwnd;
1624                    nid.uID = 1456;
1625                    nid.uCallbackMessage = WM_ICONMESSAGE;
1626                    nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
1627                    strcpy_s(nid.szTip, 19, "Xvid Video Decoder");
1628                    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
1629    
1630                    Shell_NotifyIcon(NIM_ADD, &nid);
1631    
1632                    DestroyIcon(nid.hIcon);
1633                    Tray_Icon = 1;
1634            }
1635    #endif
1636    
1637            LeaveCriticalSection(&m_mft_lock);
1638            return hr;
1639    }
1640    
1641    HRESULT CXvidDecoder::MFTGetInputCurrentType(DWORD dwInputStreamID, IMFMediaType **ppType)
1642    {
1643            DPRINTF("(MFT)GetInputCurrentType");
1644    
1645            if (ppType == NULL)
1646                    return E_POINTER;
1647    
1648            if (dwInputStreamID != 0)
1649                    return MF_E_INVALIDSTREAMNUMBER;
1650    
1651            EnterCriticalSection(&m_mft_lock);
1652    
1653            HRESULT hr = S_OK;
1654    
1655            if (!m_pInputType)
1656                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1657    
1658            if (SUCCEEDED(hr)) {
1659                    *ppType = m_pInputType;
1660                    (*ppType)->AddRef();
1661            }
1662    
1663            LeaveCriticalSection(&m_mft_lock);
1664            return hr;
1665    }
1666    
1667    HRESULT CXvidDecoder::MFTGetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType)
1668    {
1669            DPRINTF("(MFT)GetOutputCurrentType");
1670    
1671            if (ppType == NULL)
1672                    return E_POINTER;
1673    
1674            if (dwOutputStreamID != 0)
1675                    return MF_E_INVALIDSTREAMNUMBER;
1676    
1677            EnterCriticalSection(&m_mft_lock);
1678    
1679            HRESULT hr = S_OK;
1680    
1681            if (!m_pOutputType)
1682                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1683    
1684            if (SUCCEEDED(hr)) {
1685                    *ppType = m_pOutputType;
1686                    (*ppType)->AddRef();
1687            }
1688    
1689            LeaveCriticalSection(&m_mft_lock);
1690            return hr;
1691    }
1692    
1693    HRESULT CXvidDecoder::MFTGetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags)
1694    {
1695            DPRINTF("(MFT)GetInputStatus");
1696    
1697            if (pdwFlags == NULL)
1698                    return E_POINTER;
1699    
1700            if (dwInputStreamID != 0)
1701                    return MF_E_INVALIDSTREAMNUMBER;
1702    
1703            EnterCriticalSection(&m_mft_lock);
1704    
1705            /* If there's pending output sampels we don't accept new
1706               input data until ProcessOutput() or Flush() was called */
1707            if (!HasPendingOutput()) {
1708                    *pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
1709            }
1710            else {
1711                    *pdwFlags = 0;
1712            }
1713    
1714            LeaveCriticalSection(&m_mft_lock);
1715    
1716            return S_OK;
1717    }
1718    
1719    HRESULT CXvidDecoder::MFTGetOutputStatus(DWORD *pdwFlags)
1720    {
1721            DPRINTF("(MFT)GetOutputStatus");
1722    
1723            if (pdwFlags == NULL)
1724                    return E_POINTER;
1725    
1726            EnterCriticalSection(&m_mft_lock);
1727    
1728            /* We can render an output sample only after we
1729               have decoded one */
1730            if (HasPendingOutput()) {
1731                    *pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
1732            }
1733            else {
1734                    *pdwFlags = 0;
1735            }
1736    
1737            LeaveCriticalSection(&m_mft_lock);
1738    
1739            return S_OK;
1740    }
1741    
1742    HRESULT CXvidDecoder::MFTSetOutputBounds(LONGLONG hnsLowerBound, LONGLONG hnsUpperBound)
1743    {
1744            DPRINTF("(MFT)SetOutputBounds");
1745            return E_NOTIMPL;
1746    }
1747    
1748    HRESULT CXvidDecoder::MFTProcessEvent(DWORD dwInputStreamID, IMFMediaEvent *pEvent)
1749    {
1750            DPRINTF("(MFT)ProcessEvent");
1751            return E_NOTIMPL; /* We don't handle any stream events */
1752    }
1753    
1754    HRESULT CXvidDecoder::MFTProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
1755    {
1756            DPRINTF("(MFT)ProcessMessage");
1757            HRESULT hr = S_OK;
1758    
1759            EnterCriticalSection(&m_mft_lock);
1760    
1761            switch (eMessage)
1762            {
1763            case MFT_MESSAGE_COMMAND_FLUSH:
1764                    if (m_create.handle != NULL) {
1765                            DPRINTF("(MFT)CommandFlush");
1766    
1767                            xvid_dec_stats_t stats;
1768                            int used_bytes;
1769    
1770                            memset(&stats, 0, sizeof(stats));
1771                            stats.version = XVID_VERSION;
1772    
1773                            int csp = m_frame.output.csp;
1774    
1775                            m_frame.output.csp = XVID_CSP_INTERNAL;
1776                            m_frame.bitstream = NULL;
1777                            m_frame.length = -1;
1778                            m_frame.general = XVID_LOWDELAY;
1779    
1780                            do {
1781                                    used_bytes = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1782                            } while(used_bytes>=0 && stats.type <= 0);
1783    
1784                            m_frame.output.csp = csp;
1785                            m_frame.output.plane[1] = NULL; /* Don't display flushed samples */
1786    
1787                            //m_timestamp = INVALID_TIME;
1788                            //m_timelength = INVALID_TIME;
1789                            //m_rtFrame = 0;
1790            }
1791        break;
1792    
1793            case MFT_MESSAGE_COMMAND_DRAIN:
1794                    m_discont = 1; /* Set discontinuity flag */
1795                    m_rtFrame = 0;
1796                    break;
1797    
1798            case MFT_MESSAGE_SET_D3D_MANAGER:
1799                    hr = E_NOTIMPL;
1800                    break;
1801    
1802            case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
1803            case MFT_MESSAGE_NOTIFY_END_STREAMING:
1804                    break;
1805    
1806            case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
1807            case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
1808                    break;
1809            }
1810    
1811            LeaveCriticalSection(&m_mft_lock);
1812    
1813            return hr;
1814    }
1815    
1816    HRESULT CXvidDecoder::MFTProcessInput(DWORD dwInputStreamID, IMFSample *pSample, DWORD dwFlags)
1817    {
1818            DPRINTF("(MFT)ProcessInput");
1819    
1820            if (pSample == NULL)
1821                    return E_POINTER;
1822    
1823            if (dwInputStreamID != 0)
1824                    return MF_E_INVALIDSTREAMNUMBER;
1825    
1826            if (dwFlags != 0)
1827                    return E_INVALIDARG;
1828    
1829            if (!m_pInputType || !m_pOutputType) {
1830                    return MF_E_NOTACCEPTING;   /* Must have set input and output types */
1831            }
1832            else if (HasPendingOutput()) {
1833                    return MF_E_NOTACCEPTING;   /* We still have output samples to render */
1834            }
1835    
1836            xvid_dec_stats_t stats;
1837            int length;
1838    
1839            memset(&stats, 0, sizeof(stats));
1840            stats.version = XVID_VERSION;
1841    
1842            if (m_create.handle == NULL)
1843            {
1844                    if (xvid_decore_func == NULL)
1845                            return E_FAIL;
1846                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
1847                    {
1848                            DPRINTF("*** XVID_DEC_CREATE error");
1849                            return E_FAIL;
1850                    }
1851            }
1852    
1853            EnterCriticalSection(&m_mft_lock);
1854    
1855            HRESULT hr = S_OK;
1856            IMFMediaBuffer *pBuffer;
1857    
1858            if (SUCCEEDED(hr)) {
1859                    hr = pSample->ConvertToContiguousBuffer(&pBuffer);
1860            }
1861    
1862            if (SUCCEEDED(hr)) {
1863                    hr = pBuffer->Lock((BYTE**)&m_frame.bitstream, NULL, (DWORD *)&m_frame.length);
1864            }
1865    
1866            m_frame.general = XVID_LOWDELAY;
1867    
1868            if (m_discont == 1) {
1869                    m_frame.general |= XVID_DISCONTINUITY;
1870                    m_discont = 0;
1871            }
1872    
1873            if (g_config.nDeblock_Y)
1874                    m_frame.general |= XVID_DEBLOCKY;
1875    
1876            if (g_config.nDeblock_UV)
1877                    m_frame.general |= XVID_DEBLOCKUV;
1878    
1879            if (g_config.nDering_Y)
1880                    m_frame.general |= XVID_DERINGY;
1881    
1882            if (g_config.nDering_UV)
1883                    m_frame.general |= XVID_DERINGUV;
1884    
1885            if (g_config.nFilmEffect)
1886                    m_frame.general |= XVID_FILMEFFECT;
1887    
1888            m_frame.brightness = g_config.nBrightness;
1889    
1890            m_frame.output.csp &= ~XVID_CSP_VFLIP;
1891            m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0);
1892    
1893            int csp = m_frame.output.csp;
1894            m_frame.output.csp = XVID_CSP_INTERNAL;
1895    
1896        // Paranoid check.
1897            if (xvid_decore_func == NULL) {
1898                    hr = E_FAIL;
1899                    goto END_LOOP;
1900            }
1901    
1902    repeat :
1903            length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1904    
1905            if (length == XVID_ERR_MEMORY) {
1906                    hr = E_FAIL;
1907                    goto END_LOOP;
1908            }
1909            else if (length < 0)
1910            {
1911                    DPRINTF("*** XVID_DEC_DECODE");
1912                    goto END_LOOP;
1913            }
1914    
1915            if (stats.type == XVID_TYPE_NOTHING && length > 0) {
1916                    DPRINTF(" B-Frame decoder lag");
1917                    m_frame.output.plane[1] = NULL;
1918                    goto END_LOOP;
1919            }
1920    
1921            if (stats.type == XVID_TYPE_VOL)
1922            {
1923                    if (stats.data.vol.width != m_create.width ||
1924                            stats.data.vol.height != m_create.height)
1925                    {
1926                            DPRINTF("TODO: auto-resize");
1927                            m_frame.output.plane[1] = NULL;
1928                            hr = E_FAIL;
1929                    }
1930    
1931                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) { /* auto */
1932                            int par_x, par_y;
1933                            if (stats.data.vol.par == XVID_PAR_EXT) {
1934                                    par_x = stats.data.vol.par_width;
1935                                    par_y = stats.data.vol.par_height;
1936                            } else {
1937                                    par_x = PARS[stats.data.vol.par-1][0];
1938                                    par_y = PARS[stats.data.vol.par-1][1];
1939                            }
1940    
1941                            ar_x = par_x * stats.data.vol.width;
1942                            ar_y = par_y * stats.data.vol.height;
1943                    }
1944    
1945                    m_frame.bitstream = (BYTE*)m_frame.bitstream + length;
1946                    m_frame.length -= length;
1947                    goto repeat;
1948            }
1949    
1950    END_LOOP:
1951            m_frame.output.csp = csp;
1952    
1953            if (pBuffer) {
1954                    pBuffer->Unlock();
1955                    pBuffer->Release();
1956            }
1957    
1958            if (SUCCEEDED(hr)) {
1959                    /* Try to get a timestamp */
1960                    if (FAILED(pSample->GetSampleTime(&m_timestamp)))
1961                            m_timestamp = INVALID_TIME;
1962    
1963                    if (FAILED(pSample->GetSampleDuration(&m_timelength))) {
1964                            m_timelength = INVALID_TIME;
1965                    }
1966                    if (m_timestamp != INVALID_TIME && stats.type == XVID_TYPE_IVOP) {
1967                            m_rtFrame = m_timestamp;
1968                    }
1969            }
1970    
1971            LeaveCriticalSection(&m_mft_lock);
1972    
1973            return hr;
1974    }
1975    
1976    HRESULT CXvidDecoder::MFTProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus)
1977    {
1978            DPRINTF("(MFT)ProcessOutput");
1979    
1980            /* Preroll in MFT ??
1981               Flags ?? -> TODO... */
1982            if (dwFlags != 0)
1983                    return E_INVALIDARG;
1984    
1985            if (pOutputSamples == NULL || pdwStatus == NULL)
1986                    return E_POINTER;
1987    
1988            if (cOutputBufferCount != 1) /* Must be exactly one output buffer */
1989                    return E_INVALIDARG;
1990    
1991            if (pOutputSamples[0].pSample == NULL) /* Must have a sample */
1992                    return E_INVALIDARG;
1993    
1994            if (!HasPendingOutput()) { /* If there's no sample we need to decode one first */
1995                    return MF_E_TRANSFORM_NEED_MORE_INPUT;
1996            }
1997    
1998            EnterCriticalSection(&m_mft_lock);
1999    
2000            HRESULT hr = S_OK;
2001    
2002            BYTE *Dst = NULL;
2003            DWORD buffer_size;
2004    
2005            IMFMediaBuffer *pOutput = NULL;
2006    
2007            if (SUCCEEDED(hr)) {
2008                    hr = pOutputSamples[0].pSample->GetBufferByIndex(0, &pOutput); /* Get output buffer */
2009            }
2010    
2011            if (SUCCEEDED(hr)) {
2012                    hr = pOutput->GetMaxLength(&buffer_size);
2013            }
2014    
2015            if (SUCCEEDED(hr))
2016                    hr = pOutput->Lock(&Dst, NULL, NULL);
2017    
2018            if (SUCCEEDED(hr)) {
2019                    xvid_gbl_convert_t convert;
2020    
2021                    memset(&convert, 0, sizeof(convert));
2022                    convert.version = XVID_VERSION;
2023    
2024                    convert.input.csp = XVID_CSP_INTERNAL;
2025                    convert.input.plane[0] = m_frame.output.plane[0];
2026                    convert.input.plane[1] = m_frame.output.plane[1];
2027                    convert.input.plane[2] = m_frame.output.plane[2];
2028                    convert.input.stride[0] = m_frame.output.stride[0];
2029                    convert.input.stride[1] = m_frame.output.stride[1];
2030                    convert.input.stride[2] = m_frame.output.stride[2];
2031    
2032                    convert.output.csp = m_frame.output.csp;
2033                    convert.output.plane[0] = Dst;
2034                    convert.output.stride[0] = out_stride;
2035    
2036                    convert.width = m_create.width;
2037                    convert.height = m_create.height;
2038                    convert.interlacing = 0;
2039    
2040                    if (m_frame.output.plane[1] != NULL && Dst != NULL && xvid_global_func != NULL)
2041                            if (xvid_global_func(0, XVID_GBL_CONVERT, &convert, NULL) < 0) /* CSP convert into output buffer */
2042                                    hr = E_FAIL;
2043    
2044                    m_frame.output.plane[1] = NULL;
2045            }
2046    
2047            *pdwStatus = 0;
2048    
2049            if (SUCCEEDED(hr)) {
2050                    if (SUCCEEDED(hr))
2051                            hr = pOutputSamples[0].pSample->SetUINT32(MFSampleExtension_CleanPoint, TRUE); // key frame
2052    
2053                    if (SUCCEEDED(hr)) { /* Set timestamp of output sample */
2054                            if (m_timestamp != INVALID_TIME)
2055                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_timestamp);
2056                            else
2057                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_rtFrame);
2058    
2059                            if (m_timelength != INVALID_TIME)
2060                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_timelength);
2061                            else
2062                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_duration);
2063    
2064                            m_rtFrame += m_duration;
2065                    }
2066    
2067                    if (SUCCEEDED(hr))
2068                            hr = pOutput->SetCurrentLength(m_create.width * abs(m_create.height) * 4); // XXX
2069            }
2070    
2071            if (pOutput) {
2072                    pOutput->Unlock();
2073                    pOutput->Release();
2074            }
2075    
2076            LeaveCriticalSection(&m_mft_lock);
2077    
2078            return hr;
2079    }
2080    
2081    HRESULT CXvidDecoder::OnCheckInputType(IMFMediaType *pmt)
2082    {
2083            DPRINTF("(MFT)CheckInputType");
2084    
2085            HRESULT hr = S_OK;
2086    
2087            /*  Check if input type is already set. Reject any type that is not identical */
2088            if (m_pInputType) {
2089                    DWORD dwFlags = 0;
2090                    if (S_OK == m_pInputType->IsEqual(pmt, &dwFlags)) {
2091                            return S_OK;
2092                    }
2093                    else {
2094                            return MF_E_INVALIDTYPE;
2095                    }
2096            }
2097    
2098            GUID majortype = {0}, subtype = {0};
2099            UINT32 width = 0, height = 0;
2100    
2101            hr = pmt->GetMajorType(&majortype);
2102    
2103            if (SUCCEEDED(hr)) {
2104                    if (majortype != MFMediaType_Video) { /* Must be Video */
2105                            hr = MF_E_INVALIDTYPE;
2106                    }
2107            }
2108    
2109            if (m_hdll == NULL) {
2110                    HRESULT hr = OpenLib();
2111    
2112                    if (FAILED(hr) || (m_hdll == NULL)) // Paranoid checks.
2113                            hr = MF_E_INVALIDTYPE;
2114            }
2115    
2116            if (SUCCEEDED(hr)) {
2117                    hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &width, &height);
2118            }
2119    
2120            /* Check the frame size */
2121            if (SUCCEEDED(hr)) {
2122                    if (width > 4096 || height > 4096) {
2123                            hr = MF_E_INVALIDTYPE;
2124                    }
2125            }
2126            m_create.width = width;
2127            m_create.height = height;
2128    
2129            if (SUCCEEDED(hr)) {
2130                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
2131                            hr = MFGetAttributeRatio(pmt, MF_MT_PIXEL_ASPECT_RATIO, (UINT32*)&ar_x, (UINT32*)&ar_y);
2132                    }
2133            }
2134    
2135            /* TODO1: Make sure there really is a frame rate after all!
2136               TODO2: Use the framerate for something! */
2137            MFRatio fps = {0};
2138            if (SUCCEEDED(hr)) {
2139                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&fps.Numerator, (UINT32*)&fps.Denominator);
2140            }
2141    
2142            if (SUCCEEDED(hr)) {
2143                    hr = pmt->GetGUID(MF_MT_SUBTYPE, &subtype);
2144            }
2145    
2146            if (subtype == CLSID_MP4V || subtype == CLSID_MP4V_UC) {
2147                    if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
2148                            CloseLib();
2149                            hr = MF_E_INVALIDTYPE;
2150                    }
2151                    else m_create.fourcc = FOURCC_MP4V;
2152            }
2153            else if (subtype == CLSID_DIVX || subtype == CLSID_DIVX_UC) {
2154                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2155                            CloseLib();
2156                            hr = MF_E_INVALIDTYPE;
2157                    }
2158                    else m_create.fourcc = FOURCC_DIVX;
2159            }
2160            else if (subtype == CLSID_DX50 || subtype == CLSID_DX50_UC) {
2161                    if (!(g_config.supported_4cc & SUPPORT_DX50)) {
2162                            CloseLib();
2163                            hr = MF_E_INVALIDTYPE;
2164                    }
2165                    else m_create.fourcc = FOURCC_DX50;
2166            }
2167            else if (subtype == CLSID_XVID || subtype == CLSID_XVID_UC) {
2168                    m_create.fourcc = FOURCC_XVID;
2169            }
2170            else {
2171                    DPRINTF("Unknown subtype!");
2172                    CloseLib();
2173                    hr = MF_E_INVALIDTYPE;
2174            }
2175    
2176            /* haali media splitter reports VOL information in the format header */
2177            if (SUCCEEDED(hr))
2178            {
2179                    UINT32 cbSeqHeader = 0;
2180    
2181                    (void)pmt->GetBlobSize(MF_MT_MPEG_SEQUENCE_HEADER, &cbSeqHeader);
2182    
2183                    if (cbSeqHeader>0) {
2184                            xvid_dec_stats_t stats;
2185                            memset(&stats, 0, sizeof(stats));
2186                            stats.version = XVID_VERSION;
2187    
2188                            if (m_create.handle == NULL) {
2189                                    if (xvid_decore_func == NULL)
2190                                            hr = E_FAIL;
2191                                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
2192                                            DPRINTF("*** XVID_DEC_CREATE error");
2193                                            hr = E_FAIL;
2194                                    }
2195                            }
2196    
2197                            if (SUCCEEDED(hr)) {
2198                                    (void)pmt->GetAllocatedBlob(MF_MT_MPEG_SEQUENCE_HEADER, (UINT8 **)&m_frame.bitstream, (UINT32 *)&m_frame.length);
2199                                    m_frame.general = 0;
2200                                    m_frame.output.csp = XVID_CSP_NULL;
2201    
2202                                    int ret = 0;
2203                                    if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
2204                                            /* honour video dimensions reported in VOL header */
2205                                            if (stats.type == XVID_TYPE_VOL) {
2206                                                    m_create.width = stats.data.vol.width;
2207                                                    m_create.height = stats.data.vol.height;
2208                                            }
2209                                    }
2210    
2211                                    if (ret == XVID_ERR_MEMORY) hr = E_FAIL;
2212                                    CoTaskMemFree(m_frame.bitstream);
2213                            }
2214                    }
2215            }
2216    
2217            return hr;
2218    }
2219    
2220    HRESULT CXvidDecoder::OnSetInputType(IMFMediaType *pmt)
2221    {
2222            HRESULT hr = S_OK;
2223            UINT32 w, h;
2224    
2225            if (m_pInputType) m_pInputType->Release();
2226    
2227            hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &w, &h);
2228            m_create.width = w; m_create.height = h;
2229    
2230            if (SUCCEEDED(hr))
2231                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&m_frameRate.Numerator, (UINT32*)&m_frameRate.Denominator);
2232    
2233            if (SUCCEEDED(hr)) { /* Store frame duration, derived from the frame rate */
2234                    hr = MFFrameRateToAverageTimePerFrame(m_frameRate.Numerator, m_frameRate.Denominator, &m_duration);
2235            }
2236    
2237            if (SUCCEEDED(hr)) {
2238                    m_pInputType = pmt;
2239                    m_pInputType->AddRef();
2240            }
2241    
2242            return hr;
2243    }
2244    
2245    HRESULT CXvidDecoder::OnSetOutputType(IMFMediaType *pmt)
2246    {
2247            if (m_pOutputType) m_pOutputType->Release();
2248    
2249            m_pOutputType = pmt;
2250            m_pOutputType->AddRef();
2251    
2252            return S_OK;
2253    }
2254    
2255    #endif /* XVID_USE_MFT */

Legend:
Removed from v.1502  
changed lines
  Added in v.1916

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