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

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

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