--- trunk/xvidcore/dshow/src/CXvidDecoder.cpp 2004/07/25 11:13:16 1521 +++ branches/release-1_2-branch/xvidcore/dshow/src/CXvidDecoder.cpp 2009/05/28 15:52:34 1869 @@ -19,7 +19,7 @@ * 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.11 2004-07-25 11:13:16 suxen_drol Exp $ + * $Id: CXvidDecoder.cpp,v 1.16.4.1 2009-05-28 15:52:34 Isibaar Exp $ * ****************************************************************************/ @@ -82,6 +82,7 @@ { &MEDIATYPE_Video, &CLSID_DX50 }, { &MEDIATYPE_Video, &CLSID_DX50_UC }, { &MEDIATYPE_Video, &CLSID_MP4V }, + { &MEDIATYPE_Video, &CLSID_MP4V_UC }, }; const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] = @@ -204,10 +205,25 @@ #define XVID_DLL_NAME "xvidcore.dll" CXvidDecoder::CXvidDecoder(LPUNKNOWN punk, HRESULT *phr) : - CVideoTransformFilter(NAME("CXvidDecoder"), punk, CLSID_XVID) + CVideoTransformFilter(NAME("CXvidDecoder"), punk, CLSID_XVID), m_hdll (NULL) { DPRINTF("Constructor"); + xvid_decore_func = NULL; // Hmm, some strange errors appearing if I try to initialize... + xvid_global_func = NULL; // ...this in constructor's init-list. So, they assigned here. + + LoadRegistryInfo(); + + *phr = OpenLib(); +} + +HRESULT CXvidDecoder::OpenLib() +{ + DPRINTF("OpenLib"); + + if (m_hdll != NULL) + return E_UNEXPECTED; // Seems, that library already opened. + xvid_gbl_init_t init; memset(&init, 0, sizeof(init)); init.version = XVID_VERSION; @@ -216,25 +232,34 @@ if (m_hdll == NULL) { DPRINTF("dll load failed"); MessageBox(0, XVID_DLL_NAME " not found","Error", MB_TOPMOST); - return; + return E_FAIL; } xvid_global_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_global"); if (xvid_global_func == NULL) { + FreeLibrary(m_hdll); + m_hdll = NULL; MessageBox(0, "xvid_global() not found", "Error", MB_TOPMOST); - return; + return E_FAIL; } xvid_decore_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_decore"); if (xvid_decore_func == NULL) { + xvid_global_func = NULL; + FreeLibrary(m_hdll); + m_hdll = NULL; MessageBox(0, "xvid_decore() not found", "Error", MB_TOPMOST); - return; + return E_FAIL; } if (xvid_global_func(0, XVID_GBL_INIT, &init, NULL) < 0) { + xvid_global_func = NULL; + xvid_decore_func = NULL; + FreeLibrary(m_hdll); + m_hdll = NULL; MessageBox(0, "xvid_global() failed", "Error", MB_TOPMOST); - return; + return E_FAIL; } memset(&m_create, 0, sizeof(m_create)); @@ -244,8 +269,6 @@ memset(&m_frame, 0, sizeof(m_frame)); m_frame.version = XVID_VERSION; - LoadRegistryInfo(); - USE_IYUV = false; USE_YV12 = false; USE_YUY2 = false; @@ -302,13 +325,16 @@ ar_y = 20; break; } + + return S_OK; } void CXvidDecoder::CloseLib() { - DPRINTF("Destructor"); + DPRINTF("CloseLib"); - if (m_create.handle != NULL) { + if ((m_create.handle != NULL) && (xvid_decore_func != NULL)) + { xvid_decore_func(m_create.handle, XVID_DEC_DESTROY, 0, 0); m_create.handle = NULL; } @@ -317,12 +343,15 @@ FreeLibrary(m_hdll); m_hdll = NULL; } + xvid_decore_func = NULL; + xvid_global_func = NULL; } /* destructor */ CXvidDecoder::~CXvidDecoder() { + DPRINTF("Destructor"); CloseLib(); } @@ -344,6 +373,14 @@ return VFW_E_TYPE_NOT_ACCEPTED; } + if (m_hdll == NULL) + { + HRESULT hr = OpenLib(); + + if (FAILED(hr) || (m_hdll == NULL)) // Paranoid checks. + return VFW_E_TYPE_NOT_ACCEPTED; + } + if (*mtIn->FormatType() == FORMAT_VideoInfo) { VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtIn->Format(); @@ -359,6 +396,49 @@ } DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y); } + else if (*mtIn->FormatType() == FORMAT_MPEG2Video) { + MPEG2VIDEOINFO * mpgvi = (MPEG2VIDEOINFO*)mtIn->Format(); + VIDEOINFOHEADER2 * vih2 = &mpgvi->hdr; + hdr = &vih2->bmiHeader; + if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1) { + ar_x = vih2->dwPictAspectRatioX; + ar_y = vih2->dwPictAspectRatioY; + } + DPRINTF("VIDEOINFOHEADER2 AR: %d:%d", ar_x, ar_y); + + /* haali media splitter reports VOL information in the format header */ + + if (mpgvi->cbSequenceHeader>0) { + + xvid_dec_stats_t stats; + memset(&stats, 0, sizeof(stats)); + stats.version = XVID_VERSION; + + if (m_create.handle == NULL) { + if (xvid_decore_func == NULL) + return E_FAIL; + if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) { + DPRINTF("*** XVID_DEC_CREATE error"); + return E_FAIL; + } + } + + m_frame.general = 0; + m_frame.bitstream = (void*)mpgvi->dwSequenceHeader; + m_frame.length = mpgvi->cbSequenceHeader; + m_frame.output.csp = XVID_CSP_NULL; + + int ret = 0; + if ((ret=xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats)) >= 0) { + /* honour video dimensions reported in VOL header */ + if (stats.type == XVID_TYPE_VOL) { + hdr->biWidth = stats.data.vol.width; + hdr->biHeight = stats.data.vol.height; + } + } + if (ret == XVID_ERR_MEMORY) return E_FAIL; + } + } else { DPRINTF("Error: Unknown FormatType"); @@ -376,7 +456,7 @@ switch(hdr->biCompression) { - + case FOURCC_mp4v: case FOURCC_MP4V: if (!(g_config.supported_4cc & SUPPORT_MP4V)) { CloseLib(); @@ -549,19 +629,24 @@ /* (internal function) change colorspace */ +#define CALC_BI_STRIDE(width,bitcount) ((((width * bitcount) + 31) & ~31) >> 3) HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format) { + DWORD biWidth; + if (formattype == FORMAT_VideoInfo) { VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format; - m_frame.output.stride[0] = (((vih->bmiHeader.biWidth * vih->bmiHeader.biBitCount) + 31) & ~31) >> 3; + biWidth = vih->bmiHeader.biWidth; + m_frame.output.stride[0] = CALC_BI_STRIDE(vih->bmiHeader.biWidth, vih->bmiHeader.biBitCount); rgb_flip = (vih->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP); } else if (formattype == FORMAT_VideoInfo2) { VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format; - m_frame.output.stride[0] = (((vih2->bmiHeader.biWidth * vih2->bmiHeader.biBitCount) + 31) & ~31) >> 3; + biWidth = vih2->bmiHeader.biWidth; + m_frame.output.stride[0] = CALC_BI_STRIDE(vih2->bmiHeader.biWidth, vih2->bmiHeader.biBitCount); rgb_flip = (vih2->bmiHeader.biHeight < 0 ? 0 : XVID_CSP_VFLIP); } else @@ -574,14 +659,14 @@ 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 */ + m_frame.output.stride[0] = CALC_BI_STRIDE(biWidth, 8); /* 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 */ + m_frame.output.stride[0] = CALC_BI_STRIDE(biWidth, 8); /* planar format fix */ } else if (subtype == MEDIASUBTYPE_YUY2) { @@ -705,10 +790,13 @@ if (m_create.handle == NULL) { + if (xvid_decore_func == NULL) + return E_FAIL; + if (xvid_decore_func(0, XVID_DEC_CREATE, &m_create, 0) < 0) { DPRINTF("*** XVID_DEC_CREATE error"); - return S_FALSE; + return E_FAIL; } } @@ -764,6 +852,9 @@ m_frame.output.csp &= ~XVID_CSP_VFLIP; m_frame.output.csp |= rgb_flip^(g_config.nFlipVideo ? XVID_CSP_VFLIP : 0); + // Paranoid check. + if (xvid_decore_func == NULL) + return E_FAIL; @@ -772,15 +863,18 @@ if (pIn->IsPreroll() != S_OK) { length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats); - - if (length < 0) + + if (length == XVID_ERR_MEMORY) + return E_FAIL; + else if (length < 0) { DPRINTF("*** XVID_DEC_DECODE"); return S_FALSE; } else if (g_config.aspect_ratio == 0 || g_config.aspect_ratio == 1 && forced_ar == false) { + + if (stats.type != XVID_TYPE_NOTHING) { /* dont attempt to set vmr aspect ratio if no frame was returned by decoder */ // inspired by minolta! works for VMR 7 + 9 - IMediaSample2 *pOut2 = NULL; AM_SAMPLE2_PROPERTIES outProp2; if (SUCCEEDED(pOut->QueryInterface(IID_IMediaSample2, (void **)&pOut2)) && @@ -799,6 +893,7 @@ } pOut2->Release(); } + } } } else @@ -811,11 +906,13 @@ /* 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_DERING;*/ m_frame.general &= ~XVID_FILMEFFECT; length = xvid_decore_func(m_create.handle, XVID_DEC_DECODE, &m_frame, &stats); - if (length < 0) + if (length == XVID_ERR_MEMORY) + return E_FAIL; + else if (length < 0) { DPRINTF("*** XVID_DEC_DECODE"); return S_FALSE; @@ -848,8 +945,8 @@ par_x = stats.data.vol.par_width; par_y = stats.data.vol.par_height; } else { - par_x = PARS[stats.data.vol.par][0]; - par_y = PARS[stats.data.vol.par][1]; + par_x = PARS[stats.data.vol.par-1][0]; + par_y = PARS[stats.data.vol.par-1][1]; } ar_x = par_x * stats.data.vol.width;