--- branches/dev-api-4/xvidcore/dshow/src/CXvidDecoder.cpp 2003/06/09 13:55:56 1054 +++ branches/dev-api-4/xvidcore/dshow/src/CXvidDecoder.cpp 2004/01/29 07:06:04 1340 @@ -19,7 +19,15 @@ * along with this program ; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: CXvidDecoder.cpp,v 1.1.2.2 2003-06-09 13:49:00 edgomez Exp $ + * $Id: CXvidDecoder.cpp,v 1.1.2.13 2004-01-29 07:06:04 syskin 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 * ****************************************************************************/ @@ -53,6 +61,20 @@ #include "CXvidDecoder.h" #include "CAbout.h" +// Externs defined here +PostProcessing_Settings PPSettings; + +int rgb_flip; + +bool USE_IYUV; +bool USE_YV12; +bool USE_YUY2; +bool USE_YVYU; +bool USE_UYVY; +bool USE_RGB32; +bool USE_RGB24; +bool USE_RG555; +bool USE_RG565; const AMOVIESETUP_MEDIATYPE sudInputPinTypes[] = { @@ -131,8 +153,6 @@ int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate); - - STDAPI DllRegisterServer() { return AMovieDllRegisterServer2( TRUE ); @@ -179,28 +199,21 @@ -/* dummy decore() */ - -static int dummy_xvid_decore(void * handle, int opt, void * param1, void * param2) -{ - return XVID_ERR_FAIL; -} - - - /* constructor */ -#define XVID_DLL_NAME "xvid.dll" -#define XVID_GLOBAL_NAME "xvid_global" -#define XVID_DECORE_NAME "xvid_decore" +#define XVID_DLL_NAME "xvidcore.dll" CXvidDecoder::CXvidDecoder(LPUNKNOWN punk, HRESULT *phr) : CVideoTransformFilter(NAME("CXvidDecoder"), punk, CLSID_XVID) { DPRINTF("Constructor"); - m_xvid_decore = dummy_xvid_decore; - + xvid_gbl_init_t init; + memset(&init, 0, sizeof(init)); + init.version = XVID_VERSION; + + ar_x = ar_y = 0; + m_hdll = LoadLibrary(XVID_DLL_NAME); if (m_hdll == NULL) { DPRINTF("dll load failed"); @@ -208,24 +221,21 @@ return; } - m_xvid_global = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, XVID_GLOBAL_NAME); - if (m_xvid_global == NULL) { - MessageBox(0, XVID_GLOBAL_NAME "() not found", "Error", 0); + xvid_global_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_global"); + if (xvid_global_func == NULL) { + MessageBox(0, "xvid_global() not found", "Error", 0); return; } - m_xvid_decore = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, XVID_DECORE_NAME); - if (m_xvid_decore == NULL) { - MessageBox(0, XVID_DECORE_NAME "() not found", "Error", 0); + xvid_decore_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_decore"); + if (xvid_decore_func == NULL) { + MessageBox(0, "xvid_decore() not found", "Error", 0); return; } - xvid_gbl_init_t init; - memset(&init, 0, sizeof(init)); - init.version = XVID_VERSION; - if (m_xvid_global(0, XVID_GBL_INIT, &init, NULL) < 0) + if (xvid_global_func(0, XVID_GBL_INIT, &init, NULL) < 0) { - MessageBox(0, XVID_GLOBAL_NAME "() failed", "Error", 0); + MessageBox(0, "xvid_global() failed", "Error", 0); return; } @@ -235,6 +245,59 @@ memset(&m_frame, 0, sizeof(m_frame)); m_frame.version = XVID_VERSION; + + HKEY hKey; + DWORD size; + RegOpenKeyEx(XVID_REG_KEY, XVID_REG_SUBKEY, 0, KEY_READ, &hKey); + + // Set the default post-processing settings + REG_GET_N("Brightness", PPSettings.nBrightness, 25) + REG_GET_N("Deblock_Y", PPSettings.nDeblock_Y, 0) + REG_GET_N("Deblock_UV", PPSettings.nDeblock_UV, 0) + REG_GET_N("Dering", PPSettings.nDering, 0) + REG_GET_N("FilmEffect", PPSettings.nFilmEffect, 0) + REG_GET_N("ForceColorspace", PPSettings.nForceColorspace, 0) + REG_GET_N("FlipVideo", PPSettings.nFlipVideo, 0) + + RegCloseKey(hKey); + + USE_IYUV = false; + USE_YV12 = false; + USE_YUY2 = false; + USE_YVYU = false; + USE_UYVY = false; + USE_RGB32 = false; + USE_RGB24 = false; + USE_RG555 = false; + USE_RG565 = false; + + switch ( PPSettings.nForceColorspace ) + { + case FORCE_NONE: + USE_IYUV = true; + USE_YV12 = true; + USE_YUY2 = true; + USE_YVYU = true; + USE_UYVY = true; + USE_RGB32 = true; + USE_RGB24 = true; + USE_RG555 = true; + USE_RG565 = true; + break; + case FORCE_YV12: + USE_IYUV = true; + USE_YV12 = true; + break; + case FORCE_YUY2: + USE_YUY2 = true; + break; + case FORCE_RGB24: + USE_RGB24 = true; + break; + case FORCE_RGB32: + USE_RGB32 = true; + break; + } } @@ -247,7 +310,7 @@ if (m_create.handle != NULL) { - m_xvid_decore(m_create.handle, XVID_DEC_DESTROY, 0, 0); + xvid_decore_func(m_create.handle, XVID_DEC_DESTROY, 0, 0); m_create.handle = NULL; } @@ -277,11 +340,17 @@ { VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtIn->Format(); hdr = &vih->bmiHeader; + /* PAR (x:y) is (1/ppm_X):(1/ppm_Y) where ppm is pixels-per-meter + which is equal to ppm_Y:ppm_X */ + ar_x = vih->bmiHeader.biYPelsPerMeter*hdr->biWidth; + ar_y = vih->bmiHeader.biXPelsPerMeter*hdr->biHeight; } else if (*mtIn->FormatType() == FORMAT_VideoInfo2) { VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 *) mtIn->Format(); hdr = &vih2->bmiHeader; + ar_x = vih2->dwPictAspectRatioX; + ar_y = vih2->dwPictAspectRatioY; } else { @@ -318,18 +387,9 @@ } -#define USE_IYUV -#define USE_YV12 -#define USE_YUY2 -#define USE_YVYU -#define USE_UYVY -#define USE_RGB32 -#define USE_RGB24 -#define USE_RG555 -#define USE_RG565 - /* get list of supported output colorspaces */ + HRESULT CXvidDecoder::GetMediaType(int iPosition, CMediaType *mtOut) { DPRINTF("GetMediaType"); @@ -339,7 +399,7 @@ return E_UNEXPECTED; } - VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER)); + VIDEOINFOHEADER2 * vih = (VIDEOINFOHEADER2 *) mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER2)); if (vih == NULL) { return E_OUTOFMEMORY; @@ -358,77 +418,95 @@ switch(iPosition) { - case 0 : -#ifdef USE_IYUV - vih->bmiHeader.biCompression = MEDIASUBTYPE_IYUV.Data1; - vih->bmiHeader.biBitCount = 12; - mtOut->SetSubtype(&MEDIASUBTYPE_IYUV); - break; -#endif - case 1 : -#ifdef USE_YV12 - vih->bmiHeader.biCompression = MEDIASUBTYPE_YV12.Data1; - vih->bmiHeader.biBitCount = 12; - mtOut->SetSubtype(&MEDIASUBTYPE_YV12); - break; -#endif - case 2: -#ifdef USE_YUY2 + + case 0: +if ( USE_YUY2 ) +{ vih->bmiHeader.biCompression = MEDIASUBTYPE_YUY2.Data1; vih->bmiHeader.biBitCount = 16; mtOut->SetSubtype(&MEDIASUBTYPE_YUY2); break; -#endif - case 3 : -#ifdef USE_YVYU +} + case 1 : +if ( USE_YVYU ) +{ vih->bmiHeader.biCompression = MEDIASUBTYPE_YVYU.Data1; vih->bmiHeader.biBitCount = 16; mtOut->SetSubtype(&MEDIASUBTYPE_YVYU); break; -#endif - case 4 : -#ifdef USE_UYVY +} + case 2 : +if ( USE_UYVY ) +{ vih->bmiHeader.biCompression = MEDIASUBTYPE_UYVY.Data1; vih->bmiHeader.biBitCount = 16; mtOut->SetSubtype(&MEDIASUBTYPE_UYVY); break; -#endif +} + case 3 : + if ( USE_IYUV ) +{ + vih->bmiHeader.biCompression = CLSID_MEDIASUBTYPE_IYUV.Data1; + vih->bmiHeader.biBitCount = 12; + mtOut->SetSubtype(&CLSID_MEDIASUBTYPE_IYUV); + break; +} + case 4 : +if ( USE_YV12 ) +{ + vih->bmiHeader.biCompression = MEDIASUBTYPE_YV12.Data1; + vih->bmiHeader.biBitCount = 12; + mtOut->SetSubtype(&MEDIASUBTYPE_YV12); + break; +} case 5 : -#ifdef USE_RGB32 +if ( USE_RGB32 ) +{ vih->bmiHeader.biCompression = BI_RGB; vih->bmiHeader.biBitCount = 32; mtOut->SetSubtype(&MEDIASUBTYPE_RGB32); break; -#endif +} case 6 : -#ifdef USE_RGB24 +if ( USE_RGB24 ) +{ vih->bmiHeader.biCompression = BI_RGB; vih->bmiHeader.biBitCount = 24; mtOut->SetSubtype(&MEDIASUBTYPE_RGB24); break; -#endif +} case 7 : -#ifdef USE_RG555 +if ( USE_RG555 ) +{ vih->bmiHeader.biCompression = BI_RGB; vih->bmiHeader.biBitCount = 16; mtOut->SetSubtype(&MEDIASUBTYPE_RGB555); break; -#endif +} case 8 : -#ifdef USE_RG565 +if ( USE_RG565 ) +{ vih->bmiHeader.biCompression = BI_RGB; vih->bmiHeader.biBitCount = 16; mtOut->SetSubtype(&MEDIASUBTYPE_RGB565); break; -#endif +} default : return VFW_S_NO_MORE_ITEMS; } vih->bmiHeader.biSizeImage = GetBitmapSize(&vih->bmiHeader); + if (ar_x != 0 && ar_y != 0) { + vih->dwPictAspectRatioX = ar_x; + vih->dwPictAspectRatioY = ar_y; + } else { // just to be safe + vih->dwPictAspectRatioX = m_create.width; + vih->dwPictAspectRatioY = m_create.height; + } + mtOut->SetType(&MEDIATYPE_Video); - mtOut->SetFormatType(&FORMAT_VideoInfo); + mtOut->SetFormatType(&FORMAT_VideoInfo2); mtOut->SetTemporalCompression(FALSE); mtOut->SetSampleSize(vih->bmiHeader.biSizeImage); @@ -440,8 +518,6 @@ HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format) { - int rgb_flip; - if (formattype == FORMAT_VideoInfo) { VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format; @@ -459,31 +535,36 @@ return S_FALSE; } - if (subtype == MEDIASUBTYPE_IYUV) + if (subtype == CLSID_MEDIASUBTYPE_IYUV) { DPRINTF("IYUV"); + rgb_flip = 0; m_frame.output.csp = XVID_CSP_I420; m_frame.output.stride[0] = (m_frame.output.stride[0] * 2) / 3; /* planar format fix */ } else if (subtype == MEDIASUBTYPE_YV12) { DPRINTF("YV12"); + rgb_flip = 0; m_frame.output.csp = XVID_CSP_YV12; m_frame.output.stride[0] = (m_frame.output.stride[0] * 2) / 3; /* planar format fix */ } else if (subtype == MEDIASUBTYPE_YUY2) { DPRINTF("YUY2"); + rgb_flip = 0; m_frame.output.csp = XVID_CSP_YUY2; } else if (subtype == MEDIASUBTYPE_YVYU) { DPRINTF("YVYU"); + rgb_flip = 0; m_frame.output.csp = XVID_CSP_YVYU; } else if (subtype == MEDIASUBTYPE_UYVY) { DPRINTF("UYVY"); + rgb_flip = 0; m_frame.output.csp = XVID_CSP_UYVY; } else if (subtype == MEDIASUBTYPE_RGB32) @@ -590,7 +671,7 @@ if (m_create.handle == NULL) { - if (m_xvid_decore(0, XVID_DEC_CREATE, &m_create, 0) < 0) + if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) { DPRINTF("*** XVID_DEC_CREATE error"); return S_FALSE; @@ -625,14 +706,31 @@ } m_frame.general = XVID_LOWDELAY; + if (pIn->IsDiscontinuity() == S_OK) m_frame.general = XVID_DISCONTINUITY; + if (PPSettings.nDeblock_Y) + m_frame.general |= XVID_DEBLOCKY; + + if (PPSettings.nDeblock_UV) + m_frame.general |= XVID_DEBLOCKUV; +/* + if (PPSettings.nDering) + m_frame.general |= XVID_DERING; +*/ + if (PPSettings.nFilmEffect) + m_frame.general |= XVID_FILMEFFECT; + + m_frame.output.csp &= ~XVID_CSP_VFLIP; + m_frame.output.csp |= rgb_flip^(PPSettings.nFlipVideo ? XVID_CSP_VFLIP : 0); + repeat : if (pIn->IsPreroll() != S_OK) { - length = m_xvid_decore(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats); + length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats); + if (length < 0) { DPRINTF("*** XVID_DEC_DECODE"); @@ -640,11 +738,19 @@ } } else - { + { /* Preroll frame - won't be displayed */ int tmp = m_frame.output.csp; + int tmp_gen = m_frame.general; + m_frame.output.csp = XVID_CSP_NULL; - length = m_xvid_decore(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats); + /* Disable postprocessing to speed-up seeking */ + m_frame.general &= ~XVID_DEBLOCKY; + m_frame.general &= ~XVID_DEBLOCKUV; +/* m_frame.general &= ~XVID_DERING; */ + m_frame.general &= ~XVID_FILMEFFECT; + + length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats); if (length < 0) { DPRINTF("*** XVID_DEC_DECODE"); @@ -652,8 +758,15 @@ } m_frame.output.csp = tmp; + m_frame.general = tmp_gen; + } + + if (stats.type == XVID_TYPE_NOTHING) { + DPRINTF("B-Frame decoder lag"); + return S_FALSE; } + if (stats.type == XVID_TYPE_VOL) { if (stats.data.vol.width != m_create.width || @@ -663,11 +776,18 @@ return S_FALSE; } + pOut->SetDiscontinuity(TRUE); + pOut->SetSyncPoint(TRUE); + m_frame.bitstream = (BYTE*)m_frame.bitstream + length; m_frame.length -= length; goto repeat; } + if (pIn->IsPreroll() == S_OK) { + return S_FALSE; + } + return S_OK; }