mfxStatus CDecodingPipeline::RunDecoding(UINT8* DecData, UINT32 DecLen) { mfxFrameSurface1* pOutSurface = NULL; mfxBitstream* pBitstream = &m_mfxBS; mfxStatus sts = MFX_ERR_NONE; bool bErrIncompatibleVideoParams = false; CTimeInterval<> decodeTimer(m_bIsCompleteFrame); bool bDirectSync = false; // set buffer pointer and lenght for storing decoded data m_pDecData = DecData; m_DecLen = DecLen; if (MFX_CODEC_CAPTURE == this->m_mfxVideoParams.mfx.CodecId) { pBitstream = 0; } do { if ((MFX_ERR_NONE == sts) || (MFX_ERR_MORE_SURFACE == sts)) { SyncFrameSurfaces(); if (m_bEnableVPP) { SyncVppFrameSurfaces(); } if (!m_pCurrentFreeSurface) { m_pCurrentFreeSurface = m_FreeSurfacesPool.GetSurface(); } if (m_bEnableVPP) { if (!m_pCurrentFreeVppSurface) { m_pCurrentFreeVppSurface = m_FreeVppSurfacesPool.GetSurface(); } } #ifndef __SYNC_WA if (!m_pCurrentFreeSurface || !m_pCurrentFreeVppSurface) { #else if (m_bEnableVPP) { if (!m_pCurrentFreeSurface || !m_pCurrentFreeVppSurface || (m_OutputSurfacesPool.GetSurfaceCount() == m_mfxVppVideoParams.AsyncDepth)) { #endif // we stuck with no free surface available, now we will sync the outputsurface sts = MFX_ERR_NONE; // we may still get decoded frame break; } } else { if (!m_pCurrentFreeSurface || (m_OutputSurfacesPool.GetSurfaceCount() == m_mfxVideoParams.AsyncDepth)) { // we stuck with no free surface available, now we will sync the outputsurface sts = MFX_ERR_NONE; // we may still get decoded frame break; } } if (!m_pCurrentFreeOutputSurface) { m_pCurrentFreeOutputSurface = GetFreeOutputSurface(); } if (!m_pCurrentFreeOutputSurface) { sts = MFX_ERR_NOT_FOUND; break; } if (m_bIsCompleteFrame) { m_pCurrentFreeSurface->submit = m_timer_overall.Sync(); } pOutSurface = NULL; do { sts = m_pmfxDEC->DecodeFrameAsync(pBitstream, &(m_pCurrentFreeSurface->frame), &pOutSurface, &(m_pCurrentFreeOutputSurface->syncp)); if (MFX_WRN_DEVICE_BUSY == sts) { Sleep(2); // avoid SyncOutputSurface() call in case of MFX_WRN_DEVICE_BUSY } } while (MFX_WRN_DEVICE_BUSY == sts); if (m_nFirstFrameAttempt < MAX_ATTEMPT && sts == MFX_ERR_MORE_DATA) { // first frame is not decoded yet, so force decoder to generate first output m_nFirstFrameAttempt++; pBitstream = 0; sts = MFX_ERR_MORE_SURFACE; VIDSDK_PRINT_ERR_MSG((_T(" **** FORCE DECODER for firts frame output ******* \n")), m_pLogWriter); continue; } if (bDirectSync == true) break; if (sts > MFX_ERR_NONE) { // ignoring warnings... if (m_pCurrentFreeOutputSurface->syncp) { MSDK_SELF_CHECK(pOutSurface); // output is available sts = MFX_ERR_NONE; } else { // output is not available sts = MFX_ERR_MORE_SURFACE; } } else if ((MFX_ERR_MORE_DATA == sts) && pBitstream) { if (m_bIsCompleteFrame && pBitstream->DataLength) { // In low_latency mode decoder have to process bitstream completely VIDSDK_PRINT_ERR_MSG((_T("DECODER Error: Incorrect decoder behavior in low latency mode (bitstream length is not equal to 0 after decoding)\n")), m_pLogWriter); sts = MFX_ERR_UNDEFINED_BEHAVIOR; continue; } } else if ((MFX_ERR_MORE_DATA == sts) && !pBitstream) { // that's it - we reached end of stream; now we need to render bufferred data... do { sts = SyncOutputSurface(MSDK_DEC_WAIT_INTERVAL); } while (MFX_ERR_NONE == sts); if (MFX_ERR_MORE_DATA == sts) { sts = MFX_ERR_NONE; } break; } else if (MFX_ERR_INCOMPATIBLE_VIDEO_PARAM == sts) { bErrIncompatibleVideoParams = true; // need to go to the buffering loop prior to reset procedure pBitstream = NULL; sts = MFX_ERR_NONE; continue; } } if ((MFX_ERR_NONE == sts) || (MFX_ERR_MORE_DATA == sts) || (MFX_ERR_MORE_SURFACE == sts)) { // if current free surface is locked we are moving it to the used surfaces array /*if (m_pCurrentFreeSurface->frame.Data.Locked)*/ { m_UsedSurfacesPool.AddSurface(m_pCurrentFreeSurface); m_pCurrentFreeSurface = NULL; } } // check if decoded frame is available now for post processing (color conversion) if (MFX_ERR_NONE == sts) { // decoded frame is available now // if VPP need not to be used, put decoder's output in OutputSurfacesPool directly, else pass it to VPP for conversion if (!m_bEnableVPP) { msdkFrameSurface* surface = FindUsedSurface(pOutSurface); msdk_atomic_inc16(&(surface->render_lock)); m_pCurrentFreeOutputSurface->surface = surface; m_OutputSurfacesPool.AddSurface(m_pCurrentFreeOutputSurface); m_pCurrentFreeOutputSurface = NULL; } else { do { if ((m_pCurrentFreeVppSurface->frame.Info.CropW == 0) || (m_pCurrentFreeVppSurface->frame.Info.CropH == 0)) { m_pCurrentFreeVppSurface->frame.Info.CropW = pOutSurface->Info.CropW; m_pCurrentFreeVppSurface->frame.Info.CropH = pOutSurface->Info.CropH; m_pCurrentFreeVppSurface->frame.Info.CropX = pOutSurface->Info.CropX; m_pCurrentFreeVppSurface->frame.Info.CropY = pOutSurface->Info.CropY; } if (pOutSurface->Info.PicStruct != m_pCurrentFreeVppSurface->frame.Info.PicStruct) { m_pCurrentFreeVppSurface->frame.Info.PicStruct = pOutSurface->Info.PicStruct; } if ((pOutSurface->Info.PicStruct == 0) && (m_pCurrentFreeVppSurface->frame.Info.PicStruct == 0)) { m_pCurrentFreeVppSurface->frame.Info.PicStruct = pOutSurface->Info.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; } sts = m_pmfxVPP->RunFrameVPPAsync(pOutSurface, &(m_pCurrentFreeVppSurface->frame), NULL, &(m_pCurrentFreeOutputSurface->syncp)); if (MFX_WRN_DEVICE_BUSY == sts) { MSDK_SLEEP(1); // just wait and then repeat the same call to RunFrameVPPAsync } } while (MFX_WRN_DEVICE_BUSY == sts); if (MFX_ERR_NONE != sts) { break; } m_UsedVppSurfacesPool.AddSurface(m_pCurrentFreeVppSurface); msdk_atomic_inc16(&(m_pCurrentFreeVppSurface->render_lock)); m_pCurrentFreeOutputSurface->surface = m_pCurrentFreeVppSurface; m_OutputSurfacesPool.AddSurface(m_pCurrentFreeOutputSurface); m_pCurrentFreeOutputSurface = NULL; m_pCurrentFreeVppSurface = NULL; } } } while (MFX_ERR_MORE_SURFACE == sts); //while processing bDirectSync = false; if (sts == MFX_ERR_NONE) { // we got final output frame after color conversion // sync output surface and copy the frame into output buffer //memcpy_s(DecData, DecLen, m_pCurrentFreeOutputSurface->surface->frame.Data., 0); sts = SyncOutputSurface(MSDK_DEC_WAIT_INTERVAL); if (MFX_ERR_MORE_DATA == sts) { VIDSDK_PRINT_ERR_MSG((_T("fatal: failed to find output surface, that's a bug!\n")), m_pLogWriter); sts = MFX_ERR_UNKNOWN; } if (m_nFirstFrameAttempt < MAX_ATTEMPT && sts == MFX_ERR_NONE) m_nFirstFrameAttempt = MAX_ATTEMPT; } // exit in case of other errors VIDSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts, m_pLogWriter); // if we exited main decoding loop with ERR_INCOMPATIBLE_PARAM we need to send this status to caller if (bErrIncompatibleVideoParams) { sts = MFX_ERR_INCOMPATIBLE_VIDEO_PARAM; } return sts; // ERR_NONE or ERR_INCOMPATIBLE_VIDEO_PARAM }