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

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

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

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

Legend:
Removed from v.1397  
changed lines
  Added in v.1912

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