[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 1890, Tue Aug 10 14:17:40 2010 UTC revision 1962, Thu Mar 17 15:13:25 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.18 2010-08-10 14:17:40 Isibaar Exp $   * $Id: CXvidDecoder.cpp,v 1.29 2011-03-17 15:11:32 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 81  Line 89 
89          { &MEDIATYPE_Video, &CLSID_DIVX_UC },          { &MEDIATYPE_Video, &CLSID_DIVX_UC },
90          { &MEDIATYPE_Video, &CLSID_DX50 },          { &MEDIATYPE_Video, &CLSID_DX50 },
91          { &MEDIATYPE_Video, &CLSID_DX50_UC },          { &MEDIATYPE_Video, &CLSID_DX50_UC },
92            { &MEDIATYPE_Video, &CLSID_3IVX },
93            { &MEDIATYPE_Video, &CLSID_3IVX_UC },
94            { &MEDIATYPE_Video, &CLSID_3IV0 },
95            { &MEDIATYPE_Video, &CLSID_3IV0_UC },
96            { &MEDIATYPE_Video, &CLSID_3IV1 },
97            { &MEDIATYPE_Video, &CLSID_3IV1_UC },
98            { &MEDIATYPE_Video, &CLSID_3IV2 },
99            { &MEDIATYPE_Video, &CLSID_3IV2_UC },
100            { &MEDIATYPE_Video, &CLSID_LMP4 },
101            { &MEDIATYPE_Video, &CLSID_LMP4_UC },
102            { &MEDIATYPE_Video, &CLSID_RMP4 },
103            { &MEDIATYPE_Video, &CLSID_RMP4_UC },
104            { &MEDIATYPE_Video, &CLSID_SMP4 },
105            { &MEDIATYPE_Video, &CLSID_SMP4_UC },
106            { &MEDIATYPE_Video, &CLSID_HDX4 },
107            { &MEDIATYPE_Video, &CLSID_HDX4_UC },
108          { &MEDIATYPE_Video, &CLSID_MP4V },          { &MEDIATYPE_Video, &CLSID_MP4V },
109    { &MEDIATYPE_Video, &CLSID_MP4V_UC },    { &MEDIATYPE_Video, &CLSID_MP4V_UC },
110  };  };
# Line 122  Line 146 
146  {  {
147          &CLSID_XVID,                    // Filter CLSID          &CLSID_XVID,                    // Filter CLSID
148          XVID_NAME_L,                    // Filter name          XVID_NAME_L,                    // Filter name
149          MERIT_PREFERRED,                // Its merit          MERIT_PREFERRED+2,              // Its merit
150          sizeof(psudPins) / sizeof(AMOVIESETUP_PIN),     // Number of pins          sizeof(psudPins) / sizeof(AMOVIESETUP_PIN),     // Number of pins
151          psudPins                                // Pin details          psudPins                                // Pin details
152  };  };
# Line 149  Line 173 
173    
174  };  };
175    
   
176  /* 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) */
177  int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate);  int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate);
178    
179    #ifdef XVID_USE_TRAYICON
180    extern HINSTANCE g_xvid_hInst;
181    
182    static int GUI_Page = 0;
183    static int Tray_Icon = 0;
184    extern "C" void CALLBACK Configure(HWND hWndParent, HINSTANCE hInstParent, LPSTR lpCmdLine, int nCmdShow );
185    
186    LRESULT CALLBACK msg_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
187    {
188            switch ( uMsg )
189            {
190            case WM_ICONMESSAGE:
191                    switch(lParam)
192                    {
193                    case WM_LBUTTONDBLCLK:
194                            if (!GUI_Page) {
195                                    GUI_Page = 1;
196                                    Configure(hwnd, g_xvid_hInst, "", 1);
197                                    GUI_Page = 0;
198                            }
199                            break;
200                    default:
201                            return DefWindowProc(hwnd, uMsg, wParam, lParam);
202                    };
203                    break;
204    
205            case WM_DESTROY:
206                    NOTIFYICONDATA nid;
207                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
208    
209                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
210                    nid.hWnd = hwnd;
211                    nid.uID = 1456;
212    
213                    Shell_NotifyIcon(NIM_DELETE, &nid);
214                    Tray_Icon = 0;
215            default:
216                    return DefWindowProc(hwnd, uMsg, wParam, lParam);
217            }
218    
219            return TRUE; /* ok */
220    }
221    #endif
222    
223  STDAPI DllRegisterServer()  STDAPI DllRegisterServer()
224  {  {
225    #if defined(XVID_USE_MFT)
226            int inputs_num = sizeof(sudInputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE);
227            int outputs_num = sizeof(sudOutputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE);
228            MFT_REGISTER_TYPE_INFO * mft_bs = new MFT_REGISTER_TYPE_INFO[inputs_num];
229            MFT_REGISTER_TYPE_INFO * mft_csp = new MFT_REGISTER_TYPE_INFO[outputs_num];
230    
231            {
232                    int i;
233                    for(i=0;i<inputs_num;i++) {
234                            mft_bs[i].guidMajorType = *sudInputPinTypes[i].clsMajorType;
235                            mft_bs[i].guidSubtype = *sudInputPinTypes[i].clsMinorType;
236                    }
237                    for(i=0;i<outputs_num;i++) {
238                            mft_csp[i].guidMajorType = *sudOutputPinTypes[i].clsMajorType;
239                            mft_csp[i].guidSubtype = *sudOutputPinTypes[i].clsMinorType; // MFT and AM GUIDs really the same?
240                    }
241            }
242    
243            /* Register the MFT decoder */
244            MFTRegister(CLSID_XVID,                          // CLSID
245                            MFT_CATEGORY_VIDEO_DECODER,          // Category
246                            const_cast<LPWSTR>(XVID_NAME_L),     // Friendly name
247                            0,                                   // Flags
248                            inputs_num,                          // Number of input types
249                            mft_bs,                              // Input types
250                            outputs_num,                         // Number of output types
251                            mft_csp,                             // Output types
252                            NULL                                 // Attributes (optional)
253                            );
254    
255            delete[] mft_bs;
256            delete[] mft_csp;
257    #endif /* XVID_USE_MFT */
258    
259      return AMovieDllRegisterServer2( TRUE );      return AMovieDllRegisterServer2( TRUE );
260  }  }
261    
262    
263  STDAPI DllUnregisterServer()  STDAPI DllUnregisterServer()
264  {  {
265    #if defined(XVID_USE_MFT)
266            MFTUnregister(CLSID_XVID);
267    #endif
268      return AMovieDllRegisterServer2( FALSE );      return AMovieDllRegisterServer2( FALSE );
269  }  }
270    
# Line 195  Line 298 
298          return GetInterface((ISpecifyPropertyPages *) this, ppv);          return GetInterface((ISpecifyPropertyPages *) this, ppv);
299          }          }
300    
301    #if defined(XVID_USE_MFT)
302            if (riid == IID_IMFTransform)
303            {
304                    return GetInterface((IMFTransform *) this, ppv);
305            }
306    #endif
307    
308          return CVideoTransformFilter::NonDelegatingQueryInterface(riid, ppv);          return CVideoTransformFilter::NonDelegatingQueryInterface(riid, ppv);
309  }  }
310    
# Line 212  Line 322 
322      xvid_decore_func = NULL; // Hmm, some strange errors appearing if I try to initialize...      xvid_decore_func = NULL; // Hmm, some strange errors appearing if I try to initialize...
323      xvid_global_func = NULL; // ...this in constructor's init-list. So, they assigned here.      xvid_global_func = NULL; // ...this in constructor's init-list. So, they assigned here.
324    
325    #if defined(XVID_USE_MFT)
326            InitializeCriticalSection(&m_mft_lock);
327            m_pInputType = NULL;
328            m_pOutputType = NULL;
329            m_rtFrame = 0;
330            m_duration = 0;
331            m_discont = 0;
332            m_frameRate.Denominator = 1;
333            m_frameRate.Numerator = 1;
334    #endif
335    
336      LoadRegistryInfo();      LoadRegistryInfo();
337    
338      *phr = OpenLib();      *phr = OpenLib();
# Line 227  Line 348 
348          xvid_gbl_init_t init;          xvid_gbl_init_t init;
349          memset(&init, 0, sizeof(init));          memset(&init, 0, sizeof(init));
350          init.version = XVID_VERSION;          init.version = XVID_VERSION;
351            init.cpu_flags = g_config.cpu;
352    
353            xvid_gbl_info_t info;
354            memset(&info, 0, sizeof(info));
355            info.version = XVID_VERSION;
356    
357          m_hdll = LoadLibrary(XVID_DLL_NAME);          m_hdll = LoadLibrary(XVID_DLL_NAME);
358          if (m_hdll == NULL) {          if (m_hdll == NULL) {
# Line 262  Line 388 
388                  return E_FAIL;                  return E_FAIL;
389          }          }
390    
391            if (xvid_global_func(0, XVID_GBL_INFO, &info, NULL) < 0)
392            {
393            xvid_global_func = NULL;
394            xvid_decore_func = NULL;
395            FreeLibrary(m_hdll);
396            m_hdll = NULL;
397                    MessageBox(0, "xvid_global() failed", "Error", MB_TOPMOST);
398                    return E_FAIL;
399            }
400    
401          memset(&m_create, 0, sizeof(m_create));          memset(&m_create, 0, sizeof(m_create));
402          m_create.version = XVID_VERSION;          m_create.version = XVID_VERSION;
403          m_create.handle = NULL;          m_create.handle = NULL;
404        /* Decoder threads */
405        if (g_config.cpu & XVID_CPU_FORCE) {
406                    m_create.num_threads = g_config.num_threads;
407            }
408            else {
409            m_create.num_threads = info.num_threads; /* Autodetect */
410                    g_config.num_threads = info.num_threads;
411            }
412    
413          memset(&m_frame, 0, sizeof(m_frame));          memset(&m_frame, 0, sizeof(m_frame));
414          m_frame.version = XVID_VERSION;          m_frame.version = XVID_VERSION;
# Line 352  Line 496 
496  CXvidDecoder::~CXvidDecoder()  CXvidDecoder::~CXvidDecoder()
497  {  {
498      DPRINTF("Destructor");      DPRINTF("Destructor");
499    
500    #ifdef XVID_USE_TRAYICON
501            if (Tray_Icon) { /* Destroy tray icon */
502                    NOTIFYICONDATA nid;
503                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
504    
505                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
506                    nid.hWnd = MSG_hwnd;
507                    nid.uID = 1456;
508    
509                    Shell_NotifyIcon(NIM_DELETE, &nid);
510                    Tray_Icon = 0;
511            }
512    #endif
513    
514            /* Close xvidcore library */
515          CloseLib();          CloseLib();
516    
517    #if defined(XVID_USE_MFT)
518            DeleteCriticalSection(&m_mft_lock);
519    #endif
520  }  }
521    
522    
# Line 445  Line 609 
609                  CloseLib();                  CloseLib();
610                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
611          }          }
   
612          if (hdr->biHeight < 0)          if (hdr->biHeight < 0)
613          {          {
614                  DPRINTF("colorspace: inverted input format not supported");                  DPRINTF("colorspace: inverted input format not supported");
# Line 458  Line 621 
621          {          {
622    case FOURCC_mp4v:    case FOURCC_mp4v:
623          case FOURCC_MP4V:          case FOURCC_MP4V:
624            case FOURCC_lmp4 :
625            case FOURCC_LMP4 :
626            case FOURCC_rmp4 :
627            case FOURCC_RMP4 :
628            case FOURCC_smp4 :
629            case FOURCC_SMP4 :
630            case FOURCC_hdx4 :
631            case FOURCC_HDX4 :
632                  if (!(g_config.supported_4cc & SUPPORT_MP4V)) {                  if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
633                          CloseLib();                          CloseLib();
634                          return VFW_E_TYPE_NOT_ACCEPTED;                          return VFW_E_TYPE_NOT_ACCEPTED;
635                  }                  }
636                  break;                  break;
637            case FOURCC_divx :
638          case FOURCC_DIVX :          case FOURCC_DIVX :
639            case FOURCC_dx50 :
640            case FOURCC_DX50 :
641                  if (!(g_config.supported_4cc & SUPPORT_DIVX)) {                  if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
642                          CloseLib();                          CloseLib();
643                          return VFW_E_TYPE_NOT_ACCEPTED;                          return VFW_E_TYPE_NOT_ACCEPTED;
644                  }                  }
645                  break;                  break;
646          case FOURCC_DX50 :          case FOURCC_3ivx :
647                  if (!(g_config.supported_4cc & SUPPORT_DX50)) {          case FOURCC_3IVX :
648            case FOURCC_3iv0 :
649            case FOURCC_3IV0 :
650            case FOURCC_3iv1 :
651            case FOURCC_3IV1 :
652            case FOURCC_3iv2 :
653            case FOURCC_3IV2 :
654                    if (!(g_config.supported_4cc & SUPPORT_3IVX)) {
655                          CloseLib();                          CloseLib();
656                          return VFW_E_TYPE_NOT_ACCEPTED;                          return VFW_E_TYPE_NOT_ACCEPTED;
657                  }                  }
658            case FOURCC_xvid :
659          case FOURCC_XVID :          case FOURCC_XVID :
660                  break;                  break;
661    
# Line 634  Line 816 
816  /* (internal function) change colorspace */  /* (internal function) change colorspace */
817  #define CALC_BI_STRIDE(width,bitcount)  ((((width * bitcount) + 31) & ~31) >> 3)  #define CALC_BI_STRIDE(width,bitcount)  ((((width * bitcount) + 31) & ~31) >> 3)
818    
819  HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format)  HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format, int noflip)
820  {  {
821          DWORD biWidth;          DWORD biWidth;
822    
# Line 642  Line 824 
824          {          {
825                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;
826                  biWidth = vih->bmiHeader.biWidth;                  biWidth = vih->bmiHeader.biWidth;
827                  m_frame.output.stride[0] = CALC_BI_STRIDE(vih->bmiHeader.biWidth, vih->bmiHeader.biBitCount);                  out_stride = CALC_BI_STRIDE(vih->bmiHeader.biWidth, vih->bmiHeader.biBitCount);
828                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
829          }          }
830          else if (formattype == FORMAT_VideoInfo2)          else if (formattype == FORMAT_VideoInfo2)
831          {          {
832                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;
833                  biWidth = vih2->bmiHeader.biWidth;                  biWidth = vih2->bmiHeader.biWidth;
834                  m_frame.output.stride[0] = CALC_BI_STRIDE(vih2->bmiHeader.biWidth, vih2->bmiHeader.biBitCount);                  out_stride = CALC_BI_STRIDE(vih2->bmiHeader.biWidth, vih2->bmiHeader.biBitCount);
835                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
836          }          }
837          else          else
# Line 657  Line 839 
839                  return S_FALSE;                  return S_FALSE;
840          }          }
841    
842            if (noflip) rgb_flip = 0;
843    
844          if (subtype == CLSID_MEDIASUBTYPE_IYUV)          if (subtype == CLSID_MEDIASUBTYPE_IYUV)
845          {          {
846                  DPRINTF("IYUV");                  DPRINTF("IYUV");
847                  rgb_flip = 0;                  rgb_flip = 0;
848                  m_frame.output.csp = XVID_CSP_I420;                  m_frame.output.csp = XVID_CSP_I420;
849                  m_frame.output.stride[0] = CALC_BI_STRIDE(biWidth, 8);  /* planar format fix */                  out_stride = CALC_BI_STRIDE(biWidth, 8);        /* planar format fix */
850          }          }
851          else if (subtype == MEDIASUBTYPE_YV12)          else if (subtype == MEDIASUBTYPE_YV12)
852          {          {
853                  DPRINTF("YV12");                  DPRINTF("YV12");
854                  rgb_flip = 0;                  rgb_flip = 0;
855                  m_frame.output.csp = XVID_CSP_YV12;                  m_frame.output.csp = XVID_CSP_YV12;
856                  m_frame.output.stride[0] = CALC_BI_STRIDE(biWidth, 8);  /* planar format fix */                  out_stride = CALC_BI_STRIDE(biWidth, 8);        /* planar format fix */
857          }          }
858          else if (subtype == MEDIASUBTYPE_YUY2)          else if (subtype == MEDIASUBTYPE_YUY2)
859          {          {
# Line 730  Line 914 
914    
915          if (direction == PINDIR_OUTPUT)          if (direction == PINDIR_OUTPUT)
916          {          {
917                  return ChangeColorspace(*pmt->Subtype(), *pmt->FormatType(), pmt->Format());                  return ChangeColorspace(*pmt->Subtype(), *pmt->FormatType(), pmt->Format(), 0);
918          }          }
919    
920          return S_OK;          return S_OK;
# Line 742  Line 926 
926  HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)  HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
927  {  {
928          DPRINTF("CheckTransform");          DPRINTF("CheckTransform");
929    
930            return S_OK;
931    }
932    
933    /* input/output pin connection complete */
934    
935    HRESULT CXvidDecoder::CompleteConnect(PIN_DIRECTION direction, IPin *pReceivePin)
936    {
937            DPRINTF("CompleteConnect");
938    
939    #ifdef XVID_USE_TRAYICON
940            if ((direction == PINDIR_OUTPUT) && (Tray_Icon == 0))
941            {
942                    WNDCLASSEX wc;
943    
944                    wc.cbSize = sizeof(WNDCLASSEX);
945                    wc.lpfnWndProc = msg_proc;
946                    wc.style = CS_HREDRAW | CS_VREDRAW;
947                    wc.cbWndExtra = 0;
948                    wc.cbClsExtra = 0;
949                    wc.hInstance = (HINSTANCE) g_xvid_hInst;
950                    wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH);
951                    wc.lpszMenuName = NULL;
952                    wc.lpszClassName = "XVID_MSG_WINDOW";
953                    wc.hIcon = NULL;
954                    wc.hIconSm = NULL;
955                    wc.hCursor = NULL;
956                    RegisterClassEx(&wc);
957    
958                    MSG_hwnd = CreateWindowEx(0, "XVID_MSG_WINDOW", NULL, 0, CW_USEDEFAULT,
959                                      CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE) g_xvid_hInst, NULL);
960    
961                    /* display the tray icon */
962                    NOTIFYICONDATA nid;
963                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
964    
965                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
966                    nid.hWnd = MSG_hwnd;
967                    nid.uID = 1456;
968                    nid.uCallbackMessage = WM_ICONMESSAGE;
969                    nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
970                    strcpy_s(nid.szTip, 19, "Xvid Video Decoder");
971                    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
972    
973                    Shell_NotifyIcon(NIM_ADD, &nid);
974    
975                    DestroyIcon(nid.hIcon);
976                    Tray_Icon = 1;
977            }
978    #endif
979    
980          return S_OK;          return S_OK;
981  }  }
982    
983    /* input/output pin disconnected */
984    HRESULT CXvidDecoder::BreakConnect(PIN_DIRECTION direction)
985    {
986            DPRINTF("BreakConnect");
987    
988            return S_OK;
989    }
990    
991  /* alloc output buffer */  /* alloc output buffer */
992    
# Line 809  Line 1051 
1051          {          {
1052                  HRESULT result;                  HRESULT result;
1053    
1054                  result = ChangeColorspace(mtOut->subtype, mtOut->formattype, mtOut->pbFormat);                  result = ChangeColorspace(mtOut->subtype, mtOut->formattype, mtOut->pbFormat, 0);
1055                  DeleteMediaType(mtOut);                  DeleteMediaType(mtOut);
1056    
1057                  if (result != S_OK)                  if (result != S_OK)
# Line 854  Line 1096 
1096    
1097          m_frame.output.csp &= ~XVID_CSP_VFLIP;          m_frame.output.csp &= ~XVID_CSP_VFLIP;
1098          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);
1099            m_frame.output.stride[0] = out_stride;
1100    
1101      // Paranoid check.      // Paranoid check.
1102      if (xvid_decore_func == NULL)      if (xvid_decore_func == NULL)
1103                  return E_FAIL;                  return E_FAIL;
1104    
1105    
   
1106  repeat :  repeat :
1107    
1108          if (pIn->IsPreroll() != S_OK)          if (pIn->IsPreroll() != S_OK)
# Line 995  Line 1237 
1237          CoTaskMemFree(pPages->pElems);          CoTaskMemFree(pPages->pElems);
1238          return S_OK;          return S_OK;
1239  }  }
1240    
1241    /*===============================================================================
1242    // MFT Interface
1243    //=============================================================================*/
1244    #if defined(XVID_USE_MFT)
1245    #include <limits.h> // _I64_MAX
1246    #define INVALID_TIME  _I64_MAX
1247    
1248    HRESULT CXvidDecoder::MFTGetStreamLimits(DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum)
1249    {
1250            DPRINTF("(MFT)GetStreamLimits");
1251    
1252            if ((pdwInputMinimum == NULL) || (pdwInputMaximum == NULL) || (pdwOutputMinimum == NULL) || (pdwOutputMaximum == NULL))
1253                    return E_POINTER;
1254    
1255            /* Just a fixed number of streams allowed */
1256            *pdwInputMinimum = *pdwInputMaximum = 1;
1257            *pdwOutputMinimum = *pdwOutputMaximum = 1;
1258    
1259            return S_OK;
1260    }
1261    
1262    HRESULT CXvidDecoder::MFTGetStreamCount(DWORD *pcInputStreams, DWORD *pcOutputStreams)
1263    {
1264            DPRINTF("(MFT)GetStreamCount");
1265    
1266            if ((pcInputStreams == NULL) || (pcOutputStreams == NULL))
1267                    return E_POINTER;
1268    
1269            /* We have a fixed number of streams */
1270            *pcInputStreams = 1;
1271            *pcOutputStreams = 1;
1272    
1273            return S_OK;
1274    }
1275    
1276    HRESULT CXvidDecoder::MFTGetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs)
1277    {
1278            DPRINTF("(MFT)GetStreamIDs");
1279            return E_NOTIMPL; /* We have fixed number of streams, so stream ID match stream index */
1280    }
1281    
1282    HRESULT CXvidDecoder::MFTGetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo)
1283    {
1284            DPRINTF("(MFT)GetInputStreamInfo");
1285    
1286            if (pStreamInfo == NULL)
1287                    return E_POINTER;
1288    
1289            if (dwInputStreamID != 0)
1290                    return MF_E_INVALIDSTREAMNUMBER;
1291    
1292            EnterCriticalSection(&m_mft_lock);
1293    
1294            pStreamInfo->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER;
1295            pStreamInfo->hnsMaxLatency = 0;
1296    
1297            pStreamInfo->cbSize = 1; /* Need atleast 1 byte input */
1298            pStreamInfo->cbMaxLookahead = 0;
1299            pStreamInfo->cbAlignment = 1;
1300    
1301            LeaveCriticalSection(&m_mft_lock);
1302            return S_OK;
1303    }
1304    
1305    HRESULT CXvidDecoder::MFTGetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo)
1306    {
1307            DPRINTF("(MFT)GetOutputStreamInfo");
1308    
1309            if (pStreamInfo == NULL)
1310                    return E_POINTER;
1311    
1312            if (dwOutputStreamID != 0)
1313                    return MF_E_INVALIDSTREAMNUMBER;
1314    
1315            EnterCriticalSection(&m_mft_lock);
1316    
1317            pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_DISCARDABLE;
1318    
1319            if (m_pOutputType == NULL) {
1320                    pStreamInfo->cbSize = 0;
1321                    pStreamInfo->cbAlignment = 0;
1322            }
1323            else {
1324                    pStreamInfo->cbSize = m_create.width * abs(m_create.height) * 4; // XXX
1325                    pStreamInfo->cbAlignment = 1;
1326            }
1327    
1328            LeaveCriticalSection(&m_mft_lock);
1329            return S_OK;
1330    }
1331    
1332    HRESULT CXvidDecoder::GetAttributes(IMFAttributes** pAttributes)
1333    {
1334            DPRINTF("(MFT)GetAttributes");
1335            return E_NOTIMPL; /* We don't support any attributes */
1336    }
1337    
1338    HRESULT CXvidDecoder::GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes **ppAttributes)
1339    {
1340            DPRINTF("(MFT)GetInputStreamAttributes");
1341            return E_NOTIMPL; /* We don't support any attributes */
1342    }
1343    
1344    HRESULT CXvidDecoder::GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes **ppAttributes)
1345    {
1346            DPRINTF("(MFT)GetOutputStreamAttributes");
1347            return E_NOTIMPL; /* We don't support any attributes */
1348    }
1349    
1350    HRESULT CXvidDecoder::MFTDeleteInputStream(DWORD dwStreamID)
1351    {
1352            DPRINTF("(MFT)DeleteInputStream");
1353            return E_NOTIMPL; /* We have a fixed number of streams */
1354    }
1355    
1356    HRESULT CXvidDecoder::MFTAddInputStreams(DWORD cStreams, DWORD *adwStreamIDs)
1357    {
1358            DPRINTF("(MFT)AddInputStreams");
1359            return E_NOTIMPL; /* We have a fixed number of streams */
1360    }
1361    
1362    HRESULT CXvidDecoder::MFTGetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1363    {
1364            DPRINTF("(MFT)GetInputAvailableType");
1365    
1366            if (dwInputStreamID != 0)
1367                    return MF_E_INVALIDSTREAMNUMBER;
1368    
1369            DWORD i = 0;
1370            GUID *bs_guid_table[8];
1371    
1372            bs_guid_table[i++] = (GUID *)&CLSID_XVID;
1373            bs_guid_table[i++] = (GUID *)&CLSID_XVID_UC;
1374    
1375            if (g_config.supported_4cc & SUPPORT_3IVX) {
1376                    bs_guid_table[i++] = (GUID *)&CLSID_3IVX;
1377                    bs_guid_table[i++] = (GUID *)&CLSID_3IVX_UC;
1378                    bs_guid_table[i++] = (GUID *)&CLSID_3IV0;
1379                    bs_guid_table[i++] = (GUID *)&CLSID_3IV0_UC;
1380                    bs_guid_table[i++] = (GUID *)&CLSID_3IV1;
1381                    bs_guid_table[i++] = (GUID *)&CLSID_3IV1_UC;
1382                    bs_guid_table[i++] = (GUID *)&CLSID_3IV2;
1383                    bs_guid_table[i++] = (GUID *)&CLSID_3IV2_UC;
1384            }
1385            if (g_config.supported_4cc & SUPPORT_DIVX) {
1386                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX;
1387                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX_UC;
1388                    bs_guid_table[i++] = (GUID *)&CLSID_DX50;
1389                    bs_guid_table[i++] = (GUID *)&CLSID_DX50_UC;
1390            }
1391            if (g_config.supported_4cc & SUPPORT_MP4V) {
1392                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V;
1393                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V_UC;
1394                    bs_guid_table[i++] = (GUID *)&CLSID_LMP4;
1395                    bs_guid_table[i++] = (GUID *)&CLSID_LMP4_UC;
1396                    bs_guid_table[i++] = (GUID *)&CLSID_RMP4;
1397                    bs_guid_table[i++] = (GUID *)&CLSID_RMP4_UC;
1398                    bs_guid_table[i++] = (GUID *)&CLSID_SMP4;
1399                    bs_guid_table[i++] = (GUID *)&CLSID_SMP4_UC;
1400                    bs_guid_table[i++] = (GUID *)&CLSID_HDX4;
1401                    bs_guid_table[i++] = (GUID *)&CLSID_HDX4_UC;
1402            }
1403    
1404            const GUID *subtype;
1405            if (dwTypeIndex < i) {
1406                    subtype = bs_guid_table[dwTypeIndex];
1407            }
1408            else {
1409                    return MF_E_NO_MORE_TYPES;
1410            }
1411    
1412            EnterCriticalSection(&m_mft_lock);
1413    
1414            HRESULT hr = S_OK;
1415    
1416            if (ppType) {
1417                    IMFMediaType *pInputType = NULL;
1418                    hr = MFCreateMediaType(&pInputType);
1419    
1420                    if (SUCCEEDED(hr))
1421                            hr = pInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1422    
1423                    if (SUCCEEDED(hr))
1424                            hr = pInputType->SetGUID(MF_MT_SUBTYPE, *subtype);
1425    
1426                    if (SUCCEEDED(hr)) {
1427                            *ppType = pInputType;
1428                            (*ppType)->AddRef();
1429                    }
1430                    if (pInputType) pInputType->Release();
1431            }
1432    
1433            LeaveCriticalSection(&m_mft_lock);
1434    
1435            return hr;
1436    }
1437    
1438    HRESULT CXvidDecoder::MFTGetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1439    {
1440            DPRINTF("(MFT)GetOutputAvailableType");
1441    
1442            if (ppType == NULL)
1443                    return E_INVALIDARG;
1444    
1445            if (dwOutputStreamID != 0)
1446                    return MF_E_INVALIDSTREAMNUMBER;
1447    
1448            if (dwTypeIndex < 0) return E_INVALIDARG;
1449    
1450            GUID csp;
1451            int bitdepth = 8;
1452            switch(dwTypeIndex)
1453            {
1454            case 0:
1455    if ( USE_YUY2 )
1456    {
1457                    csp = MFVideoFormat_YUY2;
1458                    bitdepth = 4;
1459                    break;
1460    }
1461            case 1 :
1462    if ( USE_UYVY )
1463    {
1464                    csp = MFVideoFormat_UYVY;
1465                    bitdepth = 4;
1466                    break;
1467    }
1468            case 2  :
1469                    if ( USE_IYUV )
1470    {
1471                    csp = MFVideoFormat_IYUV;
1472                    bitdepth = 3;
1473                    break;
1474    }
1475            case 3  :
1476    if ( USE_YV12 )
1477    {
1478                    csp = MFVideoFormat_YV12;
1479                    bitdepth = 3;
1480                    break;
1481    }
1482            case 4 :
1483    if ( USE_RGB32 )
1484    {
1485                    csp = MFVideoFormat_RGB32;
1486                    bitdepth = 8;
1487                    break;
1488    }
1489            case 5 :
1490    if ( USE_RGB24 )
1491    {
1492                    csp = MFVideoFormat_RGB24;
1493                    bitdepth = 6;
1494                    break;
1495    }
1496            case 6 :
1497    if ( USE_RG555 )
1498    {
1499                    csp = MFVideoFormat_RGB555;
1500                    bitdepth = 4;
1501                    break;
1502    }
1503            case 7 :
1504    if ( USE_RG565 )
1505    {
1506                    csp = MFVideoFormat_RGB565;
1507                    bitdepth = 4;
1508                    break;
1509    }
1510            default :
1511                    return MF_E_NO_MORE_TYPES;
1512            }
1513    
1514            if (m_pInputType == NULL)
1515                    return MF_E_TRANSFORM_TYPE_NOT_SET;
1516    
1517            EnterCriticalSection(&m_mft_lock);
1518    
1519            HRESULT hr = S_OK;
1520    
1521            IMFMediaType *pOutputType = NULL;
1522            hr = MFCreateMediaType(&pOutputType);
1523    
1524            if (SUCCEEDED(hr)) {
1525                    hr = pOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1526            }
1527    
1528            if (SUCCEEDED(hr)) {
1529                    hr = pOutputType->SetGUID(MF_MT_SUBTYPE, csp);
1530        }
1531    
1532            if (SUCCEEDED(hr)) {
1533                    hr = pOutputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE);
1534            }
1535    
1536            if (SUCCEEDED(hr)) {
1537                    hr = pOutputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
1538            }
1539    
1540            if (SUCCEEDED(hr)) {
1541                    hr = pOutputType->SetUINT32(MF_MT_SAMPLE_SIZE, (m_create.height * m_create.width * bitdepth)>>1);
1542            }
1543    
1544            if (SUCCEEDED(hr)) {
1545                    hr = MFSetAttributeSize(pOutputType, MF_MT_FRAME_SIZE, m_create.width, m_create.height);
1546            }
1547    
1548            if (SUCCEEDED(hr)) {
1549                    hr = MFSetAttributeRatio(pOutputType, MF_MT_FRAME_RATE, m_frameRate.Numerator, m_frameRate.Denominator);
1550            }
1551    
1552            if (SUCCEEDED(hr)) {
1553                    hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
1554            }
1555    
1556            if (SUCCEEDED(hr)) {
1557                    hr = MFSetAttributeRatio(pOutputType, MF_MT_PIXEL_ASPECT_RATIO, ar_x, ar_y);
1558            }
1559    
1560            if (SUCCEEDED(hr)) {
1561                    *ppType = pOutputType;
1562                    (*ppType)->AddRef();
1563            }
1564    
1565            if (pOutputType) pOutputType->Release();
1566    
1567            LeaveCriticalSection(&m_mft_lock);
1568            return hr;
1569    }
1570    
1571    HRESULT CXvidDecoder::MFTSetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags)
1572    {
1573            DPRINTF("(MFT)SetInputType");
1574    
1575            if (dwInputStreamID != 0)
1576                    return MF_E_INVALIDSTREAMNUMBER;
1577    
1578            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1579                    return E_INVALIDARG;
1580    
1581            EnterCriticalSection(&m_mft_lock);
1582    
1583            HRESULT hr = S_OK;
1584    
1585            /* Actually set the type or just test it? */
1586            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1587    
1588            /* If we have samples pending the type can't be changed right now */
1589            if (HasPendingOutput())
1590                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1591    
1592            if (SUCCEEDED(hr)) {
1593            if (pType) { // /* Check the type */
1594                hr = OnCheckInputType(pType);
1595            }
1596            }
1597    
1598            if (SUCCEEDED(hr)) {
1599                    if (bReallySet) { /* Set the type if needed */
1600                            hr = OnSetInputType(pType);
1601                    }
1602            }
1603    
1604            LeaveCriticalSection(&m_mft_lock);
1605            return hr;
1606    }
1607    
1608    HRESULT CXvidDecoder::MFTSetOutputType(DWORD dwOutputStreamID, IMFMediaType *pType, DWORD dwFlags)
1609    {
1610            DPRINTF("(MFT)SetOutputType");
1611    
1612            if (dwOutputStreamID != 0)
1613                    return MF_E_INVALIDSTREAMNUMBER;
1614    
1615            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1616                    return E_INVALIDARG;
1617    
1618            HRESULT hr = S_OK;
1619    
1620            EnterCriticalSection(&m_mft_lock);
1621    
1622            /* Actually set the type or just test it? */
1623            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1624    
1625            /* If we have samples pending the type can't be changed right now */
1626            if (HasPendingOutput())
1627                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1628    
1629            if (SUCCEEDED(hr)) {
1630                    if (pType) { /* Check the type */
1631                            AM_MEDIA_TYPE *am;
1632                            hr = MFCreateAMMediaTypeFromMFMediaType(pType, GUID_NULL, &am);
1633    
1634                            if (SUCCEEDED(hr)) {
1635                                    if (FAILED(ChangeColorspace(am->subtype, am->formattype, am->pbFormat, 1))) {
1636                                            DPRINTF("(MFT)InternalCheckOutputType (MF_E_INVALIDTYPE)");
1637                                            return MF_E_INVALIDTYPE;
1638                                    }
1639    
1640                            CoTaskMemFree(am->pbFormat);
1641                            CoTaskMemFree(am);
1642                            }
1643                    }
1644            }
1645    
1646            if (SUCCEEDED(hr)) {
1647                    if (bReallySet) { /* Set the type if needed */
1648                            hr = OnSetOutputType(pType);
1649                    }
1650            }
1651    #ifdef XVID_USE_TRAYICON
1652            if (SUCCEEDED(hr) && Tray_Icon == 0) /* Create message passing window */
1653            {
1654                    WNDCLASSEX wc;
1655    
1656                    wc.cbSize = sizeof(WNDCLASSEX);
1657                    wc.lpfnWndProc = msg_proc;
1658                    wc.style = CS_HREDRAW | CS_VREDRAW;
1659                    wc.cbWndExtra = 0;
1660                    wc.cbClsExtra = 0;
1661                    wc.hInstance = (HINSTANCE) g_xvid_hInst;
1662                    wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH);
1663                    wc.lpszMenuName = NULL;
1664                    wc.lpszClassName = "XVID_MSG_WINDOW";
1665                    wc.hIcon = NULL;
1666                    wc.hIconSm = NULL;
1667                    wc.hCursor = NULL;
1668                    RegisterClassEx(&wc);
1669    
1670                    MSG_hwnd = CreateWindowEx(0, "XVID_MSG_WINDOW", NULL, 0, CW_USEDEFAULT,
1671                                      CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE) g_xvid_hInst, NULL);
1672    
1673                    /* display the tray icon */
1674                    NOTIFYICONDATA nid;
1675                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
1676    
1677                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
1678                    nid.hWnd = MSG_hwnd;
1679                    nid.uID = 1456;
1680                    nid.uCallbackMessage = WM_ICONMESSAGE;
1681                    nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
1682                    strcpy_s(nid.szTip, 19, "Xvid Video Decoder");
1683                    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
1684    
1685                    Shell_NotifyIcon(NIM_ADD, &nid);
1686    
1687                    DestroyIcon(nid.hIcon);
1688                    Tray_Icon = 1;
1689            }
1690    #endif
1691    
1692            LeaveCriticalSection(&m_mft_lock);
1693            return hr;
1694    }
1695    
1696    HRESULT CXvidDecoder::MFTGetInputCurrentType(DWORD dwInputStreamID, IMFMediaType **ppType)
1697    {
1698            DPRINTF("(MFT)GetInputCurrentType");
1699    
1700            if (ppType == NULL)
1701                    return E_POINTER;
1702    
1703            if (dwInputStreamID != 0)
1704                    return MF_E_INVALIDSTREAMNUMBER;
1705    
1706            EnterCriticalSection(&m_mft_lock);
1707    
1708            HRESULT hr = S_OK;
1709    
1710            if (!m_pInputType)
1711                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1712    
1713            if (SUCCEEDED(hr)) {
1714                    *ppType = m_pInputType;
1715                    (*ppType)->AddRef();
1716            }
1717    
1718            LeaveCriticalSection(&m_mft_lock);
1719            return hr;
1720    }
1721    
1722    HRESULT CXvidDecoder::MFTGetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType)
1723    {
1724            DPRINTF("(MFT)GetOutputCurrentType");
1725    
1726            if (ppType == NULL)
1727                    return E_POINTER;
1728    
1729            if (dwOutputStreamID != 0)
1730                    return MF_E_INVALIDSTREAMNUMBER;
1731    
1732            EnterCriticalSection(&m_mft_lock);
1733    
1734            HRESULT hr = S_OK;
1735    
1736            if (!m_pOutputType)
1737                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1738    
1739            if (SUCCEEDED(hr)) {
1740                    *ppType = m_pOutputType;
1741                    (*ppType)->AddRef();
1742            }
1743    
1744            LeaveCriticalSection(&m_mft_lock);
1745            return hr;
1746    }
1747    
1748    HRESULT CXvidDecoder::MFTGetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags)
1749    {
1750            DPRINTF("(MFT)GetInputStatus");
1751    
1752            if (pdwFlags == NULL)
1753                    return E_POINTER;
1754    
1755            if (dwInputStreamID != 0)
1756                    return MF_E_INVALIDSTREAMNUMBER;
1757    
1758            EnterCriticalSection(&m_mft_lock);
1759    
1760            /* If there's pending output sampels we don't accept new
1761               input data until ProcessOutput() or Flush() was called */
1762            if (!HasPendingOutput()) {
1763                    *pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
1764            }
1765            else {
1766                    *pdwFlags = 0;
1767            }
1768    
1769            LeaveCriticalSection(&m_mft_lock);
1770    
1771            return S_OK;
1772    }
1773    
1774    HRESULT CXvidDecoder::MFTGetOutputStatus(DWORD *pdwFlags)
1775    {
1776            DPRINTF("(MFT)GetOutputStatus");
1777    
1778            if (pdwFlags == NULL)
1779                    return E_POINTER;
1780    
1781            EnterCriticalSection(&m_mft_lock);
1782    
1783            /* We can render an output sample only after we
1784               have decoded one */
1785            if (HasPendingOutput()) {
1786                    *pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
1787            }
1788            else {
1789                    *pdwFlags = 0;
1790            }
1791    
1792            LeaveCriticalSection(&m_mft_lock);
1793    
1794            return S_OK;
1795    }
1796    
1797    HRESULT CXvidDecoder::MFTSetOutputBounds(LONGLONG hnsLowerBound, LONGLONG hnsUpperBound)
1798    {
1799            DPRINTF("(MFT)SetOutputBounds");
1800            return E_NOTIMPL;
1801    }
1802    
1803    HRESULT CXvidDecoder::MFTProcessEvent(DWORD dwInputStreamID, IMFMediaEvent *pEvent)
1804    {
1805            DPRINTF("(MFT)ProcessEvent");
1806            return E_NOTIMPL; /* We don't handle any stream events */
1807    }
1808    
1809    HRESULT CXvidDecoder::MFTProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
1810    {
1811            DPRINTF("(MFT)ProcessMessage");
1812            HRESULT hr = S_OK;
1813    
1814            EnterCriticalSection(&m_mft_lock);
1815    
1816            switch (eMessage)
1817            {
1818            case MFT_MESSAGE_COMMAND_FLUSH:
1819                    if (m_create.handle != NULL) {
1820                            DPRINTF("(MFT)CommandFlush");
1821    
1822                            xvid_dec_stats_t stats;
1823                            int used_bytes;
1824    
1825                            memset(&stats, 0, sizeof(stats));
1826                            stats.version = XVID_VERSION;
1827    
1828                            int csp = m_frame.output.csp;
1829    
1830                            m_frame.output.csp = XVID_CSP_INTERNAL;
1831                            m_frame.bitstream = NULL;
1832                            m_frame.length = -1;
1833                            m_frame.general = XVID_LOWDELAY;
1834    
1835                            do {
1836                                    used_bytes = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1837                            } while(used_bytes>=0 && stats.type <= 0);
1838    
1839                            m_frame.output.csp = csp;
1840                            m_frame.output.plane[1] = NULL; /* Don't display flushed samples */
1841    
1842                            //m_timestamp = INVALID_TIME;
1843                            //m_timelength = INVALID_TIME;
1844                            //m_rtFrame = 0;
1845            }
1846        break;
1847    
1848            case MFT_MESSAGE_COMMAND_DRAIN:
1849                    m_discont = 1; /* Set discontinuity flag */
1850                    m_rtFrame = 0;
1851                    break;
1852    
1853            case MFT_MESSAGE_SET_D3D_MANAGER:
1854                    hr = E_NOTIMPL;
1855                    break;
1856    
1857            case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
1858            case MFT_MESSAGE_NOTIFY_END_STREAMING:
1859                    break;
1860    
1861            case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
1862            case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
1863                    break;
1864            }
1865    
1866            LeaveCriticalSection(&m_mft_lock);
1867    
1868            return hr;
1869    }
1870    
1871    HRESULT CXvidDecoder::MFTProcessInput(DWORD dwInputStreamID, IMFSample *pSample, DWORD dwFlags)
1872    {
1873            DPRINTF("(MFT)ProcessInput");
1874    
1875            if (pSample == NULL)
1876                    return E_POINTER;
1877    
1878            if (dwInputStreamID != 0)
1879                    return MF_E_INVALIDSTREAMNUMBER;
1880    
1881            if (dwFlags != 0)
1882                    return E_INVALIDARG;
1883    
1884            if (!m_pInputType || !m_pOutputType) {
1885                    return MF_E_NOTACCEPTING;   /* Must have set input and output types */
1886            }
1887            else if (HasPendingOutput()) {
1888                    return MF_E_NOTACCEPTING;   /* We still have output samples to render */
1889            }
1890    
1891            xvid_dec_stats_t stats;
1892            int length;
1893    
1894            memset(&stats, 0, sizeof(stats));
1895            stats.version = XVID_VERSION;
1896    
1897            if (m_create.handle == NULL)
1898            {
1899                    if (xvid_decore_func == NULL)
1900                            return E_FAIL;
1901                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
1902                    {
1903                            DPRINTF("*** XVID_DEC_CREATE error");
1904                            return E_FAIL;
1905                    }
1906            }
1907    
1908            EnterCriticalSection(&m_mft_lock);
1909    
1910            HRESULT hr = S_OK;
1911            IMFMediaBuffer *pBuffer;
1912    
1913            if (SUCCEEDED(hr)) {
1914                    hr = pSample->ConvertToContiguousBuffer(&pBuffer);
1915            }
1916    
1917            if (SUCCEEDED(hr)) {
1918                    hr = pBuffer->Lock((BYTE**)&m_frame.bitstream, NULL, (DWORD *)&m_frame.length);
1919            }
1920    
1921            m_frame.general = XVID_LOWDELAY;
1922    
1923            if (m_discont == 1) {
1924                    m_frame.general |= XVID_DISCONTINUITY;
1925                    m_discont = 0;
1926            }
1927    
1928            if (g_config.nDeblock_Y)
1929                    m_frame.general |= XVID_DEBLOCKY;
1930    
1931            if (g_config.nDeblock_UV)
1932                    m_frame.general |= XVID_DEBLOCKUV;
1933    
1934            if (g_config.nDering_Y)
1935                    m_frame.general |= XVID_DERINGY;
1936    
1937            if (g_config.nDering_UV)
1938                    m_frame.general |= XVID_DERINGUV;
1939    
1940            if (g_config.nFilmEffect)
1941                    m_frame.general |= XVID_FILMEFFECT;
1942    
1943            m_frame.brightness = g_config.nBrightness;
1944    
1945            m_frame.output.csp &= ~XVID_CSP_VFLIP;
1946            m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0);
1947    
1948            int csp = m_frame.output.csp;
1949            m_frame.output.csp = XVID_CSP_INTERNAL;
1950    
1951        // Paranoid check.
1952            if (xvid_decore_func == NULL) {
1953                    hr = E_FAIL;
1954                    goto END_LOOP;
1955            }
1956    
1957    repeat :
1958            length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1959    
1960            if (length == XVID_ERR_MEMORY) {
1961                    hr = E_FAIL;
1962                    goto END_LOOP;
1963            }
1964            else if (length < 0)
1965            {
1966                    DPRINTF("*** XVID_DEC_DECODE");
1967                    goto END_LOOP;
1968            }
1969    
1970            if (stats.type == XVID_TYPE_NOTHING && length > 0) {
1971                    DPRINTF(" B-Frame decoder lag");
1972                    m_frame.output.plane[1] = NULL;
1973                    goto END_LOOP;
1974            }
1975    
1976            if (stats.type == XVID_TYPE_VOL)
1977            {
1978                    if (stats.data.vol.width != m_create.width ||
1979                            stats.data.vol.height != m_create.height)
1980                    {
1981                            DPRINTF("TODO: auto-resize");
1982                            m_frame.output.plane[1] = NULL;
1983                            hr = E_FAIL;
1984                    }
1985    
1986                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) { /* auto */
1987                            int par_x, par_y;
1988                            if (stats.data.vol.par == XVID_PAR_EXT) {
1989                                    par_x = stats.data.vol.par_width;
1990                                    par_y = stats.data.vol.par_height;
1991                            } else {
1992                                    par_x = PARS[stats.data.vol.par-1][0];
1993                                    par_y = PARS[stats.data.vol.par-1][1];
1994                            }
1995    
1996                            ar_x = par_x * stats.data.vol.width;
1997                            ar_y = par_y * stats.data.vol.height;
1998                    }
1999    
2000                    m_frame.bitstream = (BYTE*)m_frame.bitstream + length;
2001                    m_frame.length -= length;
2002                    goto repeat;
2003            }
2004    
2005    END_LOOP:
2006            m_frame.output.csp = csp;
2007    
2008            if (pBuffer) {
2009                    pBuffer->Unlock();
2010                    pBuffer->Release();
2011            }
2012    
2013            if (SUCCEEDED(hr)) {
2014                    /* Try to get a timestamp */
2015                    if (FAILED(pSample->GetSampleTime(&m_timestamp)))
2016                            m_timestamp = INVALID_TIME;
2017    
2018                    if (FAILED(pSample->GetSampleDuration(&m_timelength))) {
2019                            m_timelength = INVALID_TIME;
2020                    }
2021                    if (m_timestamp != INVALID_TIME && stats.type == XVID_TYPE_IVOP) {
2022                            m_rtFrame = m_timestamp;
2023                    }
2024            }
2025    
2026            LeaveCriticalSection(&m_mft_lock);
2027    
2028            return hr;
2029    }
2030    
2031    HRESULT CXvidDecoder::MFTProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus)
2032    {
2033            DPRINTF("(MFT)ProcessOutput");
2034    
2035            /* Preroll in MFT ??
2036               Flags ?? -> TODO... */
2037            if (dwFlags != 0)
2038                    return E_INVALIDARG;
2039    
2040            if (pOutputSamples == NULL || pdwStatus == NULL)
2041                    return E_POINTER;
2042    
2043            if (cOutputBufferCount != 1) /* Must be exactly one output buffer */
2044                    return E_INVALIDARG;
2045    
2046            if (pOutputSamples[0].pSample == NULL) /* Must have a sample */
2047                    return E_INVALIDARG;
2048    
2049            if (!HasPendingOutput()) { /* If there's no sample we need to decode one first */
2050                    return MF_E_TRANSFORM_NEED_MORE_INPUT;
2051            }
2052    
2053            EnterCriticalSection(&m_mft_lock);
2054    
2055            HRESULT hr = S_OK;
2056    
2057            BYTE *Dst = NULL;
2058            DWORD buffer_size;
2059    
2060            IMFMediaBuffer *pOutput = NULL;
2061    
2062            if (SUCCEEDED(hr)) {
2063                    hr = pOutputSamples[0].pSample->GetBufferByIndex(0, &pOutput); /* Get output buffer */
2064            }
2065    
2066            if (SUCCEEDED(hr)) {
2067                    hr = pOutput->GetMaxLength(&buffer_size);
2068            }
2069    
2070            if (SUCCEEDED(hr))
2071                    hr = pOutput->Lock(&Dst, NULL, NULL);
2072    
2073            if (SUCCEEDED(hr)) {
2074                    xvid_gbl_convert_t convert;
2075    
2076                    memset(&convert, 0, sizeof(convert));
2077                    convert.version = XVID_VERSION;
2078    
2079                    convert.input.csp = XVID_CSP_INTERNAL;
2080                    convert.input.plane[0] = m_frame.output.plane[0];
2081                    convert.input.plane[1] = m_frame.output.plane[1];
2082                    convert.input.plane[2] = m_frame.output.plane[2];
2083                    convert.input.stride[0] = m_frame.output.stride[0];
2084                    convert.input.stride[1] = m_frame.output.stride[1];
2085                    convert.input.stride[2] = m_frame.output.stride[2];
2086    
2087                    convert.output.csp = m_frame.output.csp;
2088                    convert.output.plane[0] = Dst;
2089                    convert.output.stride[0] = out_stride;
2090    
2091                    convert.width = m_create.width;
2092                    convert.height = m_create.height;
2093                    convert.interlacing = 0;
2094    
2095                    if (m_frame.output.plane[1] != NULL && Dst != NULL && xvid_global_func != NULL)
2096                            if (xvid_global_func(0, XVID_GBL_CONVERT, &convert, NULL) < 0) /* CSP convert into output buffer */
2097                                    hr = E_FAIL;
2098    
2099                    m_frame.output.plane[1] = NULL;
2100            }
2101    
2102            *pdwStatus = 0;
2103    
2104            if (SUCCEEDED(hr)) {
2105                    if (SUCCEEDED(hr))
2106                            hr = pOutputSamples[0].pSample->SetUINT32(MFSampleExtension_CleanPoint, TRUE); // key frame
2107    
2108                    if (SUCCEEDED(hr)) { /* Set timestamp of output sample */
2109                            if (m_timestamp != INVALID_TIME)
2110                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_timestamp);
2111                            else
2112                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_rtFrame);
2113    
2114                            if (m_timelength != INVALID_TIME)
2115                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_timelength);
2116                            else
2117                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_duration);
2118    
2119                            m_rtFrame += m_duration;
2120                    }
2121    
2122                    if (SUCCEEDED(hr))
2123                            hr = pOutput->SetCurrentLength(m_create.width * abs(m_create.height) * 4); // XXX
2124            }
2125    
2126            if (pOutput) {
2127                    pOutput->Unlock();
2128                    pOutput->Release();
2129            }
2130    
2131            LeaveCriticalSection(&m_mft_lock);
2132    
2133            return hr;
2134    }
2135    
2136    HRESULT CXvidDecoder::OnCheckInputType(IMFMediaType *pmt)
2137    {
2138            DPRINTF("(MFT)CheckInputType");
2139    
2140            HRESULT hr = S_OK;
2141    
2142            /*  Check if input type is already set. Reject any type that is not identical */
2143            if (m_pInputType) {
2144                    DWORD dwFlags = 0;
2145                    if (S_OK == m_pInputType->IsEqual(pmt, &dwFlags)) {
2146                            return S_OK;
2147                    }
2148                    else {
2149                            return MF_E_INVALIDTYPE;
2150                    }
2151            }
2152    
2153            GUID majortype = {0}, subtype = {0};
2154            UINT32 width = 0, height = 0;
2155    
2156            hr = pmt->GetMajorType(&majortype);
2157    
2158            if (SUCCEEDED(hr)) {
2159                    if (majortype != MFMediaType_Video) { /* Must be Video */
2160                            hr = MF_E_INVALIDTYPE;
2161                    }
2162            }
2163    
2164            if (m_hdll == NULL) {
2165                    HRESULT hr = OpenLib();
2166    
2167                    if (FAILED(hr) || (m_hdll == NULL)) // Paranoid checks.
2168                            hr = MF_E_INVALIDTYPE;
2169            }
2170    
2171            if (SUCCEEDED(hr)) {
2172                    hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &width, &height);
2173            }
2174    
2175            /* Check the frame size */
2176            if (SUCCEEDED(hr)) {
2177                    if (width > 4096 || height > 4096) {
2178                            hr = MF_E_INVALIDTYPE;
2179                    }
2180            }
2181            m_create.width = width;
2182            m_create.height = height;
2183    
2184            if (SUCCEEDED(hr)) {
2185                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
2186                            hr = MFGetAttributeRatio(pmt, MF_MT_PIXEL_ASPECT_RATIO, (UINT32*)&ar_x, (UINT32*)&ar_y);
2187                    }
2188            }
2189    
2190            /* TODO1: Make sure there really is a frame rate after all!
2191               TODO2: Use the framerate for something! */
2192            MFRatio fps = {0};
2193            if (SUCCEEDED(hr)) {
2194                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&fps.Numerator, (UINT32*)&fps.Denominator);
2195            }
2196    
2197            if (SUCCEEDED(hr)) {
2198                    hr = pmt->GetGUID(MF_MT_SUBTYPE, &subtype);
2199            }
2200    
2201            if (subtype == CLSID_MP4V || subtype == CLSID_MP4V_UC ||
2202                subtype == CLSID_LMP4 || subtype == CLSID_LMP4_UC ||
2203                subtype == CLSID_RMP4 || subtype == CLSID_RMP4_UC ||
2204                subtype == CLSID_SMP4 || subtype == CLSID_SMP4_UC ||
2205                subtype == CLSID_HDX4 || subtype == CLSID_HDX4_UC) {
2206                    if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
2207                            CloseLib();
2208                            hr = MF_E_INVALIDTYPE;
2209                    }
2210                    else m_create.fourcc = FOURCC_MP4V;
2211            }
2212            else if (subtype == CLSID_DIVX || subtype == CLSID_DIVX_UC) {
2213                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2214                            CloseLib();
2215                            hr = MF_E_INVALIDTYPE;
2216                    }
2217                    else m_create.fourcc = FOURCC_DIVX;
2218            }
2219            else if (subtype == CLSID_DX50 || subtype == CLSID_DX50_UC) {
2220                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2221                            CloseLib();
2222                            hr = MF_E_INVALIDTYPE;
2223                    }
2224                    else m_create.fourcc = FOURCC_DX50;
2225            }
2226            else if (subtype == CLSID_3IVX || subtype == CLSID_3IVX_UC ||
2227                     subtype == CLSID_3IV0 || subtype == CLSID_3IV0_UC ||
2228                     subtype == CLSID_3IV1 || subtype == CLSID_3IV1_UC ||
2229                     subtype == CLSID_3IV2 || subtype == CLSID_3IV2_UC) {
2230                    if (!(g_config.supported_4cc & SUPPORT_3IVX)) {
2231                            CloseLib();
2232                            hr = MF_E_INVALIDTYPE;
2233                    }
2234                    else m_create.fourcc = FOURCC_3IVX;
2235            }
2236            else if (subtype == CLSID_XVID || subtype == CLSID_XVID_UC) {
2237                    m_create.fourcc = FOURCC_XVID;
2238            }
2239            else {
2240                    DPRINTF("Unknown subtype!");
2241                    CloseLib();
2242                    hr = MF_E_INVALIDTYPE;
2243            }
2244    
2245            /* haali media splitter reports VOL information in the format header */
2246            if (SUCCEEDED(hr))
2247            {
2248                    UINT32 cbSeqHeader = 0;
2249    
2250                    (void)pmt->GetBlobSize(MF_MT_MPEG_SEQUENCE_HEADER, &cbSeqHeader);
2251    
2252                    if (cbSeqHeader>0) {
2253                            xvid_dec_stats_t stats;
2254                            memset(&stats, 0, sizeof(stats));
2255                            stats.version = XVID_VERSION;
2256    
2257                            if (m_create.handle == NULL) {
2258                                    if (xvid_decore_func == NULL)
2259                                            hr = E_FAIL;
2260                                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
2261                                            DPRINTF("*** XVID_DEC_CREATE error");
2262                                            hr = E_FAIL;
2263                                    }
2264                            }
2265    
2266                            if (SUCCEEDED(hr)) {
2267                                    (void)pmt->GetAllocatedBlob(MF_MT_MPEG_SEQUENCE_HEADER, (UINT8 **)&m_frame.bitstream, (UINT32 *)&m_frame.length);
2268                                    m_frame.general = 0;
2269                                    m_frame.output.csp = XVID_CSP_NULL;
2270    
2271                                    int ret = 0;
2272                                    if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
2273                                            /* honour video dimensions reported in VOL header */
2274                                            if (stats.type == XVID_TYPE_VOL) {
2275                                                    m_create.width = stats.data.vol.width;
2276                                                    m_create.height = stats.data.vol.height;
2277                                            }
2278                                    }
2279    
2280                                    if (ret == XVID_ERR_MEMORY) hr = E_FAIL;
2281                                    CoTaskMemFree(m_frame.bitstream);
2282                            }
2283                    }
2284            }
2285    
2286            return hr;
2287    }
2288    
2289    HRESULT CXvidDecoder::OnSetInputType(IMFMediaType *pmt)
2290    {
2291            HRESULT hr = S_OK;
2292            UINT32 w, h;
2293    
2294            if (m_pInputType) m_pInputType->Release();
2295    
2296            hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &w, &h);
2297            m_create.width = w; m_create.height = h;
2298    
2299            if (SUCCEEDED(hr))
2300                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&m_frameRate.Numerator, (UINT32*)&m_frameRate.Denominator);
2301    
2302            if (SUCCEEDED(hr)) { /* Store frame duration, derived from the frame rate */
2303                    hr = MFFrameRateToAverageTimePerFrame(m_frameRate.Numerator, m_frameRate.Denominator, &m_duration);
2304            }
2305    
2306            if (SUCCEEDED(hr)) {
2307                    m_pInputType = pmt;
2308                    m_pInputType->AddRef();
2309            }
2310    
2311            return hr;
2312    }
2313    
2314    HRESULT CXvidDecoder::OnSetOutputType(IMFMediaType *pmt)
2315    {
2316            if (m_pOutputType) m_pOutputType->Release();
2317    
2318            m_pOutputType = pmt;
2319            m_pOutputType->AddRef();
2320    
2321            return S_OK;
2322    }
2323    
2324    #endif /* XVID_USE_MFT */

Legend:
Removed from v.1890  
changed lines
  Added in v.1962

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