[svn] / trunk / xvidcore / dshow / src / CXvidDecoder.cpp Repository:
ViewVC logotype

Diff of /trunk/xvidcore/dshow/src/CXvidDecoder.cpp

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

revision 1437, Sun Apr 18 07:55:11 2004 UTC revision 2134, Mon Jan 11 17:02:15 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.7 2004-04-18 07:55:11 syskin Exp $   * $Id$
  *  
  ****************************************************************************/  
   
 /****************************************************************************  
  *  
  * 2003/12/11 - added some additional options, mainly to make the deblocking  
  *              code from xvidcore available. Most of the new code is taken  
  *              from Nic's dshow filter, (C) Nic, http://nic.dnsalias.com  
24   *   *
25   ****************************************************************************/   ****************************************************************************/
26    
# Line 36  Line 29 
29          place these paths at the top of the Tools|Options|Directories list          place these paths at the top of the Tools|Options|Directories list
30    
31          headers:          headers:
32          C:\DXVCSDK\include          C:\DX90SDK\Include
33          C:\DXVCSDK\samples\Multimedia\DirectShow\BaseClasses          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses
34    
35          libraries (optional):          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Release
36          C:\DXVCSDK\samples\Multimedia\DirectShow\BaseClasses\Release          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Debug
37  */  */
38    
39    #ifdef ENABLE_MFT
40    #define XVID_USE_MFT
41    #endif
42    
43  #include <windows.h>  #include <windows.h>
44    
# Line 55  Line 50 
50  #endif  #endif
51  #include <dvdmedia.h>   // VIDEOINFOHEADER2  #include <dvdmedia.h>   // VIDEOINFOHEADER2
52    
53  #include <xvid.h>               // XviD API  #if defined(XVID_USE_MFT)
54    #define MFT_UNIQUE_METHOD_NAMES
55    #include <mftransform.h>
56    #include <mfapi.h>
57    #include <mferror.h>
58    #include <shlwapi.h>
59    #endif
60    
61    #include <shellapi.h>
62    
63    #include <xvid.h>               // Xvid API
64    
65    #include "resource.h"
66    
67  #include "IXvidDecoder.h"  #include "IXvidDecoder.h"
68  #include "CXvidDecoder.h"  #include "CXvidDecoder.h"
# Line 81  Line 88 
88          { &MEDIATYPE_Video, &CLSID_DIVX_UC },          { &MEDIATYPE_Video, &CLSID_DIVX_UC },
89          { &MEDIATYPE_Video, &CLSID_DX50 },          { &MEDIATYPE_Video, &CLSID_DX50 },
90          { &MEDIATYPE_Video, &CLSID_DX50_UC },          { &MEDIATYPE_Video, &CLSID_DX50_UC },
91            { &MEDIATYPE_Video, &CLSID_3IVX },
92            { &MEDIATYPE_Video, &CLSID_3IVX_UC },
93            { &MEDIATYPE_Video, &CLSID_3IV0 },
94            { &MEDIATYPE_Video, &CLSID_3IV0_UC },
95            { &MEDIATYPE_Video, &CLSID_3IV1 },
96            { &MEDIATYPE_Video, &CLSID_3IV1_UC },
97            { &MEDIATYPE_Video, &CLSID_3IV2 },
98            { &MEDIATYPE_Video, &CLSID_3IV2_UC },
99            { &MEDIATYPE_Video, &CLSID_LMP4 },
100            { &MEDIATYPE_Video, &CLSID_LMP4_UC },
101            { &MEDIATYPE_Video, &CLSID_RMP4 },
102            { &MEDIATYPE_Video, &CLSID_RMP4_UC },
103            { &MEDIATYPE_Video, &CLSID_SMP4 },
104            { &MEDIATYPE_Video, &CLSID_SMP4_UC },
105            { &MEDIATYPE_Video, &CLSID_HDX4 },
106            { &MEDIATYPE_Video, &CLSID_HDX4_UC },
107          { &MEDIATYPE_Video, &CLSID_MP4V },          { &MEDIATYPE_Video, &CLSID_MP4V },
108      { &MEDIATYPE_Video, &CLSID_MP4V_UC },
109  };  };
110    
111  const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] =  const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] =
# Line 121  Line 145 
145  {  {
146          &CLSID_XVID,                    // Filter CLSID          &CLSID_XVID,                    // Filter CLSID
147          XVID_NAME_L,                    // Filter name          XVID_NAME_L,                    // Filter name
148          MERIT_PREFERRED,                // Its merit          MERIT_PREFERRED+2,              // Its merit
149          sizeof(psudPins) / sizeof(AMOVIESETUP_PIN),     // Number of pins          sizeof(psudPins) / sizeof(AMOVIESETUP_PIN),     // Number of pins
150          psudPins                                // Pin details          psudPins                                // Pin details
151  };  };
# Line 148  Line 172 
172    
173  };  };
174    
   
175  /* note: g_cTemplates must be global; used by strmbase.lib(dllentry.cpp,dllsetup.cpp) */  /* note: g_cTemplates must be global; used by strmbase.lib(dllentry.cpp,dllsetup.cpp) */
176  int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate);  int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate);
177    
178    extern HINSTANCE g_xvid_hInst;
179    
180    static int GUI_Page = 0;
181    static 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          ar_x = ar_y = 0;          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", 0);                  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                  MessageBox(0, "xvid_global() not found", "Error", 0);          FreeLibrary(m_hdll);
381                  return;          m_hdll = NULL;
382                    MessageBox(0, "xvid_global() not found", "Error", MB_TOPMOST);
383                    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                  MessageBox(0, "xvid_decore() not found", "Error", 0);          xvid_global_func = NULL;
389                  return;          FreeLibrary(m_hdll);
390            m_hdll = NULL;
391                    MessageBox(0, "xvid_decore() not found", "Error", MB_TOPMOST);
392                    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                  MessageBox(0, "xvid_global() failed", "Error", 0);          xvid_global_func = NULL;
398                  return;          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);
412                    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 285  Line 464 
464                  USE_RGB32 = true;                  USE_RGB32 = true;
465                  break;                  break;
466          }          }
467    
468            switch (g_config.aspect_ratio)
469            {
470            case 0:
471            case 1:
472                    break;
473            case 2:
474                    ar_x = 4;
475                    ar_y = 3;
476                    break;
477            case 3:
478                    ar_x = 16;
479                    ar_y = 9;
480                    break;
481            case 4:
482                    ar_x = 47;
483                    ar_y = 20;
484                    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 300  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 318  Line 550 
550          DPRINTF("CheckInputType");          DPRINTF("CheckInputType");
551          BITMAPINFOHEADER * hdr;          BITMAPINFOHEADER * hdr;
552    
553            ar_x = ar_y = 0;
554    
555          if (*mtIn->Type() != MEDIATYPE_Video)          if (*mtIn->Type() != MEDIATYPE_Video)
556          {          {
557                  DPRINTF("Error: Unknown Type");                  DPRINTF("Error: Unknown Type");
# Line 325  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();
573                  hdr = &vih->bmiHeader;                  hdr = &vih->bmiHeader;
                 /* PAR (x:y) is (1/ppm_X):(1/ppm_Y) where ppm is pixels-per-meter  
                    which is equal to ppm_Y:ppm_X */  
                 ar_x = vih->bmiHeader.biYPelsPerMeter * abs(hdr->biWidth);  
                 ar_y = vih->bmiHeader.biXPelsPerMeter * abs(hdr->biHeight);  
                 DPRINTF("VIDEOINFOHEADER PAR: %d:%d -> AR %d:%d",  
                         vih->bmiHeader.biYPelsPerMeter,vih->bmiHeader.biXPelsPerMeter, ar_x, ar_y);  
574          }          }
575          else if (*mtIn->FormatType() == FORMAT_VideoInfo2)          else if (*mtIn->FormatType() == FORMAT_VideoInfo2)
576          {          {
577                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 *) mtIn->Format();                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 *) mtIn->Format();
578                  hdr = &vih2->bmiHeader;                  hdr = &vih2->bmiHeader;
579                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
580                            ar_x = vih2->dwPictAspectRatioX;
581                            ar_y = vih2->dwPictAspectRatioY;
582                    }
583                    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;                  ar_x = vih2->dwPictAspectRatioX;
591                  ar_y = vih2->dwPictAspectRatioY;                  ar_y = vih2->dwPictAspectRatioY;
592                    }
593                  DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);                  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          {          {
# Line 350  Line 631 
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 361  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 393  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 421  Line 723 
723                  if (ar_x != 0 && ar_y != 0) {                  if (ar_x != 0 && ar_y != 0) {
724                          vih->dwPictAspectRatioX = ar_x;                          vih->dwPictAspectRatioX = ar_x;
725                          vih->dwPictAspectRatioY = ar_y;                          vih->dwPictAspectRatioY = ar_y;
726                            forced_ar = true;
727                  } else { // just to be safe                  } else { // just to be safe
728                          vih->dwPictAspectRatioX = m_create.width;                          vih->dwPictAspectRatioX = m_create.width;
729                          vih->dwPictAspectRatioY = abs(m_create.height);                          vih->dwPictAspectRatioY = abs(m_create.height);
730                            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 533  Line 845 
845    
846    
847  /* (internal function) change colorspace */  /* (internal function) change colorspace */
848    #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;
853            *bitdepth = 32;
854    
855          if (formattype == FORMAT_VideoInfo)          if (formattype == FORMAT_VideoInfo)
856          {          {
857                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;
858                  m_frame.output.stride[0] = (((vih->bmiHeader.biWidth * vih->bmiHeader.biBitCount) + 31) & ~31) >> 3;                  biWidth = vih->bmiHeader.biWidth;
859                    *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                  m_frame.output.stride[0] = (((vih2->bmiHeader.biWidth * vih2->bmiHeader.biBitCount) + 31) & ~31) >> 3;                  biWidth = vih2->bmiHeader.biWidth;
867                    *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 553  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] = (m_frame.output.stride[0] * 2) / 3;  /* 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] = (m_frame.output.stride[0] * 2) / 3;  /* 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 622  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 638  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 689  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 700  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 747  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 :
1143    
# Line 754  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 if ((g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1 && forced_ar == false) || !!(interlaced)) {
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;
1159                                    AM_SAMPLE2_PROPERTIES outProp2;
1160                                    if (SUCCEEDED(pOut->QueryInterface(IID_IMediaSample2, (void **)&pOut2)) &&
1161                                            SUCCEEDED(pOut2->GetProperties(FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, tStart), (PBYTE)&outProp2)))
1162                                    {
1163                                            CMediaType mtOut2 = m_pOutput->CurrentMediaType();
1164                                            VIDEOINFOHEADER2* vihOut2 = (VIDEOINFOHEADER2*)mtOut2.Format();
1165    
1166                                            if (*mtOut2.FormatType() == FORMAT_VideoInfo2)
1167                                            {
1168                                                    int need_format_change = 0;
1169    
1170                                                    if (vihOut2->dwPictAspectRatioX != ar_x && vihOut2->dwPictAspectRatioY != ar_y)
1171                                                    {
1172                                                            vihOut2->dwPictAspectRatioX = ar_x;
1173                                                            vihOut2->dwPictAspectRatioY = ar_y;
1174                                                            int format_change;
1175                                                    }
1176    
1177                                                    if ((interlaced) && !(vihOut2->dwInterlaceFlags & AMINTERLACE_IsInterlaced))
1178                                                    {
1179                                                            vihOut2->dwInterlaceFlags = AMINTERLACE_IsInterlaced;
1180                                                            if (interlaced > 2) {
1181                                                                    vihOut2->dwInterlaceFlags |= AMINTERLACE_Field1First;
1182                                                            }
1183                                                            need_format_change = 1;
1184                                                    }
1185                                                    else if (!interlaced && !!(vihOut2->dwInterlaceFlags & AMINTERLACE_IsInterlaced)){
1186                                                            vihOut2->dwInterlaceFlags = 0;
1187                                                            need_format_change = 1;
1188                                                    }
1189    
1190                                                    if (need_format_change) {
1191                                                            pOut2->SetMediaType(&mtOut2);
1192                                                            m_pOutput->SetMediaType(&mtOut2);
1193                                                    }
1194                                            }
1195                                            pOut2->Release();
1196                                    }
1197                            }
1198                  }                  }
1199          }          }
1200          else          else
# Line 774  Line 1211 
1211                  m_frame.general &= ~XVID_FILMEFFECT;                  m_frame.general &= ~XVID_FILMEFFECT;
1212    
1213                  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);
1214                  if (length < 0)                  if (length == XVID_ERR_MEMORY)
1215                            return E_FAIL;
1216                    else if (length < 0)
1217                  {                  {
1218              DPRINTF("*** XVID_DEC_DECODE");              DPRINTF("*** XVID_DEC_DECODE");
1219                          return S_FALSE;                          return S_FALSE;
# Line 799  Line 1238 
1238                          return S_FALSE;                          return S_FALSE;
1239                  }                  }
1240    
 //              pOut->SetDiscontinuity(TRUE);  
1241                  pOut->SetSyncPoint(TRUE);                  pOut->SetSyncPoint(TRUE);
1242    
1243                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) { /* auto */
1244                            int par_x, par_y;
1245                            if (stats.data.vol.par == XVID_PAR_EXT) {
1246                                    par_x = stats.data.vol.par_width;
1247                                    par_y = stats.data.vol.par_height;
1248                            } else {
1249                                    par_x = PARS[stats.data.vol.par-1][0];
1250                                    par_y = PARS[stats.data.vol.par-1][1];
1251                            }
1252    
1253                            ar_x = par_x * stats.data.vol.width;
1254                            ar_y = par_y * stats.data.vol.height;
1255                    }
1256    
1257                    if (!!(stats.data.vol.general & XVID_VOL_INTERLACING)) {
1258                            interlaced = (stats.data.vop.general & XVID_VOP_TOPFIELDFIRST) ? 2 : 1;
1259                    }
1260                    else if (interlaced > 0) {
1261                            interlaced = 0;
1262                    }
1263    
1264                  m_frame.bitstream = (BYTE*)m_frame.bitstream + length;                  m_frame.bitstream = (BYTE*)m_frame.bitstream + length;
1265                  m_frame.length -= length;                  m_frame.length -= length;
1266                  goto repeat;                  goto repeat;
# Line 841  Line 1300 
1300          CoTaskMemFree(pPages->pElems);          CoTaskMemFree(pPages->pElems);
1301          return S_OK;          return S_OK;
1302  }  }
1303    
1304    /*===============================================================================
1305    // MFT Interface
1306    //=============================================================================*/
1307    #if defined(XVID_USE_MFT)
1308    #include <limits.h> // _I64_MAX
1309    #define INVALID_TIME  _I64_MAX
1310    
1311    HRESULT CXvidDecoder::MFTGetStreamLimits(DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum)
1312    {
1313            DPRINTF("(MFT)GetStreamLimits");
1314    
1315            if ((pdwInputMinimum == NULL) || (pdwInputMaximum == NULL) || (pdwOutputMinimum == NULL) || (pdwOutputMaximum == NULL))
1316                    return E_POINTER;
1317    
1318            /* Just a fixed number of streams allowed */
1319            *pdwInputMinimum = *pdwInputMaximum = 1;
1320            *pdwOutputMinimum = *pdwOutputMaximum = 1;
1321    
1322            return S_OK;
1323    }
1324    
1325    HRESULT CXvidDecoder::MFTGetStreamCount(DWORD *pcInputStreams, DWORD *pcOutputStreams)
1326    {
1327            DPRINTF("(MFT)GetStreamCount");
1328    
1329            if ((pcInputStreams == NULL) || (pcOutputStreams == NULL))
1330                    return E_POINTER;
1331    
1332            /* We have a fixed number of streams */
1333            *pcInputStreams = 1;
1334            *pcOutputStreams = 1;
1335    
1336            return S_OK;
1337    }
1338    
1339    HRESULT CXvidDecoder::MFTGetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs)
1340    {
1341            DPRINTF("(MFT)GetStreamIDs");
1342            return E_NOTIMPL; /* We have fixed number of streams, so stream ID match stream index */
1343    }
1344    
1345    HRESULT CXvidDecoder::MFTGetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo)
1346    {
1347            DPRINTF("(MFT)GetInputStreamInfo");
1348    
1349            if (pStreamInfo == NULL)
1350                    return E_POINTER;
1351    
1352            if (dwInputStreamID != 0)
1353                    return MF_E_INVALIDSTREAMNUMBER;
1354    
1355            EnterCriticalSection(&m_mft_lock);
1356    
1357            pStreamInfo->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER;
1358            pStreamInfo->hnsMaxLatency = 0;
1359    
1360            pStreamInfo->cbSize = 1; /* Need atleast 1 byte input */
1361            pStreamInfo->cbMaxLookahead = 0;
1362            pStreamInfo->cbAlignment = 1;
1363    
1364            LeaveCriticalSection(&m_mft_lock);
1365            return S_OK;
1366    }
1367    
1368    HRESULT CXvidDecoder::MFTGetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo)
1369    {
1370            DPRINTF("(MFT)GetOutputStreamInfo");
1371    
1372            if (pStreamInfo == NULL)
1373                    return E_POINTER;
1374    
1375            if (dwOutputStreamID != 0)
1376                    return MF_E_INVALIDSTREAMNUMBER;
1377    
1378            EnterCriticalSection(&m_mft_lock);
1379    
1380            pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_DISCARDABLE;
1381    
1382            if (m_pOutputType == NULL) {
1383                    pStreamInfo->cbSize = 0;
1384                    pStreamInfo->cbAlignment = 0;
1385            }
1386            else {
1387                    pStreamInfo->cbSize = (m_create.width * abs(m_create.height) * m_pOutputTypeBPP) >> 3;
1388                    pStreamInfo->cbAlignment = 1;
1389            }
1390    
1391            LeaveCriticalSection(&m_mft_lock);
1392            return S_OK;
1393    }
1394    
1395    HRESULT CXvidDecoder::GetAttributes(IMFAttributes** pAttributes)
1396    {
1397            DPRINTF("(MFT)GetAttributes");
1398            return E_NOTIMPL; /* We don't support any attributes */
1399    }
1400    
1401    HRESULT CXvidDecoder::GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes **ppAttributes)
1402    {
1403            DPRINTF("(MFT)GetInputStreamAttributes");
1404            return E_NOTIMPL; /* We don't support any attributes */
1405    }
1406    
1407    HRESULT CXvidDecoder::GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes **ppAttributes)
1408    {
1409            DPRINTF("(MFT)GetOutputStreamAttributes");
1410            return E_NOTIMPL; /* We don't support any attributes */
1411    }
1412    
1413    HRESULT CXvidDecoder::MFTDeleteInputStream(DWORD dwStreamID)
1414    {
1415            DPRINTF("(MFT)DeleteInputStream");
1416            return E_NOTIMPL; /* We have a fixed number of streams */
1417    }
1418    
1419    HRESULT CXvidDecoder::MFTAddInputStreams(DWORD cStreams, DWORD *adwStreamIDs)
1420    {
1421            DPRINTF("(MFT)AddInputStreams");
1422            return E_NOTIMPL; /* We have a fixed number of streams */
1423    }
1424    
1425    HRESULT CXvidDecoder::MFTGetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1426    {
1427            DPRINTF("(MFT)GetInputAvailableType");
1428    
1429            if (dwInputStreamID != 0)
1430                    return MF_E_INVALIDSTREAMNUMBER;
1431    
1432            DWORD i = 0;
1433            GUID *bs_guid_table[32];
1434    
1435            bs_guid_table[i++] = (GUID *)&CLSID_XVID;
1436            bs_guid_table[i++] = (GUID *)&CLSID_XVID_UC;
1437    
1438            if (g_config.supported_4cc & SUPPORT_3IVX) {
1439                    bs_guid_table[i++] = (GUID *)&CLSID_3IVX;
1440                    bs_guid_table[i++] = (GUID *)&CLSID_3IVX_UC;
1441                    bs_guid_table[i++] = (GUID *)&CLSID_3IV0;
1442                    bs_guid_table[i++] = (GUID *)&CLSID_3IV0_UC;
1443                    bs_guid_table[i++] = (GUID *)&CLSID_3IV1;
1444                    bs_guid_table[i++] = (GUID *)&CLSID_3IV1_UC;
1445                    bs_guid_table[i++] = (GUID *)&CLSID_3IV2;
1446                    bs_guid_table[i++] = (GUID *)&CLSID_3IV2_UC;
1447            }
1448            if (g_config.supported_4cc & SUPPORT_DIVX) {
1449                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX;
1450                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX_UC;
1451                    bs_guid_table[i++] = (GUID *)&CLSID_DX50;
1452                    bs_guid_table[i++] = (GUID *)&CLSID_DX50_UC;
1453            }
1454            if (g_config.supported_4cc & SUPPORT_MP4V) {
1455                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V;
1456                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V_UC;
1457                    bs_guid_table[i++] = (GUID *)&CLSID_LMP4;
1458                    bs_guid_table[i++] = (GUID *)&CLSID_LMP4_UC;
1459                    bs_guid_table[i++] = (GUID *)&CLSID_RMP4;
1460                    bs_guid_table[i++] = (GUID *)&CLSID_RMP4_UC;
1461                    bs_guid_table[i++] = (GUID *)&CLSID_SMP4;
1462                    bs_guid_table[i++] = (GUID *)&CLSID_SMP4_UC;
1463                    bs_guid_table[i++] = (GUID *)&CLSID_HDX4;
1464                    bs_guid_table[i++] = (GUID *)&CLSID_HDX4_UC;
1465            }
1466    
1467            const GUID *subtype;
1468            if (dwTypeIndex < i) {
1469                    subtype = bs_guid_table[dwTypeIndex];
1470            }
1471            else {
1472                    return MF_E_NO_MORE_TYPES;
1473            }
1474    
1475            EnterCriticalSection(&m_mft_lock);
1476    
1477            HRESULT hr = S_OK;
1478    
1479            if (ppType) {
1480                    IMFMediaType *pInputType = NULL;
1481                    hr = MFCreateMediaType(&pInputType);
1482    
1483                    if (SUCCEEDED(hr))
1484                            hr = pInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1485    
1486                    if (SUCCEEDED(hr))
1487                            hr = pInputType->SetGUID(MF_MT_SUBTYPE, *subtype);
1488    
1489                    if (SUCCEEDED(hr)) {
1490                            *ppType = pInputType;
1491                            (*ppType)->AddRef();
1492                    }
1493                    if (pInputType) pInputType->Release();
1494            }
1495    
1496            LeaveCriticalSection(&m_mft_lock);
1497    
1498            return hr;
1499    }
1500    
1501    HRESULT CXvidDecoder::MFTGetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1502    {
1503            DPRINTF("(MFT)GetOutputAvailableType");
1504    
1505            if (ppType == NULL)
1506                    return E_INVALIDARG;
1507    
1508            if (dwOutputStreamID != 0)
1509                    return MF_E_INVALIDSTREAMNUMBER;
1510    
1511            if (dwTypeIndex < 0) return E_INVALIDARG;
1512    
1513            GUID csp;
1514            int bitdepth = 8;
1515            switch(dwTypeIndex)
1516            {
1517            case 0:
1518    if ( USE_YUY2 )
1519    {
1520                    csp = MFVideoFormat_YUY2;
1521                    bitdepth = 4;
1522                    break;
1523    }
1524            case 1:
1525    if ( USE_YVYU )
1526    {
1527                csp = MFVideoFormat_YVYU;
1528                bitdepth = 4;
1529                break;
1530    }
1531            case 2 :
1532    if ( USE_UYVY )
1533    {
1534                    csp = MFVideoFormat_UYVY;
1535                    bitdepth = 4;
1536                    break;
1537    }
1538            case 3  :
1539                    if ( USE_IYUV )
1540    {
1541                    csp = MFVideoFormat_IYUV;
1542                    bitdepth = 3;
1543                    break;
1544    }
1545            case 4  :
1546    if ( USE_YV12 )
1547    {
1548                    csp = MFVideoFormat_YV12;
1549                    bitdepth = 3;
1550                    break;
1551    }
1552            case 5 :
1553    if ( USE_RGB32 )
1554    {
1555                    csp = MFVideoFormat_RGB32;
1556                    bitdepth = 8;
1557                    break;
1558    }
1559            case 6 :
1560    if ( USE_RGB24 )
1561    {
1562                    csp = MFVideoFormat_RGB24;
1563                    bitdepth = 6;
1564                    break;
1565    }
1566            case 7 :
1567    if ( USE_RG555 )
1568    {
1569                    csp = MFVideoFormat_RGB555;
1570                    bitdepth = 4;
1571                    break;
1572    }
1573            case 8 :
1574    if ( USE_RG565 )
1575    {
1576                    csp = MFVideoFormat_RGB565;
1577                    bitdepth = 4;
1578                    break;
1579    }
1580            default :
1581                    return MF_E_NO_MORE_TYPES;
1582            }
1583    
1584            if (m_pInputType == NULL)
1585                    return MF_E_TRANSFORM_TYPE_NOT_SET;
1586    
1587            EnterCriticalSection(&m_mft_lock);
1588    
1589            HRESULT hr = S_OK;
1590    
1591            IMFMediaType *pOutputType = NULL;
1592            hr = MFCreateMediaType(&pOutputType);
1593    
1594            if (SUCCEEDED(hr)) {
1595                    hr = pOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1596            }
1597    
1598            if (SUCCEEDED(hr)) {
1599                    hr = pOutputType->SetGUID(MF_MT_SUBTYPE, csp);
1600        }
1601    
1602            if (SUCCEEDED(hr)) {
1603                    hr = pOutputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE);
1604            }
1605    
1606            if (SUCCEEDED(hr)) {
1607                    hr = pOutputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
1608            }
1609    
1610            if (SUCCEEDED(hr)) {
1611                    hr = pOutputType->SetUINT32(MF_MT_SAMPLE_SIZE, (abs(m_create.height) * m_create.width * bitdepth) >> 1);
1612            }
1613    
1614            if (SUCCEEDED(hr)) {
1615                    hr = MFSetAttributeSize(pOutputType, MF_MT_FRAME_SIZE, m_create.width, abs(m_create.height));
1616            }
1617    
1618            if (SUCCEEDED(hr)) {
1619                    hr = MFSetAttributeRatio(pOutputType, MF_MT_FRAME_RATE, m_frameRate.Numerator, m_frameRate.Denominator);
1620            }
1621    
1622            if (SUCCEEDED(hr)) {
1623                    if (interlaced > 1) {
1624                            hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_FieldInterleavedUpperFirst);
1625                    }
1626                    else if (interlaced) {
1627                            hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_FieldInterleavedLowerFirst);
1628                    }
1629                    else {
1630                            hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
1631                    }
1632            }
1633    
1634            if (SUCCEEDED(hr)) {
1635                    hr = MFSetAttributeRatio(pOutputType, MF_MT_PIXEL_ASPECT_RATIO, ar_x, ar_y);
1636            }
1637    
1638            if (SUCCEEDED(hr)) {
1639                    *ppType = pOutputType;
1640                    (*ppType)->AddRef();
1641            }
1642    
1643            if (pOutputType) pOutputType->Release();
1644    
1645            LeaveCriticalSection(&m_mft_lock);
1646            return hr;
1647    }
1648    
1649    HRESULT CXvidDecoder::MFTSetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags)
1650    {
1651            DPRINTF("(MFT)SetInputType");
1652    
1653            if (dwInputStreamID != 0)
1654                    return MF_E_INVALIDSTREAMNUMBER;
1655    
1656            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1657                    return E_INVALIDARG;
1658    
1659            EnterCriticalSection(&m_mft_lock);
1660    
1661            HRESULT hr = S_OK;
1662    
1663            /* Actually set the type or just test it? */
1664            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1665    
1666            /* If we have samples pending the type can't be changed right now */
1667            if (HasPendingOutput())
1668                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1669    
1670            if (SUCCEEDED(hr)) {
1671            if (pType) { /* Check the type */
1672                hr = OnCheckInputType(pType);
1673            }
1674            }
1675    
1676            if (SUCCEEDED(hr)) {
1677                    if (bReallySet) { /* Set the type if needed */
1678                            hr = OnSetInputType(pType);
1679                    }
1680            }
1681    
1682            LeaveCriticalSection(&m_mft_lock);
1683            return hr;
1684    }
1685    
1686    DWORD WINAPI CreateTrayIcon(LPVOID lpParameter)
1687    {
1688            WNDCLASSEX wc;
1689    
1690            wc.cbSize = sizeof(WNDCLASSEX);
1691            wc.lpfnWndProc = msg_proc;
1692            wc.style = CS_HREDRAW | CS_VREDRAW;
1693            wc.cbWndExtra = 0;
1694            wc.cbClsExtra = 0;
1695            wc.hInstance = (HINSTANCE)g_xvid_hInst;
1696            wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
1697            wc.lpszMenuName = NULL;
1698            wc.lpszClassName = "XVID_MSG_WINDOW";
1699            wc.hIcon = NULL;
1700            wc.hIconSm = NULL;
1701            wc.hCursor = NULL;
1702            RegisterClassEx(&wc);
1703    
1704            MSG_hwnd = CreateWindowEx(0, "XVID_MSG_WINDOW", NULL, 0, CW_USEDEFAULT,
1705                    CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE)g_xvid_hInst, NULL);
1706    
1707            /* display the tray icon */
1708            NOTIFYICONDATA nid;
1709            ZeroMemory(&nid, sizeof(NOTIFYICONDATA));
1710    
1711            nid.cbSize = sizeof(NOTIFYICONDATA);
1712            nid.hWnd = MSG_hwnd;
1713            nid.uID = 1456;
1714            nid.uVersion = NOTIFYICON_VERSION;
1715            nid.uCallbackMessage = WM_ICONMESSAGE;
1716            nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
1717            strcpy_s(nid.szTip, 19, "Xvid Video Decoder");
1718            nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_SHOWTIP;
1719    
1720            Shell_NotifyIcon(NIM_ADD, &nid);
1721            Shell_NotifyIcon(NIM_SETVERSION, &nid);
1722    
1723            DestroyIcon(nid.hIcon);
1724    
1725            MSG msg;
1726            while (MSG_hwnd && GetMessage(&msg, MSG_hwnd, 0, 0)) {
1727                    TranslateMessage(&msg);
1728                    DispatchMessage(&msg);
1729            }
1730    
1731            return 0;
1732    }
1733    
1734    HRESULT CXvidDecoder::MFTSetOutputType(DWORD dwOutputStreamID, IMFMediaType *pType, DWORD dwFlags)
1735    {
1736            DPRINTF("(MFT)SetOutputType");
1737    
1738            if (dwOutputStreamID != 0)
1739                    return MF_E_INVALIDSTREAMNUMBER;
1740    
1741            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1742                    return E_INVALIDARG;
1743    
1744            HRESULT hr = S_OK;
1745    
1746            EnterCriticalSection(&m_mft_lock);
1747    
1748            /* Actually set the type or just test it? */
1749            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1750    
1751            /* If we have samples pending the type can't be changed right now */
1752            if (HasPendingOutput())
1753                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1754    
1755            int bitdepth;
1756            if (SUCCEEDED(hr)) {
1757                    if (pType) { /* Check the type */
1758                            AM_MEDIA_TYPE *am;
1759                            hr = MFCreateAMMediaTypeFromMFMediaType(pType, GUID_NULL, &am);
1760    
1761                            if (SUCCEEDED(hr)) {
1762                                    if (FAILED(ChangeColorspace(am->subtype, am->formattype, am->pbFormat, &bitdepth, 1))) {
1763                                            DPRINTF("(MFT)InternalCheckOutputType (MF_E_INVALIDTYPE)");
1764                                            return MF_E_INVALIDTYPE;
1765                                    }
1766    
1767                            CoTaskMemFree(am->pbFormat);
1768                            CoTaskMemFree(am);
1769                            }
1770                    }
1771            }
1772    
1773            if (SUCCEEDED(hr)) {
1774                    if (bReallySet) { /* Set the type if needed */
1775                            hr = OnSetOutputType(pType, bitdepth);
1776                    }
1777            }
1778    
1779            if (SUCCEEDED(hr) && (MSG_hwnd == 0) && (m_tray_icon == 0) && (g_config.bTrayIcon != 0))
1780            {
1781                    m_thread_handle = CreateThread(NULL, 0, CreateTrayIcon, NULL, 0, NULL);  /* Create message passing window */
1782    
1783                    if (m_thread_handle)
1784                        m_tray_icon = 1;
1785            }
1786    
1787            LeaveCriticalSection(&m_mft_lock);
1788    
1789            return hr;
1790    }
1791    
1792    HRESULT CXvidDecoder::MFTGetInputCurrentType(DWORD dwInputStreamID, IMFMediaType **ppType)
1793    {
1794            DPRINTF("(MFT)GetInputCurrentType");
1795    
1796            if (ppType == NULL)
1797                    return E_POINTER;
1798    
1799            if (dwInputStreamID != 0)
1800                    return MF_E_INVALIDSTREAMNUMBER;
1801    
1802            EnterCriticalSection(&m_mft_lock);
1803    
1804            HRESULT hr = S_OK;
1805    
1806            if (!m_pInputType)
1807                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1808    
1809            if (SUCCEEDED(hr)) {
1810                    *ppType = m_pInputType;
1811                    (*ppType)->AddRef();
1812            }
1813    
1814            LeaveCriticalSection(&m_mft_lock);
1815            return hr;
1816    }
1817    
1818    HRESULT CXvidDecoder::MFTGetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType)
1819    {
1820            DPRINTF("(MFT)GetOutputCurrentType");
1821    
1822            if (ppType == NULL)
1823                    return E_POINTER;
1824    
1825            if (dwOutputStreamID != 0)
1826                    return MF_E_INVALIDSTREAMNUMBER;
1827    
1828            EnterCriticalSection(&m_mft_lock);
1829    
1830            HRESULT hr = S_OK;
1831    
1832            if (!m_pOutputType)
1833                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1834    
1835            if (SUCCEEDED(hr)) {
1836                    *ppType = m_pOutputType;
1837                    (*ppType)->AddRef();
1838            }
1839    
1840            LeaveCriticalSection(&m_mft_lock);
1841            return hr;
1842    }
1843    
1844    HRESULT CXvidDecoder::MFTGetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags)
1845    {
1846            DPRINTF("(MFT)GetInputStatus");
1847    
1848            if (pdwFlags == NULL)
1849                    return E_POINTER;
1850    
1851            if (dwInputStreamID != 0)
1852                    return MF_E_INVALIDSTREAMNUMBER;
1853    
1854            EnterCriticalSection(&m_mft_lock);
1855    
1856            /* If there's pending output samples we don't accept new
1857               input data until ProcessOutput() or Flush() was called */
1858            if (!HasPendingOutput()) {
1859                    *pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
1860            }
1861            else {
1862                    *pdwFlags = 0;
1863            }
1864    
1865            LeaveCriticalSection(&m_mft_lock);
1866    
1867            return S_OK;
1868    }
1869    
1870    HRESULT CXvidDecoder::MFTGetOutputStatus(DWORD *pdwFlags)
1871    {
1872            DPRINTF("(MFT)GetOutputStatus");
1873    
1874            if (pdwFlags == NULL)
1875                    return E_POINTER;
1876    
1877            EnterCriticalSection(&m_mft_lock);
1878    
1879            /* We can render an output sample only after we
1880               have decoded one */
1881            if (HasPendingOutput()) {
1882                    *pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
1883            }
1884            else {
1885                    *pdwFlags = 0;
1886            }
1887    
1888            LeaveCriticalSection(&m_mft_lock);
1889    
1890            return S_OK;
1891    }
1892    
1893    HRESULT CXvidDecoder::MFTSetOutputBounds(LONGLONG hnsLowerBound, LONGLONG hnsUpperBound)
1894    {
1895            DPRINTF("(MFT)SetOutputBounds");
1896            return E_NOTIMPL;
1897    }
1898    
1899    HRESULT CXvidDecoder::MFTProcessEvent(DWORD dwInputStreamID, IMFMediaEvent *pEvent)
1900    {
1901            DPRINTF("(MFT)ProcessEvent");
1902            return E_NOTIMPL; /* We don't handle any stream events */
1903    }
1904    
1905    HRESULT CXvidDecoder::MFTProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
1906    {
1907            DPRINTF("(MFT)ProcessMessage");
1908            HRESULT hr = S_OK;
1909    
1910            EnterCriticalSection(&m_mft_lock);
1911    
1912            switch (eMessage)
1913            {
1914            case MFT_MESSAGE_COMMAND_FLUSH:
1915                    if (m_create.handle != NULL) {
1916                            DPRINTF("(MFT)CommandFlush");
1917    
1918                            xvid_dec_stats_t stats;
1919                            int used_bytes;
1920    
1921                            memset(&stats, 0, sizeof(stats));
1922                            stats.version = XVID_VERSION;
1923    
1924                            int csp = m_frame.output.csp;
1925    
1926                            m_frame.output.csp = XVID_CSP_INTERNAL;
1927                            m_frame.bitstream = NULL;
1928                            m_frame.length = -1;
1929                            m_frame.general = XVID_LOWDELAY;
1930    
1931                            do {
1932                                    used_bytes = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1933                            } while(used_bytes>=0 && stats.type <= 0);
1934    
1935                            m_frame.output.csp = csp;
1936                            m_frame.output.plane[1] = NULL; /* Don't display flushed samples */
1937    
1938                            //m_timestamp = INVALID_TIME;
1939                            //m_timelength = INVALID_TIME;
1940                            //m_rtFrame = 0;
1941            }
1942        break;
1943    
1944            case MFT_MESSAGE_COMMAND_DRAIN:
1945                    m_discont = 1; /* Set discontinuity flag */
1946                    m_rtFrame = 0;
1947                    break;
1948    
1949            case MFT_MESSAGE_SET_D3D_MANAGER:
1950                    hr = E_NOTIMPL;
1951                    break;
1952    
1953            case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
1954            case MFT_MESSAGE_NOTIFY_END_STREAMING:
1955                    break;
1956    
1957            case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
1958            case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
1959                    break;
1960            }
1961    
1962            LeaveCriticalSection(&m_mft_lock);
1963    
1964            return hr;
1965    }
1966    
1967    HRESULT CXvidDecoder::MFTProcessInput(DWORD dwInputStreamID, IMFSample *pSample, DWORD dwFlags)
1968    {
1969            DPRINTF("(MFT)ProcessInput");
1970    
1971            if (pSample == NULL)
1972                    return E_POINTER;
1973    
1974            if (dwInputStreamID != 0)
1975                    return MF_E_INVALIDSTREAMNUMBER;
1976    
1977            if (dwFlags != 0)
1978                    return E_INVALIDARG;
1979    
1980            if (!m_pInputType || !m_pOutputType) {
1981                    return MF_E_NOTACCEPTING;   /* Must have set input and output types */
1982            }
1983            else if (HasPendingOutput()) {
1984                    return MF_E_NOTACCEPTING;   /* We still have output samples to render */
1985            }
1986    
1987            xvid_dec_stats_t stats;
1988            int length;
1989    
1990            memset(&stats, 0, sizeof(stats));
1991            stats.version = XVID_VERSION;
1992    
1993            if (m_create.handle == NULL)
1994            {
1995                    if (xvid_decore_func == NULL)
1996                            return E_FAIL;
1997                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
1998                    {
1999                            DPRINTF("*** XVID_DEC_CREATE error");
2000                            return E_FAIL;
2001                    }
2002            }
2003    
2004            EnterCriticalSection(&m_mft_lock);
2005    
2006            HRESULT hr = S_OK;
2007            IMFMediaBuffer *pBuffer;
2008    
2009            int need_format_change = 0;
2010    
2011            if (SUCCEEDED(hr)) {
2012                    hr = pSample->ConvertToContiguousBuffer(&pBuffer);
2013            }
2014    
2015            if (SUCCEEDED(hr)) {
2016                    hr = pBuffer->Lock((BYTE**)&m_frame.bitstream, NULL, (DWORD *)&m_frame.length);
2017            }
2018    
2019            m_frame.general = XVID_LOWDELAY;
2020    
2021            if (m_discont == 1) {
2022                    m_frame.general |= XVID_DISCONTINUITY;
2023                    m_discont = 0;
2024            }
2025    
2026            if (g_config.nDeblock_Y)
2027                    m_frame.general |= XVID_DEBLOCKY;
2028    
2029            if (g_config.nDeblock_UV)
2030                    m_frame.general |= XVID_DEBLOCKUV;
2031    
2032            if (g_config.nDering_Y)
2033                    m_frame.general |= XVID_DERINGY;
2034    
2035            if (g_config.nDering_UV)
2036                    m_frame.general |= XVID_DERINGUV;
2037    
2038            if (g_config.nFilmEffect)
2039                    m_frame.general |= XVID_FILMEFFECT;
2040    
2041            m_frame.brightness = g_config.nBrightness;
2042    
2043            m_frame.output.csp &= ~XVID_CSP_VFLIP;
2044            m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0);
2045    
2046            int csp = m_frame.output.csp;
2047            m_frame.output.csp = XVID_CSP_INTERNAL;
2048    
2049        // Paranoid check.
2050            if (xvid_decore_func == NULL) {
2051                    hr = E_FAIL;
2052                    goto END_LOOP;
2053            }
2054    
2055    repeat :
2056            length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
2057    
2058            if (length == XVID_ERR_MEMORY) {
2059                    hr = E_FAIL;
2060                    goto END_LOOP;
2061            }
2062            else if (length < 0)
2063            {
2064                    DPRINTF("*** XVID_DEC_DECODE");
2065                    goto END_LOOP;
2066            }
2067    
2068            if (stats.type == XVID_TYPE_NOTHING && length > 0) {
2069                    DPRINTF(" B-Frame decoder lag");
2070                    m_frame.output.plane[1] = NULL;
2071                    goto END_LOOP;
2072            }
2073    
2074            if (stats.type == XVID_TYPE_VOL)
2075            {
2076                    if (stats.data.vol.width != m_create.width ||
2077                            stats.data.vol.height != m_create.height)
2078                    {
2079                            DPRINTF("TODO: auto-resize");
2080                            m_frame.output.plane[1] = NULL;
2081                            hr = E_FAIL;
2082                    }
2083    
2084                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) { /* auto */
2085                            int par_x, par_y;
2086                            if (stats.data.vol.par == XVID_PAR_EXT) {
2087                                    par_x = stats.data.vol.par_width;
2088                                    par_y = stats.data.vol.par_height;
2089                            } else {
2090                                    par_x = PARS[stats.data.vol.par-1][0];
2091                                    par_y = PARS[stats.data.vol.par-1][1];
2092                            }
2093    
2094                            ar_x = par_x * stats.data.vol.width;
2095                            ar_y = par_y * stats.data.vol.height;
2096    
2097                            need_format_change = 1;
2098                    }
2099    
2100                    if (!!(stats.data.vol.general & XVID_VOL_INTERLACING)) {
2101                            interlaced = (stats.data.vop.general & XVID_VOP_TOPFIELDFIRST) ? 2 : 1;
2102                            need_format_change = 1;
2103                    }
2104                    else {
2105                            if (interlaced > 0) {
2106                                    interlaced = 0;
2107                                    need_format_change = 1;
2108                            }
2109                    }
2110    
2111                    m_frame.bitstream = (BYTE*)m_frame.bitstream + length;
2112                    m_frame.length -= length;
2113                    goto repeat;
2114            }
2115    
2116    END_LOOP:
2117            m_frame.output.csp = csp;
2118    
2119            if (pBuffer) {
2120                    pBuffer->Unlock();
2121                    pBuffer->Release();
2122            }
2123    
2124            if (SUCCEEDED(hr)) {
2125                    /* Try to get a timestamp */
2126                    if (FAILED(pSample->GetSampleTime(&m_timestamp)))
2127                            m_timestamp = INVALID_TIME;
2128    
2129                    if (FAILED(pSample->GetSampleDuration(&m_timelength))) {
2130                            m_timelength = INVALID_TIME;
2131                    }
2132                    if (m_timestamp != INVALID_TIME && stats.type == XVID_TYPE_IVOP) {
2133                            m_rtFrame = m_timestamp;
2134                    }
2135            }
2136    
2137            if (need_format_change) {
2138                    IMFMediaType *pOutputType = NULL;
2139                    hr = MFTGetOutputCurrentType(0, &pOutputType);
2140    
2141                    if (SUCCEEDED(hr)) {
2142                            if (interlaced > 1) {
2143                                    hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_FieldInterleavedUpperFirst);
2144                            }
2145                            else if (interlaced) {
2146                                    hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_FieldInterleavedLowerFirst);
2147                            }
2148                            else {
2149                                    hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
2150                            }
2151                    }
2152    
2153                    if (SUCCEEDED(hr)) {
2154                            hr = MFSetAttributeRatio(pOutputType, MF_MT_PIXEL_ASPECT_RATIO, ar_x, ar_y);
2155                    }
2156    
2157                    if (SUCCEEDED(hr)) {
2158                            MFTSetOutputType(0, pOutputType, 0);
2159                    }
2160    
2161                    if (pOutputType) pOutputType->Release();
2162            }
2163    
2164            LeaveCriticalSection(&m_mft_lock);
2165    
2166            return hr;
2167    }
2168    
2169    HRESULT CXvidDecoder::MFTProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus)
2170    {
2171            DPRINTF("(MFT)ProcessOutput");
2172    
2173            /* Preroll in MFT ??
2174               Flags ?? -> TODO... */
2175            if (dwFlags != 0)
2176                    return E_INVALIDARG;
2177    
2178            if (pOutputSamples == NULL || pdwStatus == NULL)
2179                    return E_POINTER;
2180    
2181            if (cOutputBufferCount != 1) /* Must be exactly one output buffer */
2182                    return E_INVALIDARG;
2183    
2184            if (pOutputSamples[0].pSample == NULL) /* Must have a sample */
2185                    return E_INVALIDARG;
2186    
2187            if (!HasPendingOutput()) { /* If there's no sample we need to decode one first */
2188                    return MF_E_TRANSFORM_NEED_MORE_INPUT;
2189            }
2190    
2191            EnterCriticalSection(&m_mft_lock);
2192    
2193            HRESULT hr = S_OK;
2194    
2195            BYTE *Dst = NULL;
2196            DWORD buffer_size;
2197            LONG stride = m_create.width;
2198            IMFMediaBuffer *pOutput = NULL;
2199            IMF2DBuffer *pOutput2D = NULL;
2200    
2201            if (SUCCEEDED(hr)) {
2202                    hr = pOutputSamples[0].pSample->GetBufferByIndex(0, &pOutput); /* Get output buffer */
2203            }
2204    
2205            if (SUCCEEDED(hr)) {
2206                    hr = pOutput->GetMaxLength(&buffer_size);
2207            }
2208    
2209            if (SUCCEEDED(hr)) {
2210                    hr = pOutput->QueryInterface(IID_IMF2DBuffer, (void **)&pOutput2D);
2211            }
2212    
2213            if (SUCCEEDED(hr)) {
2214                    hr = pOutput2D->Lock2D(&Dst, &stride);
2215            }
2216            else {
2217                    hr = pOutput->Lock(&Dst, NULL, NULL);
2218            }
2219    
2220            if (SUCCEEDED(hr)) {
2221                    xvid_gbl_convert_t convert;
2222    
2223                    memset(&convert, 0, sizeof(convert));
2224                    convert.version = XVID_VERSION;
2225    
2226                    convert.input.csp = XVID_CSP_INTERNAL;
2227                    convert.input.plane[0] = m_frame.output.plane[0];
2228                    convert.input.plane[1] = m_frame.output.plane[1];
2229                    convert.input.plane[2] = m_frame.output.plane[2];
2230                    convert.input.stride[0] = m_frame.output.stride[0];
2231                    convert.input.stride[1] = m_frame.output.stride[1];
2232                    convert.input.stride[2] = m_frame.output.stride[2];
2233    
2234                    convert.output.csp = m_frame.output.csp;
2235                    convert.output.plane[0] = Dst;
2236                    convert.output.stride[0] = stride;
2237    
2238                    convert.width = m_create.width;
2239                    convert.height = m_create.height;
2240                    convert.interlacing = (interlaced > 0) ? 1 : 0;
2241    
2242                    if (m_frame.output.plane[1] != NULL && Dst != NULL && xvid_global_func != NULL)
2243                            if (xvid_global_func(0, XVID_GBL_CONVERT, &convert, NULL) < 0) /* CSP convert into output buffer */
2244                                    hr = E_FAIL;
2245                    m_frame.output.plane[1] = NULL;
2246            }
2247    
2248            *pdwStatus = 0;
2249    
2250            if (SUCCEEDED(hr)) {
2251                    if (SUCCEEDED(hr))
2252                            hr = pOutputSamples[0].pSample->SetUINT32(MFSampleExtension_CleanPoint, TRUE); // key frame
2253    
2254                    if (SUCCEEDED(hr)) { /* Set timestamp of output sample */
2255                            if (m_timestamp != INVALID_TIME)
2256                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_timestamp);
2257                            else
2258                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_rtFrame);
2259    
2260                            if (m_timelength != INVALID_TIME)
2261                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_timelength);
2262                            else
2263                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_duration);
2264    
2265                            m_rtFrame += m_duration;
2266                    }
2267    
2268                    if (SUCCEEDED(hr))
2269                            hr = pOutput->SetCurrentLength((m_create.width * abs(m_create.height) * m_pOutputTypeBPP) >> 3);
2270            }
2271    
2272            if (pOutput2D) {
2273                    pOutput2D->Unlock2D();
2274                    pOutput2D->Release();
2275                    if (pOutput)
2276                        pOutput->Release();
2277            }
2278            else if (pOutput) {
2279                    pOutput->Unlock();
2280                    pOutput->Release();
2281            }
2282    
2283            LeaveCriticalSection(&m_mft_lock);
2284    
2285            return hr;
2286    }
2287    
2288    HRESULT CXvidDecoder::OnCheckInputType(IMFMediaType *pmt)
2289    {
2290            DPRINTF("(MFT)CheckInputType");
2291    
2292            HRESULT hr = S_OK;
2293    
2294            /*  Check if input type is already set. Reject any type that is not identical */
2295            if (m_pInputType) {
2296                    DWORD dwFlags = 0;
2297                    if (S_OK == m_pInputType->IsEqual(pmt, &dwFlags)) {
2298                            return S_OK;
2299                    }
2300                    else {
2301                            return MF_E_INVALIDTYPE;
2302                    }
2303            }
2304    
2305            GUID majortype = {0}, subtype = {0};
2306            UINT32 width = 0, height = 0;
2307    
2308            hr = pmt->GetMajorType(&majortype);
2309    
2310            if (SUCCEEDED(hr)) {
2311                    if (majortype != MFMediaType_Video) { /* Must be Video */
2312                            hr = MF_E_INVALIDTYPE;
2313                    }
2314            }
2315    
2316            if (m_hdll == NULL) {
2317                    HRESULT hr = OpenLib();
2318    
2319                    if (FAILED(hr) || (m_hdll == NULL)) // Paranoid checks.
2320                            hr = MF_E_INVALIDTYPE;
2321            }
2322    
2323            if (SUCCEEDED(hr)) {
2324                    hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &width, &height);
2325            }
2326    
2327            /* Check the frame size */
2328            if (SUCCEEDED(hr)) {
2329                    if (width > 4096 || height > 4096) {
2330                            hr = MF_E_INVALIDTYPE;
2331                    }
2332            }
2333            m_create.width = width;
2334            m_create.height = height;
2335    
2336            if (SUCCEEDED(hr)) {
2337                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
2338                            hr = MFGetAttributeRatio(pmt, MF_MT_PIXEL_ASPECT_RATIO, (UINT32*)&ar_x, (UINT32*)&ar_y);
2339                    }
2340            }
2341    
2342            /* TODO1: Make sure there really is a frame rate after all!
2343               TODO2: Use the framerate for something! */
2344            MFRatio fps = {0};
2345            if (SUCCEEDED(hr)) {
2346                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&fps.Numerator, (UINT32*)&fps.Denominator);
2347            }
2348    
2349            if (SUCCEEDED(hr)) {
2350                    hr = pmt->GetGUID(MF_MT_SUBTYPE, &subtype);
2351            }
2352    
2353            if (subtype == CLSID_MP4V || subtype == CLSID_MP4V_UC ||
2354                subtype == CLSID_LMP4 || subtype == CLSID_LMP4_UC ||
2355                subtype == CLSID_RMP4 || subtype == CLSID_RMP4_UC ||
2356                subtype == CLSID_SMP4 || subtype == CLSID_SMP4_UC ||
2357                subtype == CLSID_HDX4 || subtype == CLSID_HDX4_UC) {
2358                    if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
2359                            CloseLib();
2360                            hr = MF_E_INVALIDTYPE;
2361                    }
2362                    else m_create.fourcc = FOURCC_MP4V;
2363            }
2364            else if (subtype == CLSID_DIVX || subtype == CLSID_DIVX_UC) {
2365                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2366                            CloseLib();
2367                            hr = MF_E_INVALIDTYPE;
2368                    }
2369                    else m_create.fourcc = FOURCC_DIVX;
2370            }
2371            else if (subtype == CLSID_DX50 || subtype == CLSID_DX50_UC) {
2372                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2373                            CloseLib();
2374                            hr = MF_E_INVALIDTYPE;
2375                    }
2376                    else m_create.fourcc = FOURCC_DX50;
2377            }
2378            else if (subtype == CLSID_3IVX || subtype == CLSID_3IVX_UC ||
2379                     subtype == CLSID_3IV0 || subtype == CLSID_3IV0_UC ||
2380                     subtype == CLSID_3IV1 || subtype == CLSID_3IV1_UC ||
2381                     subtype == CLSID_3IV2 || subtype == CLSID_3IV2_UC) {
2382                    if (!(g_config.supported_4cc & SUPPORT_3IVX)) {
2383                            CloseLib();
2384                            hr = MF_E_INVALIDTYPE;
2385                    }
2386                    else m_create.fourcc = FOURCC_3IVX;
2387            }
2388            else if (subtype == CLSID_XVID || subtype == CLSID_XVID_UC) {
2389                    m_create.fourcc = FOURCC_XVID;
2390            }
2391            else {
2392                    DPRINTF("Unknown subtype!");
2393                    CloseLib();
2394                    hr = MF_E_INVALIDTYPE;
2395            }
2396    
2397            /* haali media splitter reports VOL information in the format header */
2398            if (SUCCEEDED(hr))
2399            {
2400                    UINT32 cbSeqHeader = 0;
2401    
2402                    (void)pmt->GetBlobSize(MF_MT_MPEG_SEQUENCE_HEADER, &cbSeqHeader);
2403    
2404                    if (cbSeqHeader>0) {
2405                            xvid_dec_stats_t stats;
2406                            memset(&stats, 0, sizeof(stats));
2407                            stats.version = XVID_VERSION;
2408    
2409                            if (m_create.handle == NULL) {
2410                                    if (xvid_decore_func == NULL)
2411                                            hr = E_FAIL;
2412                                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
2413                                            DPRINTF("*** XVID_DEC_CREATE error");
2414                                            hr = E_FAIL;
2415                                    }
2416                            }
2417    
2418                            if (SUCCEEDED(hr)) {
2419                                    (void)pmt->GetAllocatedBlob(MF_MT_MPEG_SEQUENCE_HEADER, (UINT8 **)&m_frame.bitstream, (UINT32 *)&m_frame.length);
2420                                    m_frame.general = 0;
2421                                    m_frame.output.csp = XVID_CSP_NULL;
2422    
2423                                    int ret = 0;
2424                                    if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
2425                                            /* honour video dimensions reported in VOL header */
2426                                            if (stats.type == XVID_TYPE_VOL) {
2427                                                    m_create.width = stats.data.vol.width;
2428                                                    m_create.height = stats.data.vol.height;
2429                                            }
2430                                    }
2431    
2432                                    if (ret == XVID_ERR_MEMORY) hr = E_FAIL;
2433                                    CoTaskMemFree(m_frame.bitstream);
2434                            }
2435                    }
2436            }
2437    
2438            return hr;
2439    }
2440    
2441    HRESULT CXvidDecoder::OnSetInputType(IMFMediaType *pmt)
2442    {
2443            HRESULT hr = S_OK;
2444            UINT32 w, h;
2445    
2446            if (m_pInputType) m_pInputType->Release();
2447    
2448            hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &w, &h);
2449            m_create.width = w; m_create.height = h;
2450    
2451            if (SUCCEEDED(hr))
2452                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&m_frameRate.Numerator, (UINT32*)&m_frameRate.Denominator);
2453    
2454            if (SUCCEEDED(hr)) { /* Store frame duration, derived from the frame rate */
2455                    hr = MFFrameRateToAverageTimePerFrame(m_frameRate.Numerator, m_frameRate.Denominator, &m_duration);
2456            }
2457    
2458            if (SUCCEEDED(hr)) {
2459                    m_pInputType = pmt;
2460                    m_pInputType->AddRef();
2461            }
2462    
2463            return hr;
2464    }
2465    
2466    HRESULT CXvidDecoder::OnSetOutputType(IMFMediaType *pmt, int bitdepth)
2467    {
2468            if (m_pOutputType) m_pOutputType->Release();
2469    
2470            m_pOutputType = pmt;
2471            m_pOutputType->AddRef();
2472            m_pOutputTypeBPP = bitdepth;
2473    
2474            return S_OK;
2475    }
2476    
2477    #endif /* XVID_USE_MFT */

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

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