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

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

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

trunk/xvidcore/dshow/src/CXvidDecoder.cpp revision 1896, Sat Oct 16 12:20:30 2010 UTC branches/release-1_3-branch/xvidcore/dshow/src/CXvidDecoder.cpp revision 1946, Thu Jan 27 13:18:13 2011 UTC
# Line 20  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.19 2010-10-16 12:20:30 Isibaar Exp $   * $Id: CXvidDecoder.cpp,v 1.25.2.2 2011-01-27 13:18:13 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 44  Line 36 
36          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Debug          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Debug
37  */  */
38    
39  //#define XVID_USE_TRAYICON  /*
40    #define XVID_USE_MFT
41    #define XVID_USE_TRAYICON
42    */
43    
44  #include <windows.h>  #include <windows.h>
45    
# Line 56  Line 51 
51  #endif  #endif
52  #include <dvdmedia.h>   // VIDEOINFOHEADER2  #include <dvdmedia.h>   // VIDEOINFOHEADER2
53    
54    #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>  #include <shellapi.h>
63    
64  #include <xvid.h>               // Xvid API  #include <xvid.h>               // Xvid API
# Line 127  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 161  Line 164 
164  extern HINSTANCE g_xvid_hInst;  extern HINSTANCE g_xvid_hInst;
165    
166  static int GUI_Page = 0;  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 );  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)  LRESULT CALLBACK msg_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
# Line 182  Line 186 
186                  };                  };
187                  break;                  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:          default:
200                  return DefWindowProc(hwnd, uMsg, wParam, lParam);                  return DefWindowProc(hwnd, uMsg, wParam, lParam);
201          }          }
# Line 192  Line 206 
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 231  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 248  Line 306 
306      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...
307      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.
308    
309  #ifdef XVID_USE_TRAYICON  #if defined(XVID_USE_MFT)
310          MSG_hwnd = NULL;          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  #endif
319    
320      LoadRegistryInfo();      LoadRegistryInfo();
# Line 267  Line 332 
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) {
# Line 302  Line 372 
372                  return E_FAIL;                  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);
382                    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;
# Line 392  Line 480 
480  CXvidDecoder::~CXvidDecoder()  CXvidDecoder::~CXvidDecoder()
481  {  {
482      DPRINTF("Destructor");      DPRINTF("Destructor");
         CloseLib();  
483    
484  #ifdef XVID_USE_TRAYICON  #ifdef XVID_USE_TRAYICON
485          if (MSG_hwnd != NULL) {          if (Tray_Icon) { /* Destroy tray icon */
486                  NOTIFYICONDATA nid;                  NOTIFYICONDATA nid;
487                  nid.cbSize = sizeof(NOTIFYICONDATA);                  ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
488    
489                    nid.cbSize = NOTIFYICONDATA_V1_SIZE;
490                  nid.hWnd = MSG_hwnd;                  nid.hWnd = MSG_hwnd;
491                  nid.uID = 100;                  nid.uID = 1456;
492    
493                  Shell_NotifyIcon(NIM_DELETE, &nid);                  Shell_NotifyIcon(NIM_DELETE, &nid);
494                    Tray_Icon = 0;
                 DestroyWindow(MSG_hwnd);  
                 MSG_hwnd = NULL;  
495          }          }
496  #endif  #endif
497    
498            /* Close xvidcore library */
499            CloseLib();
500    
501    #if defined(XVID_USE_MFT)
502            DeleteCriticalSection(&m_mft_lock);
503    #endif
504  }  }
505    
506    
# Line 499  Line 593 
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 696  Line 789 
789          {          {
790                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;
791                  biWidth = vih->bmiHeader.biWidth;                  biWidth = vih->bmiHeader.biWidth;
792                  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);
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                  biWidth = vih2->bmiHeader.biWidth;                  biWidth = vih2->bmiHeader.biWidth;
799                  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);
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 716  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] = CALC_BI_STRIDE(biWidth, 8);  /* 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] = CALC_BI_STRIDE(biWidth, 8);  /* 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 807  Line 900 
900          DPRINTF("CompleteConnect");          DPRINTF("CompleteConnect");
901    
902  #ifdef XVID_USE_TRAYICON  #ifdef XVID_USE_TRAYICON
903          if ((direction == PINDIR_OUTPUT) && (MSG_hwnd == NULL))          if ((direction == PINDIR_OUTPUT) && (Tray_Icon == 0))
904          {          {
905                  WNDCLASSEX wc;                  WNDCLASSEX wc;
906    
# Line 830  Line 923 
923    
924                  /* display the tray icon */                  /* display the tray icon */
925                  NOTIFYICONDATA nid;                  NOTIFYICONDATA nid;
926                    ZeroMemory(&nid,sizeof(NOTIFYICONDATA));
927    
928                  nid.cbSize = sizeof(NOTIFYICONDATA);                  nid.cbSize = NOTIFYICONDATA_V1_SIZE;
929                  nid.hWnd = MSG_hwnd;                  nid.hWnd = MSG_hwnd;
930                  nid.uID = 100;                  nid.uID = 1456;
                 nid.uVersion = NOTIFYICON_VERSION;  
931                  nid.uCallbackMessage = WM_ICONMESSAGE;                  nid.uCallbackMessage = WM_ICONMESSAGE;
932                  nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));                  nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
933                  strcpy_s(nid.szTip, 19, "Xvid Video Decoder");                  strcpy_s(nid.szTip, 19, "Xvid Video Decoder");
934                  nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;                  nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
935    
936                  Shell_NotifyIcon(NIM_ADD, &nid);                  Shell_NotifyIcon(NIM_ADD, &nid);
937    
938                    DestroyIcon(nid.hIcon);
939                    Tray_Icon = 1;
940          }          }
941  #endif  #endif
942    
# Line 852  Line 948 
948  {  {
949          DPRINTF("BreakConnect");          DPRINTF("BreakConnect");
950    
 #ifdef XVID_USE_TRAYICON  
         if ((direction == PINDIR_OUTPUT) && (MSG_hwnd != NULL)) {  
                 NOTIFYICONDATA nid;  
   
                 nid.cbSize = sizeof(NOTIFYICONDATA);  
                 nid.hWnd = MSG_hwnd;  
                 nid.uID = 100;  
                 nid.uVersion = NOTIFYICON_VERSION;  
   
                 if(Shell_NotifyIcon(NIM_DELETE, &nid) == TRUE) {  
                         DestroyWindow(MSG_hwnd);  
                         MSG_hwnd = NULL;  
                 }  
         }  
 #endif  
   
951          return S_OK;          return S_OK;
952  }  }
953    
# Line 979  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.      // Paranoid check.
1065      if (xvid_decore_func == NULL)      if (xvid_decore_func == NULL)
1066                  return E_FAIL;                  return E_FAIL;
1067    
1068    
   
1069  repeat :  repeat :
1070    
1071          if (pIn->IsPreroll() != S_OK)          if (pIn->IsPreroll() != S_OK)
# Line 1120  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.1896  
changed lines
  Added in v.1946

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