[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 1633, Thu Sep 15 10:52:28 2005 UTC revision 2024, Thu Jul 7 14:59:39 2011 UTC
# Line 1  Line 1 
1  /*****************************************************************************  /*****************************************************************************
2   *   *
3   *  XVID MPEG-4 VIDEO CODEC   *  XVID MPEG-4 VIDEO CODEC
4   *  - XviD Decoder part of the DShow Filter  -   *  - Xvid Decoder part of the DShow Filter  -
5   *   *
6   *  Copyright(C) 2002-2004 Peter Ross <pross@xvid.org>   *  Copyright(C) 2002-2011 Peter Ross <pross@xvid.org>
7     *               2003-2011 Michael Militzer <michael@xvid.org>
8   *   *
9   *  This program is free software ; you can redistribute it and/or modify   *  This program is free software ; you can redistribute it and/or modify
10   *  it under the terms of the GNU General Public License as published by   *  it under the terms of the GNU General Public License as published by
# Line 19  Line 20 
20   *  along with this program ; if not, write to the Free Software   *  along with this program ; if not, write to the Free Software
21   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22   *   *
23   * $Id: CXvidDecoder.cpp,v 1.15 2005-09-15 10:52:28 suxen_drol 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 43  Line 36 
36          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Debug          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Debug
37  */  */
38    
39    #ifdef ENABLE_MFT
40    #define XVID_USE_MFT
41    #endif
42    
43  #include <windows.h>  #include <windows.h>
44    
# Line 55  Line 50 
50  #endif  #endif
51  #include <dvdmedia.h>   // VIDEOINFOHEADER2  #include <dvdmedia.h>   // VIDEOINFOHEADER2
52    
53  #include <xvid.h>               // XviD API  #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>
62    
63    #include <xvid.h>               // Xvid API
64    
65    #include "resource.h"
66    
67  #include "IXvidDecoder.h"  #include "IXvidDecoder.h"
68  #include "CXvidDecoder.h"  #include "CXvidDecoder.h"
# Line 81  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 },
109  };  };
110    
111  const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] =  const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] =
# Line 121  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 148  Line 172 
172    
173  };  };
174    
   
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    
178    extern HINSTANCE g_xvid_hInst;
179    
180    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 );
183    
184    LRESULT CALLBACK msg_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
185    {
186            switch ( uMsg )
187            {
188            case WM_ICONMESSAGE:
189                    switch(lParam)
190                    {
191                    case WM_LBUTTONDBLCLK:
192                            if (!GUI_Page) {
193                                    GUI_Page = 1;
194                                    Configure(hwnd, g_xvid_hInst, "", 1);
195                                    GUI_Page = 0;
196                            }
197                            break;
198                    default:
199                            return DefWindowProc(hwnd, uMsg, wParam, lParam);
200                    };
201                    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:
214                    return DefWindowProc(hwnd, uMsg, wParam, lParam);
215            }
216    
217            return TRUE; /* ok */
218    }
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 194  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 201  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    #if defined(XVID_USE_MFT)
321            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
330    
331      LoadRegistryInfo();      LoadRegistryInfo();
332    
333      *phr = OpenLib();      *phr = OpenLib();
334    
335            {
336          TCHAR lpFilename[MAX_PATH];
337              int sLen = GetModuleFileName(NULL, lpFilename, MAX_PATH);
338    #ifdef _UNICODE
339              if ((sLen >= 11) && (_wcsnicmp(&(lpFilename[sLen - 11]), TEXT("dllhost.exe"), 11) == 0)) {
340    #else
341              if ((sLen >= 11) && (_strnicmp(&(lpFilename[sLen - 11]), TEXT("dllhost.exe"), 11) == 0)) {
342    #endif
343                if (Tray_Icon == 0) Tray_Icon = -1; // create no tray icon upon thumbnail generation
344              }
345              else
346            if (Tray_Icon == -1) Tray_Icon = 0; // can show tray icon
347            }
348    
349  }  }
350    
351  HRESULT CXvidDecoder::OpenLib()  HRESULT CXvidDecoder::OpenLib()
# Line 226  Line 358 
358          xvid_gbl_init_t init;          xvid_gbl_init_t init;
359          memset(&init, 0, sizeof(init));          memset(&init, 0, sizeof(init));
360          init.version = XVID_VERSION;          init.version = XVID_VERSION;
361            init.cpu_flags = g_config.cpu;
362    
363            xvid_gbl_info_t info;
364            memset(&info, 0, sizeof(info));
365            info.version = XVID_VERSION;
366    
367          m_hdll = LoadLibrary(XVID_DLL_NAME);          m_hdll = LoadLibrary(XVID_DLL_NAME);
368          if (m_hdll == NULL) {          if (m_hdll == NULL) {
369                  DPRINTF("dll load failed");                  DPRINTF("dll load failed");
370                  MessageBox(0, XVID_DLL_NAME " not found","Error", MB_TOPMOST);                  MessageBox(0, XVID_DLL_NAME TEXT(" not found"), TEXT("Error"), MB_TOPMOST);
371                  return E_FAIL;                  return E_FAIL;
372          }          }
373    
# Line 238  Line 375 
375          if (xvid_global_func == NULL) {          if (xvid_global_func == NULL) {
376          FreeLibrary(m_hdll);          FreeLibrary(m_hdll);
377          m_hdll = NULL;          m_hdll = NULL;
378                  MessageBox(0, "xvid_global() not found", "Error", MB_TOPMOST);                  MessageBox(0, TEXT("xvid_global() not found"), TEXT("Error"), MB_TOPMOST);
379                  return E_FAIL;                  return E_FAIL;
380          }          }
381    
# Line 247  Line 384 
384          xvid_global_func = NULL;          xvid_global_func = NULL;
385          FreeLibrary(m_hdll);          FreeLibrary(m_hdll);
386          m_hdll = NULL;          m_hdll = NULL;
387                  MessageBox(0, "xvid_decore() not found", "Error", MB_TOPMOST);                  MessageBox(0, TEXT("xvid_decore() not found"), TEXT("Error"), MB_TOPMOST);
388                  return E_FAIL;                  return E_FAIL;
389          }          }
390    
# Line 257  Line 394 
394          xvid_decore_func = NULL;          xvid_decore_func = NULL;
395          FreeLibrary(m_hdll);          FreeLibrary(m_hdll);
396          m_hdll = NULL;          m_hdll = NULL;
397                  MessageBox(0, "xvid_global() failed", "Error", MB_TOPMOST);                  MessageBox(0, TEXT("xvid_global() failed"), TEXT("Error"), MB_TOPMOST);
398                    return E_FAIL;
399            }
400    
401            if (xvid_global_func(0, XVID_GBL_INFO, &info, NULL) < 0)
402            {
403            xvid_global_func = NULL;
404            xvid_decore_func = NULL;
405            FreeLibrary(m_hdll);
406            m_hdll = NULL;
407                    MessageBox(0, TEXT("xvid_global() failed"), TEXT("Error"), MB_TOPMOST);
408                  return E_FAIL;                  return E_FAIL;
409          }          }
410    
411          memset(&m_create, 0, sizeof(m_create));          memset(&m_create, 0, sizeof(m_create));
412          m_create.version = XVID_VERSION;          m_create.version = XVID_VERSION;
413          m_create.handle = NULL;          m_create.handle = NULL;
414        /* Decoder threads */
415        if (g_config.cpu & XVID_CPU_FORCE) {
416                    m_create.num_threads = g_config.num_threads;
417            }
418            else {
419            m_create.num_threads = info.num_threads; /* Autodetect */
420                    g_config.num_threads = info.num_threads;
421            }
422    
423          memset(&m_frame, 0, sizeof(m_frame));          memset(&m_frame, 0, sizeof(m_frame));
424          m_frame.version = XVID_VERSION;          m_frame.version = XVID_VERSION;
# Line 351  Line 506 
506  CXvidDecoder::~CXvidDecoder()  CXvidDecoder::~CXvidDecoder()
507  {  {
508      DPRINTF("Destructor");      DPRINTF("Destructor");
509    
510            if (Tray_Icon > 0) { /* Destroy tray icon */
511                    NOTIFYICONDATA nid;
512                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
513    
514                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
515                    nid.hWnd = MSG_hwnd;
516                    nid.uID = 1456;
517    
518                    Shell_NotifyIcon(NIM_DELETE, &nid);
519                    Tray_Icon = 0;
520            }
521    
522            /* Close xvidcore library */
523          CloseLib();          CloseLib();
524    
525    #if defined(XVID_USE_MFT)
526            DeleteCriticalSection(&m_mft_lock);
527    #endif
528  }  }
529    
530    
# Line 395  Line 568 
568                  }                  }
569                  DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);                  DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);
570          }          }
571      else if (*mtIn->FormatType() == FORMAT_MPEG2Video) {
572        MPEG2VIDEOINFO * mpgvi = (MPEG2VIDEOINFO*)mtIn->Format();
573        VIDEOINFOHEADER2 * vih2 = &mpgvi->hdr;
574                    hdr = &vih2->bmiHeader;
575                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
576                            ar_x = vih2->dwPictAspectRatioX;
577                            ar_y = vih2->dwPictAspectRatioY;
578                    }
579                    DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);
580    
581        /* haali media splitter reports VOL information in the format header */
582    
583        if (mpgvi->cbSequenceHeader>0) {
584    
585          xvid_dec_stats_t stats;
586                memset(&stats, 0, sizeof(stats));
587                stats.version = XVID_VERSION;
588    
589                if (m_create.handle == NULL) {
590                        if (xvid_decore_func == NULL)
591                                return E_FAIL;
592                        if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
593              DPRINTF("*** XVID_DEC_CREATE error");
594                                return E_FAIL;
595                        }
596                }
597    
598          m_frame.general = 0;
599          m_frame.bitstream = (void*)mpgvi->dwSequenceHeader;
600          m_frame.length = mpgvi->cbSequenceHeader;
601          m_frame.output.csp = XVID_CSP_NULL;
602    
603          int ret = 0;
604          if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
605            /* honour video dimensions reported in VOL header */
606                  if (stats.type == XVID_TYPE_VOL) {
607              hdr->biWidth = stats.data.vol.width;
608              hdr->biHeight = stats.data.vol.height;
609                      }
610              }
611          if (ret == XVID_ERR_MEMORY) return E_FAIL;
612            }
613      }
614          else          else
615          {          {
616                  DPRINTF("Error: Unknown FormatType");                  DPRINTF("Error: Unknown FormatType");
617                  CloseLib();                  CloseLib();
618                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
619          }          }
   
620          if (hdr->biHeight < 0)          if (hdr->biHeight < 0)
621          {          {
622                  DPRINTF("colorspace: inverted input format not supported");                  DPRINTF("colorspace: inverted input format not supported");
# Line 412  Line 627 
627    
628          switch(hdr->biCompression)          switch(hdr->biCompression)
629          {          {
630            case FOURCC_mp4v :
631          case FOURCC_MP4V:          case FOURCC_MP4V:
632            case FOURCC_lmp4 :
633            case FOURCC_LMP4 :
634            case FOURCC_rmp4 :
635            case FOURCC_RMP4 :
636            case FOURCC_smp4 :
637            case FOURCC_SMP4 :
638            case FOURCC_hdx4 :
639            case FOURCC_HDX4 :
640                  if (!(g_config.supported_4cc & SUPPORT_MP4V)) {                  if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
641                          CloseLib();                          CloseLib();
642                          return VFW_E_TYPE_NOT_ACCEPTED;                          return VFW_E_TYPE_NOT_ACCEPTED;
643                  }                  }
644                  break;                  break;
645            case FOURCC_divx :
646          case FOURCC_DIVX :          case FOURCC_DIVX :
647            case FOURCC_dx50 :
648            case FOURCC_DX50 :
649                  if (!(g_config.supported_4cc & SUPPORT_DIVX)) {                  if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
650                          CloseLib();                          CloseLib();
651                          return VFW_E_TYPE_NOT_ACCEPTED;                          return VFW_E_TYPE_NOT_ACCEPTED;
652                  }                  }
653                  break;                  break;
654          case FOURCC_DX50 :          case FOURCC_3ivx :
655                  if (!(g_config.supported_4cc & SUPPORT_DX50)) {          case FOURCC_3IVX :
656            case FOURCC_3iv0 :
657            case FOURCC_3IV0 :
658            case FOURCC_3iv1 :
659            case FOURCC_3IV1 :
660            case FOURCC_3iv2 :
661            case FOURCC_3IV2 :
662                    if (!(g_config.supported_4cc & SUPPORT_3IVX)) {
663                          CloseLib();                          CloseLib();
664                          return VFW_E_TYPE_NOT_ACCEPTED;                          return VFW_E_TYPE_NOT_ACCEPTED;
665                  }                  }
666            case FOURCC_xvid :
667          case FOURCC_XVID :          case FOURCC_XVID :
668                  break;                  break;
669    
# Line 444  Line 678 
678                  CloseLib();                  CloseLib();
679                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
680          }          }
681    
682            m_create.fourcc = hdr->biCompression;
683    
684          return S_OK;          return S_OK;
685  }  }
686    
# Line 587  Line 824 
824  /* (internal function) change colorspace */  /* (internal function) change colorspace */
825  #define CALC_BI_STRIDE(width,bitcount)  ((((width * bitcount) + 31) & ~31) >> 3)  #define CALC_BI_STRIDE(width,bitcount)  ((((width * bitcount) + 31) & ~31) >> 3)
826    
827  HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format)  HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format, int noflip)
828  {  {
829          DWORD biWidth;          DWORD biWidth;
830    
# Line 595  Line 832 
832          {          {
833                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;
834                  biWidth = vih->bmiHeader.biWidth;                  biWidth = vih->bmiHeader.biWidth;
835                  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);
836                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
837          }          }
838          else if (formattype == FORMAT_VideoInfo2)          else if (formattype == FORMAT_VideoInfo2)
839          {          {
840                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;
841                  biWidth = vih2->bmiHeader.biWidth;                  biWidth = vih2->bmiHeader.biWidth;
842                  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);
843                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
844          }          }
845          else          else
# Line 610  Line 847 
847                  return S_FALSE;                  return S_FALSE;
848          }          }
849    
850            if (noflip) rgb_flip = 0;
851    
852          if (subtype == CLSID_MEDIASUBTYPE_IYUV)          if (subtype == CLSID_MEDIASUBTYPE_IYUV)
853          {          {
854                  DPRINTF("IYUV");                  DPRINTF("IYUV");
855                  rgb_flip = 0;                  rgb_flip = 0;
856                  m_frame.output.csp = XVID_CSP_I420;                  m_frame.output.csp = XVID_CSP_I420;
857                  m_frame.output.stride[0] = CALC_BI_STRIDE(biWidth, 8);  /* planar format fix */                  out_stride = CALC_BI_STRIDE(biWidth, 8);        /* planar format fix */
858          }          }
859          else if (subtype == MEDIASUBTYPE_YV12)          else if (subtype == MEDIASUBTYPE_YV12)
860          {          {
861                  DPRINTF("YV12");                  DPRINTF("YV12");
862                  rgb_flip = 0;                  rgb_flip = 0;
863                  m_frame.output.csp = XVID_CSP_YV12;                  m_frame.output.csp = XVID_CSP_YV12;
864                  m_frame.output.stride[0] = CALC_BI_STRIDE(biWidth, 8);  /* planar format fix */                  out_stride = CALC_BI_STRIDE(biWidth, 8);        /* planar format fix */
865          }          }
866          else if (subtype == MEDIASUBTYPE_YUY2)          else if (subtype == MEDIASUBTYPE_YUY2)
867          {          {
# Line 683  Line 922 
922    
923          if (direction == PINDIR_OUTPUT)          if (direction == PINDIR_OUTPUT)
924          {          {
925                  return ChangeColorspace(*pmt->Subtype(), *pmt->FormatType(), pmt->Format());                  return ChangeColorspace(*pmt->Subtype(), *pmt->FormatType(), pmt->Format(), 0);
926          }          }
927    
928          return S_OK;          return S_OK;
# Line 695  Line 934 
934  HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)  HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
935  {  {
936          DPRINTF("CheckTransform");          DPRINTF("CheckTransform");
937    
938            return S_OK;
939    }
940    
941    /* input/output pin connection complete */
942    
943    HRESULT CXvidDecoder::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin)
944    {
945            DPRINTF("CompleteConnect");
946    
947            if ((direction == PINDIR_OUTPUT) && (Tray_Icon == 0) && (g_config.bTrayIcon != 0))
948            {
949                    WNDCLASSEX wc;
950    
951                    wc.cbSize = sizeof(WNDCLASSEX);
952                    wc.lpfnWndProc = msg_proc;
953                    wc.style = CS_HREDRAW | CS_VREDRAW;
954                    wc.cbWndExtra = 0;
955                    wc.cbClsExtra = 0;
956                    wc.hInstance = (HINSTANCE) g_xvid_hInst;
957                    wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH);
958                    wc.lpszMenuName = NULL;
959                    wc.lpszClassName = TEXT("XVID_MSG_WINDOW");
960                    wc.hIcon = NULL;
961                    wc.hIconSm = NULL;
962                    wc.hCursor = NULL;
963                    RegisterClassEx(&wc);
964    
965                    MSG_hwnd = CreateWindowEx(0, TEXT("XVID_MSG_WINDOW"), NULL, 0, CW_USEDEFAULT,
966                            CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE) g_xvid_hInst, NULL);
967    
968                    /* display the tray icon */
969                    NOTIFYICONDATA nid;
970                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
971    
972                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
973                    nid.hWnd = MSG_hwnd;
974                    nid.uID = 1456;
975                    nid.uCallbackMessage = WM_ICONMESSAGE;
976                    nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
977                    lstrcpy(nid.szTip, TEXT("Xvid Video Decoder"));
978                    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
979    
980                    Shell_NotifyIcon(NIM_ADD, &nid);
981    
982                    DestroyIcon(nid.hIcon);
983                    Tray_Icon = 1;
984            }
985    
986          return S_OK;          return S_OK;
987  }  }
988    
989    /* input/output pin disconnected */
990    HRESULT CXvidDecoder::BreakConnect(PIN_DIRECTION direction)
991    {
992            DPRINTF("BreakConnect");
993    
994            return S_OK;
995    }
996    
997  /* alloc output buffer */  /* alloc output buffer */
998    
# Line 752  Line 1047 
1047                  if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)                  if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
1048                  {                  {
1049              DPRINTF("*** XVID_DEC_CREATE error");              DPRINTF("*** XVID_DEC_CREATE error");
1050                          return S_FALSE;                          return E_FAIL;
1051                  }                  }
1052          }          }
1053    
# Line 762  Line 1057 
1057          {          {
1058                  HRESULT result;                  HRESULT result;
1059    
1060                  result = ChangeColorspace(mtOut->subtype, mtOut->formattype, mtOut->pbFormat);                  result = ChangeColorspace(mtOut->subtype, mtOut->formattype, mtOut->pbFormat, 0);
1061                  DeleteMediaType(mtOut);                  DeleteMediaType(mtOut);
1062    
1063                  if (result != S_OK)                  if (result != S_OK)
# Line 807  Line 1102 
1102    
1103          m_frame.output.csp &= ~XVID_CSP_VFLIP;          m_frame.output.csp &= ~XVID_CSP_VFLIP;
1104          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);
1105            m_frame.output.stride[0] = out_stride;
1106    
1107      // Paranoid check.      // Paranoid check.
1108      if (xvid_decore_func == NULL)      if (xvid_decore_func == NULL)
1109                  return E_FAIL;                  return E_FAIL;
1110    
1111    
   
1112  repeat :  repeat :
1113    
1114          if (pIn->IsPreroll() != S_OK)          if (pIn->IsPreroll() != S_OK)
1115          {          {
1116                  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);
1117    
1118                  if (length < 0)                  if (length == XVID_ERR_MEMORY)
1119                            return E_FAIL;
1120                    else if (length < 0)
1121                  {                  {
1122              DPRINTF("*** XVID_DEC_DECODE");              DPRINTF("*** XVID_DEC_DECODE");
1123                          return S_FALSE;                          return S_FALSE;
# Line 864  Line 1161 
1161                  m_frame.general &= ~XVID_FILMEFFECT;                  m_frame.general &= ~XVID_FILMEFFECT;
1162    
1163                  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);
1164                  if (length < 0)                  if (length == XVID_ERR_MEMORY)
1165                            return E_FAIL;
1166                    else if (length < 0)
1167                  {                  {
1168              DPRINTF("*** XVID_DEC_DECODE");              DPRINTF("*** XVID_DEC_DECODE");
1169                          return S_FALSE;                          return S_FALSE;
# Line 944  Line 1243 
1243          CoTaskMemFree(pPages->pElems);          CoTaskMemFree(pPages->pElems);
1244          return S_OK;          return S_OK;
1245  }  }
1246    
1247    /*===============================================================================
1248    // MFT Interface
1249    //=============================================================================*/
1250    #if defined(XVID_USE_MFT)
1251    #include <limits.h> // _I64_MAX
1252    #define INVALID_TIME  _I64_MAX
1253    
1254    HRESULT CXvidDecoder::MFTGetStreamLimits(DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum)
1255    {
1256            DPRINTF("(MFT)GetStreamLimits");
1257    
1258            if ((pdwInputMinimum == NULL) || (pdwInputMaximum == NULL) || (pdwOutputMinimum == NULL) || (pdwOutputMaximum == NULL))
1259                    return E_POINTER;
1260    
1261            /* Just a fixed number of streams allowed */
1262            *pdwInputMinimum = *pdwInputMaximum = 1;
1263            *pdwOutputMinimum = *pdwOutputMaximum = 1;
1264    
1265            return S_OK;
1266    }
1267    
1268    HRESULT CXvidDecoder::MFTGetStreamCount(DWORD *pcInputStreams, DWORD *pcOutputStreams)
1269    {
1270            DPRINTF("(MFT)GetStreamCount");
1271    
1272            if ((pcInputStreams == NULL) || (pcOutputStreams == NULL))
1273                    return E_POINTER;
1274    
1275            /* We have a fixed number of streams */
1276            *pcInputStreams = 1;
1277            *pcOutputStreams = 1;
1278    
1279            return S_OK;
1280    }
1281    
1282    HRESULT CXvidDecoder::MFTGetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs)
1283    {
1284            DPRINTF("(MFT)GetStreamIDs");
1285            return E_NOTIMPL; /* We have fixed number of streams, so stream ID match stream index */
1286    }
1287    
1288    HRESULT CXvidDecoder::MFTGetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo)
1289    {
1290            DPRINTF("(MFT)GetInputStreamInfo");
1291    
1292            if (pStreamInfo == NULL)
1293                    return E_POINTER;
1294    
1295            if (dwInputStreamID != 0)
1296                    return MF_E_INVALIDSTREAMNUMBER;
1297    
1298            EnterCriticalSection(&m_mft_lock);
1299    
1300            pStreamInfo->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER;
1301            pStreamInfo->hnsMaxLatency = 0;
1302    
1303            pStreamInfo->cbSize = 1; /* Need atleast 1 byte input */
1304            pStreamInfo->cbMaxLookahead = 0;
1305            pStreamInfo->cbAlignment = 1;
1306    
1307            LeaveCriticalSection(&m_mft_lock);
1308            return S_OK;
1309    }
1310    
1311    HRESULT CXvidDecoder::MFTGetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo)
1312    {
1313            DPRINTF("(MFT)GetOutputStreamInfo");
1314    
1315            if (pStreamInfo == NULL)
1316                    return E_POINTER;
1317    
1318            if (dwOutputStreamID != 0)
1319                    return MF_E_INVALIDSTREAMNUMBER;
1320    
1321            EnterCriticalSection(&m_mft_lock);
1322    
1323            pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_DISCARDABLE;
1324    
1325            if (m_pOutputType == NULL) {
1326                    pStreamInfo->cbSize = 0;
1327                    pStreamInfo->cbAlignment = 0;
1328            }
1329            else {
1330                    pStreamInfo->cbSize = m_create.width * abs(m_create.height) * 4; // XXX
1331                    pStreamInfo->cbAlignment = 1;
1332            }
1333    
1334            LeaveCriticalSection(&m_mft_lock);
1335            return S_OK;
1336    }
1337    
1338    HRESULT CXvidDecoder::GetAttributes(IMFAttributes** pAttributes)
1339    {
1340            DPRINTF("(MFT)GetAttributes");
1341            return E_NOTIMPL; /* We don't support any attributes */
1342    }
1343    
1344    HRESULT CXvidDecoder::GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes **ppAttributes)
1345    {
1346            DPRINTF("(MFT)GetInputStreamAttributes");
1347            return E_NOTIMPL; /* We don't support any attributes */
1348    }
1349    
1350    HRESULT CXvidDecoder::GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes **ppAttributes)
1351    {
1352            DPRINTF("(MFT)GetOutputStreamAttributes");
1353            return E_NOTIMPL; /* We don't support any attributes */
1354    }
1355    
1356    HRESULT CXvidDecoder::MFTDeleteInputStream(DWORD dwStreamID)
1357    {
1358            DPRINTF("(MFT)DeleteInputStream");
1359            return E_NOTIMPL; /* We have a fixed number of streams */
1360    }
1361    
1362    HRESULT CXvidDecoder::MFTAddInputStreams(DWORD cStreams, DWORD *adwStreamIDs)
1363    {
1364            DPRINTF("(MFT)AddInputStreams");
1365            return E_NOTIMPL; /* We have a fixed number of streams */
1366    }
1367    
1368    HRESULT CXvidDecoder::MFTGetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1369    {
1370            DPRINTF("(MFT)GetInputAvailableType");
1371    
1372            if (dwInputStreamID != 0)
1373                    return MF_E_INVALIDSTREAMNUMBER;
1374    
1375            DWORD i = 0;
1376            GUID *bs_guid_table[8];
1377    
1378            bs_guid_table[i++] = (GUID *)&CLSID_XVID;
1379            bs_guid_table[i++] = (GUID *)&CLSID_XVID_UC;
1380    
1381            if (g_config.supported_4cc & SUPPORT_3IVX) {
1382                    bs_guid_table[i++] = (GUID *)&CLSID_3IVX;
1383                    bs_guid_table[i++] = (GUID *)&CLSID_3IVX_UC;
1384                    bs_guid_table[i++] = (GUID *)&CLSID_3IV0;
1385                    bs_guid_table[i++] = (GUID *)&CLSID_3IV0_UC;
1386                    bs_guid_table[i++] = (GUID *)&CLSID_3IV1;
1387                    bs_guid_table[i++] = (GUID *)&CLSID_3IV1_UC;
1388                    bs_guid_table[i++] = (GUID *)&CLSID_3IV2;
1389                    bs_guid_table[i++] = (GUID *)&CLSID_3IV2_UC;
1390            }
1391            if (g_config.supported_4cc & SUPPORT_DIVX) {
1392                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX;
1393                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX_UC;
1394                    bs_guid_table[i++] = (GUID *)&CLSID_DX50;
1395                    bs_guid_table[i++] = (GUID *)&CLSID_DX50_UC;
1396            }
1397            if (g_config.supported_4cc & SUPPORT_MP4V) {
1398                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V;
1399                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V_UC;
1400                    bs_guid_table[i++] = (GUID *)&CLSID_LMP4;
1401                    bs_guid_table[i++] = (GUID *)&CLSID_LMP4_UC;
1402                    bs_guid_table[i++] = (GUID *)&CLSID_RMP4;
1403                    bs_guid_table[i++] = (GUID *)&CLSID_RMP4_UC;
1404                    bs_guid_table[i++] = (GUID *)&CLSID_SMP4;
1405                    bs_guid_table[i++] = (GUID *)&CLSID_SMP4_UC;
1406                    bs_guid_table[i++] = (GUID *)&CLSID_HDX4;
1407                    bs_guid_table[i++] = (GUID *)&CLSID_HDX4_UC;
1408            }
1409    
1410            const GUID *subtype;
1411            if (dwTypeIndex < i) {
1412                    subtype = bs_guid_table[dwTypeIndex];
1413            }
1414            else {
1415                    return MF_E_NO_MORE_TYPES;
1416            }
1417    
1418            EnterCriticalSection(&m_mft_lock);
1419    
1420            HRESULT hr = S_OK;
1421    
1422            if (ppType) {
1423                    IMFMediaType *pInputType = NULL;
1424                    hr = MFCreateMediaType(&pInputType);
1425    
1426                    if (SUCCEEDED(hr))
1427                            hr = pInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1428    
1429                    if (SUCCEEDED(hr))
1430                            hr = pInputType->SetGUID(MF_MT_SUBTYPE, *subtype);
1431    
1432                    if (SUCCEEDED(hr)) {
1433                            *ppType = pInputType;
1434                            (*ppType)->AddRef();
1435                    }
1436                    if (pInputType) pInputType->Release();
1437            }
1438    
1439            LeaveCriticalSection(&m_mft_lock);
1440    
1441            return hr;
1442    }
1443    
1444    HRESULT CXvidDecoder::MFTGetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1445    {
1446            DPRINTF("(MFT)GetOutputAvailableType");
1447    
1448            if (ppType == NULL)
1449                    return E_INVALIDARG;
1450    
1451            if (dwOutputStreamID != 0)
1452                    return MF_E_INVALIDSTREAMNUMBER;
1453    
1454            if (dwTypeIndex < 0) return E_INVALIDARG;
1455    
1456            GUID csp;
1457            int bitdepth = 8;
1458            switch(dwTypeIndex)
1459            {
1460            case 0:
1461    if ( USE_YUY2 )
1462    {
1463                    csp = MFVideoFormat_YUY2;
1464                    bitdepth = 4;
1465                    break;
1466    }
1467            case 1 :
1468    if ( USE_UYVY )
1469    {
1470                    csp = MFVideoFormat_UYVY;
1471                    bitdepth = 4;
1472                    break;
1473    }
1474            case 2  :
1475                    if ( USE_IYUV )
1476    {
1477                    csp = MFVideoFormat_IYUV;
1478                    bitdepth = 3;
1479                    break;
1480    }
1481            case 3  :
1482    if ( USE_YV12 )
1483    {
1484                    csp = MFVideoFormat_YV12;
1485                    bitdepth = 3;
1486                    break;
1487    }
1488            case 4 :
1489    if ( USE_RGB32 )
1490    {
1491                    csp = MFVideoFormat_RGB32;
1492                    bitdepth = 8;
1493                    break;
1494    }
1495            case 5 :
1496    if ( USE_RGB24 )
1497    {
1498                    csp = MFVideoFormat_RGB24;
1499                    bitdepth = 6;
1500                    break;
1501    }
1502            case 6 :
1503    if ( USE_RG555 )
1504    {
1505                    csp = MFVideoFormat_RGB555;
1506                    bitdepth = 4;
1507                    break;
1508    }
1509            case 7 :
1510    if ( USE_RG565 )
1511    {
1512                    csp = MFVideoFormat_RGB565;
1513                    bitdepth = 4;
1514                    break;
1515    }
1516            default :
1517                    return MF_E_NO_MORE_TYPES;
1518            }
1519    
1520            if (m_pInputType == NULL)
1521                    return MF_E_TRANSFORM_TYPE_NOT_SET;
1522    
1523            EnterCriticalSection(&m_mft_lock);
1524    
1525            HRESULT hr = S_OK;
1526    
1527            IMFMediaType *pOutputType = NULL;
1528            hr = MFCreateMediaType(&pOutputType);
1529    
1530            if (SUCCEEDED(hr)) {
1531                    hr = pOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1532            }
1533    
1534            if (SUCCEEDED(hr)) {
1535                    hr = pOutputType->SetGUID(MF_MT_SUBTYPE, csp);
1536        }
1537    
1538            if (SUCCEEDED(hr)) {
1539                    hr = pOutputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE);
1540            }
1541    
1542            if (SUCCEEDED(hr)) {
1543                    hr = pOutputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
1544            }
1545    
1546            if (SUCCEEDED(hr)) {
1547                    hr = pOutputType->SetUINT32(MF_MT_SAMPLE_SIZE, (m_create.height * m_create.width * bitdepth)>>1);
1548            }
1549    
1550            if (SUCCEEDED(hr)) {
1551                    hr = MFSetAttributeSize(pOutputType, MF_MT_FRAME_SIZE, m_create.width, m_create.height);
1552            }
1553    
1554            if (SUCCEEDED(hr)) {
1555                    hr = MFSetAttributeRatio(pOutputType, MF_MT_FRAME_RATE, m_frameRate.Numerator, m_frameRate.Denominator);
1556            }
1557    
1558            if (SUCCEEDED(hr)) {
1559                    hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
1560            }
1561    
1562            if (SUCCEEDED(hr)) {
1563                    hr = MFSetAttributeRatio(pOutputType, MF_MT_PIXEL_ASPECT_RATIO, ar_x, ar_y);
1564            }
1565    
1566            if (SUCCEEDED(hr)) {
1567                    *ppType = pOutputType;
1568                    (*ppType)->AddRef();
1569            }
1570    
1571            if (pOutputType) pOutputType->Release();
1572    
1573            LeaveCriticalSection(&m_mft_lock);
1574            return hr;
1575    }
1576    
1577    HRESULT CXvidDecoder::MFTSetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags)
1578    {
1579            DPRINTF("(MFT)SetInputType");
1580    
1581            if (dwInputStreamID != 0)
1582                    return MF_E_INVALIDSTREAMNUMBER;
1583    
1584            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1585                    return E_INVALIDARG;
1586    
1587            EnterCriticalSection(&m_mft_lock);
1588    
1589            HRESULT hr = S_OK;
1590    
1591            /* Actually set the type or just test it? */
1592            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1593    
1594            /* If we have samples pending the type can't be changed right now */
1595            if (HasPendingOutput())
1596                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1597    
1598            if (SUCCEEDED(hr)) {
1599            if (pType) { // /* Check the type */
1600                hr = OnCheckInputType(pType);
1601            }
1602            }
1603    
1604            if (SUCCEEDED(hr)) {
1605                    if (bReallySet) { /* Set the type if needed */
1606                            hr = OnSetInputType(pType);
1607                    }
1608            }
1609    
1610            LeaveCriticalSection(&m_mft_lock);
1611            return hr;
1612    }
1613    
1614    HRESULT CXvidDecoder::MFTSetOutputType(DWORD dwOutputStreamID, IMFMediaType *pType, DWORD dwFlags)
1615    {
1616            DPRINTF("(MFT)SetOutputType");
1617    
1618            if (dwOutputStreamID != 0)
1619                    return MF_E_INVALIDSTREAMNUMBER;
1620    
1621            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1622                    return E_INVALIDARG;
1623    
1624            HRESULT hr = S_OK;
1625    
1626            EnterCriticalSection(&m_mft_lock);
1627    
1628            /* Actually set the type or just test it? */
1629            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1630    
1631            /* If we have samples pending the type can't be changed right now */
1632            if (HasPendingOutput())
1633                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1634    
1635            if (SUCCEEDED(hr)) {
1636                    if (pType) { /* Check the type */
1637                            AM_MEDIA_TYPE *am;
1638                            hr = MFCreateAMMediaTypeFromMFMediaType(pType, GUID_NULL, &am);
1639    
1640                            if (SUCCEEDED(hr)) {
1641                                    if (FAILED(ChangeColorspace(am->subtype, am->formattype, am->pbFormat, 1))) {
1642                                            DPRINTF("(MFT)InternalCheckOutputType (MF_E_INVALIDTYPE)");
1643                                            return MF_E_INVALIDTYPE;
1644                                    }
1645    
1646                            CoTaskMemFree(am->pbFormat);
1647                            CoTaskMemFree(am);
1648                            }
1649                    }
1650            }
1651    
1652            if (SUCCEEDED(hr)) {
1653                    if (bReallySet) { /* Set the type if needed */
1654                            hr = OnSetOutputType(pType);
1655                    }
1656            }
1657    
1658            if (SUCCEEDED(hr) && (Tray_Icon == 0) && (g_config.bTrayIcon != 0)) /* Create message passing window */
1659            {
1660                    WNDCLASSEX wc;
1661    
1662                    wc.cbSize = sizeof(WNDCLASSEX);
1663                    wc.lpfnWndProc = msg_proc;
1664                    wc.style = CS_HREDRAW | CS_VREDRAW;
1665                    wc.cbWndExtra = 0;
1666                    wc.cbClsExtra = 0;
1667                    wc.hInstance = (HINSTANCE) g_xvid_hInst;
1668                    wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH);
1669                    wc.lpszMenuName = NULL;
1670                    wc.lpszClassName = TEXT("XVID_MSG_WINDOW");
1671                    wc.hIcon = NULL;
1672                    wc.hIconSm = NULL;
1673                    wc.hCursor = NULL;
1674                    RegisterClassEx(&wc);
1675    
1676                    MSG_hwnd = CreateWindowEx(0, TEXT("XVID_MSG_WINDOW"), NULL, 0, CW_USEDEFAULT,
1677                                      CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE) g_xvid_hInst, NULL);
1678    
1679                    /* display the tray icon */
1680                    NOTIFYICONDATA nid;
1681                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
1682    
1683                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
1684                    nid.hWnd = MSG_hwnd;
1685                    nid.uID = 1456;
1686                    nid.uCallbackMessage = WM_ICONMESSAGE;
1687                    nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
1688                    lstrcpy(nid.szTip, TEXT("Xvid Video Decoder"));
1689                    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
1690    
1691                    Shell_NotifyIcon(NIM_ADD, &nid);
1692    
1693                    DestroyIcon(nid.hIcon);
1694                    Tray_Icon = 1;
1695            }
1696    
1697            LeaveCriticalSection(&m_mft_lock);
1698            return hr;
1699    }
1700    
1701    HRESULT CXvidDecoder::MFTGetInputCurrentType(DWORD dwInputStreamID, IMFMediaType **ppType)
1702    {
1703            DPRINTF("(MFT)GetInputCurrentType");
1704    
1705            if (ppType == NULL)
1706                    return E_POINTER;
1707    
1708            if (dwInputStreamID != 0)
1709                    return MF_E_INVALIDSTREAMNUMBER;
1710    
1711            EnterCriticalSection(&m_mft_lock);
1712    
1713            HRESULT hr = S_OK;
1714    
1715            if (!m_pInputType)
1716                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1717    
1718            if (SUCCEEDED(hr)) {
1719                    *ppType = m_pInputType;
1720                    (*ppType)->AddRef();
1721            }
1722    
1723            LeaveCriticalSection(&m_mft_lock);
1724            return hr;
1725    }
1726    
1727    HRESULT CXvidDecoder::MFTGetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType)
1728    {
1729            DPRINTF("(MFT)GetOutputCurrentType");
1730    
1731            if (ppType == NULL)
1732                    return E_POINTER;
1733    
1734            if (dwOutputStreamID != 0)
1735                    return MF_E_INVALIDSTREAMNUMBER;
1736    
1737            EnterCriticalSection(&m_mft_lock);
1738    
1739            HRESULT hr = S_OK;
1740    
1741            if (!m_pOutputType)
1742                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1743    
1744            if (SUCCEEDED(hr)) {
1745                    *ppType = m_pOutputType;
1746                    (*ppType)->AddRef();
1747            }
1748    
1749            LeaveCriticalSection(&m_mft_lock);
1750            return hr;
1751    }
1752    
1753    HRESULT CXvidDecoder::MFTGetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags)
1754    {
1755            DPRINTF("(MFT)GetInputStatus");
1756    
1757            if (pdwFlags == NULL)
1758                    return E_POINTER;
1759    
1760            if (dwInputStreamID != 0)
1761                    return MF_E_INVALIDSTREAMNUMBER;
1762    
1763            EnterCriticalSection(&m_mft_lock);
1764    
1765            /* If there's pending output sampels we don't accept new
1766               input data until ProcessOutput() or Flush() was called */
1767            if (!HasPendingOutput()) {
1768                    *pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
1769            }
1770            else {
1771                    *pdwFlags = 0;
1772            }
1773    
1774            LeaveCriticalSection(&m_mft_lock);
1775    
1776            return S_OK;
1777    }
1778    
1779    HRESULT CXvidDecoder::MFTGetOutputStatus(DWORD *pdwFlags)
1780    {
1781            DPRINTF("(MFT)GetOutputStatus");
1782    
1783            if (pdwFlags == NULL)
1784                    return E_POINTER;
1785    
1786            EnterCriticalSection(&m_mft_lock);
1787    
1788            /* We can render an output sample only after we
1789               have decoded one */
1790            if (HasPendingOutput()) {
1791                    *pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
1792            }
1793            else {
1794                    *pdwFlags = 0;
1795            }
1796    
1797            LeaveCriticalSection(&m_mft_lock);
1798    
1799            return S_OK;
1800    }
1801    
1802    HRESULT CXvidDecoder::MFTSetOutputBounds(LONGLONG hnsLowerBound, LONGLONG hnsUpperBound)
1803    {
1804            DPRINTF("(MFT)SetOutputBounds");
1805            return E_NOTIMPL;
1806    }
1807    
1808    HRESULT CXvidDecoder::MFTProcessEvent(DWORD dwInputStreamID, IMFMediaEvent *pEvent)
1809    {
1810            DPRINTF("(MFT)ProcessEvent");
1811            return E_NOTIMPL; /* We don't handle any stream events */
1812    }
1813    
1814    HRESULT CXvidDecoder::MFTProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
1815    {
1816            DPRINTF("(MFT)ProcessMessage");
1817            HRESULT hr = S_OK;
1818    
1819            EnterCriticalSection(&m_mft_lock);
1820    
1821            switch (eMessage)
1822            {
1823            case MFT_MESSAGE_COMMAND_FLUSH:
1824                    if (m_create.handle != NULL) {
1825                            DPRINTF("(MFT)CommandFlush");
1826    
1827                            xvid_dec_stats_t stats;
1828                            int used_bytes;
1829    
1830                            memset(&stats, 0, sizeof(stats));
1831                            stats.version = XVID_VERSION;
1832    
1833                            int csp = m_frame.output.csp;
1834    
1835                            m_frame.output.csp = XVID_CSP_INTERNAL;
1836                            m_frame.bitstream = NULL;
1837                            m_frame.length = -1;
1838                            m_frame.general = XVID_LOWDELAY;
1839    
1840                            do {
1841                                    used_bytes = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1842                            } while(used_bytes>=0 && stats.type <= 0);
1843    
1844                            m_frame.output.csp = csp;
1845                            m_frame.output.plane[1] = NULL; /* Don't display flushed samples */
1846    
1847                            //m_timestamp = INVALID_TIME;
1848                            //m_timelength = INVALID_TIME;
1849                            //m_rtFrame = 0;
1850            }
1851        break;
1852    
1853            case MFT_MESSAGE_COMMAND_DRAIN:
1854                    m_discont = 1; /* Set discontinuity flag */
1855                    m_rtFrame = 0;
1856                    break;
1857    
1858            case MFT_MESSAGE_SET_D3D_MANAGER:
1859                    hr = E_NOTIMPL;
1860                    break;
1861    
1862            case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
1863            case MFT_MESSAGE_NOTIFY_END_STREAMING:
1864                    break;
1865    
1866            case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
1867            case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
1868                    break;
1869            }
1870    
1871            LeaveCriticalSection(&m_mft_lock);
1872    
1873            return hr;
1874    }
1875    
1876    HRESULT CXvidDecoder::MFTProcessInput(DWORD dwInputStreamID, IMFSample *pSample, DWORD dwFlags)
1877    {
1878            DPRINTF("(MFT)ProcessInput");
1879    
1880            if (pSample == NULL)
1881                    return E_POINTER;
1882    
1883            if (dwInputStreamID != 0)
1884                    return MF_E_INVALIDSTREAMNUMBER;
1885    
1886            if (dwFlags != 0)
1887                    return E_INVALIDARG;
1888    
1889            if (!m_pInputType || !m_pOutputType) {
1890                    return MF_E_NOTACCEPTING;   /* Must have set input and output types */
1891            }
1892            else if (HasPendingOutput()) {
1893                    return MF_E_NOTACCEPTING;   /* We still have output samples to render */
1894            }
1895    
1896            xvid_dec_stats_t stats;
1897            int length;
1898    
1899            memset(&stats, 0, sizeof(stats));
1900            stats.version = XVID_VERSION;
1901    
1902            if (m_create.handle == NULL)
1903            {
1904                    if (xvid_decore_func == NULL)
1905                            return E_FAIL;
1906                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
1907                    {
1908                            DPRINTF("*** XVID_DEC_CREATE error");
1909                            return E_FAIL;
1910                    }
1911            }
1912    
1913            EnterCriticalSection(&m_mft_lock);
1914    
1915            HRESULT hr = S_OK;
1916            IMFMediaBuffer *pBuffer = NULL;
1917    
1918            if (SUCCEEDED(hr)) {
1919                    hr = pSample->ConvertToContiguousBuffer(&pBuffer);
1920            }
1921    
1922            if (SUCCEEDED(hr)) {
1923                    hr = pBuffer->Lock((BYTE**)&m_frame.bitstream, NULL, (DWORD *)&m_frame.length);
1924            }
1925    
1926            m_frame.general = XVID_LOWDELAY;
1927    
1928            if (m_discont == 1) {
1929                    m_frame.general |= XVID_DISCONTINUITY;
1930                    m_discont = 0;
1931            }
1932    
1933            if (g_config.nDeblock_Y)
1934                    m_frame.general |= XVID_DEBLOCKY;
1935    
1936            if (g_config.nDeblock_UV)
1937                    m_frame.general |= XVID_DEBLOCKUV;
1938    
1939            if (g_config.nDering_Y)
1940                    m_frame.general |= XVID_DERINGY;
1941    
1942            if (g_config.nDering_UV)
1943                    m_frame.general |= XVID_DERINGUV;
1944    
1945            if (g_config.nFilmEffect)
1946                    m_frame.general |= XVID_FILMEFFECT;
1947    
1948            m_frame.brightness = g_config.nBrightness;
1949    
1950            m_frame.output.csp &= ~XVID_CSP_VFLIP;
1951            m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0);
1952    
1953            int csp = m_frame.output.csp;
1954            m_frame.output.csp = XVID_CSP_INTERNAL;
1955    
1956        // Paranoid check.
1957            if (xvid_decore_func == NULL) {
1958                    hr = E_FAIL;
1959                    goto END_LOOP;
1960            }
1961    
1962    repeat :
1963            length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1964    
1965            if (length == XVID_ERR_MEMORY) {
1966                    hr = E_FAIL;
1967                    goto END_LOOP;
1968            }
1969            else if (length < 0)
1970            {
1971                    DPRINTF("*** XVID_DEC_DECODE");
1972                    goto END_LOOP;
1973            }
1974    
1975            if (stats.type == XVID_TYPE_NOTHING && length > 0) {
1976                    DPRINTF(" B-Frame decoder lag");
1977                    m_frame.output.plane[1] = NULL;
1978                    goto END_LOOP;
1979            }
1980    
1981            if (stats.type == XVID_TYPE_VOL)
1982            {
1983                    if (stats.data.vol.width != m_create.width ||
1984                            stats.data.vol.height != m_create.height)
1985                    {
1986                            DPRINTF("TODO: auto-resize");
1987                            m_frame.output.plane[1] = NULL;
1988                            hr = E_FAIL;
1989                    }
1990    
1991                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) { /* auto */
1992                            int par_x, par_y;
1993                            if (stats.data.vol.par == XVID_PAR_EXT) {
1994                                    par_x = stats.data.vol.par_width;
1995                                    par_y = stats.data.vol.par_height;
1996                            } else {
1997                                    par_x = PARS[stats.data.vol.par-1][0];
1998                                    par_y = PARS[stats.data.vol.par-1][1];
1999                            }
2000    
2001                            ar_x = par_x * stats.data.vol.width;
2002                            ar_y = par_y * stats.data.vol.height;
2003                    }
2004    
2005                    m_frame.bitstream = (BYTE*)m_frame.bitstream + length;
2006                    m_frame.length -= length;
2007                    goto repeat;
2008            }
2009    
2010    END_LOOP:
2011            m_frame.output.csp = csp;
2012    
2013            if (pBuffer) {
2014                    pBuffer->Unlock();
2015                    pBuffer->Release();
2016            }
2017    
2018            if (SUCCEEDED(hr)) {
2019                    /* Try to get a timestamp */
2020                    if (FAILED(pSample->GetSampleTime(&m_timestamp)))
2021                            m_timestamp = INVALID_TIME;
2022    
2023                    if (FAILED(pSample->GetSampleDuration(&m_timelength))) {
2024                            m_timelength = INVALID_TIME;
2025                    }
2026                    if (m_timestamp != INVALID_TIME && stats.type == XVID_TYPE_IVOP) {
2027                            m_rtFrame = m_timestamp;
2028                    }
2029            }
2030    
2031            LeaveCriticalSection(&m_mft_lock);
2032    
2033            return hr;
2034    }
2035    
2036    HRESULT CXvidDecoder::MFTProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus)
2037    {
2038            DPRINTF("(MFT)ProcessOutput");
2039    
2040            /* Preroll in MFT ??
2041               Flags ?? -> TODO... */
2042            if (dwFlags != 0)
2043                    return E_INVALIDARG;
2044    
2045            if (pOutputSamples == NULL || pdwStatus == NULL)
2046                    return E_POINTER;
2047    
2048            if (cOutputBufferCount != 1) /* Must be exactly one output buffer */
2049                    return E_INVALIDARG;
2050    
2051            if (pOutputSamples[0].pSample == NULL) /* Must have a sample */
2052                    return E_INVALIDARG;
2053    
2054            if (!HasPendingOutput()) { /* If there's no sample we need to decode one first */
2055                    return MF_E_TRANSFORM_NEED_MORE_INPUT;
2056            }
2057    
2058            EnterCriticalSection(&m_mft_lock);
2059    
2060            HRESULT hr = S_OK;
2061    
2062            BYTE *Dst = NULL;
2063            DWORD buffer_size;
2064    
2065            IMFMediaBuffer *pOutput = NULL;
2066    
2067            if (SUCCEEDED(hr)) {
2068                    hr = pOutputSamples[0].pSample->GetBufferByIndex(0, &pOutput); /* Get output buffer */
2069            }
2070    
2071            if (SUCCEEDED(hr)) {
2072                    hr = pOutput->GetMaxLength(&buffer_size);
2073            }
2074    
2075            if (SUCCEEDED(hr))
2076                    hr = pOutput->Lock(&Dst, NULL, NULL);
2077    
2078            if (SUCCEEDED(hr)) {
2079                    xvid_gbl_convert_t convert;
2080    
2081                    memset(&convert, 0, sizeof(convert));
2082                    convert.version = XVID_VERSION;
2083    
2084                    convert.input.csp = XVID_CSP_INTERNAL;
2085                    convert.input.plane[0] = m_frame.output.plane[0];
2086                    convert.input.plane[1] = m_frame.output.plane[1];
2087                    convert.input.plane[2] = m_frame.output.plane[2];
2088                    convert.input.stride[0] = m_frame.output.stride[0];
2089                    convert.input.stride[1] = m_frame.output.stride[1];
2090                    convert.input.stride[2] = m_frame.output.stride[2];
2091    
2092                    convert.output.csp = m_frame.output.csp;
2093                    convert.output.plane[0] = Dst;
2094                    convert.output.stride[0] = out_stride;
2095    
2096                    convert.width = m_create.width;
2097                    convert.height = m_create.height;
2098                    convert.interlacing = 0;
2099    
2100                    if (m_frame.output.plane[1] != NULL && Dst != NULL && xvid_global_func != NULL)
2101                            if (xvid_global_func(0, XVID_GBL_CONVERT, &convert, NULL) < 0) /* CSP convert into output buffer */
2102                                    hr = E_FAIL;
2103    
2104                    m_frame.output.plane[1] = NULL;
2105            }
2106    
2107            *pdwStatus = 0;
2108    
2109            if (SUCCEEDED(hr)) {
2110                    if (SUCCEEDED(hr))
2111                            hr = pOutputSamples[0].pSample->SetUINT32(MFSampleExtension_CleanPoint, TRUE); // key frame
2112    
2113                    if (SUCCEEDED(hr)) { /* Set timestamp of output sample */
2114                            if (m_timestamp != INVALID_TIME)
2115                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_timestamp);
2116                            else
2117                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_rtFrame);
2118    
2119                            if (m_timelength != INVALID_TIME)
2120                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_timelength);
2121                            else
2122                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_duration);
2123    
2124                            m_rtFrame += m_duration;
2125                    }
2126    
2127                    if (SUCCEEDED(hr))
2128                            hr = pOutput->SetCurrentLength(m_create.width * abs(m_create.height) * 4); // XXX
2129            }
2130    
2131            if (pOutput) {
2132                    pOutput->Unlock();
2133                    pOutput->Release();
2134            }
2135    
2136            LeaveCriticalSection(&m_mft_lock);
2137    
2138            return hr;
2139    }
2140    
2141    HRESULT CXvidDecoder::OnCheckInputType(IMFMediaType *pmt)
2142    {
2143            DPRINTF("(MFT)CheckInputType");
2144    
2145            HRESULT hr = S_OK;
2146    
2147            /*  Check if input type is already set. Reject any type that is not identical */
2148            if (m_pInputType) {
2149                    DWORD dwFlags = 0;
2150                    if (S_OK == m_pInputType->IsEqual(pmt, &dwFlags)) {
2151                            return S_OK;
2152                    }
2153                    else {
2154                            return MF_E_INVALIDTYPE;
2155                    }
2156            }
2157    
2158            GUID majortype = {0}, subtype = {0};
2159            UINT32 width = 0, height = 0;
2160    
2161            hr = pmt->GetMajorType(&majortype);
2162    
2163            if (SUCCEEDED(hr)) {
2164                    if (majortype != MFMediaType_Video) { /* Must be Video */
2165                            hr = MF_E_INVALIDTYPE;
2166                    }
2167            }
2168    
2169            if (m_hdll == NULL) {
2170                    HRESULT hr2 = OpenLib();
2171    
2172                    if (FAILED(hr2) || (m_hdll == NULL)) // Paranoid checks.
2173                            hr = MF_E_INVALIDTYPE;
2174            }
2175    
2176            if (SUCCEEDED(hr)) {
2177                    hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &width, &height);
2178            }
2179    
2180            /* Check the frame size */
2181            if (SUCCEEDED(hr)) {
2182                    if (width > 4096 || height > 4096) {
2183                            hr = MF_E_INVALIDTYPE;
2184                    }
2185            }
2186            m_create.width = width;
2187            m_create.height = height;
2188    
2189            if (SUCCEEDED(hr)) {
2190                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
2191                            hr = MFGetAttributeRatio(pmt, MF_MT_PIXEL_ASPECT_RATIO, (UINT32*)&ar_x, (UINT32*)&ar_y);
2192                    }
2193            }
2194    
2195            /* TODO1: Make sure there really is a frame rate after all!
2196               TODO2: Use the framerate for something! */
2197            MFRatio fps = {0};
2198            if (SUCCEEDED(hr)) {
2199                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&fps.Numerator, (UINT32*)&fps.Denominator);
2200            }
2201    
2202            if (SUCCEEDED(hr)) {
2203                    hr = pmt->GetGUID(MF_MT_SUBTYPE, &subtype);
2204            }
2205    
2206            if (subtype == CLSID_MP4V || subtype == CLSID_MP4V_UC ||
2207                subtype == CLSID_LMP4 || subtype == CLSID_LMP4_UC ||
2208                subtype == CLSID_RMP4 || subtype == CLSID_RMP4_UC ||
2209                subtype == CLSID_SMP4 || subtype == CLSID_SMP4_UC ||
2210                subtype == CLSID_HDX4 || subtype == CLSID_HDX4_UC) {
2211                    if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
2212                            CloseLib();
2213                            hr = MF_E_INVALIDTYPE;
2214                    }
2215                    else m_create.fourcc = FOURCC_MP4V;
2216            }
2217            else if (subtype == CLSID_DIVX || subtype == CLSID_DIVX_UC) {
2218                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2219                            CloseLib();
2220                            hr = MF_E_INVALIDTYPE;
2221                    }
2222                    else m_create.fourcc = FOURCC_DIVX;
2223            }
2224            else if (subtype == CLSID_DX50 || subtype == CLSID_DX50_UC) {
2225                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2226                            CloseLib();
2227                            hr = MF_E_INVALIDTYPE;
2228                    }
2229                    else m_create.fourcc = FOURCC_DX50;
2230            }
2231            else if (subtype == CLSID_3IVX || subtype == CLSID_3IVX_UC ||
2232                     subtype == CLSID_3IV0 || subtype == CLSID_3IV0_UC ||
2233                     subtype == CLSID_3IV1 || subtype == CLSID_3IV1_UC ||
2234                     subtype == CLSID_3IV2 || subtype == CLSID_3IV2_UC) {
2235                    if (!(g_config.supported_4cc & SUPPORT_3IVX)) {
2236                            CloseLib();
2237                            hr = MF_E_INVALIDTYPE;
2238                    }
2239                    else m_create.fourcc = FOURCC_3IVX;
2240            }
2241            else if (subtype == CLSID_XVID || subtype == CLSID_XVID_UC) {
2242                    m_create.fourcc = FOURCC_XVID;
2243            }
2244            else {
2245                    DPRINTF("Unknown subtype!");
2246                    CloseLib();
2247                    hr = MF_E_INVALIDTYPE;
2248            }
2249    
2250            /* haali media splitter reports VOL information in the format header */
2251            if (SUCCEEDED(hr))
2252            {
2253                    UINT32 cbSeqHeader = 0;
2254    
2255                    (void)pmt->GetBlobSize(MF_MT_MPEG_SEQUENCE_HEADER, &cbSeqHeader);
2256    
2257                    if (cbSeqHeader>0) {
2258                            xvid_dec_stats_t stats;
2259                            memset(&stats, 0, sizeof(stats));
2260                            stats.version = XVID_VERSION;
2261    
2262                            if (m_create.handle == NULL) {
2263                                    if (xvid_decore_func == NULL)
2264                                            hr = E_FAIL;
2265                                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
2266                                            DPRINTF("*** XVID_DEC_CREATE error");
2267                                            hr = E_FAIL;
2268                                    }
2269                            }
2270    
2271                            if (SUCCEEDED(hr)) {
2272                                    (void)pmt->GetAllocatedBlob(MF_MT_MPEG_SEQUENCE_HEADER, (UINT8 **)&m_frame.bitstream, (UINT32 *)&m_frame.length);
2273                                    m_frame.general = 0;
2274                                    m_frame.output.csp = XVID_CSP_NULL;
2275    
2276                                    int ret = 0;
2277                                    if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
2278                                            /* honour video dimensions reported in VOL header */
2279                                            if (stats.type == XVID_TYPE_VOL) {
2280                                                    m_create.width = stats.data.vol.width;
2281                                                    m_create.height = stats.data.vol.height;
2282                                            }
2283                                    }
2284    
2285                                    if (ret == XVID_ERR_MEMORY) hr = E_FAIL;
2286                                    CoTaskMemFree(m_frame.bitstream);
2287                            }
2288                    }
2289            }
2290    
2291            return hr;
2292    }
2293    
2294    HRESULT CXvidDecoder::OnSetInputType(IMFMediaType *pmt)
2295    {
2296            HRESULT hr = S_OK;
2297            UINT32 w, h;
2298    
2299            if (m_pInputType) m_pInputType->Release();
2300    
2301            hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &w, &h);
2302            m_create.width = w; m_create.height = h;
2303    
2304            if (SUCCEEDED(hr))
2305                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&m_frameRate.Numerator, (UINT32*)&m_frameRate.Denominator);
2306    
2307            if (SUCCEEDED(hr)) { /* Store frame duration, derived from the frame rate */
2308                    hr = MFFrameRateToAverageTimePerFrame(m_frameRate.Numerator, m_frameRate.Denominator, &m_duration);
2309            }
2310    
2311            if (SUCCEEDED(hr)) {
2312                    m_pInputType = pmt;
2313                    m_pInputType->AddRef();
2314            }
2315    
2316            return hr;
2317    }
2318    
2319    HRESULT CXvidDecoder::OnSetOutputType(IMFMediaType *pmt)
2320    {
2321            if (m_pOutputType) m_pOutputType->Release();
2322    
2323            m_pOutputType = pmt;
2324            m_pOutputType->AddRef();
2325    
2326            return S_OK;
2327    }
2328    
2329    #endif /* XVID_USE_MFT */

Legend:
Removed from v.1633  
changed lines
  Added in v.2024

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