[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 1896, Sat Oct 16 12:20:30 2010 UTC revision 1898, Sun Oct 17 18:31:52 2010 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.20 2010-10-17 18:31:46 Isibaar Exp $
24   *   *
25   ****************************************************************************/   ****************************************************************************/
26    
# Line 44  Line 44 
44          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Debug          C:\DX90SDK\Samples\C++\DirectShow\BaseClasses\Debug
45  */  */
46    
47    //#define XVID_USE_MFT
48  //#define XVID_USE_TRAYICON  //#define XVID_USE_TRAYICON
49    
50  #include <windows.h>  #include <windows.h>
# Line 56  Line 57 
57  #endif  #endif
58  #include <dvdmedia.h>   // VIDEOINFOHEADER2  #include <dvdmedia.h>   // VIDEOINFOHEADER2
59    
60    #if defined(XVID_USE_MFT)
61    #define MFT_UNIQUE_METHOD_NAMES
62    #include <mftransform.h>
63    #include <mfapi.h>
64    #include <mferror.h>
65    #include <shlwapi.h>
66    #endif
67    
68  #include <shellapi.h>  #include <shellapi.h>
69    
70  #include <xvid.h>               // Xvid API  #include <xvid.h>               // Xvid API
# Line 192  Line 201 
201    
202  STDAPI DllRegisterServer()  STDAPI DllRegisterServer()
203  {  {
204    #if defined(XVID_USE_MFT)
205            int inputs_num = sizeof(sudInputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE);
206            int outputs_num = sizeof(sudOutputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE);
207            MFT_REGISTER_TYPE_INFO * mft_bs = new MFT_REGISTER_TYPE_INFO[inputs_num];
208            MFT_REGISTER_TYPE_INFO * mft_csp = new MFT_REGISTER_TYPE_INFO[outputs_num];
209    
210            {
211                    int i;
212                    for(i=0;i<inputs_num;i++) {
213                            mft_bs[i].guidMajorType = *sudInputPinTypes[i].clsMajorType;
214                            mft_bs[i].guidSubtype = *sudInputPinTypes[i].clsMinorType;
215                    }
216                    for(i=0;i<outputs_num;i++) {
217                            mft_csp[i].guidMajorType = *sudOutputPinTypes[i].clsMajorType;
218                            mft_csp[i].guidSubtype = *sudOutputPinTypes[i].clsMinorType; // MFT and AM GUIDs really the same?
219                    }
220            }
221    
222            /* Register the MFT decoder */
223            MFTRegister(CLSID_XVID,                          // CLSID
224                            MFT_CATEGORY_VIDEO_DECODER,          // Category
225                            const_cast<LPWSTR>(XVID_NAME_L),     // Friendly name
226                            0,                                   // Flags
227                            inputs_num,                          // Number of input types
228                            mft_bs,                              // Input types
229                            outputs_num,                         // Number of output types
230                            mft_csp,                             // Output types
231                            NULL                                 // Attributes (optional)
232                            );
233    
234            delete[] mft_bs;
235            delete[] mft_csp;
236    #endif /* XVID_USE_MFT */
237    
238      return AMovieDllRegisterServer2( TRUE );      return AMovieDllRegisterServer2( TRUE );
239  }  }
240    
241    
242  STDAPI DllUnregisterServer()  STDAPI DllUnregisterServer()
243  {  {
244    #if defined(XVID_USE_MFT)
245            MFTUnregister(CLSID_XVID);
246    #endif
247      return AMovieDllRegisterServer2( FALSE );      return AMovieDllRegisterServer2( FALSE );
248  }  }
249    
# Line 231  Line 277 
277          return GetInterface((ISpecifyPropertyPages *) this, ppv);          return GetInterface((ISpecifyPropertyPages *) this, ppv);
278          }          }
279    
280    #if defined(XVID_USE_MFT)
281            if (riid == IID_IMFTransform)
282            {
283                    return GetInterface((IMFTransform *) this, ppv);
284            }
285    #endif
286    
287          return CVideoTransformFilter::NonDelegatingQueryInterface(riid, ppv);          return CVideoTransformFilter::NonDelegatingQueryInterface(riid, ppv);
288  }  }
289    
# Line 252  Line 305 
305          MSG_hwnd = NULL;          MSG_hwnd = NULL;
306  #endif  #endif
307    
308    #if defined(XVID_USE_MFT)
309            InitializeCriticalSection(&m_mft_lock);
310            m_pInputType = NULL;
311            m_pOutputType = NULL;
312            m_rtFrame = 0;
313            m_duration = 0;
314            m_discont = 0;
315            m_frameRate.Denominator = 1;
316            m_frameRate.Numerator = 1;
317    #endif
318    
319      LoadRegistryInfo();      LoadRegistryInfo();
320    
321      *phr = OpenLib();      *phr = OpenLib();
# Line 407  Line 471 
471                  MSG_hwnd = NULL;                  MSG_hwnd = NULL;
472          }          }
473  #endif  #endif
474    
475    #if defined(XVID_USE_MFT)
476            DeleteCriticalSection(&m_mft_lock);
477    #endif
478  }  }
479    
480    
# Line 499  Line 567 
567                  CloseLib();                  CloseLib();
568                  return VFW_E_TYPE_NOT_ACCEPTED;                  return VFW_E_TYPE_NOT_ACCEPTED;
569          }          }
   
570          if (hdr->biHeight < 0)          if (hdr->biHeight < 0)
571          {          {
572                  DPRINTF("colorspace: inverted input format not supported");                  DPRINTF("colorspace: inverted input format not supported");
# Line 696  Line 763 
763          {          {
764                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;                  VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;
765                  biWidth = vih->bmiHeader.biWidth;                  biWidth = vih->bmiHeader.biWidth;
766                  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);
767                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
768          }          }
769          else if (formattype == FORMAT_VideoInfo2)          else if (formattype == FORMAT_VideoInfo2)
770          {          {
771                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;                  VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;
772                  biWidth = vih2->bmiHeader.biWidth;                  biWidth = vih2->bmiHeader.biWidth;
773                  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);
774                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);                  rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP);
775          }          }
776          else          else
# Line 716  Line 783 
783                  DPRINTF("IYUV");                  DPRINTF("IYUV");
784                  rgb_flip = 0;                  rgb_flip = 0;
785                  m_frame.output.csp = XVID_CSP_I420;                  m_frame.output.csp = XVID_CSP_I420;
786                  m_frame.output.stride[0] = CALC_BI_STRIDE(biWidth, 8);  /* planar format fix */                  out_stride = CALC_BI_STRIDE(biWidth, 8);        /* planar format fix */
787          }          }
788          else if (subtype == MEDIASUBTYPE_YV12)          else if (subtype == MEDIASUBTYPE_YV12)
789          {          {
790                  DPRINTF("YV12");                  DPRINTF("YV12");
791                  rgb_flip = 0;                  rgb_flip = 0;
792                  m_frame.output.csp = XVID_CSP_YV12;                  m_frame.output.csp = XVID_CSP_YV12;
793                  m_frame.output.stride[0] = CALC_BI_STRIDE(biWidth, 8);  /* planar format fix */                  out_stride = CALC_BI_STRIDE(biWidth, 8);        /* planar format fix */
794          }          }
795          else if (subtype == MEDIASUBTYPE_YUY2)          else if (subtype == MEDIASUBTYPE_YUY2)
796          {          {
# Line 979  Line 1046 
1046    
1047          m_frame.output.csp &= ~XVID_CSP_VFLIP;          m_frame.output.csp &= ~XVID_CSP_VFLIP;
1048          m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0);          m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0);
1049            m_frame.output.stride[0] = out_stride;
1050    
1051      // Paranoid check.      // Paranoid check.
1052      if (xvid_decore_func == NULL)      if (xvid_decore_func == NULL)
1053                  return E_FAIL;                  return E_FAIL;
1054    
1055    
   
1056  repeat :  repeat :
1057    
1058          if (pIn->IsPreroll() != S_OK)          if (pIn->IsPreroll() != S_OK)
# Line 1120  Line 1187 
1187          CoTaskMemFree(pPages->pElems);          CoTaskMemFree(pPages->pElems);
1188          return S_OK;          return S_OK;
1189  }  }
1190    
1191    /*===============================================================================
1192    // MFT Interface
1193    //=============================================================================*/
1194    #if defined(XVID_USE_MFT)
1195    #include <limits.h> // _I64_MAX
1196    #define INVALID_TIME  _I64_MAX
1197    
1198    HRESULT CXvidDecoder::MFTGetStreamLimits(DWORD *pdwInputMinimum, DWORD *pdwInputMaximum, DWORD *pdwOutputMinimum, DWORD *pdwOutputMaximum)
1199    {
1200            DPRINTF("(MFT)GetStreamLimits");
1201    
1202            if ((pdwInputMinimum == NULL) || (pdwInputMaximum == NULL) || (pdwOutputMinimum == NULL) || (pdwOutputMaximum == NULL))
1203                    return E_POINTER;
1204    
1205            /* Just a fixed number of streams allowed */
1206            *pdwInputMinimum = *pdwInputMaximum = 1;
1207            *pdwOutputMinimum = *pdwOutputMaximum = 1;
1208    
1209            return S_OK;
1210    }
1211    
1212    HRESULT CXvidDecoder::MFTGetStreamCount(DWORD *pcInputStreams, DWORD *pcOutputStreams)
1213    {
1214            DPRINTF("(MFT)GetStreamCount");
1215    
1216            if ((pcInputStreams == NULL) || (pcOutputStreams == NULL))
1217                    return E_POINTER;
1218    
1219            /* We have a fixed number of streams */
1220            *pcInputStreams = 1;
1221            *pcOutputStreams = 1;
1222    
1223            return S_OK;
1224    }
1225    
1226    HRESULT CXvidDecoder::MFTGetStreamIDs(DWORD dwInputIDArraySize, DWORD *pdwInputIDs, DWORD dwOutputIDArraySize, DWORD *pdwOutputIDs)
1227    {
1228            DPRINTF("(MFT)GetStreamIDs");
1229            return E_NOTIMPL; /* We have fixed number of streams, so stream ID match stream index */
1230    }
1231    
1232    HRESULT CXvidDecoder::MFTGetInputStreamInfo(DWORD dwInputStreamID, MFT_INPUT_STREAM_INFO *pStreamInfo)
1233    {
1234            DPRINTF("(MFT)GetInputStreamInfo");
1235    
1236            if (pStreamInfo == NULL)
1237                    return E_POINTER;
1238    
1239            if (dwInputStreamID != 0)
1240                    return MF_E_INVALIDSTREAMNUMBER;
1241    
1242            EnterCriticalSection(&m_mft_lock);
1243    
1244            pStreamInfo->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER;
1245            pStreamInfo->hnsMaxLatency = 0;
1246    
1247            pStreamInfo->cbSize = 1; /* Need atleast 1 byte input */
1248            pStreamInfo->cbMaxLookahead = 0;
1249            pStreamInfo->cbAlignment = 1;
1250    
1251            LeaveCriticalSection(&m_mft_lock);
1252            return S_OK;
1253    }
1254    
1255    HRESULT CXvidDecoder::MFTGetOutputStreamInfo(DWORD dwOutputStreamID, MFT_OUTPUT_STREAM_INFO *pStreamInfo)
1256    {
1257            DPRINTF("(MFT)GetOutputStreamInfo");
1258    
1259            if (pStreamInfo == NULL)
1260                    return E_POINTER;
1261    
1262            if (dwOutputStreamID != 0)
1263                    return MF_E_INVALIDSTREAMNUMBER;
1264    
1265            EnterCriticalSection(&m_mft_lock);
1266    
1267            pStreamInfo->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_DISCARDABLE;
1268    
1269            if (m_pOutputType == NULL) {
1270                    pStreamInfo->cbSize = 0;
1271                    pStreamInfo->cbAlignment = 0;
1272            }
1273            else {
1274                    pStreamInfo->cbSize = m_create.width * abs(m_create.height) * 4; // XXX
1275                    pStreamInfo->cbAlignment = 1;
1276            }
1277    
1278            LeaveCriticalSection(&m_mft_lock);
1279            return S_OK;
1280    }
1281    
1282    HRESULT CXvidDecoder::GetAttributes(IMFAttributes** pAttributes)
1283    {
1284            DPRINTF("(MFT)GetAttributes");
1285            return E_NOTIMPL; /* We don't support any attributes */
1286    }
1287    
1288    HRESULT CXvidDecoder::GetInputStreamAttributes(DWORD dwInputStreamID, IMFAttributes **ppAttributes)
1289    {
1290            DPRINTF("(MFT)GetInputStreamAttributes");
1291            return E_NOTIMPL; /* We don't support any attributes */
1292    }
1293    
1294    HRESULT CXvidDecoder::GetOutputStreamAttributes(DWORD dwOutputStreamID, IMFAttributes **ppAttributes)
1295    {
1296            DPRINTF("(MFT)GetOutputStreamAttributes");
1297            return E_NOTIMPL; /* We don't support any attributes */
1298    }
1299    
1300    HRESULT CXvidDecoder::MFTDeleteInputStream(DWORD dwStreamID)
1301    {
1302            DPRINTF("(MFT)DeleteInputStream");
1303            return E_NOTIMPL; /* We have a fixed number of streams */
1304    }
1305    
1306    HRESULT CXvidDecoder::MFTAddInputStreams(DWORD cStreams, DWORD *adwStreamIDs)
1307    {
1308            DPRINTF("(MFT)AddInputStreams");
1309            return E_NOTIMPL; /* We have a fixed number of streams */
1310    }
1311    
1312    HRESULT CXvidDecoder::MFTGetInputAvailableType(DWORD dwInputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1313    {
1314            DPRINTF("(MFT)GetInputAvailableType");
1315    
1316            if (dwInputStreamID != 0)
1317                    return MF_E_INVALIDSTREAMNUMBER;
1318    
1319            DWORD i = 0;
1320            GUID *bs_guid_table[8];
1321    
1322            bs_guid_table[i++] = (GUID *)&CLSID_XVID;
1323            bs_guid_table[i++] = (GUID *)&CLSID_XVID_UC;
1324    
1325            if (g_config.supported_4cc & SUPPORT_DX50) {
1326                    bs_guid_table[i++] = (GUID *)&CLSID_DX50;
1327                    bs_guid_table[i++] = (GUID *)&CLSID_DX50_UC;
1328            }
1329            if (g_config.supported_4cc & SUPPORT_DIVX) {
1330                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX;
1331                    bs_guid_table[i++] = (GUID *)&CLSID_DIVX_UC;
1332            }
1333            if (g_config.supported_4cc & SUPPORT_MP4V) {
1334                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V;
1335                    bs_guid_table[i++] = (GUID *)&CLSID_MP4V_UC;
1336            }
1337    
1338            const GUID *subtype;
1339            if (dwTypeIndex < i) {
1340                    subtype = bs_guid_table[dwTypeIndex];
1341            }
1342            else {
1343                    return MF_E_NO_MORE_TYPES;
1344            }
1345    
1346            EnterCriticalSection(&m_mft_lock);
1347    
1348            HRESULT hr = S_OK;
1349    
1350            if (ppType) {
1351                    IMFMediaType *pInputType = NULL;
1352                    hr = MFCreateMediaType(&pInputType);
1353    
1354                    if (SUCCEEDED(hr))
1355                            hr = pInputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1356    
1357                    if (SUCCEEDED(hr))
1358                            hr = pInputType->SetGUID(MF_MT_SUBTYPE, *subtype);
1359    
1360                    if (SUCCEEDED(hr)) {
1361                            *ppType = pInputType;
1362                            (*ppType)->AddRef();
1363                    }
1364                    if (pInputType) pInputType->Release();
1365            }
1366    
1367            LeaveCriticalSection(&m_mft_lock);
1368    
1369            return hr;
1370    }
1371    
1372    HRESULT CXvidDecoder::MFTGetOutputAvailableType(DWORD dwOutputStreamID, DWORD dwTypeIndex, IMFMediaType **ppType)
1373    {
1374            DPRINTF("(MFT)GetOutputAvailableType");
1375    
1376            if (ppType == NULL)
1377                    return E_INVALIDARG;
1378    
1379            if (dwOutputStreamID != 0)
1380                    return MF_E_INVALIDSTREAMNUMBER;
1381    
1382            if (dwTypeIndex < 0) return E_INVALIDARG;
1383    
1384            GUID csp;
1385            int bitdepth = 8;
1386            switch(dwTypeIndex)
1387            {
1388            case 0:
1389    if ( USE_YUY2 )
1390    {
1391                    csp = MFVideoFormat_YUY2;
1392                    bitdepth = 4;
1393                    break;
1394    }
1395            case 1 :
1396    if ( USE_UYVY )
1397    {
1398                    csp = MFVideoFormat_UYVY;
1399                    bitdepth = 4;
1400                    break;
1401    }
1402            case 2  :
1403                    if ( USE_IYUV )
1404    {
1405                    csp = MFVideoFormat_IYUV;
1406                    bitdepth = 3;
1407                    break;
1408    }
1409            case 3  :
1410    if ( USE_YV12 )
1411    {
1412                    csp = MFVideoFormat_YV12;
1413                    bitdepth = 3;
1414                    break;
1415    }
1416            case 4 :
1417    if ( USE_RGB32 )
1418    {
1419                    csp = MFVideoFormat_RGB32;
1420                    bitdepth = 8;
1421                    break;
1422    }
1423            case 5 :
1424    if ( USE_RGB24 )
1425    {
1426                    csp = MFVideoFormat_RGB24;
1427                    bitdepth = 6;
1428                    break;
1429    }
1430            case 6 :
1431    if ( USE_RG555 )
1432    {
1433                    csp = MFVideoFormat_RGB555;
1434                    bitdepth = 4;
1435                    break;
1436    }
1437            case 7 :
1438    if ( USE_RG565 )
1439    {
1440                    csp = MFVideoFormat_RGB565;
1441                    bitdepth = 4;
1442                    break;
1443    }
1444            default :
1445                    return MF_E_NO_MORE_TYPES;
1446            }
1447    
1448            if (m_pInputType == NULL)
1449                    return MF_E_TRANSFORM_TYPE_NOT_SET;
1450    
1451            EnterCriticalSection(&m_mft_lock);
1452    
1453            HRESULT hr = S_OK;
1454    
1455            IMFMediaType *pOutputType = NULL;
1456            hr = MFCreateMediaType(&pOutputType);
1457    
1458            if (SUCCEEDED(hr)) {
1459                    hr = pOutputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
1460            }
1461    
1462            if (SUCCEEDED(hr)) {
1463                    hr = pOutputType->SetGUID(MF_MT_SUBTYPE, csp);
1464        }
1465    
1466            if (SUCCEEDED(hr)) {
1467                    hr = pOutputType->SetUINT32(MF_MT_FIXED_SIZE_SAMPLES, TRUE);
1468            }
1469    
1470            if (SUCCEEDED(hr)) {
1471                    hr = pOutputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
1472            }
1473    
1474            if (SUCCEEDED(hr)) {
1475                    hr = pOutputType->SetUINT32(MF_MT_SAMPLE_SIZE, (m_create.height * m_create.width * bitdepth)>>1);
1476            }
1477    
1478            if (SUCCEEDED(hr)) {
1479                    hr = MFSetAttributeSize(pOutputType, MF_MT_FRAME_SIZE, m_create.width, m_create.height);
1480            }
1481    
1482            if (SUCCEEDED(hr)) {
1483                    hr = MFSetAttributeRatio(pOutputType, MF_MT_FRAME_RATE, m_frameRate.Numerator, m_frameRate.Denominator);
1484            }
1485    
1486            if (SUCCEEDED(hr)) {
1487                    hr = pOutputType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);
1488            }
1489    
1490            if (SUCCEEDED(hr)) {
1491                    hr = MFSetAttributeRatio(pOutputType, MF_MT_PIXEL_ASPECT_RATIO, ar_x, ar_y);
1492            }
1493    
1494            if (SUCCEEDED(hr)) {
1495                    *ppType = pOutputType;
1496                    (*ppType)->AddRef();
1497            }
1498    
1499            if (pOutputType) pOutputType->Release();
1500    
1501            LeaveCriticalSection(&m_mft_lock);
1502            return hr;
1503    }
1504    
1505    HRESULT CXvidDecoder::MFTSetInputType(DWORD dwInputStreamID, IMFMediaType *pType, DWORD dwFlags)
1506    {
1507            DPRINTF("(MFT)SetInputType");
1508    
1509            if (dwInputStreamID != 0)
1510                    return MF_E_INVALIDSTREAMNUMBER;
1511    
1512            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1513                    return E_INVALIDARG;
1514    
1515            EnterCriticalSection(&m_mft_lock);
1516    
1517            HRESULT hr = S_OK;
1518    
1519            /* Actually set the type or just test it? */
1520            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1521    
1522            /* If we have samples pending the type can't be changed right now */
1523            if (HasPendingOutput())
1524                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1525    
1526            if (SUCCEEDED(hr)) {
1527            if (pType) { // /* Check the type */
1528                hr = OnCheckInputType(pType);
1529            }
1530            }
1531    
1532            if (SUCCEEDED(hr)) {
1533                    if (bReallySet) { /* Set the type if needed */
1534                            hr = OnSetInputType(pType);
1535                    }
1536            }
1537    
1538            LeaveCriticalSection(&m_mft_lock);
1539            return hr;
1540    }
1541    
1542    HRESULT CXvidDecoder::MFTSetOutputType(DWORD dwOutputStreamID, IMFMediaType *pType, DWORD dwFlags)
1543    {
1544            DPRINTF("(MFT)SetOutputType");
1545    
1546            if (dwOutputStreamID != 0)
1547                    return MF_E_INVALIDSTREAMNUMBER;
1548    
1549            if (dwFlags & ~MFT_SET_TYPE_TEST_ONLY)
1550                    return E_INVALIDARG;
1551    
1552            HRESULT hr = S_OK;
1553    
1554            EnterCriticalSection(&m_mft_lock);
1555    
1556            /* Actually set the type or just test it?
1557            BOOL bReallySet = ((dwFlags & MFT_SET_TYPE_TEST_ONLY) == 0);
1558    
1559            /* If we have samples pending the type can't be changed right now */
1560            if (HasPendingOutput())
1561                    hr = MF_E_TRANSFORM_CANNOT_CHANGE_MEDIATYPE_WHILE_PROCESSING;
1562    
1563            if (SUCCEEDED(hr)) {
1564                    if (pType) { /* Check the type */
1565                            AM_MEDIA_TYPE *am;
1566                            hr = MFCreateAMMediaTypeFromMFMediaType(pType, GUID_NULL, &am);
1567    
1568                            if (SUCCEEDED(hr)) {
1569                                    if (FAILED(ChangeColorspace(am->subtype, am->formattype, am->pbFormat))) {
1570                                            DPRINTF("(MFT)InternalCheckOutputType (MF_E_INVALIDTYPE)");
1571                                            return MF_E_INVALIDTYPE;
1572                                    }
1573    
1574                            CoTaskMemFree(am->pbFormat);
1575                            CoTaskMemFree(am);
1576                            }
1577                    }
1578            }
1579    
1580            if (SUCCEEDED(hr)) {
1581                    if (bReallySet) { /* Set the type if needed */
1582                            hr = OnSetOutputType(pType);
1583                    }
1584            }
1585    
1586    #ifdef XVID_USE_TRAYICON
1587            if (SUCCEEDED(hr) && MSG_hwnd == NULL) /* Create message passing window */
1588            {
1589                    WNDCLASSEX wc;
1590    
1591                    wc.cbSize = sizeof(WNDCLASSEX);
1592                    wc.lpfnWndProc = msg_proc;
1593                    wc.style = CS_HREDRAW | CS_VREDRAW;
1594                    wc.cbWndExtra = 0;
1595                    wc.cbClsExtra = 0;
1596                    wc.hInstance = (HINSTANCE) g_xvid_hInst;
1597                    wc.hbrBackground = (HBRUSH) GetStockObject(NULL_BRUSH);
1598                    wc.lpszMenuName = NULL;
1599                    wc.lpszClassName = "XVID_MSG_WINDOW";
1600                    wc.hIcon = NULL;
1601                    wc.hIconSm = NULL;
1602                    wc.hCursor = NULL;
1603                    RegisterClassEx(&wc);
1604    
1605                    MSG_hwnd = CreateWindowEx(0, "XVID_MSG_WINDOW", NULL, 0, CW_USEDEFAULT,
1606                                      CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, (HINSTANCE) g_xvid_hInst, NULL);
1607    
1608                    /* display the tray icon */
1609                    NOTIFYICONDATA nid;
1610    
1611                    nid.cbSize = sizeof(NOTIFYICONDATA);
1612                    nid.hWnd = MSG_hwnd;
1613                    nid.uID = 100;
1614                    nid.uVersion = NOTIFYICON_VERSION;
1615                    nid.uCallbackMessage = WM_ICONMESSAGE;
1616                    nid.hIcon = LoadIcon(g_xvid_hInst, MAKEINTRESOURCE(IDI_ICON));
1617                    strcpy_s(nid.szTip, 19, "Xvid Video Decoder");
1618                    nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
1619    
1620                    Shell_NotifyIcon(NIM_ADD, &nid);
1621            }
1622    #endif
1623    
1624            LeaveCriticalSection(&m_mft_lock);
1625            return hr;
1626    }
1627    
1628    HRESULT CXvidDecoder::MFTGetInputCurrentType(DWORD dwInputStreamID, IMFMediaType **ppType)
1629    {
1630            DPRINTF("(MFT)GetInputCurrentType");
1631    
1632            if (ppType == NULL)
1633                    return E_POINTER;
1634    
1635            if (dwInputStreamID != 0)
1636                    return MF_E_INVALIDSTREAMNUMBER;
1637    
1638            EnterCriticalSection(&m_mft_lock);
1639    
1640            HRESULT hr = S_OK;
1641    
1642            if (!m_pInputType)
1643                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1644    
1645            if (SUCCEEDED(hr)) {
1646                    *ppType = m_pInputType;
1647                    (*ppType)->AddRef();
1648            }
1649    
1650            LeaveCriticalSection(&m_mft_lock);
1651            return hr;
1652    }
1653    
1654    HRESULT CXvidDecoder::MFTGetOutputCurrentType(DWORD dwOutputStreamID, IMFMediaType **ppType)
1655    {
1656            DPRINTF("(MFT)GetOutputCurrentType");
1657    
1658            if (ppType == NULL)
1659                    return E_POINTER;
1660    
1661            if (dwOutputStreamID != 0)
1662                    return MF_E_INVALIDSTREAMNUMBER;
1663    
1664            EnterCriticalSection(&m_mft_lock);
1665    
1666            HRESULT hr = S_OK;
1667    
1668            if (!m_pOutputType)
1669                    hr = MF_E_TRANSFORM_TYPE_NOT_SET;
1670    
1671            if (SUCCEEDED(hr)) {
1672                    *ppType = m_pOutputType;
1673                    (*ppType)->AddRef();
1674            }
1675    
1676            LeaveCriticalSection(&m_mft_lock);
1677            return hr;
1678    }
1679    
1680    HRESULT CXvidDecoder::MFTGetInputStatus(DWORD dwInputStreamID, DWORD *pdwFlags)
1681    {
1682            DPRINTF("(MFT)GetInputStatus");
1683    
1684            if (pdwFlags == NULL)
1685                    return E_POINTER;
1686    
1687            if (dwInputStreamID != 0)
1688                    return MF_E_INVALIDSTREAMNUMBER;
1689    
1690            EnterCriticalSection(&m_mft_lock);
1691    
1692            /* If there's pending output sampels we don't accept new
1693               input data until ProcessOutput() or Flush() was called */
1694            if (!HasPendingOutput()) {
1695                    *pdwFlags = MFT_INPUT_STATUS_ACCEPT_DATA;
1696            }
1697            else {
1698                    *pdwFlags = 0;
1699            }
1700    
1701            LeaveCriticalSection(&m_mft_lock);
1702    
1703            return S_OK;
1704    }
1705    
1706    HRESULT CXvidDecoder::MFTGetOutputStatus(DWORD *pdwFlags)
1707    {
1708            DPRINTF("(MFT)GetOutputStatus");
1709    
1710            if (pdwFlags == NULL)
1711                    return E_POINTER;
1712    
1713            EnterCriticalSection(&m_mft_lock);
1714    
1715            /* We can render an output sample only after we
1716               have decoded one */
1717            if (HasPendingOutput()) {
1718                    *pdwFlags = MFT_OUTPUT_STATUS_SAMPLE_READY;
1719            }
1720            else {
1721                    *pdwFlags = 0;
1722            }
1723    
1724            LeaveCriticalSection(&m_mft_lock);
1725    
1726            return S_OK;
1727    }
1728    
1729    HRESULT CXvidDecoder::MFTSetOutputBounds(LONGLONG hnsLowerBound, LONGLONG hnsUpperBound)
1730    {
1731            DPRINTF("(MFT)SetOutputBounds");
1732            return E_NOTIMPL;
1733    }
1734    
1735    HRESULT CXvidDecoder::MFTProcessEvent(DWORD dwInputStreamID, IMFMediaEvent *pEvent)
1736    {
1737            DPRINTF("(MFT)ProcessEvent");
1738            return E_NOTIMPL; /* We don't handle any stream events */
1739    }
1740    
1741    HRESULT CXvidDecoder::MFTProcessMessage(MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam)
1742    {
1743            DPRINTF("(MFT)ProcessMessage");
1744            HRESULT hr = S_OK;
1745    
1746            EnterCriticalSection(&m_mft_lock);
1747    
1748            switch (eMessage)
1749            {
1750            case MFT_MESSAGE_COMMAND_FLUSH:
1751                    if (m_create.handle != NULL) {
1752                            DPRINTF("(MFT)CommandFlush");
1753    
1754                            xvid_dec_stats_t stats;
1755                            int used_bytes;
1756    
1757                            memset(&stats, 0, sizeof(stats));
1758                            stats.version = XVID_VERSION;
1759    
1760                            int csp = m_frame.output.csp;
1761    
1762                            m_frame.output.csp = XVID_CSP_INTERNAL;
1763                            m_frame.bitstream = NULL;
1764                            m_frame.length = -1;
1765                            m_frame.general = XVID_LOWDELAY;
1766    
1767                            do {
1768                                    used_bytes = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1769                            } while(used_bytes>=0 && stats.type <= 0);
1770    
1771                            m_frame.output.csp = csp;
1772                            m_frame.output.plane[1] = NULL; /* Don't display flushed samples */
1773    
1774                            //m_timestamp = INVALID_TIME;
1775                            //m_timelength = INVALID_TIME;
1776                            //m_rtFrame = 0;
1777            }
1778        break;
1779    
1780            case MFT_MESSAGE_COMMAND_DRAIN:
1781                    m_discont = 1; /* Set discontinuity flag */
1782                    m_rtFrame = 0;
1783                    break;
1784    
1785            case MFT_MESSAGE_SET_D3D_MANAGER:
1786                    hr = E_NOTIMPL;
1787                    break;
1788    
1789            case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
1790            case MFT_MESSAGE_NOTIFY_END_STREAMING:
1791                    break;
1792    
1793            case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
1794            case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
1795                    break;
1796            }
1797    
1798            LeaveCriticalSection(&m_mft_lock);
1799    
1800            return hr;
1801    }
1802    
1803    HRESULT CXvidDecoder::MFTProcessInput(DWORD dwInputStreamID, IMFSample *pSample, DWORD dwFlags)
1804    {
1805            DPRINTF("(MFT)ProcessInput");
1806    
1807            if (pSample == NULL)
1808                    return E_POINTER;
1809    
1810            if (dwInputStreamID != 0)
1811                    return MF_E_INVALIDSTREAMNUMBER;
1812    
1813            if (dwFlags != 0)
1814                    return E_INVALIDARG;
1815    
1816            if (!m_pInputType || !m_pOutputType) {
1817                    return MF_E_NOTACCEPTING;   /* Must have set input and output types */
1818            }
1819            else if (HasPendingOutput()) {
1820                    return MF_E_NOTACCEPTING;   /* We still have output samples to render */
1821            }
1822    
1823            xvid_dec_stats_t stats;
1824            int length;
1825    
1826            memset(&stats, 0, sizeof(stats));
1827            stats.version = XVID_VERSION;
1828    
1829            if (m_create.handle == NULL)
1830            {
1831                    if (xvid_decore_func == NULL)
1832                            return E_FAIL;
1833                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0)
1834                    {
1835                            DPRINTF("*** XVID_DEC_CREATE error");
1836                            return E_FAIL;
1837                    }
1838            }
1839    
1840            EnterCriticalSection(&m_mft_lock);
1841    
1842            HRESULT hr = S_OK;
1843            IMFMediaBuffer *pBuffer;
1844    
1845            if (SUCCEEDED(hr)) {
1846                    hr = pSample->ConvertToContiguousBuffer(&pBuffer);
1847            }
1848    
1849            if (SUCCEEDED(hr)) {
1850                    hr = pBuffer->Lock((BYTE**)&m_frame.bitstream, NULL, (DWORD *)&m_frame.length);
1851            }
1852    
1853            m_frame.general = XVID_LOWDELAY;
1854    
1855            if (m_discont == 1) {
1856                    m_frame.general |= XVID_DISCONTINUITY;
1857                    m_discont = 0;
1858            }
1859    
1860            if (g_config.nDeblock_Y)
1861                    m_frame.general |= XVID_DEBLOCKY;
1862    
1863            if (g_config.nDeblock_UV)
1864                    m_frame.general |= XVID_DEBLOCKUV;
1865    
1866            if (g_config.nDering_Y)
1867                    m_frame.general |= XVID_DERINGY;
1868    
1869            if (g_config.nDering_UV)
1870                    m_frame.general |= XVID_DERINGUV;
1871    
1872            if (g_config.nFilmEffect)
1873                    m_frame.general |= XVID_FILMEFFECT;
1874    
1875            m_frame.brightness = g_config.nBrightness;
1876    
1877            m_frame.output.csp &= ~XVID_CSP_VFLIP;
1878            m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0);
1879    
1880            int csp = m_frame.output.csp;
1881            m_frame.output.csp = XVID_CSP_INTERNAL;
1882    
1883        // Paranoid check.
1884            if (xvid_decore_func == NULL) {
1885                    hr = E_FAIL;
1886                    goto END_LOOP;
1887            }
1888    
1889    repeat :
1890            length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats);
1891    
1892            if (length == XVID_ERR_MEMORY) {
1893                    hr = E_FAIL;
1894                    goto END_LOOP;
1895            }
1896            else if (length < 0)
1897            {
1898                    DPRINTF("*** XVID_DEC_DECODE");
1899                    goto END_LOOP;
1900            }
1901    
1902            if (stats.type == XVID_TYPE_NOTHING && length > 0) {
1903                    DPRINTF(" B-Frame decoder lag");
1904                    m_frame.output.plane[1] = NULL;
1905                    goto END_LOOP;
1906            }
1907    
1908            if (stats.type == XVID_TYPE_VOL)
1909            {
1910                    if (stats.data.vol.width != m_create.width ||
1911                            stats.data.vol.height != m_create.height)
1912                    {
1913                            DPRINTF("TODO: auto-resize");
1914                            m_frame.output.plane[1] = NULL;
1915                            hr = E_FAIL;
1916                    }
1917    
1918                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) { /* auto */
1919                            int par_x, par_y;
1920                            if (stats.data.vol.par == XVID_PAR_EXT) {
1921                                    par_x = stats.data.vol.par_width;
1922                                    par_y = stats.data.vol.par_height;
1923                            } else {
1924                                    par_x = PARS[stats.data.vol.par-1][0];
1925                                    par_y = PARS[stats.data.vol.par-1][1];
1926                            }
1927    
1928                            ar_x = par_x * stats.data.vol.width;
1929                            ar_y = par_y * stats.data.vol.height;
1930                    }
1931    
1932                    m_frame.bitstream = (BYTE*)m_frame.bitstream + length;
1933                    m_frame.length -= length;
1934                    goto repeat;
1935            }
1936    
1937    END_LOOP:
1938            m_frame.output.csp = csp;
1939    
1940            if (pBuffer) {
1941                    pBuffer->Unlock();
1942                    pBuffer->Release();
1943            }
1944    
1945            if (SUCCEEDED(hr)) {
1946                    /* Try to get a timestamp */
1947                    if (FAILED(pSample->GetSampleTime(&m_timestamp)))
1948                            m_timestamp = INVALID_TIME;
1949    
1950                    if (FAILED(pSample->GetSampleDuration(&m_timelength))) {
1951                            m_timelength = INVALID_TIME;
1952                    }
1953            }
1954    
1955            LeaveCriticalSection(&m_mft_lock);
1956    
1957            return hr;
1958    }
1959    
1960    HRESULT CXvidDecoder::MFTProcessOutput(DWORD dwFlags, DWORD cOutputBufferCount, MFT_OUTPUT_DATA_BUFFER *pOutputSamples, DWORD *pdwStatus)
1961    {
1962            DPRINTF("(MFT)ProcessOutput");
1963    
1964            /* Preroll in MFT ??
1965               Flags ?? -> TODO... */
1966            if (dwFlags != 0)
1967                    return E_INVALIDARG;
1968    
1969            if (pOutputSamples == NULL || pdwStatus == NULL)
1970                    return E_POINTER;
1971    
1972            if (cOutputBufferCount != 1) /* Must be exactly one output buffer */
1973                    return E_INVALIDARG;
1974    
1975            if (pOutputSamples[0].pSample == NULL) /* Must have a sample */
1976                    return E_INVALIDARG;
1977    
1978            if (!HasPendingOutput()) { /* If there's no sample we need to decode one first */
1979                    return MF_E_TRANSFORM_NEED_MORE_INPUT;
1980            }
1981    
1982            EnterCriticalSection(&m_mft_lock);
1983    
1984            HRESULT hr = S_OK;
1985    
1986            BYTE *Dst = NULL;
1987            DWORD buffer_size;
1988    
1989            IMFMediaBuffer *pOutput = NULL;
1990    
1991            if (SUCCEEDED(hr)) {
1992                    hr = pOutputSamples[0].pSample->GetBufferByIndex(0, &pOutput); /* Get output buffer */
1993            }
1994    
1995            if (SUCCEEDED(hr)) {
1996                    hr = pOutput->GetMaxLength(&buffer_size);
1997            }
1998    
1999            if (SUCCEEDED(hr))
2000                    hr = pOutput->Lock(&Dst, NULL, NULL);
2001    
2002            if (SUCCEEDED(hr)) {
2003                    xvid_gbl_convert_t convert;
2004    
2005                    memset(&convert, 0, sizeof(convert));
2006                    convert.version = XVID_VERSION;
2007    
2008                    convert.input.csp = XVID_CSP_INTERNAL;
2009                    convert.input.plane[0] = m_frame.output.plane[0];
2010                    convert.input.plane[1] = m_frame.output.plane[1];
2011                    convert.input.plane[2] = m_frame.output.plane[2];
2012                    convert.input.stride[0] = m_frame.output.stride[0];
2013                    convert.input.stride[1] = m_frame.output.stride[1];
2014                    convert.input.stride[2] = m_frame.output.stride[2];
2015    
2016                    convert.output.csp = m_frame.output.csp;
2017                    convert.output.plane[0] = Dst;
2018                    convert.output.stride[0] = out_stride;
2019    
2020                    convert.width = m_create.width;
2021                    convert.height = m_create.height;
2022                    convert.interlacing = 0;
2023    
2024                    if (m_frame.output.plane[1] != NULL && Dst != NULL && xvid_global_func != NULL)
2025                            if (xvid_global_func(0, XVID_GBL_CONVERT, &convert, NULL) < 0) /* CSP convert into output buffer */
2026                                    hr = E_FAIL;
2027    
2028                    m_frame.output.plane[1] = NULL;
2029            }
2030    
2031            *pdwStatus = 0;
2032    
2033            if (SUCCEEDED(hr)) {
2034                    if (SUCCEEDED(hr))
2035                            hr = pOutputSamples[0].pSample->SetUINT32(MFSampleExtension_CleanPoint, TRUE); // key frame
2036    
2037                    if (SUCCEEDED(hr)) { /* Set timestamp of output sample */
2038                            if (m_timestamp != INVALID_TIME)
2039                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_timestamp);
2040                            else
2041                                    hr = pOutputSamples[0].pSample->SetSampleTime(m_rtFrame);
2042    
2043                            if (m_timelength != INVALID_TIME)
2044                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_timelength);
2045                            else
2046                                    hr = pOutputSamples[0].pSample->SetSampleDuration(m_duration);
2047    
2048                            m_rtFrame += m_duration;
2049                    }
2050    
2051                    if (SUCCEEDED(hr))
2052                            hr = pOutput->SetCurrentLength(m_create.width * abs(m_create.height) * 4); // XXX
2053            }
2054    
2055            if (pOutput) {
2056                    pOutput->Unlock();
2057                    pOutput->Release();
2058            }
2059    
2060            LeaveCriticalSection(&m_mft_lock);
2061    
2062            return hr;
2063    }
2064    
2065    HRESULT CXvidDecoder::OnCheckInputType(IMFMediaType *pmt)
2066    {
2067            DPRINTF("(MFT)CheckInputType");
2068    
2069            HRESULT hr = S_OK;
2070    
2071            /*  Check if input type is already set. Reject any type that is not identical */
2072            if (m_pInputType) {
2073                    DWORD dwFlags = 0;
2074                    if (S_OK == m_pInputType->IsEqual(pmt, &dwFlags)) {
2075                            return S_OK;
2076                    }
2077                    else {
2078                            return MF_E_INVALIDTYPE;
2079                    }
2080            }
2081    
2082            GUID majortype = {0}, subtype = {0};
2083            UINT32 width = 0, height = 0;
2084    
2085            hr = pmt->GetMajorType(&majortype);
2086    
2087            if (SUCCEEDED(hr)) {
2088                    if (majortype != MFMediaType_Video) { /* Must be Video */
2089                            hr = MF_E_INVALIDTYPE;
2090                    }
2091            }
2092    
2093            if (m_hdll == NULL) {
2094                    HRESULT hr = OpenLib();
2095    
2096                    if (FAILED(hr) || (m_hdll == NULL)) // Paranoid checks.
2097                            hr = MF_E_INVALIDTYPE;
2098            }
2099    
2100            if (SUCCEEDED(hr)) {
2101                    hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &width, &height);
2102            }
2103    
2104            /* Check the frame size */
2105            if (SUCCEEDED(hr)) {
2106                    if (width > 4096 || height > 4096) {
2107                            hr = MF_E_INVALIDTYPE;
2108                    }
2109            }
2110            m_create.width = width;
2111            m_create.height = height;
2112    
2113            if (SUCCEEDED(hr)) {
2114                    if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) {
2115                            hr = MFGetAttributeRatio(pmt, MF_MT_PIXEL_ASPECT_RATIO, (UINT32*)&ar_x, (UINT32*)&ar_y);
2116                    }
2117            }
2118    
2119            /* TODO1: Make sure there really is a frame rate after all!
2120               TODO2: Use the framerate for something! */
2121            MFRatio fps = {0};
2122            if (SUCCEEDED(hr)) {
2123                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&fps.Numerator, (UINT32*)&fps.Denominator);
2124            }
2125    
2126            if (SUCCEEDED(hr)) {
2127                    hr = pmt->GetGUID(MF_MT_SUBTYPE, &subtype);
2128            }
2129    
2130            if (subtype == CLSID_MP4V || subtype == CLSID_MP4V_UC) {
2131                    if (!(g_config.supported_4cc & SUPPORT_MP4V)) {
2132                            CloseLib();
2133                            hr = MF_E_INVALIDTYPE;
2134                    }
2135                    else m_create.fourcc = FOURCC_MP4V;
2136            }
2137            else if (subtype == CLSID_DIVX || subtype == CLSID_DIVX_UC) {
2138                    if (!(g_config.supported_4cc & SUPPORT_DIVX)) {
2139                            CloseLib();
2140                            hr = MF_E_INVALIDTYPE;
2141                    }
2142                    else m_create.fourcc = FOURCC_DIVX;
2143            }
2144            else if (subtype == CLSID_DX50 || subtype == CLSID_DX50_UC) {
2145                    if (!(g_config.supported_4cc & SUPPORT_DX50)) {
2146                            CloseLib();
2147                            hr = MF_E_INVALIDTYPE;
2148                    }
2149                    else m_create.fourcc = FOURCC_DX50;
2150            }
2151            else if (subtype == CLSID_XVID || subtype == CLSID_XVID_UC) {
2152                    m_create.fourcc = FOURCC_XVID;
2153            }
2154            else {
2155                    DPRINTF("Unknown subtype!");
2156                    CloseLib();
2157                    hr = MF_E_INVALIDTYPE;
2158            }
2159    
2160            /* haali media splitter reports VOL information in the format header */
2161            if (SUCCEEDED(hr))
2162            {
2163                    UINT32 cbSeqHeader = 0;
2164    
2165                    (void)pmt->GetBlobSize(MF_MT_MPEG_SEQUENCE_HEADER, &cbSeqHeader);
2166    
2167                    if (cbSeqHeader>0) {
2168                            xvid_dec_stats_t stats;
2169                            memset(&stats, 0, sizeof(stats));
2170                            stats.version = XVID_VERSION;
2171    
2172                            if (m_create.handle == NULL) {
2173                                    if (xvid_decore_func == NULL)
2174                                            hr = E_FAIL;
2175                                    if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) {
2176                                            DPRINTF("*** XVID_DEC_CREATE error");
2177                                            hr = E_FAIL;
2178                                    }
2179                            }
2180    
2181                            if (SUCCEEDED(hr)) {
2182                                    (void)pmt->GetAllocatedBlob(MF_MT_MPEG_SEQUENCE_HEADER, (UINT8 **)&m_frame.bitstream, (UINT32 *)&m_frame.length);
2183                                    m_frame.general = 0;
2184                                    m_frame.output.csp = XVID_CSP_NULL;
2185    
2186                                    int ret = 0;
2187                                    if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) {
2188                                            /* honour video dimensions reported in VOL header */
2189                                            if (stats.type == XVID_TYPE_VOL) {
2190                                                    m_create.width = stats.data.vol.width;
2191                                                    m_create.height = stats.data.vol.height;
2192                                            }
2193                                    }
2194    
2195                                    if (ret == XVID_ERR_MEMORY) hr = E_FAIL;
2196                                    CoTaskMemFree(m_frame.bitstream);
2197                            }
2198                    }
2199            }
2200    
2201            return hr;
2202    }
2203    
2204    HRESULT CXvidDecoder::OnSetInputType(IMFMediaType *pmt)
2205    {
2206            HRESULT hr = S_OK;
2207            UINT32 w, h;
2208    
2209            if (m_pInputType) m_pInputType->Release();
2210    
2211            hr = MFGetAttributeSize(pmt, MF_MT_FRAME_SIZE, &w, &h);
2212            m_create.width = w; m_create.height = h;
2213    
2214            if (SUCCEEDED(hr))
2215                    hr = MFGetAttributeRatio(pmt, MF_MT_FRAME_RATE, (UINT32*)&m_frameRate.Numerator, (UINT32*)&m_frameRate.Denominator);
2216    
2217            if (SUCCEEDED(hr)) { /* Store frame duration, derived from the frame rate */
2218                    hr = MFFrameRateToAverageTimePerFrame(m_frameRate.Numerator, m_frameRate.Denominator, &m_duration);
2219            }
2220    
2221            if (SUCCEEDED(hr)) {
2222                    m_pInputType = pmt;
2223                    m_pInputType->AddRef();
2224            }
2225    
2226            return hr;
2227    }
2228    
2229    HRESULT CXvidDecoder::OnSetOutputType(IMFMediaType *pmt)
2230    {
2231            if (m_pOutputType) m_pOutputType->Release();
2232    
2233            m_pOutputType = pmt;
2234            m_pOutputType->AddRef();
2235    
2236            return S_OK;
2237    }
2238    
2239    #endif /* XVID_USE_MFT */

Legend:
Removed from v.1896  
changed lines
  Added in v.1898

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