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

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

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