[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 1901, Fri Oct 29 14:33:39 2010 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-2010 Peter Ross <pross@xvid.org>
7     *               2003-2010 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: CXvidDecoder.cpp,v 1.22 2010-10-29 14:33:39 Isibaar Exp $
24   *   *
25   ****************************************************************************/   ****************************************************************************/
26    
# Line 36  Line 37 
37          place these paths at the top of the Tools|Options|Directories list          place these paths at the top of the Tools|Options|Directories list
38    
39          headers:          headers:
40          C:\DXVCSDK\include          C:\DX90SDK\Include
41          C:\DXVCSDK\samples\Multimedia\DirectShow\BaseClasses          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses
42    
43          libraries (optional):          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Release
44          C:\DXVCSDK\samples\Multimedia\DirectShow\BaseClasses\Release          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Debug
45  */  */
46    
47    #define XVID_USE_MFT
48    #define XVID_USE_TRAYICON
49    
50  #include <windows.h>  #include <windows.h>
51    
# Line 55  Line 57 
57  #endif  #endif
58  #include <dvdmedia.h>   // VIDEOINFOHEADER2  #include <dvdmedia.h>   // VIDEOINFOHEADER2
59    
60  #include <xvid.h>               // XviD API  #if defined(XVID_USE_MFT)
61    #define MFT_UNIQUE_METHOD_NAMES
62    #include <mftransform.h>
63    #include <mfapi.h>
64    #include <mferror.h>
65    #include <shlwapi.h>
66    #endif
67    
68    #include <shellapi.h>
69    
70    #include <xvid.h>               // Xvid API
71    
72    #include "resource.h"
73    
74  #include "IXvidDecoder.h"  #include "IXvidDecoder.h"
75  #include "CXvidDecoder.h"  #include "CXvidDecoder.h"
# Line 82  Line 96 
96          { &MEDIATYPE_Video, &CLSID_DX50 },          { &MEDIATYPE_Video, &CLSID_DX50 },
97          { &MEDIATYPE_Video, &CLSID_DX50_UC },          { &MEDIATYPE_Video, &CLSID_DX50_UC },
98          { &MEDIATYPE_Video, &CLSID_MP4V },          { &MEDIATYPE_Video, &CLSID_MP4V },
99      { &MEDIATYPE_Video, &CLSID_MP4V_UC },
100  };  };
101    
102  const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] =  const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] =
# Line 148  Line 163 
163    
164  };  };
165    
   
166  /* 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) */
167  int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate);  int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate);
168    
169    #ifdef XVID_USE_TRAYICON
170    extern HINSTANCE g_xvid_hInst;
171    
172    static int GUI_Page = 0;
173    static int Tray_Icon = 0;
174    extern "C" void CALLBACK Configure(HWND hWndParent, HINSTANCE hInstParent, LPSTR lpCmdLine, int nCmdShow );
175    
176    LRESULT CALLBACK msg_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
177    {
178            switch ( uMsg )
179            {
180            case WM_ICONMESSAGE:
181                    switch(lParam)
182                    {
183                    case WM_LBUTTONDBLCLK:
184                            if (!GUI_Page) {
185                                    GUI_Page = 1;
186                                    Configure(hwnd, g_xvid_hInst, "", 1);
187                                    GUI_Page = 0;
188                            }
189                            break;
190                    default:
191                            return DefWindowProc(hwnd, uMsg, wParam, lParam);
192                    };
193                    break;
194    
195            case WM_DESTROY:
196                    NOTIFYICONDATA nid;
197                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
198    
199                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
200                    nid.hWnd = hwnd;
201                    nid.uID = 1456;
202    
203                    Shell_NotifyIcon(NIM_DELETE, &nid);
204                    Tray_Icon = 0;
205            default:
206                    return DefWindowProc(hwnd, uMsg, wParam, lParam);
207            }
208    
209            return TRUE; /* ok */
210    }
211    #endif
212    
213  STDAPI DllRegisterServer()  STDAPI DllRegisterServer()
214  {  {
215    #if defined(XVID_USE_MFT)
216            int inputs_num = sizeof(sudInputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE);
217            int outputs_num = sizeof(sudOutputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE);
218            MFT_REGISTER_TYPE_INFO * mft_bs = new MFT_REGISTER_TYPE_INFO[inputs_num];
219            MFT_REGISTER_TYPE_INFO * mft_csp = new MFT_REGISTER_TYPE_INFO[outputs_num];
220    
221            {
222                    int i;
223                    for(i=0;i<inputs_num;i++) {
224                            mft_bs[i].guidMajorType = *sudInputPinTypes[i].clsMajorType;
225                            mft_bs[i].guidSubtype = *sudInputPinTypes[i].clsMinorType;
226                    }
227                    for(i=0;i<outputs_num;i++) {
228                            mft_csp[i].guidMajorType = *sudOutputPinTypes[i].clsMajorType;
229                            mft_csp[i].guidSubtype = *sudOutputPinTypes[i].clsMinorType; // MFT and AM GUIDs really the same?
230                    }
231            }
232    
233            /* Register the MFT decoder */
234            MFTRegister(CLSID_XVID,                          // CLSID
235                            MFT_CATEGORY_VIDEO_DECODER,          // Category
236                            const_cast<LPWSTR>(XVID_NAME_L),     // Friendly name
237                            0,                                   // Flags
238                            inputs_num,                          // Number of input types
239                            mft_bs,                              // Input types
240                            outputs_num,                         // Number of output types
241                            mft_csp,                             // Output types
242                            NULL                                 // Attributes (optional)
243                            );
244    
245            delete[] mft_bs;
246            delete[] mft_csp;
247    #endif /* XVID_USE_MFT */
248    
249      return AMovieDllRegisterServer2( TRUE );      return AMovieDllRegisterServer2( TRUE );
250  }  }
251    
252    
253  STDAPI DllUnregisterServer()  STDAPI DllUnregisterServer()
254  {  {
255    #if defined(XVID_USE_MFT)
256            MFTUnregister(CLSID_XVID);
257    #endif
258      return AMovieDllRegisterServer2( FALSE );      return AMovieDllRegisterServer2( FALSE );
259  }  }
260    
# Line 194  Line 288 
288          return GetInterface((ISpecifyPropertyPages *) this, ppv);          return GetInterface((ISpecifyPropertyPages *) this, ppv);
289          }          }
290    
291    #if defined(XVID_USE_MFT)
292            if (riid == IID_IMFTransform)
293            {
294                    return GetInterface((IMFTransform *) this, ppv);
295            }
296    #endif
297    
298          return CVideoTransformFilter::NonDelegatingQueryInterface(riid, ppv);          return CVideoTransformFilter::NonDelegatingQueryInterface(riid, ppv);
299  }  }
300    
# Line 204  Line 305 
305  #define XVID_DLL_NAME "xvidcore.dll"  #define XVID_DLL_NAME "xvidcore.dll"
306    
307  CXvidDecoder::CXvidDecoder(LPUNKNOWN punk, HRESULT *phr) :  CXvidDecoder::CXvidDecoder(LPUNKNOWN punk, HRESULT *phr) :
308      CVideoTransformFilter(NAME("CXvidDecoder"), punk, CLSID_XVID)      CVideoTransformFilter(NAME("CXvidDecoder"), punk, CLSID_XVID), m_hdll (NULL)
309  {  {
310          DPRINTF("Constructor");          DPRINTF("Constructor");
311    
312        xvid_decore_func = NULL; // Hmm, some strange errors appearing if I try to initialize...
313        xvid_global_func = NULL; // ...this in constructor's init-list. So, they assigned here.
314    
315    #if defined(XVID_USE_MFT)
316            InitializeCriticalSection(&m_mft_lock);
317            m_pInputType = NULL;
318            m_pOutputType = NULL;
319            m_rtFrame = 0;
320            m_duration = 0;
321            m_discont = 0;
322            m_frameRate.Denominator = 1;
323            m_frameRate.Numerator = 1;
324    #endif
325    
326        LoadRegistryInfo();
327    
328        *phr = OpenLib();
329    }
330    
331    HRESULT CXvidDecoder::OpenLib()
332    {
333        DPRINTF("OpenLib");
334    
335        if (m_hdll != NULL)
336                    return E_UNEXPECTED; // Seems, that library already opened.
337    
338          xvid_gbl_init_t init;          xvid_gbl_init_t init;
339          memset(&init, 0, sizeof(init));          memset(&init, 0, sizeof(init));
340          init.version = XVID_VERSION;          init.version = XVID_VERSION;
341    
         ar_x = ar_y = 0;  
   
342          m_hdll = LoadLibrary(XVID_DLL_NAME);          m_hdll = LoadLibrary(XVID_DLL_NAME);
343          if (m_hdll == NULL) {          if (m_hdll == NULL) {
344                  DPRINTF("dll load failed");                  DPRINTF("dll load failed");
345                  MessageBox(0, XVID_DLL_NAME " not found","Error", 0);                  MessageBox(0, XVID_DLL_NAME " not found","Error", MB_TOPMOST);
346                  return;                  return E_FAIL;
347          }          }
348    
349          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");
350          if (xvid_global_func == NULL) {          if (xvid_global_func == NULL) {
351                  MessageBox(0, "xvid_global() not found", "Error", 0);          FreeLibrary(m_hdll);
352                  return;          m_hdll = NULL;
353                    MessageBox(0, "xvid_global() not found", "Error", MB_TOPMOST);
354                    return E_FAIL;
355          }          }
356    
357          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");
358          if (xvid_decore_func == NULL) {          if (xvid_decore_func == NULL) {
359                  MessageBox(0, "xvid_decore() not found", "Error", 0);          xvid_global_func = NULL;
360                  return;          FreeLibrary(m_hdll);
361            m_hdll = NULL;
362                    MessageBox(0, "xvid_decore() not found", "Error", MB_TOPMOST);
363                    return E_FAIL;
364          }          }
365    
366          if (xvid_global_func(0, XVID_GBL_INIT, &init, NULL) < 0)          if (xvid_global_func(0, XVID_GBL_INIT, &init, NULL) < 0)
367          {          {
368                  MessageBox(0, "xvid_global() failed", "Error", 0);          xvid_global_func = NULL;
369                  return;          xvid_decore_func = NULL;
370            FreeLibrary(m_hdll);
371            m_hdll = NULL;
372                    MessageBox(0, "xvid_global() failed", "Error", MB_TOPMOST);
373                    return E_FAIL;
374          }          }
375    
376          memset(&m_create, 0, sizeof(m_create));          memset(&m_create, 0, sizeof(m_create));
# Line 246  Line 380 
380          memset(&m_frame, 0, sizeof(m_frame));          memset(&m_frame, 0, sizeof(m_frame));
381          m_frame.version = XVID_VERSION;          m_frame.version = XVID_VERSION;
382    
         LoadRegistryInfo();  
   
383          USE_IYUV = false;          USE_IYUV = false;
384          USE_YV12 = false;          USE_YV12 = false;
385          USE_YUY2 = false;          USE_YUY2 = false;
# Line 285  Line 417 
417                  USE_RGB32 = true;                  USE_RGB32 = true;
418                  break;                  break;
419          }          }
420    
421            switch (g_config.aspect_ratio)
422            {
423            case 0:
424            case 1:
425                    break;
426            case 2:
427                    ar_x = 4;
428                    ar_y = 3;
429                    break;
430            case 3:
431                    ar_x = 16;
432                    ar_y = 9;
433                    break;
434            case 4:
435                    ar_x = 47;
436                    ar_y = 20;
437                    break;
438            }
439    
440            return S_OK;
441  }  }
442    
443  void CXvidDecoder::CloseLib()  void CXvidDecoder::CloseLib()
444  {  {
445          DPRINTF("Destructor");          DPRINTF("CloseLib");
446    
447          if (m_create.handle != NULL) {          if ((m_create.handle != NULL) && (xvid_decore_func != NULL))
448            {
449                  xvid_decore_func(m_create.handle, XVID_DEC_DESTROY, 0, 0);                  xvid_decore_func(m_create.handle, XVID_DEC_DESTROY, 0, 0);
450                  m_create.handle = NULL;                  m_create.handle = NULL;
451          }          }
# Line 300  Line 454 
454                  FreeLibrary(m_hdll);                  FreeLibrary(m_hdll);
455                  m_hdll = NULL;                  m_hdll = NULL;
456          }          }
457        xvid_decore_func = NULL;
458        xvid_global_func = NULL;
459  }  }
460    
461  /* destructor */  /* destructor */
462    
463  CXvidDecoder::~CXvidDecoder()  CXvidDecoder::~CXvidDecoder()
464  {  {
465        DPRINTF("Destructor");
466    
467    #ifdef XVID_USE_TRAYICON
468            if (Tray_Icon) { /* Destroy tray icon */
469                    NOTIFYICONDATA nid;
470                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
471    
472                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
473                    nid.hWnd = MSG_hwnd;
474                    nid.uID = 1456;
475    
476                    Shell_NotifyIcon(NIM_DELETE, &nid);
477                    Tray_Icon = 0;
478            }
479    #endif
480    
481            /* Close xvidcore library */
482          CloseLib();          CloseLib();
483    
484    #if defined(XVID_USE_MFT)
485            DeleteCriticalSection(&m_mft_lock);
486    #endif
487  }  }
488    
489    
# Line 318  Line 495 
495          DPRINTF("CheckInputType");          DPRINTF("CheckInputType");
496          BITMAPINFOHEADER * hdr;          BITMAPINFOHEADER * hdr;
497    
498            ar_x = ar_y = 0;
499    
500          if (*mtIn->Type() != MEDIATYPE_Video)          if (*mtIn->Type() != MEDIATYPE_Video)
501          {          {
502                  DPRINTF("Error: Unknown Type");                  DPRINTF("Error: Unknown Type");
# Line 325  Line 504 
504                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
505          }          }
506    
507        if (m_hdll == NULL)
508        {
509                    HRESULT hr = OpenLib();
510    
511            if (FAILED(hr) || (m_hdll == NULL)) // Paranoid checks.
512                            return VFW_E_TYPE_NOT_ACCEPTED;
513        }
514    
515          if (*mtIn->FormatType() == FORMAT_VideoInfo)          if (*mtIn->FormatType() == FORMAT_VideoInfo)
516          {          {
517                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtIn->Format();                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtIn->Format();
518                  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);  
519          }          }
520          else if (*mtIn->FormatType() == FORMAT_VideoInfo2)          else if (*mtIn->FormatType() == FORMAT_VideoInfo2)
521          {          {
522                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 *) mtIn->Format();                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 *) mtIn->Format();
523                  hdr = &vih2->bmiHeader;                  hdr = &vih2->bmiHeader;
524                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
525                  ar_x = vih2->dwPictAspectRatioX;                  ar_x = vih2->dwPictAspectRatioX;
526                  ar_y = vih2->dwPictAspectRatioY;                  ar_y = vih2->dwPictAspectRatioY;
527                    }
528                    DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);
529            }
530      else if (*mtIn->FormatType() == FORMAT_MPEG2Video) {
531        MPEG2VIDEOINFO * mpgvi = (MPEG2VIDEOINFO*)mtIn->Format();
532        VIDEOINFOHEADER2 * vih2 = &mpgvi->hdr;
533                    hdr = &vih2->bmiHeader;
534                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
535                            ar_x = vih2->dwPictAspectRatioX;
536                            ar_y = vih2->dwPictAspectRatioY;
537                    }
538                  DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);                  DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y);
539    
540        /* haali media splitter reports VOL information in the format header */
541    
542        if (mpgvi->cbSequenceHeader>0) {
543    
544          xvid_dec_stats_t stats;
545                memset(&stats, 0, sizeof(stats));
546                stats.version = XVID_VERSION;
547    
548                if (m_create.handle == NULL) {
549                        if (xvid_decore_func == NULL)
550                                return E_FAIL;
551                        if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
552              DPRINTF("*** XVID_DEC_CREATE error");
553                                return E_FAIL;
554                        }
555                }
556    
557          m_frame.general = 0;
558          m_frame.bitstream = (void*)mpgvi->dwSequenceHeader;
559          m_frame.length = mpgvi->cbSequenceHeader;
560          m_frame.output.csp = XVID_CSP_NULL;
561    
562          int ret = 0;
563          if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
564            /* honour video dimensions reported in VOL header */
565                  if (stats.type == XVID_TYPE_VOL) {
566              hdr->biWidth = stats.data.vol.width;
567              hdr->biHeight = stats.data.vol.height;
568                      }
569              }
570          if (ret == XVID_ERR_MEMORY) return E_FAIL;
571            }
572          }          }
573          else          else
574          {          {
# Line 350  Line 576 
576                  CloseLib();                  CloseLib();
577                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
578          }          }
   
579          if (hdr->biHeight < 0)          if (hdr->biHeight < 0)
580          {          {
581                  DPRINTF("colorspace: inverted input format not supported");                  DPRINTF("colorspace: inverted input format not supported");
# Line 361  Line 586 
586    
587          switch(hdr->biCompression)          switch(hdr->biCompression)
588          {          {
589      case FOURCC_mp4v:
590          case FOURCC_MP4V:          case FOURCC_MP4V:
591                  if (!(g_config.supported_4cc & SUPPORT_MP4V)) {                  if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
592                          CloseLib();                          CloseLib();
# Line 393  Line 618 
618                  CloseLib();                  CloseLib();
619                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
620          }          }
621    
622            m_create.fourcc = hdr->biCompression;
623    
624          return S_OK;          return S_OK;
625  }  }
626    
# Line 421  Line 649 
649                  if (ar_x != 0 && ar_y != 0) {                  if (ar_x != 0 && ar_y != 0) {
650                          vih->dwPictAspectRatioX = ar_x;                          vih->dwPictAspectRatioX = ar_x;
651                          vih->dwPictAspectRatioY = ar_y;                          vih->dwPictAspectRatioY = ar_y;
652                            forced_ar = true;
653                  } else { // just to be safe                  } else { // just to be safe
654                          vih->dwPictAspectRatioX = m_create.width;                          vih->dwPictAspectRatioX = m_create.width;
655                          vih->dwPictAspectRatioY = abs(m_create.height);                          vih->dwPictAspectRatioY = abs(m_create.height);
656                            forced_ar = false;
657                  }                  }
   
658          } else {          } else {
659    
660                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER));                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER));
# Line 533  Line 762 
762    
763    
764  /* (internal function) change colorspace */  /* (internal function) change colorspace */
765    #define CALC_BI_STRIDE(width,bitcount)  ((((width * bitcount) + 31) & ~31) >> 3)
766    
767  HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format)  HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format)
768  {  {
769            DWORD biWidth;
770    
771          if (formattype == FORMAT_VideoInfo)          if (formattype == FORMAT_VideoInfo)
772          {          {
773                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;
774                  m_frame.output.stride[0] = (((vih->bmiHeader.biWidth * vih->bmiHeader.biBitCount) + 31) & ~31) >> 3;                  biWidth = vih->bmiHeader.biWidth;
775                    out_stride = CALC_BI_STRIDE(vih->bmiHeader.biWidth, vih->bmiHeader.biBitCount);
776                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
777          }          }
778          else if (formattype == FORMAT_VideoInfo2)          else if (formattype == FORMAT_VideoInfo2)
779          {          {
780                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;
781                  m_frame.output.stride[0] = (((vih2->bmiHeader.biWidth * vih2->bmiHeader.biBitCount) + 31) & ~31) >> 3;                  biWidth = vih2->bmiHeader.biWidth;
782                    out_stride = CALC_BI_STRIDE(vih2->bmiHeader.biWidth, vih2->bmiHeader.biBitCount);
783                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
784          }          }
785          else          else
# Line 558  Line 792 
792                  DPRINTF("IYUV");                  DPRINTF("IYUV");
793                  rgb_flip = 0;                  rgb_flip = 0;
794                  m_frame.output.csp = XVID_CSP_I420;                  m_frame.output.csp = XVID_CSP_I420;
795                  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 */
796          }          }
797          else if (subtype == MEDIASUBTYPE_YV12)          else if (subtype == MEDIASUBTYPE_YV12)
798          {          {
799                  DPRINTF("YV12");                  DPRINTF("YV12");
800                  rgb_flip = 0;                  rgb_flip = 0;
801                  m_frame.output.csp = XVID_CSP_YV12;                  m_frame.output.csp = XVID_CSP_YV12;
802                  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 */
803          }          }
804          else if (subtype == MEDIASUBTYPE_YUY2)          else if (subtype == MEDIASUBTYPE_YUY2)
805          {          {
# Line 638  Line 872 
872  HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)  HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
873  {  {
874          DPRINTF("CheckTransform");          DPRINTF("CheckTransform");
875    
876            return S_OK;
877    }
878    
879    /* input/output pin connection complete */
880    
881    HRESULT CXvidDecoder::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin)
882    {
883            DPRINTF("CompleteConnect");
884    
885    #ifdef XVID_USE_TRAYICON
886            if ((direction == PINDIR_OUTPUT) && (Tray_Icon == 0))
887            {
888                    WNDCLASSEX wc;
889    
890                    wc.cbSize = sizeof(WNDCLASSEX);
891                    wc.lpfnWndProc = msg_proc;
892                    wc.style = CS_HREDRAW | CS_VREDRAW;
893                    wc.cbWndExtra = 0;
894                    wc.cbClsExtra = 0;
895                    wc.hInstance = (HINSTANCE) g_xvid_hInst;
896                    wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH);
897                    wc.lpszMenuName = NULL;
898                    wc.lpszClassName = "XVID_MSG_WINDOW";
899                    wc.hIcon = NULL;
900                    wc.hIconSm = NULL;
901                    wc.hCursor = NULL;
902                    RegisterClassEx(&wc);
903    
904                    MSG_hwnd = CreateWindowEx(0, "XVID_MSG_WINDOW", NULL, 0, CW_USEDEFAULT,
905                                      CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE) g_xvid_hInst, NULL);
906    
907                    /* display the tray icon */
908                    NOTIFYICONDATA nid;
909                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
910    
911                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
912                    nid.hWnd = MSG_hwnd;
913                    nid.uID = 1456;
914                    nid.uCallbackMessage = WM_ICONMESSAGE;
915                    nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
916                    strcpy_s(nid.szTip, 19, "Xvid Video Decoder");
917                    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
918    
919                    Shell_NotifyIcon(NIM_ADD, &nid);
920    
921                    DestroyIcon(nid.hIcon);
922                    Tray_Icon = 1;
923            }
924    #endif
925    
926          return S_OK;          return S_OK;
927  }  }
928    
929    /* input/output pin disconnected */
930    HRESULT CXvidDecoder::BreakConnect(PIN_DIRECTION direction)
931    {
932            DPRINTF("BreakConnect");
933    
934            return S_OK;
935    }
936    
937  /* alloc output buffer */  /* alloc output buffer */
938    
# Line 689  Line 981 
981    
982          if (m_create.handle == NULL)          if (m_create.handle == NULL)
983          {          {
984                    if (xvid_decore_func == NULL)
985                            return E_FAIL;
986    
987                  if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)                  if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
988                  {                  {
989              DPRINTF("*** XVID_DEC_CREATE error");              DPRINTF("*** XVID_DEC_CREATE error");
990                          return S_FALSE;                          return E_FAIL;
991                  }                  }
992          }          }
993    
# Line 747  Line 1042 
1042    
1043          m_frame.output.csp &= ~XVID_CSP_VFLIP;          m_frame.output.csp &= ~XVID_CSP_VFLIP;
1044          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);
1045            m_frame.output.stride[0] = out_stride;
1046    
1047        // Paranoid check.
1048        if (xvid_decore_func == NULL)
1049                    return E_FAIL;
1050    
1051    
1052  repeat :  repeat :
1053    
# Line 754  Line 1055 
1055          {          {
1056                  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);
1057    
1058                  if (length < 0)                  if (length == XVID_ERR_MEMORY)
1059                            return E_FAIL;
1060                    else if (length < 0)
1061                  {                  {
1062              DPRINTF("*** XVID_DEC_DECODE");              DPRINTF("*** XVID_DEC_DECODE");
1063                          return S_FALSE;                          return S_FALSE;
1064                    } else
1065                            if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1 && forced_ar == false) {
1066    
1067          if (stats.type != XVID_TYPE_NOTHING) {  /* dont attempt to set vmr aspect ratio if no frame was returned by decoder */
1068                            // inspired by minolta! works for VMR 7 + 9
1069                            IMediaSample2 *pOut2 = NULL;
1070                            AM_SAMPLE2_PROPERTIES outProp2;
1071                            if (SUCCEEDED(pOut->QueryInterface(IID_IMediaSample2, (void **)&pOut2)) &&
1072                                    SUCCEEDED(pOut2->GetProperties(FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, tStart), (PBYTE)&outProp2)))
1073                            {
1074                                    CMediaType mtOut2 = m_pOutput->CurrentMediaType();
1075                                    VIDEOINFOHEADER2* vihOut2 = (VIDEOINFOHEADER2*)mtOut2.Format();
1076    
1077                                    if (*mtOut2.FormatType() == FORMAT_VideoInfo2 &&
1078                                            vihOut2->dwPictAspectRatioX != ar_x && vihOut2->dwPictAspectRatioY != ar_y)
1079                                    {
1080                                            vihOut2->dwPictAspectRatioX = ar_x;
1081                                            vihOut2->dwPictAspectRatioY = ar_y;
1082                                            pOut2->SetMediaType(&mtOut2);
1083                                            m_pOutput->SetMediaType(&mtOut2);
1084                                    }
1085                                    pOut2->Release();
1086                            }
1087          }
1088                  }                  }
1089          }          }
1090          else          else
# Line 774  Line 1101 
1101                  m_frame.general &= ~XVID_FILMEFFECT;                  m_frame.general &= ~XVID_FILMEFFECT;
1102    
1103                  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);
1104                  if (length < 0)                  if (length == XVID_ERR_MEMORY)
1105                            return E_FAIL;
1106                    else if (length < 0)
1107                  {                  {
1108              DPRINTF("*** XVID_DEC_DECODE");              DPRINTF("*** XVID_DEC_DECODE");
1109                          return S_FALSE;                          return S_FALSE;
# Line 799  Line 1128 
1128                          return S_FALSE;                          return S_FALSE;
1129                  }                  }
1130    
 //              pOut->SetDiscontinuity(TRUE);  
1131                  pOut->SetSyncPoint(TRUE);                  pOut->SetSyncPoint(TRUE);
1132    
1133                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) { /* auto */
1134                            int par_x, par_y;
1135                            if (stats.data.vol.par == XVID_PAR_EXT) {
1136                                    par_x = stats.data.vol.par_width;
1137                                    par_y = stats.data.vol.par_height;
1138                            } else {
1139                                    par_x = PARS[stats.data.vol.par-1][0];
1140                                    par_y = PARS[stats.data.vol.par-1][1];
1141                            }
1142    
1143                            ar_x = par_x * stats.data.vol.width;
1144                            ar_y = par_y * stats.data.vol.height;
1145                    }
1146    
1147                  m_frame.bitstream = (BYTE*)m_frame.bitstream + length;                  m_frame.bitstream = (BYTE*)m_frame.bitstream + length;
1148                  m_frame.length -= length;                  m_frame.length -= length;
1149                  goto repeat;                  goto repeat;
# Line 841  Line 1183 
1183          CoTaskMemFree(pPages->pElems);          CoTaskMemFree(pPages->pElems);
1184          return S_OK;          return S_OK;
1185  }  }
1186    
1187    /*===============================================================================
1188    // MFT Interface
1189    //=============================================================================*/
1190    #if defined(XVID_USE_MFT)
1191    #include <limits.h> // _I64_MAX
1192    #define INVALID_TIME  _I64_MAX
1193    
1194    HRESULT CXvidDecoder::MFTGetStreamLimits(DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum)
1195    {
1196            DPRINTF("(MFT)GetStreamLimits");
1197    
1198            if ((pdwInputMinimum == NULL) || (pdwInputMaximum == NULL) || (pdwOutputMinimum == NULL) || (pdwOutputMaximum == NULL))
1199                    return E_POINTER;
1200    
1201            /* Just a fixed number of streams allowed */
1202            *pdwInputMinimum = *pdwInputMaximum = 1;
1203            *pdwOutputMinimum = *pdwOutputMaximum = 1;
1204    
1205            return S_OK;
1206    }
1207    
1208    HRESULT CXvidDecoder::MFTGetStreamCount(DWORD *pcInputStreams, DWORD *pcOutputStreams)
1209    {
1210            DPRINTF("(MFT)GetStreamCount");
1211    
1212            if ((pcInputStreams == NULL) || (pcOutputStreams == NULL))
1213                    return E_POINTER;
1214    
1215            /* We have a fixed number of streams */
1216            *pcInputStreams = 1;
1217            *pcOutputStreams = 1;
1218    
1219            return S_OK;
1220    }
1221    
1222    HRESULT CXvidDecoder::MFTGetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs)
1223    {
1224            DPRINTF("(MFT)GetStreamIDs");
1225            return E_NOTIMPL; /* We have fixed number of streams, so stream ID match stream index */
1226    }
1227    
1228    HRESULT CXvidDecoder::MFTGetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo)
1229    {
1230            DPRINTF("(MFT)GetInputStreamInfo");
1231    
1232            if (pStreamInfo == NULL)
1233                    return E_POINTER;
1234    
1235            if (dwInputStreamID != 0)
1236                    return MF_E_INVALIDSTREAMNUMBER;
1237    
1238            EnterCriticalSection(&m_mft_lock);
1239    
1240            pStreamInfo->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER;
1241            pStreamInfo->hnsMaxLatency = 0;
1242    
1243            pStreamInfo->cbSize = 1; /* Need atleast 1 byte input */
1244            pStreamInfo->cbMaxLookahead = 0;
1245            pStreamInfo->cbAlignment = 1;
1246    
1247            LeaveCriticalSection(&m_mft_lock);
1248            return S_OK;
1249    }
1250    
1251    HRESULT CXvidDecoder::MFTGetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo)
1252    {
1253            DPRINTF("(MFT)GetOutputStreamInfo");
1254    
1255            if (pStreamInfo == NULL)
1256                    return E_POINTER;
1257    
1258            if (dwOutputStreamID != 0)
1259                    return MF_E_INVALIDSTREAMNUMBER;
1260    
1261            EnterCriticalSection(&m_mft_lock);
1262    
1263            pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_DISCARDABLE;
1264    
1265            if (m_pOutputType == NULL) {
1266                    pStreamInfo->cbSize = 0;
1267                    pStreamInfo->cbAlignment = 0;
1268            }
1269            else {
1270                    pStreamInfo->cbSize = m_create.width * abs(m_create.height) * 4; // XXX
1271                    pStreamInfo->cbAlignment = 1;
1272            }
1273    
1274            LeaveCriticalSection(&m_mft_lock);
1275            return S_OK;
1276    }
1277    
1278    HRESULT CXvidDecoder::GetAttributes(IMFAttributes** pAttributes)
1279    {
1280            DPRINTF("(MFT)GetAttributes");
1281            return E_NOTIMPL; /* We don't support any attributes */
1282    }
1283    
1284    HRESULT CXvidDecoder::GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes **ppAttributes)
1285    {
1286            DPRINTF("(MFT)GetInputStreamAttributes");
1287            return E_NOTIMPL; /* We don't support any attributes */
1288    }
1289    
1290    HRESULT CXvidDecoder::GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes **ppAttributes)
1291    {
1292            DPRINTF("(MFT)GetOutputStreamAttributes");
1293            return E_NOTIMPL; /* We don't support any attributes */
1294    }
1295    
1296    HRESULT CXvidDecoder::MFTDeleteInputStream(DWORD dwStreamID)
1297    {
1298            DPRINTF("(MFT)DeleteInputStream");
1299            return E_NOTIMPL; /* We have a fixed number of streams */
1300    }
1301    
1302    HRESULT CXvidDecoder::MFTAddInputStreams(DWORD cStreams, DWORD *adwStreamIDs)
1303    {
1304            DPRINTF("(MFT)AddInputStreams");
1305            return E_NOTIMPL; /* We have a fixed number of streams */
1306    }
1307    
1308    HRESULT CXvidDecoder::MFTGetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1309    {
1310            DPRINTF("(MFT)GetInputAvailableType");
1311    
1312            if (dwInputStreamID != 0)
1313                    return MF_E_INVALIDSTREAMNUMBER;
1314    
1315            DWORD i = 0;
1316            GUID *bs_guid_table[8];
1317    
1318            bs_guid_table[i++] = (GUID *)&CLSID_XVID;
1319            bs_guid_table[i++] = (GUID *)&CLSID_XVID_UC;
1320    
1321            if (g_config.supported_4cc & SUPPORT_DX50) {
1322                    bs_guid_table[i++] = (GUID *)&CLSID_DX50;
1323                    bs_guid_table[i++] = (GUID *)&CLSID_DX50_UC;
1324            }
1325            if (g_config.supported_4cc & SUPPORT_DIVX) {
1326                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX;
1327                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX_UC;
1328            }
1329            if (g_config.supported_4cc & SUPPORT_MP4V) {
1330                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V;
1331                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V_UC;
1332            }
1333    
1334            const GUID *subtype;
1335            if (dwTypeIndex < i) {
1336                    subtype = bs_guid_table[dwTypeIndex];
1337            }
1338            else {
1339                    return MF_E_NO_MORE_TYPES;
1340            }
1341    
1342            EnterCriticalSection(&m_mft_lock);
1343    
1344            HRESULT hr = S_OK;
1345    
1346            if (ppType) {
1347                    IMFMediaType *pInputType = NULL;
1348                    hr = MFCreateMediaType(&pInputType);
1349    
1350                    if (SUCCEEDED(hr))
1351                            hr = pInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1352    
1353                    if (SUCCEEDED(hr))
1354                            hr = pInputType->SetGUID(MF_MT_SUBTYPE, *subtype);
1355    
1356                    if (SUCCEEDED(hr)) {
1357                            *ppType = pInputType;
1358                            (*ppType)->AddRef();
1359                    }
1360                    if (pInputType) pInputType->Release();
1361            }
1362    
1363            LeaveCriticalSection(&m_mft_lock);
1364    
1365            return hr;
1366    }
1367    
1368    HRESULT CXvidDecoder::MFTGetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1369    {
1370            DPRINTF("(MFT)GetOutputAvailableType");
1371    
1372            if (ppType == NULL)
1373                    return E_INVALIDARG;
1374    
1375            if (dwOutputStreamID != 0)
1376                    return MF_E_INVALIDSTREAMNUMBER;
1377    
1378            if (dwTypeIndex < 0) return E_INVALIDARG;
1379    
1380            GUID csp;
1381            int bitdepth = 8;
1382            switch(dwTypeIndex)
1383            {
1384            case 0:
1385    if ( USE_YUY2 )
1386    {
1387                    csp = MFVideoFormat_YUY2;
1388                    bitdepth = 4;
1389                    break;
1390    }
1391            case 1 :
1392    if ( USE_UYVY )
1393    {
1394                    csp = MFVideoFormat_UYVY;
1395                    bitdepth = 4;
1396                    break;
1397    }
1398            case 2  :
1399                    if ( USE_IYUV )
1400    {
1401                    csp = MFVideoFormat_IYUV;
1402                    bitdepth = 3;
1403                    break;
1404    }
1405            case 3  :
1406    if ( USE_YV12 )
1407    {
1408                    csp = MFVideoFormat_YV12;
1409                    bitdepth = 3;
1410                    break;
1411    }
1412            case 4 :
1413    if ( USE_RGB32 )
1414    {
1415                    csp = MFVideoFormat_RGB32;
1416                    bitdepth = 8;
1417                    break;
1418    }
1419            case 5 :
1420    if ( USE_RGB24 )
1421    {
1422                    csp = MFVideoFormat_RGB24;
1423                    bitdepth = 6;
1424                    break;
1425    }
1426            case 6 :
1427    if ( USE_RG555 )
1428    {
1429                    csp = MFVideoFormat_RGB555;
1430                    bitdepth = 4;
1431                    break;
1432    }
1433            case 7 :
1434    if ( USE_RG565 )
1435    {
1436                    csp = MFVideoFormat_RGB565;
1437                    bitdepth = 4;
1438                    break;
1439    }
1440            default :
1441                    return MF_E_NO_MORE_TYPES;
1442            }
1443    
1444            if (m_pInputType == NULL)
1445                    return MF_E_TRANSFORM_TYPE_NOT_SET;
1446    
1447            EnterCriticalSection(&m_mft_lock);
1448    
1449            HRESULT hr = S_OK;
1450    
1451            IMFMediaType *pOutputType = NULL;
1452            hr = MFCreateMediaType(&pOutputType);
1453    
1454            if (SUCCEEDED(hr)) {
1455                    hr = pOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1456            }
1457    
1458            if (SUCCEEDED(hr)) {
1459                    hr = pOutputType->SetGUID(MF_MT_SUBTYPE, csp);
1460        }
1461    
1462            if (SUCCEEDED(hr)) {
1463                    hr = pOutputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE);
1464            }
1465    
1466            if (SUCCEEDED(hr)) {
1467                    hr = pOutputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
1468            }
1469    
1470            if (SUCCEEDED(hr)) {
1471                    hr = pOutputType->SetUINT32(MF_MT_SAMPLE_SIZE, (m_create.height * m_create.width * bitdepth)>>1);
1472            }
1473    
1474            if (SUCCEEDED(hr)) {
1475                    hr = MFSetAttributeSize(pOutputType, MF_MT_FRAME_SIZE, m_create.width, m_create.height);
1476            }
1477    
1478            if (SUCCEEDED(hr)) {
1479                    hr = MFSetAttributeRatio(pOutputType, MF_MT_FRAME_RATE, m_frameRate.Numerator, m_frameRate.Denominator);
1480            }
1481    
1482            if (SUCCEEDED(hr)) {
1483                    hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
1484            }
1485    
1486            if (SUCCEEDED(hr)) {
1487                    hr = MFSetAttributeRatio(pOutputType, MF_MT_PIXEL_ASPECT_RATIO, ar_x, ar_y);
1488            }
1489    
1490            if (SUCCEEDED(hr)) {
1491                    *ppType = pOutputType;
1492                    (*ppType)->AddRef();
1493            }
1494    
1495            if (pOutputType) pOutputType->Release();
1496    
1497            LeaveCriticalSection(&m_mft_lock);
1498            return hr;
1499    }
1500    
1501    HRESULT CXvidDecoder::MFTSetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags)
1502    {
1503            DPRINTF("(MFT)SetInputType");
1504    
1505            if (dwInputStreamID != 0)
1506                    return MF_E_INVALIDSTREAMNUMBER;
1507    
1508            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1509                    return E_INVALIDARG;
1510    
1511            EnterCriticalSection(&m_mft_lock);
1512    
1513            HRESULT hr = S_OK;
1514    
1515            /* Actually set the type or just test it? */
1516            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1517    
1518            /* If we have samples pending the type can't be changed right now */
1519            if (HasPendingOutput())
1520                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1521    
1522            if (SUCCEEDED(hr)) {
1523            if (pType) { // /* Check the type */
1524                hr = OnCheckInputType(pType);
1525            }
1526            }
1527    
1528            if (SUCCEEDED(hr)) {
1529                    if (bReallySet) { /* Set the type if needed */
1530                            hr = OnSetInputType(pType);
1531                    }
1532            }
1533    
1534            LeaveCriticalSection(&m_mft_lock);
1535            return hr;
1536    }
1537    
1538    HRESULT CXvidDecoder::MFTSetOutputType(DWORD dwOutputStreamID, IMFMediaType *pType, DWORD dwFlags)
1539    {
1540            DPRINTF("(MFT)SetOutputType");
1541    
1542            if (dwOutputStreamID != 0)
1543                    return MF_E_INVALIDSTREAMNUMBER;
1544    
1545            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1546                    return E_INVALIDARG;
1547    
1548            HRESULT hr = S_OK;
1549    
1550            EnterCriticalSection(&m_mft_lock);
1551    
1552            /* Actually set the type or just test it? */
1553            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1554    
1555            /* If we have samples pending the type can't be changed right now */
1556            if (HasPendingOutput())
1557                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1558    
1559            if (SUCCEEDED(hr)) {
1560                    if (pType) { /* Check the type */
1561                            AM_MEDIA_TYPE *am;
1562                            hr = MFCreateAMMediaTypeFromMFMediaType(pType, GUID_NULL, &am);
1563    
1564                            if (SUCCEEDED(hr)) {
1565                                    if (FAILED(ChangeColorspace(am->subtype, am->formattype, am->pbFormat))) {
1566                                            DPRINTF("(MFT)InternalCheckOutputType (MF_E_INVALIDTYPE)");
1567                                            return MF_E_INVALIDTYPE;
1568                                    }
1569    
1570                            CoTaskMemFree(am->pbFormat);
1571                            CoTaskMemFree(am);
1572                            }
1573                    }
1574            }
1575    
1576            if (SUCCEEDED(hr)) {
1577                    if (bReallySet) { /* Set the type if needed */
1578                            hr = OnSetOutputType(pType);
1579                    }
1580            }
1581    
1582    #ifdef XVID_USE_TRAYICON
1583            if (SUCCEEDED(hr) && Tray_Icon == 0) /* Create message passing window */
1584            {
1585                    WNDCLASSEX wc;
1586    
1587                    wc.cbSize = sizeof(WNDCLASSEX);
1588                    wc.lpfnWndProc = msg_proc;
1589                    wc.style = CS_HREDRAW | CS_VREDRAW;
1590                    wc.cbWndExtra = 0;
1591                    wc.cbClsExtra = 0;
1592                    wc.hInstance = (HINSTANCE) g_xvid_hInst;
1593                    wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH);
1594                    wc.lpszMenuName = NULL;
1595                    wc.lpszClassName = "XVID_MSG_WINDOW";
1596                    wc.hIcon = NULL;
1597                    wc.hIconSm = NULL;
1598                    wc.hCursor = NULL;
1599                    RegisterClassEx(&wc);
1600    
1601                    MSG_hwnd = CreateWindowEx(0, "XVID_MSG_WINDOW", NULL, 0, CW_USEDEFAULT,
1602                                      CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE) g_xvid_hInst, NULL);
1603    
1604                    /* display the tray icon */
1605                    NOTIFYICONDATA nid;
1606                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
1607    
1608                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
1609                    nid.hWnd = MSG_hwnd;
1610                    nid.uID = 1456;
1611                    nid.uCallbackMessage = WM_ICONMESSAGE;
1612                    nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
1613                    strcpy_s(nid.szTip, 19, "Xvid Video Decoder");
1614                    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
1615    
1616                    Shell_NotifyIcon(NIM_ADD, &nid);
1617    
1618                    DestroyIcon(nid.hIcon);
1619                    Tray_Icon = 1;
1620            }
1621    #endif
1622    
1623            LeaveCriticalSection(&m_mft_lock);
1624            return hr;
1625    }
1626    
1627    HRESULT CXvidDecoder::MFTGetInputCurrentType(DWORD dwInputStreamID, IMFMediaType **ppType)
1628    {
1629            DPRINTF("(MFT)GetInputCurrentType");
1630    
1631            if (ppType == NULL)
1632                    return E_POINTER;
1633    
1634            if (dwInputStreamID != 0)
1635                    return MF_E_INVALIDSTREAMNUMBER;
1636    
1637            EnterCriticalSection(&m_mft_lock);
1638    
1639            HRESULT hr = S_OK;
1640    
1641            if (!m_pInputType)
1642                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1643    
1644            if (SUCCEEDED(hr)) {
1645                    *ppType = m_pInputType;
1646                    (*ppType)->AddRef();
1647            }
1648    
1649            LeaveCriticalSection(&m_mft_lock);
1650            return hr;
1651    }
1652    
1653    HRESULT CXvidDecoder::MFTGetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType)
1654    {
1655            DPRINTF("(MFT)GetOutputCurrentType");
1656    
1657            if (ppType == NULL)
1658                    return E_POINTER;
1659    
1660            if (dwOutputStreamID != 0)
1661                    return MF_E_INVALIDSTREAMNUMBER;
1662    
1663            EnterCriticalSection(&m_mft_lock);
1664    
1665            HRESULT hr = S_OK;
1666    
1667            if (!m_pOutputType)
1668                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1669    
1670            if (SUCCEEDED(hr)) {
1671                    *ppType = m_pOutputType;
1672                    (*ppType)->AddRef();
1673            }
1674    
1675            LeaveCriticalSection(&m_mft_lock);
1676            return hr;
1677    }
1678    
1679    HRESULT CXvidDecoder::MFTGetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags)
1680    {
1681            DPRINTF("(MFT)GetInputStatus");
1682    
1683            if (pdwFlags == NULL)
1684                    return E_POINTER;
1685    
1686            if (dwInputStreamID != 0)
1687                    return MF_E_INVALIDSTREAMNUMBER;
1688    
1689            EnterCriticalSection(&m_mft_lock);
1690    
1691            /* If there's pending output sampels we don't accept new
1692               input data until ProcessOutput() or Flush() was called */
1693            if (!HasPendingOutput()) {
1694                    *pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
1695            }
1696            else {
1697                    *pdwFlags = 0;
1698            }
1699    
1700            LeaveCriticalSection(&m_mft_lock);
1701    
1702            return S_OK;
1703    }
1704    
1705    HRESULT CXvidDecoder::MFTGetOutputStatus(DWORD *pdwFlags)
1706    {
1707            DPRINTF("(MFT)GetOutputStatus");
1708    
1709            if (pdwFlags == NULL)
1710                    return E_POINTER;
1711    
1712            EnterCriticalSection(&m_mft_lock);
1713    
1714            /* We can render an output sample only after we
1715               have decoded one */
1716            if (HasPendingOutput()) {
1717                    *pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
1718            }
1719            else {
1720                    *pdwFlags = 0;
1721            }
1722    
1723            LeaveCriticalSection(&m_mft_lock);
1724    
1725            return S_OK;
1726    }
1727    
1728    HRESULT CXvidDecoder::MFTSetOutputBounds(LONGLONG hnsLowerBound, LONGLONG hnsUpperBound)
1729    {
1730            DPRINTF("(MFT)SetOutputBounds");
1731            return E_NOTIMPL;
1732    }
1733    
1734    HRESULT CXvidDecoder::MFTProcessEvent(DWORD dwInputStreamID, IMFMediaEvent *pEvent)
1735    {
1736            DPRINTF("(MFT)ProcessEvent");
1737            return E_NOTIMPL; /* We don't handle any stream events */
1738    }
1739    
1740    HRESULT CXvidDecoder::MFTProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
1741    {
1742            DPRINTF("(MFT)ProcessMessage");
1743            HRESULT hr = S_OK;
1744    
1745            EnterCriticalSection(&m_mft_lock);
1746    
1747            switch (eMessage)
1748            {
1749            case MFT_MESSAGE_COMMAND_FLUSH:
1750                    if (m_create.handle != NULL) {
1751                            DPRINTF("(MFT)CommandFlush");
1752    
1753                            xvid_dec_stats_t stats;
1754                            int used_bytes;
1755    
1756                            memset(&stats, 0, sizeof(stats));
1757                            stats.version = XVID_VERSION;
1758    
1759                            int csp = m_frame.output.csp;
1760    
1761                            m_frame.output.csp = XVID_CSP_INTERNAL;
1762                            m_frame.bitstream = NULL;
1763                            m_frame.length = -1;
1764                            m_frame.general = XVID_LOWDELAY;
1765    
1766                            do {
1767                                    used_bytes = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1768                            } while(used_bytes>=0 && stats.type <= 0);
1769    
1770                            m_frame.output.csp = csp;
1771                            m_frame.output.plane[1] = NULL; /* Don't display flushed samples */
1772    
1773                            //m_timestamp = INVALID_TIME;
1774                            //m_timelength = INVALID_TIME;
1775                            //m_rtFrame = 0;
1776            }
1777        break;
1778    
1779            case MFT_MESSAGE_COMMAND_DRAIN:
1780                    m_discont = 1; /* Set discontinuity flag */
1781                    m_rtFrame = 0;
1782                    break;
1783    
1784            case MFT_MESSAGE_SET_D3D_MANAGER:
1785                    hr = E_NOTIMPL;
1786                    break;
1787    
1788            case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
1789            case MFT_MESSAGE_NOTIFY_END_STREAMING:
1790                    break;
1791    
1792            case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
1793            case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
1794                    break;
1795            }
1796    
1797            LeaveCriticalSection(&m_mft_lock);
1798    
1799            return hr;
1800    }
1801    
1802    HRESULT CXvidDecoder::MFTProcessInput(DWORD dwInputStreamID, IMFSample *pSample, DWORD dwFlags)
1803    {
1804            DPRINTF("(MFT)ProcessInput");
1805    
1806            if (pSample == NULL)
1807                    return E_POINTER;
1808    
1809            if (dwInputStreamID != 0)
1810                    return MF_E_INVALIDSTREAMNUMBER;
1811    
1812            if (dwFlags != 0)
1813                    return E_INVALIDARG;
1814    
1815            if (!m_pInputType || !m_pOutputType) {
1816                    return MF_E_NOTACCEPTING;   /* Must have set input and output types */
1817            }
1818            else if (HasPendingOutput()) {
1819                    return MF_E_NOTACCEPTING;   /* We still have output samples to render */
1820            }
1821    
1822            xvid_dec_stats_t stats;
1823            int length;
1824    
1825            memset(&stats, 0, sizeof(stats));
1826            stats.version = XVID_VERSION;
1827    
1828            if (m_create.handle == NULL)
1829            {
1830                    if (xvid_decore_func == NULL)
1831                            return E_FAIL;
1832                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
1833                    {
1834                            DPRINTF("*** XVID_DEC_CREATE error");
1835                            return E_FAIL;
1836                    }
1837            }
1838    
1839            EnterCriticalSection(&m_mft_lock);
1840    
1841            HRESULT hr = S_OK;
1842            IMFMediaBuffer *pBuffer;
1843    
1844            if (SUCCEEDED(hr)) {
1845                    hr = pSample->ConvertToContiguousBuffer(&pBuffer);
1846            }
1847    
1848            if (SUCCEEDED(hr)) {
1849                    hr = pBuffer->Lock((BYTE**)&m_frame.bitstream, NULL, (DWORD *)&m_frame.length);
1850            }
1851    
1852            m_frame.general = XVID_LOWDELAY;
1853    
1854            if (m_discont == 1) {
1855                    m_frame.general |= XVID_DISCONTINUITY;
1856                    m_discont = 0;
1857            }
1858    
1859            if (g_config.nDeblock_Y)
1860                    m_frame.general |= XVID_DEBLOCKY;
1861    
1862            if (g_config.nDeblock_UV)
1863                    m_frame.general |= XVID_DEBLOCKUV;
1864    
1865            if (g_config.nDering_Y)
1866                    m_frame.general |= XVID_DERINGY;
1867    
1868            if (g_config.nDering_UV)
1869                    m_frame.general |= XVID_DERINGUV;
1870    
1871            if (g_config.nFilmEffect)
1872                    m_frame.general |= XVID_FILMEFFECT;
1873    
1874            m_frame.brightness = g_config.nBrightness;
1875    
1876            m_frame.output.csp &= ~XVID_CSP_VFLIP;
1877            m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0);
1878    
1879            int csp = m_frame.output.csp;
1880            m_frame.output.csp = XVID_CSP_INTERNAL;
1881    
1882        // Paranoid check.
1883            if (xvid_decore_func == NULL) {
1884                    hr = E_FAIL;
1885                    goto END_LOOP;
1886            }
1887    
1888    repeat :
1889            length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1890    
1891            if (length == XVID_ERR_MEMORY) {
1892                    hr = E_FAIL;
1893                    goto END_LOOP;
1894            }
1895            else if (length < 0)
1896            {
1897                    DPRINTF("*** XVID_DEC_DECODE");
1898                    goto END_LOOP;
1899            }
1900    
1901            if (stats.type == XVID_TYPE_NOTHING && length > 0) {
1902                    DPRINTF(" B-Frame decoder lag");
1903                    m_frame.output.plane[1] = NULL;
1904                    goto END_LOOP;
1905            }
1906    
1907            if (stats.type == XVID_TYPE_VOL)
1908            {
1909                    if (stats.data.vol.width != m_create.width ||
1910                            stats.data.vol.height != m_create.height)
1911                    {
1912                            DPRINTF("TODO: auto-resize");
1913                            m_frame.output.plane[1] = NULL;
1914                            hr = E_FAIL;
1915                    }
1916    
1917                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) { /* auto */
1918                            int par_x, par_y;
1919                            if (stats.data.vol.par == XVID_PAR_EXT) {
1920                                    par_x = stats.data.vol.par_width;
1921                                    par_y = stats.data.vol.par_height;
1922                            } else {
1923                                    par_x = PARS[stats.data.vol.par-1][0];
1924                                    par_y = PARS[stats.data.vol.par-1][1];
1925                            }
1926    
1927                            ar_x = par_x * stats.data.vol.width;
1928                            ar_y = par_y * stats.data.vol.height;
1929                    }
1930    
1931                    m_frame.bitstream = (BYTE*)m_frame.bitstream + length;
1932                    m_frame.length -= length;
1933                    goto repeat;
1934            }
1935    
1936    END_LOOP:
1937            m_frame.output.csp = csp;
1938    
1939            if (pBuffer) {
1940                    pBuffer->Unlock();
1941                    pBuffer->Release();
1942            }
1943    
1944            if (SUCCEEDED(hr)) {
1945                    /* Try to get a timestamp */
1946                    if (FAILED(pSample->GetSampleTime(&m_timestamp)))
1947                            m_timestamp = INVALID_TIME;
1948    
1949                    if (FAILED(pSample->GetSampleDuration(&m_timelength))) {
1950                            m_timelength = INVALID_TIME;
1951                    }
1952            }
1953    
1954            LeaveCriticalSection(&m_mft_lock);
1955    
1956            return hr;
1957    }
1958    
1959    HRESULT CXvidDecoder::MFTProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus)
1960    {
1961            DPRINTF("(MFT)ProcessOutput");
1962    
1963            /* Preroll in MFT ??
1964               Flags ?? -> TODO... */
1965            if (dwFlags != 0)
1966                    return E_INVALIDARG;
1967    
1968            if (pOutputSamples == NULL || pdwStatus == NULL)
1969                    return E_POINTER;
1970    
1971            if (cOutputBufferCount != 1) /* Must be exactly one output buffer */
1972                    return E_INVALIDARG;
1973    
1974            if (pOutputSamples[0].pSample == NULL) /* Must have a sample */
1975                    return E_INVALIDARG;
1976    
1977            if (!HasPendingOutput()) { /* If there's no sample we need to decode one first */
1978                    return MF_E_TRANSFORM_NEED_MORE_INPUT;
1979            }
1980    
1981            EnterCriticalSection(&m_mft_lock);
1982    
1983            HRESULT hr = S_OK;
1984    
1985            BYTE *Dst = NULL;
1986            DWORD buffer_size;
1987    
1988            IMFMediaBuffer *pOutput = NULL;
1989    
1990            if (SUCCEEDED(hr)) {
1991                    hr = pOutputSamples[0].pSample->GetBufferByIndex(0, &pOutput); /* Get output buffer */
1992            }
1993    
1994            if (SUCCEEDED(hr)) {
1995                    hr = pOutput->GetMaxLength(&buffer_size);
1996            }
1997    
1998            if (SUCCEEDED(hr))
1999                    hr = pOutput->Lock(&Dst, NULL, NULL);
2000    
2001            if (SUCCEEDED(hr)) {
2002                    xvid_gbl_convert_t convert;
2003    
2004                    memset(&convert, 0, sizeof(convert));
2005                    convert.version = XVID_VERSION;
2006    
2007                    convert.input.csp = XVID_CSP_INTERNAL;
2008                    convert.input.plane[0] = m_frame.output.plane[0];
2009                    convert.input.plane[1] = m_frame.output.plane[1];
2010                    convert.input.plane[2] = m_frame.output.plane[2];
2011                    convert.input.stride[0] = m_frame.output.stride[0];
2012                    convert.input.stride[1] = m_frame.output.stride[1];
2013                    convert.input.stride[2] = m_frame.output.stride[2];
2014    
2015                    convert.output.csp = m_frame.output.csp;
2016                    convert.output.plane[0] = Dst;
2017                    convert.output.stride[0] = out_stride;
2018    
2019                    convert.width = m_create.width;
2020                    convert.height = m_create.height;
2021                    convert.interlacing = 0;
2022    
2023                    if (m_frame.output.plane[1] != NULL && Dst != NULL && xvid_global_func != NULL)
2024                            if (xvid_global_func(0, XVID_GBL_CONVERT, &convert, NULL) < 0) /* CSP convert into output buffer */
2025                                    hr = E_FAIL;
2026    
2027                    m_frame.output.plane[1] = NULL;
2028            }
2029    
2030            *pdwStatus = 0;
2031    
2032            if (SUCCEEDED(hr)) {
2033                    if (SUCCEEDED(hr))
2034                            hr = pOutputSamples[0].pSample->SetUINT32(MFSampleExtension_CleanPoint, TRUE); // key frame
2035    
2036                    if (SUCCEEDED(hr)) { /* Set timestamp of output sample */
2037                            if (m_timestamp != INVALID_TIME)
2038                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_timestamp);
2039                            else
2040                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_rtFrame);
2041    
2042                            if (m_timelength != INVALID_TIME)
2043                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_timelength);
2044                            else
2045                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_duration);
2046    
2047                            m_rtFrame += m_duration;
2048                    }
2049    
2050                    if (SUCCEEDED(hr))
2051                            hr = pOutput->SetCurrentLength(m_create.width * abs(m_create.height) * 4); // XXX
2052            }
2053    
2054            if (pOutput) {
2055                    pOutput->Unlock();
2056                    pOutput->Release();
2057            }
2058    
2059            LeaveCriticalSection(&m_mft_lock);
2060    
2061            return hr;
2062    }
2063    
2064    HRESULT CXvidDecoder::OnCheckInputType(IMFMediaType *pmt)
2065    {
2066            DPRINTF("(MFT)CheckInputType");
2067    
2068            HRESULT hr = S_OK;
2069    
2070            /*  Check if input type is already set. Reject any type that is not identical */
2071            if (m_pInputType) {
2072                    DWORD dwFlags = 0;
2073                    if (S_OK == m_pInputType->IsEqual(pmt, &dwFlags)) {
2074                            return S_OK;
2075                    }
2076                    else {
2077                            return MF_E_INVALIDTYPE;
2078                    }
2079            }
2080    
2081            GUID majortype = {0}, subtype = {0};
2082            UINT32 width = 0, height = 0;
2083    
2084            hr = pmt->GetMajorType(&majortype);
2085    
2086            if (SUCCEEDED(hr)) {
2087                    if (majortype != MFMediaType_Video) { /* Must be Video */
2088                            hr = MF_E_INVALIDTYPE;
2089                    }
2090            }
2091    
2092            if (m_hdll == NULL) {
2093                    HRESULT hr = OpenLib();
2094    
2095                    if (FAILED(hr) || (m_hdll == NULL)) // Paranoid checks.
2096                            hr = MF_E_INVALIDTYPE;
2097            }
2098    
2099            if (SUCCEEDED(hr)) {
2100                    hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &width, &height);
2101            }
2102    
2103            /* Check the frame size */
2104            if (SUCCEEDED(hr)) {
2105                    if (width > 4096 || height > 4096) {
2106                            hr = MF_E_INVALIDTYPE;
2107                    }
2108            }
2109            m_create.width = width;
2110            m_create.height = height;
2111    
2112            if (SUCCEEDED(hr)) {
2113                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
2114                            hr = MFGetAttributeRatio(pmt, MF_MT_PIXEL_ASPECT_RATIO, (UINT32*)&ar_x, (UINT32*)&ar_y);
2115                    }
2116            }
2117    
2118            /* TODO1: Make sure there really is a frame rate after all!
2119               TODO2: Use the framerate for something! */
2120            MFRatio fps = {0};
2121            if (SUCCEEDED(hr)) {
2122                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&fps.Numerator, (UINT32*)&fps.Denominator);
2123            }
2124    
2125            if (SUCCEEDED(hr)) {
2126                    hr = pmt->GetGUID(MF_MT_SUBTYPE, &subtype);
2127            }
2128    
2129            if (subtype == CLSID_MP4V || subtype == CLSID_MP4V_UC) {
2130                    if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
2131                            CloseLib();
2132                            hr = MF_E_INVALIDTYPE;
2133                    }
2134                    else m_create.fourcc = FOURCC_MP4V;
2135            }
2136            else if (subtype == CLSID_DIVX || subtype == CLSID_DIVX_UC) {
2137                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2138                            CloseLib();
2139                            hr = MF_E_INVALIDTYPE;
2140                    }
2141                    else m_create.fourcc = FOURCC_DIVX;
2142            }
2143            else if (subtype == CLSID_DX50 || subtype == CLSID_DX50_UC) {
2144                    if (!(g_config.supported_4cc & SUPPORT_DX50)) {
2145                            CloseLib();
2146                            hr = MF_E_INVALIDTYPE;
2147                    }
2148                    else m_create.fourcc = FOURCC_DX50;
2149            }
2150            else if (subtype == CLSID_XVID || subtype == CLSID_XVID_UC) {
2151                    m_create.fourcc = FOURCC_XVID;
2152            }
2153            else {
2154                    DPRINTF("Unknown subtype!");
2155                    CloseLib();
2156                    hr = MF_E_INVALIDTYPE;
2157            }
2158    
2159            /* haali media splitter reports VOL information in the format header */
2160            if (SUCCEEDED(hr))
2161            {
2162                    UINT32 cbSeqHeader = 0;
2163    
2164                    (void)pmt->GetBlobSize(MF_MT_MPEG_SEQUENCE_HEADER, &cbSeqHeader);
2165    
2166                    if (cbSeqHeader>0) {
2167                            xvid_dec_stats_t stats;
2168                            memset(&stats, 0, sizeof(stats));
2169                            stats.version = XVID_VERSION;
2170    
2171                            if (m_create.handle == NULL) {
2172                                    if (xvid_decore_func == NULL)
2173                                            hr = E_FAIL;
2174                                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
2175                                            DPRINTF("*** XVID_DEC_CREATE error");
2176                                            hr = E_FAIL;
2177                                    }
2178                            }
2179    
2180                            if (SUCCEEDED(hr)) {
2181                                    (void)pmt->GetAllocatedBlob(MF_MT_MPEG_SEQUENCE_HEADER, (UINT8 **)&m_frame.bitstream, (UINT32 *)&m_frame.length);
2182                                    m_frame.general = 0;
2183                                    m_frame.output.csp = XVID_CSP_NULL;
2184    
2185                                    int ret = 0;
2186                                    if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
2187                                            /* honour video dimensions reported in VOL header */
2188                                            if (stats.type == XVID_TYPE_VOL) {
2189                                                    m_create.width = stats.data.vol.width;
2190                                                    m_create.height = stats.data.vol.height;
2191                                            }
2192                                    }
2193    
2194                                    if (ret == XVID_ERR_MEMORY) hr = E_FAIL;
2195                                    CoTaskMemFree(m_frame.bitstream);
2196                            }
2197                    }
2198            }
2199    
2200            return hr;
2201    }
2202    
2203    HRESULT CXvidDecoder::OnSetInputType(IMFMediaType *pmt)
2204    {
2205            HRESULT hr = S_OK;
2206            UINT32 w, h;
2207    
2208            if (m_pInputType) m_pInputType->Release();
2209    
2210            hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &w, &h);
2211            m_create.width = w; m_create.height = h;
2212    
2213            if (SUCCEEDED(hr))
2214                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&m_frameRate.Numerator, (UINT32*)&m_frameRate.Denominator);
2215    
2216            if (SUCCEEDED(hr)) { /* Store frame duration, derived from the frame rate */
2217                    hr = MFFrameRateToAverageTimePerFrame(m_frameRate.Numerator, m_frameRate.Denominator, &m_duration);
2218            }
2219    
2220            if (SUCCEEDED(hr)) {
2221                    m_pInputType = pmt;
2222                    m_pInputType->AddRef();
2223            }
2224    
2225            return hr;
2226    }
2227    
2228    HRESULT CXvidDecoder::OnSetOutputType(IMFMediaType *pmt)
2229    {
2230            if (m_pOutputType) m_pOutputType->Release();
2231    
2232            m_pOutputType = pmt;
2233            m_pOutputType->AddRef();
2234    
2235            return S_OK;
2236    }
2237    
2238    #endif /* XVID_USE_MFT */

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

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