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

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

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

trunk/xvidcore/dshow/src/CXvidDecoder.cpp revision 1558, Mon Oct 25 10:29:10 2004 UTC branches/release-1_3-branch/xvidcore/dshow/src/CXvidDecoder.cpp revision 2114, Sun Jun 14 19:18:14 2015 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-2012 Michael Militzer <michael@xvid.org>
8   *   *
9   *  This program is free software ; you can redistribute it and/or modify   *  This program is free software ; you can redistribute it and/or modify
10   *  it under the terms of the GNU General Public License as published by   *  it under the terms of the GNU General Public License as published by
# Line 19  Line 20 
20   *  along with this program ; if not, write to the Free Software   *  along with this program ; if not, write to the Free Software
21   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22   *   *
23   * $Id: CXvidDecoder.cpp,v 1.13 2004-10-25 10:29:10 suxen_drol Exp $   * $Id$
  *  
  ****************************************************************************/  
   
 /****************************************************************************  
  *  
  * 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 HWND MSG_hwnd = NULL; /* message handler window */
182    
183    extern "C" void CALLBACK Configure(HWND hWndParent, HINSTANCE hInstParent, LPSTR lpCmdLine, int nCmdShow );
184    
185    LRESULT CALLBACK msg_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
186    {
187            switch ( uMsg )
188            {
189            case WM_ICONMESSAGE:
190                    switch(lParam)
191                    {
192                    case WM_LBUTTONUP:
193                    case WM_LBUTTONDBLCLK:
194                            if (!GUI_Page) {
195                                    GUI_Page = 1;
196                                    Configure(hwnd, g_xvid_hInst, "", 1);
197                                    GUI_Page = 0;
198                            }
199                            break;
200                    default:
201                            return DefWindowProc(hwnd, uMsg, wParam, lParam);
202                    };
203                    break;
204    
205            case WM_DESTROY:
206                    NOTIFYICONDATA nid;
207                    ZeroMemory(&nid, sizeof(NOTIFYICONDATA));
208    
209                    nid.cbSize = sizeof(NOTIFYICONDATA);
210                    nid.hWnd = hwnd;
211                    nid.uID = 1456;
212                    Shell_NotifyIcon(NIM_DELETE, &nid);
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_MFT_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(NAME("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            m_tray_icon = 0;
321            m_startClock = clock();
322    
323    #if defined(XVID_USE_MFT)
324            InitializeCriticalSection(&m_mft_lock);
325            m_pInputType = NULL;
326            m_pOutputType = NULL;
327            m_pOutputTypeBPP = 32;
328            m_rtFrame = 0;
329            m_duration = 0;
330            m_discont = 0;
331            m_frameRate.Denominator = 1;
332            m_frameRate.Numerator = 1;
333            m_thread_handle = NULL;
334    #endif
335    
336        LoadRegistryInfo();
337    
338        *phr = OpenLib();
339    
340            {
341                    TCHAR lpFilename[MAX_PATH];
342                    int sLen = GetModuleFileName(NULL, lpFilename, MAX_PATH);
343    #ifdef _UNICODE
344                    if ((sLen >= 11) && (_wcsnicmp(&(lpFilename[sLen - 11]), TEXT("dllhost.exe"), 11) == 0)) {
345    #else
346                    if ((sLen >= 11) && (_strnicmp(&(lpFilename[sLen - 11]), TEXT("dllhost.exe"), 11) == 0)) {
347    #endif
348                            if (m_tray_icon == 0) m_tray_icon = -1; // create no tray icon upon thumbnail generation
349                    }
350            }
351    
352    }
353    
354    HRESULT CXvidDecoder::OpenLib()
355    {
356        DPRINTF("OpenLib");
357    
358        if (m_hdll != NULL)
359                    return E_UNEXPECTED; // Seems, that library already opened.
360    
361          xvid_gbl_init_t init;          xvid_gbl_init_t init;
362          memset(&init, 0, sizeof(init));          memset(&init, 0, sizeof(init));
363          init.version = XVID_VERSION;          init.version = XVID_VERSION;
364            init.cpu_flags = g_config.cpu;
365    
366            xvid_gbl_info_t info;
367            memset(&info, 0, sizeof(info));
368            info.version = XVID_VERSION;
369    
370          m_hdll = LoadLibrary(XVID_DLL_NAME);          m_hdll = LoadLibrary(XVID_DLL_NAME);
371          if (m_hdll == NULL) {          if (m_hdll == NULL) {
372                  DPRINTF("dll load failed");                  DPRINTF("dll load failed");
373                  MessageBox(0, XVID_DLL_NAME " not found","Error", MB_TOPMOST);                  MessageBox(0, XVID_DLL_NAME " not found","Error", MB_TOPMOST);
374                  return;                  return E_FAIL;
375          }          }
376    
377          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");
378          if (xvid_global_func == NULL) {          if (xvid_global_func == NULL) {
379            FreeLibrary(m_hdll);
380            m_hdll = NULL;
381                  MessageBox(0, "xvid_global() not found", "Error", MB_TOPMOST);                  MessageBox(0, "xvid_global() not found", "Error", MB_TOPMOST);
382                  return;                  return E_FAIL;
383          }          }
384    
385          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");
386          if (xvid_decore_func == NULL) {          if (xvid_decore_func == NULL) {
387            xvid_global_func = NULL;
388            FreeLibrary(m_hdll);
389            m_hdll = NULL;
390                  MessageBox(0, "xvid_decore() not found", "Error", MB_TOPMOST);                  MessageBox(0, "xvid_decore() not found", "Error", MB_TOPMOST);
391                  return;                  return E_FAIL;
392          }          }
393    
394          if (xvid_global_func(0, XVID_GBL_INIT, &init, NULL) < 0)          if (xvid_global_func(0, XVID_GBL_INIT, &init, NULL) < 0)
395          {          {
396            xvid_global_func = NULL;
397            xvid_decore_func = NULL;
398            FreeLibrary(m_hdll);
399            m_hdll = NULL;
400                    MessageBox(0, "xvid_global() failed", "Error", MB_TOPMOST);
401                    return E_FAIL;
402            }
403    
404            if (xvid_global_func(0, XVID_GBL_INFO, &info, NULL) < 0)
405            {
406            xvid_global_func = NULL;
407            xvid_decore_func = NULL;
408            FreeLibrary(m_hdll);
409            m_hdll = NULL;
410                  MessageBox(0, "xvid_global() failed", "Error", MB_TOPMOST);                  MessageBox(0, "xvid_global() failed", "Error", MB_TOPMOST);
411                  return;                  return E_FAIL;
412          }          }
413    
414          memset(&m_create, 0, sizeof(m_create));          memset(&m_create, 0, sizeof(m_create));
415          m_create.version = XVID_VERSION;          m_create.version = XVID_VERSION;
416          m_create.handle = NULL;          m_create.handle = NULL;
417        /* Decoder threads */
418        if (g_config.cpu & XVID_CPU_FORCE) {
419                    m_create.num_threads = g_config.num_threads;
420            }
421            else {
422            m_create.num_threads = info.num_threads; /* Autodetect */
423                    g_config.num_threads = info.num_threads;
424            }
425    
426          memset(&m_frame, 0, sizeof(m_frame));          memset(&m_frame, 0, sizeof(m_frame));
427          m_frame.version = XVID_VERSION;          m_frame.version = XVID_VERSION;
428    
         LoadRegistryInfo();  
   
429          USE_IYUV = false;          USE_IYUV = false;
430          USE_YV12 = false;          USE_YV12 = false;
431          USE_YUY2 = false;          USE_YUY2 = false;
# Line 302  Line 482 
482                  ar_y = 20;                  ar_y = 20;
483                  break;                  break;
484          }          }
485    
486            return S_OK;
487  }  }
488    
489  void CXvidDecoder::CloseLib()  void CXvidDecoder::CloseLib()
490  {  {
491          DPRINTF("Destructor");          DPRINTF("CloseLib");
492    
493          if (m_create.handle != NULL) {          if ((m_create.handle != NULL) && (xvid_decore_func != NULL))
494            {
495                  xvid_decore_func(m_create.handle, XVID_DEC_DESTROY, 0, 0);                  xvid_decore_func(m_create.handle, XVID_DEC_DESTROY, 0, 0);
496                  m_create.handle = NULL;                  m_create.handle = NULL;
497          }          }
# Line 317  Line 500 
500                  FreeLibrary(m_hdll);                  FreeLibrary(m_hdll);
501                  m_hdll = NULL;                  m_hdll = NULL;
502          }          }
503        xvid_decore_func = NULL;
504        xvid_global_func = NULL;
505  }  }
506    
507  /* destructor */  /* destructor */
508    
509  CXvidDecoder::~CXvidDecoder()  CXvidDecoder::~CXvidDecoder()
510  {  {
511        DPRINTF("Destructor");
512    
513            if ((MSG_hwnd != NULL) && (m_tray_icon == 1)) { /* Destroy tray icon */
514                    SendMessage(MSG_hwnd, WM_CLOSE, 0, 0);
515            }
516    
517            /* Close xvidcore library */
518          CloseLib();          CloseLib();
519    
520            clock_t endClock = clock();
521            if (((endClock - m_startClock) / CLOCKS_PER_SEC) > 3) {
522                    SaveRegistryInfo((endClock - m_startClock) / (CLOCKS_PER_SEC / 10));
523            }
524    
525            if ((MSG_hwnd != 0) && (m_tray_icon == 1)) { /* Final clean-up */
526              MSG_hwnd = 0;
527              Sleep(200);
528              m_tray_icon = 0;
529    #if defined(XVID_USE_MFT)
530              if (m_thread_handle) {
531                      TerminateThread(m_thread_handle, 0);
532                      CloseHandle(m_thread_handle);
533                      m_thread_handle = NULL;
534              }
535    #endif
536            }
537    
538    #if defined(XVID_USE_MFT)
539            DeleteCriticalSection(&m_mft_lock);
540    #endif
541  }  }
542    
543    
# Line 344  Line 558 
558                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
559          }          }
560    
561        if (m_hdll == NULL)
562        {
563                    HRESULT hr = OpenLib();
564    
565            if (FAILED(hr) || (m_hdll == NULL)) // Paranoid checks.
566                            return VFW_E_TYPE_NOT_ACCEPTED;
567        }
568    
569          if (*mtIn->FormatType() == FORMAT_VideoInfo)          if (*mtIn->FormatType() == FORMAT_VideoInfo)
570          {          {
571                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtIn->Format();                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtIn->Format();
# Line 359  Line 581 
581                  }                  }
582                  DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);                  DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);
583          }          }
584      else if (*mtIn->FormatType() == FORMAT_MPEG2Video) {
585        MPEG2VIDEOINFO * mpgvi = (MPEG2VIDEOINFO*)mtIn->Format();
586        VIDEOINFOHEADER2 * vih2 = &mpgvi->hdr;
587                    hdr = &vih2->bmiHeader;
588                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
589                            ar_x = vih2->dwPictAspectRatioX;
590                            ar_y = vih2->dwPictAspectRatioY;
591                    }
592                    DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);
593    
594        /* haali media splitter reports VOL information in the format header */
595    
596        if (mpgvi->cbSequenceHeader>0) {
597    
598          xvid_dec_stats_t stats;
599                memset(&stats, 0, sizeof(stats));
600                stats.version = XVID_VERSION;
601    
602                if (m_create.handle == NULL) {
603                        if (xvid_decore_func == NULL)
604                                return E_FAIL;
605                        if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
606              DPRINTF("*** XVID_DEC_CREATE error");
607                                return E_FAIL;
608                        }
609                }
610    
611          m_frame.general = 0;
612          m_frame.bitstream = (void*)mpgvi->dwSequenceHeader;
613          m_frame.length = mpgvi->cbSequenceHeader;
614          m_frame.output.csp = XVID_CSP_NULL;
615    
616          int ret = 0;
617          if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
618            /* honour video dimensions reported in VOL header */
619                  if (stats.type == XVID_TYPE_VOL) {
620              hdr->biWidth = stats.data.vol.width;
621              hdr->biHeight = stats.data.vol.height;
622                      }
623              }
624          if (ret == XVID_ERR_MEMORY) return E_FAIL;
625            }
626      }
627          else          else
628          {          {
629                  DPRINTF("Error: Unknown FormatType");                  DPRINTF("Error: Unknown FormatType");
630                  CloseLib();                  CloseLib();
631                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
632          }          }
   
633          if (hdr->biHeight < 0)          if (hdr->biHeight < 0)
634          {          {
635                  DPRINTF("colorspace: inverted input format not supported");                  DPRINTF("colorspace: inverted input format not supported");
# Line 376  Line 640 
640    
641          switch(hdr->biCompression)          switch(hdr->biCompression)
642          {          {
643            case FOURCC_mp4v :
644          case FOURCC_MP4V:          case FOURCC_MP4V:
645            case FOURCC_lmp4 :
646            case FOURCC_LMP4 :
647            case FOURCC_rmp4 :
648            case FOURCC_RMP4 :
649            case FOURCC_smp4 :
650            case FOURCC_SMP4 :
651            case FOURCC_hdx4 :
652            case FOURCC_HDX4 :
653                  if (!(g_config.supported_4cc & SUPPORT_MP4V)) {                  if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
654                          CloseLib();                          CloseLib();
655                          return VFW_E_TYPE_NOT_ACCEPTED;                          return VFW_E_TYPE_NOT_ACCEPTED;
656                  }                  }
657                  break;                  break;
658            case FOURCC_divx :
659          case FOURCC_DIVX :          case FOURCC_DIVX :
660            case FOURCC_dx50 :
661            case FOURCC_DX50 :
662                  if (!(g_config.supported_4cc & SUPPORT_DIVX)) {                  if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
663                          CloseLib();                          CloseLib();
664                          return VFW_E_TYPE_NOT_ACCEPTED;                          return VFW_E_TYPE_NOT_ACCEPTED;
665                  }                  }
666                  break;                  break;
667          case FOURCC_DX50 :          case FOURCC_3ivx :
668                  if (!(g_config.supported_4cc & SUPPORT_DX50)) {          case FOURCC_3IVX :
669            case FOURCC_3iv0 :
670            case FOURCC_3IV0 :
671            case FOURCC_3iv1 :
672            case FOURCC_3IV1 :
673            case FOURCC_3iv2 :
674            case FOURCC_3IV2 :
675                    if (!(g_config.supported_4cc & SUPPORT_3IVX)) {
676                          CloseLib();                          CloseLib();
677                          return VFW_E_TYPE_NOT_ACCEPTED;                          return VFW_E_TYPE_NOT_ACCEPTED;
678                  }                  }
679            case FOURCC_xvid :
680          case FOURCC_XVID :          case FOURCC_XVID :
681                  break;                  break;
682    
# Line 408  Line 691 
691                  CloseLib();                  CloseLib();
692                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
693          }          }
694    
695            m_create.fourcc = hdr->biCompression;
696    
697          return S_OK;          return S_OK;
698  }  }
699    
# Line 551  Line 837 
837  /* (internal function) change colorspace */  /* (internal function) change colorspace */
838  #define CALC_BI_STRIDE(width,bitcount)  ((((width * bitcount) + 31) & ~31) >> 3)  #define CALC_BI_STRIDE(width,bitcount)  ((((width * bitcount) + 31) & ~31) >> 3)
839    
840  HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format)  HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void *format, int *bitdepth, int noflip)
841  {  {
842          DWORD biWidth;          DWORD biWidth;
843            *bitdepth = 32;
844    
845          if (formattype == FORMAT_VideoInfo)          if (formattype == FORMAT_VideoInfo)
846          {          {
847                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;
848                  biWidth = vih->bmiHeader.biWidth;                  biWidth = vih->bmiHeader.biWidth;
849                  m_frame.output.stride[0] = CALC_BI_STRIDE(vih->bmiHeader.biWidth, vih->bmiHeader.biBitCount);                  *bitdepth = vih->bmiHeader.biBitCount;
850                    out_stride = CALC_BI_STRIDE(vih->bmiHeader.biWidth, vih->bmiHeader.biBitCount);
851                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
852          }          }
853          else if (formattype == FORMAT_VideoInfo2)          else if (formattype == FORMAT_VideoInfo2)
854          {          {
855                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;
856                  biWidth = vih2->bmiHeader.biWidth;                  biWidth = vih2->bmiHeader.biWidth;
857                  m_frame.output.stride[0] = CALC_BI_STRIDE(vih2->bmiHeader.biWidth, vih2->bmiHeader.biBitCount);                  *bitdepth = vih2->bmiHeader.biBitCount;
858                    out_stride = CALC_BI_STRIDE(vih2->bmiHeader.biWidth, vih2->bmiHeader.biBitCount);
859                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
860          }          }
861          else          else
# Line 574  Line 863 
863                  return S_FALSE;                  return S_FALSE;
864          }          }
865    
866            if (noflip) rgb_flip = 0;
867    
868          if (subtype == CLSID_MEDIASUBTYPE_IYUV)          if (subtype == CLSID_MEDIASUBTYPE_IYUV)
869          {          {
870                  DPRINTF("IYUV");                  DPRINTF("IYUV");
871                  rgb_flip = 0;                  rgb_flip = 0;
872                  m_frame.output.csp = XVID_CSP_I420;                  m_frame.output.csp = XVID_CSP_I420;
873                  m_frame.output.stride[0] = CALC_BI_STRIDE(biWidth, 8);  /* planar format fix */                  out_stride = CALC_BI_STRIDE(biWidth, 8);        /* planar format fix */
874          }          }
875          else if (subtype == MEDIASUBTYPE_YV12)          else if (subtype == MEDIASUBTYPE_YV12)
876          {          {
877                  DPRINTF("YV12");                  DPRINTF("YV12");
878                  rgb_flip = 0;                  rgb_flip = 0;
879                  m_frame.output.csp = XVID_CSP_YV12;                  m_frame.output.csp = XVID_CSP_YV12;
880                  m_frame.output.stride[0] = CALC_BI_STRIDE(biWidth, 8);  /* planar format fix */                  out_stride = CALC_BI_STRIDE(biWidth, 8);        /* planar format fix */
881          }          }
882          else if (subtype == MEDIASUBTYPE_YUY2)          else if (subtype == MEDIASUBTYPE_YUY2)
883          {          {
# Line 643  Line 934 
934    
935  HRESULT CXvidDecoder::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt)  HRESULT CXvidDecoder::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt)
936  {  {
937            int bitdepth;
938          DPRINTF("SetMediaType");          DPRINTF("SetMediaType");
939    
940          if (direction == PINDIR_OUTPUT)          if (direction == PINDIR_OUTPUT)
941          {          {
942                  return ChangeColorspace(*pmt->Subtype(), *pmt->FormatType(), pmt->Format());                  return ChangeColorspace(*pmt->Subtype(), *pmt->FormatType(), pmt->Format(), &bitdepth, 0);
943          }          }
944    
945          return S_OK;          return S_OK;
# Line 659  Line 951 
951  HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)  HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
952  {  {
953          DPRINTF("CheckTransform");          DPRINTF("CheckTransform");
954    
955            return S_OK;
956    }
957    
958    /* input/output pin connection complete */
959    
960    HRESULT CXvidDecoder::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin)
961    {
962            DPRINTF("CompleteConnect");
963    
964            if ((direction == PINDIR_OUTPUT) && (MSG_hwnd == 0) && (m_tray_icon == 0) && (g_config.bTrayIcon != 0))
965            {
966                    WNDCLASSEX wc;
967    
968                    wc.cbSize = sizeof(WNDCLASSEX);
969                    wc.lpfnWndProc = msg_proc;
970                    wc.style = CS_HREDRAW | CS_VREDRAW;
971                    wc.cbWndExtra = 0;
972                    wc.cbClsExtra = 0;
973                    wc.hInstance = (HINSTANCE) g_xvid_hInst;
974                    wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH);
975                    wc.lpszMenuName = NULL;
976                    wc.lpszClassName = "XVID_MSG_WINDOW";
977                    wc.hIcon = NULL;
978                    wc.hIconSm = NULL;
979                    wc.hCursor = NULL;
980                    RegisterClassEx(&wc);
981    
982                    MSG_hwnd = CreateWindowEx(0, "XVID_MSG_WINDOW", NULL, 0, CW_USEDEFAULT,
983                                      CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE) g_xvid_hInst, NULL);
984    
985                    /* display the tray icon */
986                    NOTIFYICONDATA nid;
987                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
988    
989                    nid.cbSize = sizeof(NOTIFYICONDATA);
990                    nid.hWnd = MSG_hwnd;
991                    nid.uID = 1456;
992                    nid.uVersion = NOTIFYICON_VERSION;
993                    nid.uCallbackMessage = WM_ICONMESSAGE;
994                    nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
995                    strcpy_s(nid.szTip, 19, "Xvid Video Decoder");
996                    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_SHOWTIP;
997    
998                    Shell_NotifyIcon(NIM_ADD, &nid);
999                    Shell_NotifyIcon(NIM_SETVERSION, &nid);
1000    
1001                    DestroyIcon(nid.hIcon);
1002                    m_tray_icon = 1;
1003            }
1004    
1005          return S_OK;          return S_OK;
1006  }  }
1007    
1008    /* input/output pin disconnected */
1009    HRESULT CXvidDecoder::BreakConnect(PIN_DIRECTION direction)
1010    {
1011            DPRINTF("BreakConnect");
1012    
1013            return S_OK;
1014    }
1015    
1016  /* alloc output buffer */  /* alloc output buffer */
1017    
# Line 710  Line 1060 
1060    
1061          if (m_create.handle == NULL)          if (m_create.handle == NULL)
1062          {          {
1063                    if (xvid_decore_func == NULL)
1064                            return E_FAIL;
1065    
1066                  if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)                  if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
1067                  {                  {
1068              DPRINTF("*** XVID_DEC_CREATE error");              DPRINTF("*** XVID_DEC_CREATE error");
1069                          return S_FALSE;                          return E_FAIL;
1070                  }                  }
1071          }          }
1072    
# Line 721  Line 1074 
1074          pOut->GetMediaType(&mtOut);          pOut->GetMediaType(&mtOut);
1075          if (mtOut != NULL)          if (mtOut != NULL)
1076          {          {
1077                    int bitdepth;
1078                  HRESULT result;                  HRESULT result;
1079    
1080                  result = ChangeColorspace(mtOut->subtype, mtOut->formattype, mtOut->pbFormat);                  result = ChangeColorspace(mtOut->subtype, mtOut->formattype, mtOut->pbFormat, &bitdepth, 0);
1081                  DeleteMediaType(mtOut);                  DeleteMediaType(mtOut);
1082    
1083                  if (result != S_OK)                  if (result != S_OK)
# Line 768  Line 1122 
1122    
1123          m_frame.output.csp &= ~XVID_CSP_VFLIP;          m_frame.output.csp &= ~XVID_CSP_VFLIP;
1124          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);
1125            m_frame.output.stride[0] = out_stride;
1126    
1127        // Paranoid check.
1128        if (xvid_decore_func == NULL)
1129                    return E_FAIL;
1130    
1131    
1132  repeat :  repeat :
# Line 778  Line 1135 
1135          {          {
1136                  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);
1137    
1138                  if (length < 0)                  if (length == XVID_ERR_MEMORY)
1139                            return E_FAIL;
1140                    else if (length < 0)
1141                  {                  {
1142              DPRINTF("*** XVID_DEC_DECODE");              DPRINTF("*** XVID_DEC_DECODE");
1143                          return S_FALSE;                          return S_FALSE;
1144                  } else                  } else
1145                          if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1 && forced_ar == false) {                          if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1 && forced_ar == false) {
                         // inspired by minolta! works for VMR 7 + 9  
1146    
1147          if (stats.type != XVID_TYPE_NOTHING) {  /* dont attempt to set vmr aspect ratio if no frame was returned by decoder */
1148                            // inspired by minolta! works for VMR 7 + 9
1149                          IMediaSample2 *pOut2 = NULL;                          IMediaSample2 *pOut2 = NULL;
1150                          AM_SAMPLE2_PROPERTIES outProp2;                          AM_SAMPLE2_PROPERTIES outProp2;
1151                          if (SUCCEEDED(pOut->QueryInterface(IID_IMediaSample2, (void **)&pOut2)) &&                          if (SUCCEEDED(pOut->QueryInterface(IID_IMediaSample2, (void **)&pOut2)) &&
# Line 806  Line 1166 
1166                          }                          }
1167                  }                  }
1168          }          }
1169            }
1170          else          else
1171          {       /* Preroll frame - won't be displayed */          {       /* Preroll frame - won't be displayed */
1172                  int tmp = m_frame.output.csp;                  int tmp = m_frame.output.csp;
# Line 820  Line 1181 
1181                  m_frame.general &= ~XVID_FILMEFFECT;                  m_frame.general &= ~XVID_FILMEFFECT;
1182    
1183                  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);
1184                  if (length < 0)                  if (length == XVID_ERR_MEMORY)
1185                            return E_FAIL;
1186                    else if (length < 0)
1187                  {                  {
1188              DPRINTF("*** XVID_DEC_DECODE");              DPRINTF("*** XVID_DEC_DECODE");
1189                          return S_FALSE;                          return S_FALSE;
# Line 900  Line 1263 
1263          CoTaskMemFree(pPages->pElems);          CoTaskMemFree(pPages->pElems);
1264          return S_OK;          return S_OK;
1265  }  }
1266    
1267    /*===============================================================================
1268    // MFT Interface
1269    //=============================================================================*/
1270    #if defined(XVID_USE_MFT)
1271    #include <limits.h> // _I64_MAX
1272    #define INVALID_TIME  _I64_MAX
1273    
1274    HRESULT CXvidDecoder::MFTGetStreamLimits(DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum)
1275    {
1276            DPRINTF("(MFT)GetStreamLimits");
1277    
1278            if ((pdwInputMinimum == NULL) || (pdwInputMaximum == NULL) || (pdwOutputMinimum == NULL) || (pdwOutputMaximum == NULL))
1279                    return E_POINTER;
1280    
1281            /* Just a fixed number of streams allowed */
1282            *pdwInputMinimum = *pdwInputMaximum = 1;
1283            *pdwOutputMinimum = *pdwOutputMaximum = 1;
1284    
1285            return S_OK;
1286    }
1287    
1288    HRESULT CXvidDecoder::MFTGetStreamCount(DWORD *pcInputStreams, DWORD *pcOutputStreams)
1289    {
1290            DPRINTF("(MFT)GetStreamCount");
1291    
1292            if ((pcInputStreams == NULL) || (pcOutputStreams == NULL))
1293                    return E_POINTER;
1294    
1295            /* We have a fixed number of streams */
1296            *pcInputStreams = 1;
1297            *pcOutputStreams = 1;
1298    
1299            return S_OK;
1300    }
1301    
1302    HRESULT CXvidDecoder::MFTGetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs)
1303    {
1304            DPRINTF("(MFT)GetStreamIDs");
1305            return E_NOTIMPL; /* We have fixed number of streams, so stream ID match stream index */
1306    }
1307    
1308    HRESULT CXvidDecoder::MFTGetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo)
1309    {
1310            DPRINTF("(MFT)GetInputStreamInfo");
1311    
1312            if (pStreamInfo == NULL)
1313                    return E_POINTER;
1314    
1315            if (dwInputStreamID != 0)
1316                    return MF_E_INVALIDSTREAMNUMBER;
1317    
1318            EnterCriticalSection(&m_mft_lock);
1319    
1320            pStreamInfo->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER;
1321            pStreamInfo->hnsMaxLatency = 0;
1322    
1323            pStreamInfo->cbSize = 1; /* Need atleast 1 byte input */
1324            pStreamInfo->cbMaxLookahead = 0;
1325            pStreamInfo->cbAlignment = 1;
1326    
1327            LeaveCriticalSection(&m_mft_lock);
1328            return S_OK;
1329    }
1330    
1331    HRESULT CXvidDecoder::MFTGetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo)
1332    {
1333            DPRINTF("(MFT)GetOutputStreamInfo");
1334    
1335            if (pStreamInfo == NULL)
1336                    return E_POINTER;
1337    
1338            if (dwOutputStreamID != 0)
1339                    return MF_E_INVALIDSTREAMNUMBER;
1340    
1341            EnterCriticalSection(&m_mft_lock);
1342    
1343            pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_DISCARDABLE;
1344    
1345            if (m_pOutputType == NULL) {
1346                    pStreamInfo->cbSize = 0;
1347                    pStreamInfo->cbAlignment = 0;
1348            }
1349            else {
1350                    pStreamInfo->cbSize = (m_create.width * abs(m_create.height) * m_pOutputTypeBPP) >> 3;
1351                    pStreamInfo->cbAlignment = 1;
1352            }
1353    
1354            LeaveCriticalSection(&m_mft_lock);
1355            return S_OK;
1356    }
1357    
1358    HRESULT CXvidDecoder::GetAttributes(IMFAttributes** pAttributes)
1359    {
1360            DPRINTF("(MFT)GetAttributes");
1361            return E_NOTIMPL; /* We don't support any attributes */
1362    }
1363    
1364    HRESULT CXvidDecoder::GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes **ppAttributes)
1365    {
1366            DPRINTF("(MFT)GetInputStreamAttributes");
1367            return E_NOTIMPL; /* We don't support any attributes */
1368    }
1369    
1370    HRESULT CXvidDecoder::GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes **ppAttributes)
1371    {
1372            DPRINTF("(MFT)GetOutputStreamAttributes");
1373            return E_NOTIMPL; /* We don't support any attributes */
1374    }
1375    
1376    HRESULT CXvidDecoder::MFTDeleteInputStream(DWORD dwStreamID)
1377    {
1378            DPRINTF("(MFT)DeleteInputStream");
1379            return E_NOTIMPL; /* We have a fixed number of streams */
1380    }
1381    
1382    HRESULT CXvidDecoder::MFTAddInputStreams(DWORD cStreams, DWORD *adwStreamIDs)
1383    {
1384            DPRINTF("(MFT)AddInputStreams");
1385            return E_NOTIMPL; /* We have a fixed number of streams */
1386    }
1387    
1388    HRESULT CXvidDecoder::MFTGetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1389    {
1390            DPRINTF("(MFT)GetInputAvailableType");
1391    
1392            if (dwInputStreamID != 0)
1393                    return MF_E_INVALIDSTREAMNUMBER;
1394    
1395            DWORD i = 0;
1396            GUID *bs_guid_table[8];
1397    
1398            bs_guid_table[i++] = (GUID *)&CLSID_XVID;
1399            bs_guid_table[i++] = (GUID *)&CLSID_XVID_UC;
1400    
1401            if (g_config.supported_4cc & SUPPORT_3IVX) {
1402                    bs_guid_table[i++] = (GUID *)&CLSID_3IVX;
1403                    bs_guid_table[i++] = (GUID *)&CLSID_3IVX_UC;
1404                    bs_guid_table[i++] = (GUID *)&CLSID_3IV0;
1405                    bs_guid_table[i++] = (GUID *)&CLSID_3IV0_UC;
1406                    bs_guid_table[i++] = (GUID *)&CLSID_3IV1;
1407                    bs_guid_table[i++] = (GUID *)&CLSID_3IV1_UC;
1408                    bs_guid_table[i++] = (GUID *)&CLSID_3IV2;
1409                    bs_guid_table[i++] = (GUID *)&CLSID_3IV2_UC;
1410            }
1411            if (g_config.supported_4cc & SUPPORT_DIVX) {
1412                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX;
1413                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX_UC;
1414                    bs_guid_table[i++] = (GUID *)&CLSID_DX50;
1415                    bs_guid_table[i++] = (GUID *)&CLSID_DX50_UC;
1416            }
1417            if (g_config.supported_4cc & SUPPORT_MP4V) {
1418                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V;
1419                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V_UC;
1420                    bs_guid_table[i++] = (GUID *)&CLSID_LMP4;
1421                    bs_guid_table[i++] = (GUID *)&CLSID_LMP4_UC;
1422                    bs_guid_table[i++] = (GUID *)&CLSID_RMP4;
1423                    bs_guid_table[i++] = (GUID *)&CLSID_RMP4_UC;
1424                    bs_guid_table[i++] = (GUID *)&CLSID_SMP4;
1425                    bs_guid_table[i++] = (GUID *)&CLSID_SMP4_UC;
1426                    bs_guid_table[i++] = (GUID *)&CLSID_HDX4;
1427                    bs_guid_table[i++] = (GUID *)&CLSID_HDX4_UC;
1428            }
1429    
1430            const GUID *subtype;
1431            if (dwTypeIndex < i) {
1432                    subtype = bs_guid_table[dwTypeIndex];
1433            }
1434            else {
1435                    return MF_E_NO_MORE_TYPES;
1436            }
1437    
1438            EnterCriticalSection(&m_mft_lock);
1439    
1440            HRESULT hr = S_OK;
1441    
1442            if (ppType) {
1443                    IMFMediaType *pInputType = NULL;
1444                    hr = MFCreateMediaType(&pInputType);
1445    
1446                    if (SUCCEEDED(hr))
1447                            hr = pInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1448    
1449                    if (SUCCEEDED(hr))
1450                            hr = pInputType->SetGUID(MF_MT_SUBTYPE, *subtype);
1451    
1452                    if (SUCCEEDED(hr)) {
1453                            *ppType = pInputType;
1454                            (*ppType)->AddRef();
1455                    }
1456                    if (pInputType) pInputType->Release();
1457            }
1458    
1459            LeaveCriticalSection(&m_mft_lock);
1460    
1461            return hr;
1462    }
1463    
1464    HRESULT CXvidDecoder::MFTGetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1465    {
1466            DPRINTF("(MFT)GetOutputAvailableType");
1467    
1468            if (ppType == NULL)
1469                    return E_INVALIDARG;
1470    
1471            if (dwOutputStreamID != 0)
1472                    return MF_E_INVALIDSTREAMNUMBER;
1473    
1474            if (dwTypeIndex < 0) return E_INVALIDARG;
1475    
1476            GUID csp;
1477            int bitdepth = 8;
1478            switch(dwTypeIndex)
1479            {
1480            case 0:
1481    if ( USE_YUY2 )
1482    {
1483                    csp = MFVideoFormat_YUY2;
1484                    bitdepth = 4;
1485                    break;
1486    }
1487            case 1:
1488    if ( USE_YVYU )
1489    {
1490                csp = MFVideoFormat_YVYU;
1491                bitdepth = 4;
1492                break;
1493    }
1494            case 2 :
1495    if ( USE_UYVY )
1496    {
1497                    csp = MFVideoFormat_UYVY;
1498                    bitdepth = 4;
1499                    break;
1500    }
1501            case 3  :
1502                    if ( USE_IYUV )
1503    {
1504                    csp = MFVideoFormat_IYUV;
1505                    bitdepth = 3;
1506                    break;
1507    }
1508            case 4  :
1509    if ( USE_YV12 )
1510    {
1511                    csp = MFVideoFormat_YV12;
1512                    bitdepth = 3;
1513                    break;
1514    }
1515            case 5 :
1516    if ( USE_RGB32 )
1517    {
1518                    csp = MFVideoFormat_RGB32;
1519                    bitdepth = 8;
1520                    break;
1521    }
1522            case 6 :
1523    if ( USE_RGB24 )
1524    {
1525                    csp = MFVideoFormat_RGB24;
1526                    bitdepth = 6;
1527                    break;
1528    }
1529            case 7 :
1530    if ( USE_RG555 )
1531    {
1532                    csp = MFVideoFormat_RGB555;
1533                    bitdepth = 4;
1534                    break;
1535    }
1536            case 8 :
1537    if ( USE_RG565 )
1538    {
1539                    csp = MFVideoFormat_RGB565;
1540                    bitdepth = 4;
1541                    break;
1542    }
1543            default :
1544                    return MF_E_NO_MORE_TYPES;
1545            }
1546    
1547            if (m_pInputType == NULL)
1548                    return MF_E_TRANSFORM_TYPE_NOT_SET;
1549    
1550            EnterCriticalSection(&m_mft_lock);
1551    
1552            HRESULT hr = S_OK;
1553    
1554            IMFMediaType *pOutputType = NULL;
1555            hr = MFCreateMediaType(&pOutputType);
1556    
1557            if (SUCCEEDED(hr)) {
1558                    hr = pOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1559            }
1560    
1561            if (SUCCEEDED(hr)) {
1562                    hr = pOutputType->SetGUID(MF_MT_SUBTYPE, csp);
1563        }
1564    
1565            if (SUCCEEDED(hr)) {
1566                    hr = pOutputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE);
1567            }
1568    
1569            if (SUCCEEDED(hr)) {
1570                    hr = pOutputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
1571            }
1572    
1573            if (SUCCEEDED(hr)) {
1574                    hr = pOutputType->SetUINT32(MF_MT_SAMPLE_SIZE, (abs(m_create.height) * m_create.width * bitdepth) >> 1);
1575            }
1576    
1577            if (SUCCEEDED(hr)) {
1578                    hr = MFSetAttributeSize(pOutputType, MF_MT_FRAME_SIZE, m_create.width, abs(m_create.height));
1579            }
1580    
1581            if (SUCCEEDED(hr)) {
1582                    hr = MFSetAttributeRatio(pOutputType, MF_MT_FRAME_RATE, m_frameRate.Numerator, m_frameRate.Denominator);
1583            }
1584    
1585            if (SUCCEEDED(hr)) {
1586                    hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
1587            }
1588    
1589            if (SUCCEEDED(hr)) {
1590                    hr = MFSetAttributeRatio(pOutputType, MF_MT_PIXEL_ASPECT_RATIO, ar_x, ar_y);
1591            }
1592    
1593            if (SUCCEEDED(hr)) {
1594                    *ppType = pOutputType;
1595                    (*ppType)->AddRef();
1596            }
1597    
1598            if (pOutputType) pOutputType->Release();
1599    
1600            LeaveCriticalSection(&m_mft_lock);
1601            return hr;
1602    }
1603    
1604    HRESULT CXvidDecoder::MFTSetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags)
1605    {
1606            DPRINTF("(MFT)SetInputType");
1607    
1608            if (dwInputStreamID != 0)
1609                    return MF_E_INVALIDSTREAMNUMBER;
1610    
1611            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1612                    return E_INVALIDARG;
1613    
1614            EnterCriticalSection(&m_mft_lock);
1615    
1616            HRESULT hr = S_OK;
1617    
1618            /* Actually set the type or just test it? */
1619            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1620    
1621            /* If we have samples pending the type can't be changed right now */
1622            if (HasPendingOutput())
1623                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1624    
1625            if (SUCCEEDED(hr)) {
1626            if (pType) { /* Check the type */
1627                hr = OnCheckInputType(pType);
1628            }
1629            }
1630    
1631            if (SUCCEEDED(hr)) {
1632                    if (bReallySet) { /* Set the type if needed */
1633                            hr = OnSetInputType(pType);
1634                    }
1635            }
1636    
1637            LeaveCriticalSection(&m_mft_lock);
1638            return hr;
1639    }
1640    
1641    DWORD WINAPI CreateTrayIcon(LPVOID lpParameter)
1642    {
1643            WNDCLASSEX wc;
1644    
1645            wc.cbSize = sizeof(WNDCLASSEX);
1646            wc.lpfnWndProc = msg_proc;
1647            wc.style = CS_HREDRAW | CS_VREDRAW;
1648            wc.cbWndExtra = 0;
1649            wc.cbClsExtra = 0;
1650            wc.hInstance = (HINSTANCE)g_xvid_hInst;
1651            wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
1652            wc.lpszMenuName = NULL;
1653            wc.lpszClassName = "XVID_MSG_WINDOW";
1654            wc.hIcon = NULL;
1655            wc.hIconSm = NULL;
1656            wc.hCursor = NULL;
1657            RegisterClassEx(&wc);
1658    
1659            MSG_hwnd = CreateWindowEx(0, "XVID_MSG_WINDOW", NULL, 0, CW_USEDEFAULT,
1660                    CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE)g_xvid_hInst, NULL);
1661    
1662            /* display the tray icon */
1663            NOTIFYICONDATA nid;
1664            ZeroMemory(&nid, sizeof(NOTIFYICONDATA));
1665    
1666            nid.cbSize = sizeof(NOTIFYICONDATA);
1667            nid.hWnd = MSG_hwnd;
1668            nid.uID = 1456;
1669            nid.uVersion = NOTIFYICON_VERSION;
1670            nid.uCallbackMessage = WM_ICONMESSAGE;
1671            nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
1672            strcpy_s(nid.szTip, 19, "Xvid Video Decoder");
1673            nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_SHOWTIP;
1674    
1675            Shell_NotifyIcon(NIM_ADD, &nid);
1676            Shell_NotifyIcon(NIM_SETVERSION, &nid);
1677    
1678            DestroyIcon(nid.hIcon);
1679    
1680            MSG msg;
1681            while (MSG_hwnd && GetMessage(&msg, MSG_hwnd, 0, 0)) {
1682                    TranslateMessage(&msg);
1683                    DispatchMessage(&msg);
1684            }
1685    
1686            return 0;
1687    }
1688    
1689    HRESULT CXvidDecoder::MFTSetOutputType(DWORD dwOutputStreamID, IMFMediaType *pType, DWORD dwFlags)
1690    {
1691            DPRINTF("(MFT)SetOutputType");
1692    
1693            if (dwOutputStreamID != 0)
1694                    return MF_E_INVALIDSTREAMNUMBER;
1695    
1696            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1697                    return E_INVALIDARG;
1698    
1699            HRESULT hr = S_OK;
1700    
1701            EnterCriticalSection(&m_mft_lock);
1702    
1703            /* Actually set the type or just test it? */
1704            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1705    
1706            /* If we have samples pending the type can't be changed right now */
1707            if (HasPendingOutput())
1708                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1709    
1710            int bitdepth;
1711            if (SUCCEEDED(hr)) {
1712                    if (pType) { /* Check the type */
1713                            AM_MEDIA_TYPE *am;
1714                            hr = MFCreateAMMediaTypeFromMFMediaType(pType, GUID_NULL, &am);
1715    
1716                            if (SUCCEEDED(hr)) {
1717                                    if (FAILED(ChangeColorspace(am->subtype, am->formattype, am->pbFormat, &bitdepth, 1))) {
1718                                            DPRINTF("(MFT)InternalCheckOutputType (MF_E_INVALIDTYPE)");
1719                                            return MF_E_INVALIDTYPE;
1720                                    }
1721    
1722                            CoTaskMemFree(am->pbFormat);
1723                            CoTaskMemFree(am);
1724                            }
1725                    }
1726            }
1727    
1728            if (SUCCEEDED(hr)) {
1729                    if (bReallySet) { /* Set the type if needed */
1730                            hr = OnSetOutputType(pType, bitdepth);
1731                    }
1732            }
1733    
1734            if (SUCCEEDED(hr) && (MSG_hwnd == 0) && (m_tray_icon == 0) && (g_config.bTrayIcon != 0))
1735            {
1736                    m_thread_handle = CreateThread(NULL, 0, CreateTrayIcon, NULL, 0, NULL);  /* Create message passing window */
1737    
1738                    if (m_thread_handle)
1739                        m_tray_icon = 1;
1740            }
1741    
1742            LeaveCriticalSection(&m_mft_lock);
1743    
1744            return hr;
1745    }
1746    
1747    HRESULT CXvidDecoder::MFTGetInputCurrentType(DWORD dwInputStreamID, IMFMediaType **ppType)
1748    {
1749            DPRINTF("(MFT)GetInputCurrentType");
1750    
1751            if (ppType == NULL)
1752                    return E_POINTER;
1753    
1754            if (dwInputStreamID != 0)
1755                    return MF_E_INVALIDSTREAMNUMBER;
1756    
1757            EnterCriticalSection(&m_mft_lock);
1758    
1759            HRESULT hr = S_OK;
1760    
1761            if (!m_pInputType)
1762                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1763    
1764            if (SUCCEEDED(hr)) {
1765                    *ppType = m_pInputType;
1766                    (*ppType)->AddRef();
1767            }
1768    
1769            LeaveCriticalSection(&m_mft_lock);
1770            return hr;
1771    }
1772    
1773    HRESULT CXvidDecoder::MFTGetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType)
1774    {
1775            DPRINTF("(MFT)GetOutputCurrentType");
1776    
1777            if (ppType == NULL)
1778                    return E_POINTER;
1779    
1780            if (dwOutputStreamID != 0)
1781                    return MF_E_INVALIDSTREAMNUMBER;
1782    
1783            EnterCriticalSection(&m_mft_lock);
1784    
1785            HRESULT hr = S_OK;
1786    
1787            if (!m_pOutputType)
1788                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1789    
1790            if (SUCCEEDED(hr)) {
1791                    *ppType = m_pOutputType;
1792                    (*ppType)->AddRef();
1793            }
1794    
1795            LeaveCriticalSection(&m_mft_lock);
1796            return hr;
1797    }
1798    
1799    HRESULT CXvidDecoder::MFTGetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags)
1800    {
1801            DPRINTF("(MFT)GetInputStatus");
1802    
1803            if (pdwFlags == NULL)
1804                    return E_POINTER;
1805    
1806            if (dwInputStreamID != 0)
1807                    return MF_E_INVALIDSTREAMNUMBER;
1808    
1809            EnterCriticalSection(&m_mft_lock);
1810    
1811            /* If there's pending output samples we don't accept new
1812               input data until ProcessOutput() or Flush() was called */
1813            if (!HasPendingOutput()) {
1814                    *pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
1815            }
1816            else {
1817                    *pdwFlags = 0;
1818            }
1819    
1820            LeaveCriticalSection(&m_mft_lock);
1821    
1822            return S_OK;
1823    }
1824    
1825    HRESULT CXvidDecoder::MFTGetOutputStatus(DWORD *pdwFlags)
1826    {
1827            DPRINTF("(MFT)GetOutputStatus");
1828    
1829            if (pdwFlags == NULL)
1830                    return E_POINTER;
1831    
1832            EnterCriticalSection(&m_mft_lock);
1833    
1834            /* We can render an output sample only after we
1835               have decoded one */
1836            if (HasPendingOutput()) {
1837                    *pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
1838            }
1839            else {
1840                    *pdwFlags = 0;
1841            }
1842    
1843            LeaveCriticalSection(&m_mft_lock);
1844    
1845            return S_OK;
1846    }
1847    
1848    HRESULT CXvidDecoder::MFTSetOutputBounds(LONGLONG hnsLowerBound, LONGLONG hnsUpperBound)
1849    {
1850            DPRINTF("(MFT)SetOutputBounds");
1851            return E_NOTIMPL;
1852    }
1853    
1854    HRESULT CXvidDecoder::MFTProcessEvent(DWORD dwInputStreamID, IMFMediaEvent *pEvent)
1855    {
1856            DPRINTF("(MFT)ProcessEvent");
1857            return E_NOTIMPL; /* We don't handle any stream events */
1858    }
1859    
1860    HRESULT CXvidDecoder::MFTProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
1861    {
1862            DPRINTF("(MFT)ProcessMessage");
1863            HRESULT hr = S_OK;
1864    
1865            EnterCriticalSection(&m_mft_lock);
1866    
1867            switch (eMessage)
1868            {
1869            case MFT_MESSAGE_COMMAND_FLUSH:
1870                    if (m_create.handle != NULL) {
1871                            DPRINTF("(MFT)CommandFlush");
1872    
1873                            xvid_dec_stats_t stats;
1874                            int used_bytes;
1875    
1876                            memset(&stats, 0, sizeof(stats));
1877                            stats.version = XVID_VERSION;
1878    
1879                            int csp = m_frame.output.csp;
1880    
1881                            m_frame.output.csp = XVID_CSP_INTERNAL;
1882                            m_frame.bitstream = NULL;
1883                            m_frame.length = -1;
1884                            m_frame.general = XVID_LOWDELAY;
1885    
1886                            do {
1887                                    used_bytes = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1888                            } while(used_bytes>=0 && stats.type <= 0);
1889    
1890                            m_frame.output.csp = csp;
1891                            m_frame.output.plane[1] = NULL; /* Don't display flushed samples */
1892    
1893                            //m_timestamp = INVALID_TIME;
1894                            //m_timelength = INVALID_TIME;
1895                            //m_rtFrame = 0;
1896            }
1897        break;
1898    
1899            case MFT_MESSAGE_COMMAND_DRAIN:
1900                    m_discont = 1; /* Set discontinuity flag */
1901                    m_rtFrame = 0;
1902                    break;
1903    
1904            case MFT_MESSAGE_SET_D3D_MANAGER:
1905                    hr = E_NOTIMPL;
1906                    break;
1907    
1908            case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
1909            case MFT_MESSAGE_NOTIFY_END_STREAMING:
1910                    break;
1911    
1912            case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
1913            case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
1914                    break;
1915            }
1916    
1917            LeaveCriticalSection(&m_mft_lock);
1918    
1919            return hr;
1920    }
1921    
1922    HRESULT CXvidDecoder::MFTProcessInput(DWORD dwInputStreamID, IMFSample *pSample, DWORD dwFlags)
1923    {
1924            DPRINTF("(MFT)ProcessInput");
1925    
1926            if (pSample == NULL)
1927                    return E_POINTER;
1928    
1929            if (dwInputStreamID != 0)
1930                    return MF_E_INVALIDSTREAMNUMBER;
1931    
1932            if (dwFlags != 0)
1933                    return E_INVALIDARG;
1934    
1935            if (!m_pInputType || !m_pOutputType) {
1936                    return MF_E_NOTACCEPTING;   /* Must have set input and output types */
1937            }
1938            else if (HasPendingOutput()) {
1939                    return MF_E_NOTACCEPTING;   /* We still have output samples to render */
1940            }
1941    
1942            xvid_dec_stats_t stats;
1943            int length;
1944    
1945            memset(&stats, 0, sizeof(stats));
1946            stats.version = XVID_VERSION;
1947    
1948            if (m_create.handle == NULL)
1949            {
1950                    if (xvid_decore_func == NULL)
1951                            return E_FAIL;
1952                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
1953                    {
1954                            DPRINTF("*** XVID_DEC_CREATE error");
1955                            return E_FAIL;
1956                    }
1957            }
1958    
1959            EnterCriticalSection(&m_mft_lock);
1960    
1961            HRESULT hr = S_OK;
1962            IMFMediaBuffer *pBuffer;
1963    
1964            if (SUCCEEDED(hr)) {
1965                    hr = pSample->ConvertToContiguousBuffer(&pBuffer);
1966            }
1967    
1968            if (SUCCEEDED(hr)) {
1969                    hr = pBuffer->Lock((BYTE**)&m_frame.bitstream, NULL, (DWORD *)&m_frame.length);
1970            }
1971    
1972            m_frame.general = XVID_LOWDELAY;
1973    
1974            if (m_discont == 1) {
1975                    m_frame.general |= XVID_DISCONTINUITY;
1976                    m_discont = 0;
1977            }
1978    
1979            if (g_config.nDeblock_Y)
1980                    m_frame.general |= XVID_DEBLOCKY;
1981    
1982            if (g_config.nDeblock_UV)
1983                    m_frame.general |= XVID_DEBLOCKUV;
1984    
1985            if (g_config.nDering_Y)
1986                    m_frame.general |= XVID_DERINGY;
1987    
1988            if (g_config.nDering_UV)
1989                    m_frame.general |= XVID_DERINGUV;
1990    
1991            if (g_config.nFilmEffect)
1992                    m_frame.general |= XVID_FILMEFFECT;
1993    
1994            m_frame.brightness = g_config.nBrightness;
1995    
1996            m_frame.output.csp &= ~XVID_CSP_VFLIP;
1997            m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0);
1998    
1999            int csp = m_frame.output.csp;
2000            m_frame.output.csp = XVID_CSP_INTERNAL;
2001    
2002        // Paranoid check.
2003            if (xvid_decore_func == NULL) {
2004                    hr = E_FAIL;
2005                    goto END_LOOP;
2006            }
2007    
2008    repeat :
2009            length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
2010    
2011            if (length == XVID_ERR_MEMORY) {
2012                    hr = E_FAIL;
2013                    goto END_LOOP;
2014            }
2015            else if (length < 0)
2016            {
2017                    DPRINTF("*** XVID_DEC_DECODE");
2018                    goto END_LOOP;
2019            }
2020    
2021            if (stats.type == XVID_TYPE_NOTHING && length > 0) {
2022                    DPRINTF(" B-Frame decoder lag");
2023                    m_frame.output.plane[1] = NULL;
2024                    goto END_LOOP;
2025            }
2026    
2027            if (stats.type == XVID_TYPE_VOL)
2028            {
2029                    if (stats.data.vol.width != m_create.width ||
2030                            stats.data.vol.height != m_create.height)
2031                    {
2032                            DPRINTF("TODO: auto-resize");
2033                            m_frame.output.plane[1] = NULL;
2034                            hr = E_FAIL;
2035                    }
2036    
2037                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) { /* auto */
2038                            int par_x, par_y;
2039                            if (stats.data.vol.par == XVID_PAR_EXT) {
2040                                    par_x = stats.data.vol.par_width;
2041                                    par_y = stats.data.vol.par_height;
2042                            } else {
2043                                    par_x = PARS[stats.data.vol.par-1][0];
2044                                    par_y = PARS[stats.data.vol.par-1][1];
2045                            }
2046    
2047                            ar_x = par_x * stats.data.vol.width;
2048                            ar_y = par_y * stats.data.vol.height; /* TODO: Actually set the newly determined AR on the output sample type
2049                                                                                                               or it'll have no effect at all... */
2050                    }
2051    
2052                    m_frame.bitstream = (BYTE*)m_frame.bitstream + length;
2053                    m_frame.length -= length;
2054                    goto repeat;
2055            }
2056    
2057    END_LOOP:
2058            m_frame.output.csp = csp;
2059    
2060            if (pBuffer) {
2061                    pBuffer->Unlock();
2062                    pBuffer->Release();
2063            }
2064    
2065            if (SUCCEEDED(hr)) {
2066                    /* Try to get a timestamp */
2067                    if (FAILED(pSample->GetSampleTime(&m_timestamp)))
2068                            m_timestamp = INVALID_TIME;
2069    
2070                    if (FAILED(pSample->GetSampleDuration(&m_timelength))) {
2071                            m_timelength = INVALID_TIME;
2072                    }
2073                    if (m_timestamp != INVALID_TIME && stats.type == XVID_TYPE_IVOP) {
2074                            m_rtFrame = m_timestamp;
2075                    }
2076            }
2077    
2078            LeaveCriticalSection(&m_mft_lock);
2079    
2080            return hr;
2081    }
2082    
2083    HRESULT CXvidDecoder::MFTProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus)
2084    {
2085            DPRINTF("(MFT)ProcessOutput");
2086    
2087            /* Preroll in MFT ??
2088               Flags ?? -> TODO... */
2089            if (dwFlags != 0)
2090                    return E_INVALIDARG;
2091    
2092            if (pOutputSamples == NULL || pdwStatus == NULL)
2093                    return E_POINTER;
2094    
2095            if (cOutputBufferCount != 1) /* Must be exactly one output buffer */
2096                    return E_INVALIDARG;
2097    
2098            if (pOutputSamples[0].pSample == NULL) /* Must have a sample */
2099                    return E_INVALIDARG;
2100    
2101            if (!HasPendingOutput()) { /* If there's no sample we need to decode one first */
2102                    return MF_E_TRANSFORM_NEED_MORE_INPUT;
2103            }
2104    
2105            EnterCriticalSection(&m_mft_lock);
2106    
2107            HRESULT hr = S_OK;
2108    
2109            BYTE *Dst = NULL;
2110            DWORD buffer_size;
2111            LONG stride = m_create.width;
2112            IMFMediaBuffer *pOutput = NULL;
2113            IMF2DBuffer *pOutput2D = NULL;
2114    
2115            if (SUCCEEDED(hr)) {
2116                    hr = pOutputSamples[0].pSample->GetBufferByIndex(0, &pOutput); /* Get output buffer */
2117            }
2118    
2119            if (SUCCEEDED(hr)) {
2120                    hr = pOutput->GetMaxLength(&buffer_size);
2121            }
2122    
2123            if (SUCCEEDED(hr)) {
2124                    hr = pOutput->QueryInterface(IID_IMF2DBuffer, (void **)&pOutput2D);
2125            }
2126    
2127            if (SUCCEEDED(hr)) {
2128                    hr = pOutput2D->Lock2D(&Dst, &stride);
2129            }
2130            else {
2131                    hr = pOutput->Lock(&Dst, NULL, NULL);
2132            }
2133    
2134            if (SUCCEEDED(hr)) {
2135                    xvid_gbl_convert_t convert;
2136    
2137                    memset(&convert, 0, sizeof(convert));
2138                    convert.version = XVID_VERSION;
2139    
2140                    convert.input.csp = XVID_CSP_INTERNAL;
2141                    convert.input.plane[0] = m_frame.output.plane[0];
2142                    convert.input.plane[1] = m_frame.output.plane[1];
2143                    convert.input.plane[2] = m_frame.output.plane[2];
2144                    convert.input.stride[0] = m_frame.output.stride[0];
2145                    convert.input.stride[1] = m_frame.output.stride[1];
2146                    convert.input.stride[2] = m_frame.output.stride[2];
2147    
2148                    convert.output.csp = m_frame.output.csp;
2149                    convert.output.plane[0] = Dst;
2150                    convert.output.stride[0] = stride;
2151    
2152                    convert.width = m_create.width;
2153                    convert.height = m_create.height;
2154                    convert.interlacing = 0;
2155    
2156                    if (m_frame.output.plane[1] != NULL && Dst != NULL && xvid_global_func != NULL)
2157                            if (xvid_global_func(0, XVID_GBL_CONVERT, &convert, NULL) < 0) /* CSP convert into output buffer */
2158                                    hr = E_FAIL;
2159                    m_frame.output.plane[1] = NULL;
2160            }
2161    
2162            *pdwStatus = 0;
2163    
2164            if (SUCCEEDED(hr)) {
2165                    if (SUCCEEDED(hr))
2166                            hr = pOutputSamples[0].pSample->SetUINT32(MFSampleExtension_CleanPoint, TRUE); // key frame
2167    
2168                    if (SUCCEEDED(hr)) { /* Set timestamp of output sample */
2169                            if (m_timestamp != INVALID_TIME)
2170                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_timestamp);
2171                            else
2172                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_rtFrame);
2173    
2174                            if (m_timelength != INVALID_TIME)
2175                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_timelength);
2176                            else
2177                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_duration);
2178    
2179                            m_rtFrame += m_duration;
2180                    }
2181    
2182                    if (SUCCEEDED(hr))
2183                            hr = pOutput->SetCurrentLength((m_create.width * abs(m_create.height) * m_pOutputTypeBPP) >> 3);
2184            }
2185    
2186            if (pOutput2D) {
2187                    pOutput2D->Unlock2D();
2188                    pOutput2D->Release();
2189                    if (pOutput)
2190                        pOutput->Release();
2191            }
2192            else if (pOutput) {
2193                    pOutput->Unlock();
2194                    pOutput->Release();
2195            }
2196    
2197            LeaveCriticalSection(&m_mft_lock);
2198    
2199            return hr;
2200    }
2201    
2202    HRESULT CXvidDecoder::OnCheckInputType(IMFMediaType *pmt)
2203    {
2204            DPRINTF("(MFT)CheckInputType");
2205    
2206            HRESULT hr = S_OK;
2207    
2208            /*  Check if input type is already set. Reject any type that is not identical */
2209            if (m_pInputType) {
2210                    DWORD dwFlags = 0;
2211                    if (S_OK == m_pInputType->IsEqual(pmt, &dwFlags)) {
2212                            return S_OK;
2213                    }
2214                    else {
2215                            return MF_E_INVALIDTYPE;
2216                    }
2217            }
2218    
2219            GUID majortype = {0}, subtype = {0};
2220            UINT32 width = 0, height = 0;
2221    
2222            hr = pmt->GetMajorType(&majortype);
2223    
2224            if (SUCCEEDED(hr)) {
2225                    if (majortype != MFMediaType_Video) { /* Must be Video */
2226                            hr = MF_E_INVALIDTYPE;
2227                    }
2228            }
2229    
2230            if (m_hdll == NULL) {
2231                    HRESULT hr = OpenLib();
2232    
2233                    if (FAILED(hr) || (m_hdll == NULL)) // Paranoid checks.
2234                            hr = MF_E_INVALIDTYPE;
2235            }
2236    
2237            if (SUCCEEDED(hr)) {
2238                    hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &width, &height);
2239            }
2240    
2241            /* Check the frame size */
2242            if (SUCCEEDED(hr)) {
2243                    if (width > 4096 || height > 4096) {
2244                            hr = MF_E_INVALIDTYPE;
2245                    }
2246            }
2247            m_create.width = width;
2248            m_create.height = height;
2249    
2250            if (SUCCEEDED(hr)) {
2251                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
2252                            hr = MFGetAttributeRatio(pmt, MF_MT_PIXEL_ASPECT_RATIO, (UINT32*)&ar_x, (UINT32*)&ar_y);
2253                    }
2254            }
2255    
2256            /* TODO1: Make sure there really is a frame rate after all!
2257               TODO2: Use the framerate for something! */
2258            MFRatio fps = {0};
2259            if (SUCCEEDED(hr)) {
2260                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&fps.Numerator, (UINT32*)&fps.Denominator);
2261            }
2262    
2263            if (SUCCEEDED(hr)) {
2264                    hr = pmt->GetGUID(MF_MT_SUBTYPE, &subtype);
2265            }
2266    
2267            if (subtype == CLSID_MP4V || subtype == CLSID_MP4V_UC ||
2268                subtype == CLSID_LMP4 || subtype == CLSID_LMP4_UC ||
2269                subtype == CLSID_RMP4 || subtype == CLSID_RMP4_UC ||
2270                subtype == CLSID_SMP4 || subtype == CLSID_SMP4_UC ||
2271                subtype == CLSID_HDX4 || subtype == CLSID_HDX4_UC) {
2272                    if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
2273                            CloseLib();
2274                            hr = MF_E_INVALIDTYPE;
2275                    }
2276                    else m_create.fourcc = FOURCC_MP4V;
2277            }
2278            else if (subtype == CLSID_DIVX || subtype == CLSID_DIVX_UC) {
2279                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2280                            CloseLib();
2281                            hr = MF_E_INVALIDTYPE;
2282                    }
2283                    else m_create.fourcc = FOURCC_DIVX;
2284            }
2285            else if (subtype == CLSID_DX50 || subtype == CLSID_DX50_UC) {
2286                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2287                            CloseLib();
2288                            hr = MF_E_INVALIDTYPE;
2289                    }
2290                    else m_create.fourcc = FOURCC_DX50;
2291            }
2292            else if (subtype == CLSID_3IVX || subtype == CLSID_3IVX_UC ||
2293                     subtype == CLSID_3IV0 || subtype == CLSID_3IV0_UC ||
2294                     subtype == CLSID_3IV1 || subtype == CLSID_3IV1_UC ||
2295                     subtype == CLSID_3IV2 || subtype == CLSID_3IV2_UC) {
2296                    if (!(g_config.supported_4cc & SUPPORT_3IVX)) {
2297                            CloseLib();
2298                            hr = MF_E_INVALIDTYPE;
2299                    }
2300                    else m_create.fourcc = FOURCC_3IVX;
2301            }
2302            else if (subtype == CLSID_XVID || subtype == CLSID_XVID_UC) {
2303                    m_create.fourcc = FOURCC_XVID;
2304            }
2305            else {
2306                    DPRINTF("Unknown subtype!");
2307                    CloseLib();
2308                    hr = MF_E_INVALIDTYPE;
2309            }
2310    
2311            /* haali media splitter reports VOL information in the format header */
2312            if (SUCCEEDED(hr))
2313            {
2314                    UINT32 cbSeqHeader = 0;
2315    
2316                    (void)pmt->GetBlobSize(MF_MT_MPEG_SEQUENCE_HEADER, &cbSeqHeader);
2317    
2318                    if (cbSeqHeader>0) {
2319                            xvid_dec_stats_t stats;
2320                            memset(&stats, 0, sizeof(stats));
2321                            stats.version = XVID_VERSION;
2322    
2323                            if (m_create.handle == NULL) {
2324                                    if (xvid_decore_func == NULL)
2325                                            hr = E_FAIL;
2326                                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
2327                                            DPRINTF("*** XVID_DEC_CREATE error");
2328                                            hr = E_FAIL;
2329                                    }
2330                            }
2331    
2332                            if (SUCCEEDED(hr)) {
2333                                    (void)pmt->GetAllocatedBlob(MF_MT_MPEG_SEQUENCE_HEADER, (UINT8 **)&m_frame.bitstream, (UINT32 *)&m_frame.length);
2334                                    m_frame.general = 0;
2335                                    m_frame.output.csp = XVID_CSP_NULL;
2336    
2337                                    int ret = 0;
2338                                    if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
2339                                            /* honour video dimensions reported in VOL header */
2340                                            if (stats.type == XVID_TYPE_VOL) {
2341                                                    m_create.width = stats.data.vol.width;
2342                                                    m_create.height = stats.data.vol.height;
2343                                            }
2344                                    }
2345    
2346                                    if (ret == XVID_ERR_MEMORY) hr = E_FAIL;
2347                                    CoTaskMemFree(m_frame.bitstream);
2348                            }
2349                    }
2350            }
2351    
2352            return hr;
2353    }
2354    
2355    HRESULT CXvidDecoder::OnSetInputType(IMFMediaType *pmt)
2356    {
2357            HRESULT hr = S_OK;
2358            UINT32 w, h;
2359    
2360            if (m_pInputType) m_pInputType->Release();
2361    
2362            hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &w, &h);
2363            m_create.width = w; m_create.height = h;
2364    
2365            if (SUCCEEDED(hr))
2366                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&m_frameRate.Numerator, (UINT32*)&m_frameRate.Denominator);
2367    
2368            if (SUCCEEDED(hr)) { /* Store frame duration, derived from the frame rate */
2369                    hr = MFFrameRateToAverageTimePerFrame(m_frameRate.Numerator, m_frameRate.Denominator, &m_duration);
2370            }
2371    
2372            if (SUCCEEDED(hr)) {
2373                    m_pInputType = pmt;
2374                    m_pInputType->AddRef();
2375            }
2376    
2377            return hr;
2378    }
2379    
2380    HRESULT CXvidDecoder::OnSetOutputType(IMFMediaType *pmt, int bitdepth)
2381    {
2382            if (m_pOutputType) m_pOutputType->Release();
2383    
2384            m_pOutputType = pmt;
2385            m_pOutputType->AddRef();
2386            m_pOutputTypeBPP = bitdepth;
2387    
2388            return S_OK;
2389    }
2390    
2391    #endif /* XVID_USE_MFT */

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

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