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

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

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