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

Legend:
Removed from v.1521  
changed lines
  Added in v.1946

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