mfxStatus QSV_Encoder_Internal::Drain() { mfxStatus sts = MFX_ERR_NONE; // // Drain the buffered encoded frames // while (MFX_ERR_NONE <= sts) { int nTaskIdx = GetFreeTaskIndex(m_pTaskPool, m_nTaskPool); if (MFX_ERR_NOT_FOUND == nTaskIdx) { // No more free tasks, need to sync sts = m_session.SyncOperation(m_pTaskPool[m_nFirstSyncTask].syncp, 60000); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); m_pTaskPool[m_nFirstSyncTask].syncp = NULL; m_nFirstSyncTask = (m_nFirstSyncTask + 1) % m_nTaskPool; } else { for (;;) { // Encode a frame asychronously (returns immediately) sts = m_pmfxENC->EncodeFrameAsync(NULL, NULL, &m_pTaskPool[nTaskIdx].mfxBS, &m_pTaskPool[nTaskIdx].syncp); if (MFX_ERR_NONE < sts && !m_pTaskPool[nTaskIdx].syncp) { // Repeat the call if warning and no output if (MFX_WRN_DEVICE_BUSY == sts) MSDK_SLEEP(1); // Wait if device is busy, then repeat the same call } else if (MFX_ERR_NONE < sts && m_pTaskPool[nTaskIdx].syncp) { sts = MFX_ERR_NONE; // Ignore warnings if output is available break; } else break; } } } // MFX_ERR_MORE_DATA indicates that there are no more buffered frames, exit in case of other errors MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); // // Sync all remaining tasks in task pool // while (m_pTaskPool[m_nFirstSyncTask].syncp) { sts = m_session.SyncOperation(m_pTaskPool[m_nFirstSyncTask].syncp, 60000); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); m_pTaskPool[m_nFirstSyncTask].syncp = NULL; m_nFirstSyncTask = (m_nFirstSyncTask + 1) % m_nTaskPool; } return sts; }
mfxStatus IntelDecoder::FlushDecoderAndRender() { mfxStatus sts = MFX_ERR_NONE; mfxGetTime(&tStart); // // Stage 2: Retrieve the buffered decoded frames // while (MFX_ERR_NONE <= sts || MFX_ERR_MORE_SURFACE == sts) { if (MFX_WRN_DEVICE_BUSY == sts) MSDK_SLEEP(1); // Wait if device is busy, then repeat the same call to DecodeFrameAsync nIndex = GetFreeSurfaceIndex(pmfxSurfaces, numSurfaces); // Find free frame surface MSDK_CHECK_ERROR(MFX_ERR_NOT_FOUND, nIndex, MFX_ERR_MEMORY_ALLOC); // Decode a frame asychronously (returns immediately) sts = mfxDEC->DecodeFrameAsync(NULL, pmfxSurfaces[nIndex], &pmfxOutSurface, &syncp); // Ignore warnings if output is available, // if no output and no action required just repeat the DecodeFrameAsync call if (MFX_ERR_NONE < sts && syncp) sts = MFX_ERR_NONE; if (MFX_ERR_NONE == sts) sts = pSession->SyncOperation(syncp, 60000); // Synchronize. Waits until decoded frame is ready if (MFX_ERR_NONE == sts) { ++nFrame; if (impl_type == MFX_IMPL_SOFTWARE) { outMan.Render(pmfxOutSurface); } else { // Surface locking required when read/write D3D surfaces sts = pMfxAllocator->Lock(pMfxAllocator->pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data)); MSDK_BREAK_ON_ERROR(sts); outMan.Render(pmfxOutSurface); sts = pMfxAllocator->Unlock(pMfxAllocator->pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data)); } printf("Frame number: %d\r", nFrame); fflush(stdout); } } // MFX_ERR_MORE_DATA indicates that all buffers has been fetched, exit in case of other errors MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); mfxGetTime(&tEnd); elapsed += TimeDiffMsec(tEnd, tStart) / 1000; double fps = ((double)nFrame / elapsed); printf("\nExecution time: %3.2f s (%3.2f fps)\n", elapsed, fps); return sts; }
mfxStatus IntelDecoder::RunDecodeAndRender() { mfxStatus sts = MFX_ERR_NONE; // =============================================================== // Start decoding the frames from the stream // mfxGetTime(&tStart); pmfxOutSurface = NULL; pmfxOutSurface_sw = NULL; nIndex = 0; nIndex2 = 0; nFrame = 0; // // Stage 1: Main decoding loop // while (MFX_ERR_NONE <= sts || MFX_ERR_MORE_DATA == sts || MFX_ERR_MORE_SURFACE == sts) { if (MFX_WRN_DEVICE_BUSY == sts) MSDK_SLEEP(1); // Wait if device is busy, then repeat the same call to DecodeFrameAsync if (MFX_ERR_MORE_DATA == sts) { sts = ReadBitStreamData(&mfxBS, fSource); // Read more data into input bit stream MSDK_BREAK_ON_ERROR(sts); } if (MFX_ERR_MORE_SURFACE == sts || MFX_ERR_NONE == sts) { nIndex = GetFreeSurfaceIndex(pmfxSurfaces, numSurfaces); // Find free frame surface MSDK_CHECK_ERROR(MFX_ERR_NOT_FOUND, nIndex, MFX_ERR_MEMORY_ALLOC); } // Decode a frame asychronously (returns immediately) // - If input bitstream contains multiple frames DecodeFrameAsync will start decoding multiple frames, and remove them from bitstream sts = mfxDEC->DecodeFrameAsync(&mfxBS, pmfxSurfaces[nIndex], &pmfxOutSurface, &syncp); // Ignore warnings if output is available, // if no output and no action required just repeat the DecodeFrameAsync call if (MFX_ERR_NONE < sts && syncp) sts = MFX_ERR_NONE; if (MFX_ERR_NONE == sts) sts = pSession->SyncOperation(syncp, 60000); // Synchronize. Wait until decoded frame is ready if (MFX_ERR_NONE == sts) { ++nFrame; if (impl_type == MFX_IMPL_SOFTWARE) { outMan.Render(pmfxOutSurface); } else { // Surface locking required when read/write video surfaces sts = pMfxAllocator->Lock(pMfxAllocator->pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data)); MSDK_BREAK_ON_ERROR(sts); outMan.Render(pmfxOutSurface); sts = pMfxAllocator->Unlock(pMfxAllocator->pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data)); MSDK_BREAK_ON_ERROR(sts); } printf("Frame number: %d\r", nFrame); fflush(stdout); } } // MFX_ERR_MORE_DATA means that file has ended, need to go to buffering loop, exit in case of other errors MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); mfxGetTime(&tEnd); elapsed = TimeDiffMsec(tEnd, tStart) / 1000; double fps = ((double)nFrame / elapsed); printf("\nExecution time: %3.2f s (%3.2f fps)\n", elapsed, fps); return sts; }
mfxStatus QSV_Encoder_Internal::Encode(uint64_t ts, uint8_t *pDataY, uint8_t *pDataUV, uint32_t strideY, uint32_t strideUV, mfxBitstream **pBS) { mfxStatus sts = MFX_ERR_NONE; *pBS = NULL; int nSurfIdx = GetFreeSurfaceIndex(m_pmfxSurfaces, m_nSurfNum); // Find free input frame surface int nTaskIdx = GetFreeTaskIndex(m_pTaskPool, m_nTaskPool); if (MFX_ERR_NOT_FOUND == nTaskIdx || MFX_ERR_NOT_FOUND == nSurfIdx) { // No more free tasks or surfaces, need to sync sts = m_session.SyncOperation(m_pTaskPool[m_nFirstSyncTask].syncp, 60000); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); mfxU8 *pTemp = m_outBitstream.Data; memcpy(&m_outBitstream, &m_pTaskPool[m_nFirstSyncTask].mfxBS, sizeof(mfxBitstream)); m_pTaskPool[m_nFirstSyncTask].mfxBS.Data = pTemp; m_pTaskPool[m_nFirstSyncTask].mfxBS.DataLength = 0; m_pTaskPool[m_nFirstSyncTask].mfxBS.DataOffset = 0; m_pTaskPool[m_nFirstSyncTask].syncp = NULL; m_nFirstSyncTask = (m_nFirstSyncTask + 1) % m_nTaskPool; *pBS = &m_outBitstream; if (nTaskIdx == MFX_ERR_NOT_FOUND) nTaskIdx = GetFreeTaskIndex(m_pTaskPool, m_nTaskPool); if (nSurfIdx == MFX_ERR_NOT_FOUND) nSurfIdx = GetFreeSurfaceIndex(m_pmfxSurfaces, m_nSurfNum); } mfxFrameSurface1 *pSurface = m_pmfxSurfaces[nSurfIdx]; sts = m_mfxAllocator.Lock(m_mfxAllocator.pthis, pSurface->Data.MemId, &(pSurface->Data)); sts = LoadNV12(pSurface, pDataY, pDataUV, strideY, strideUV); pSurface->Data.TimeStamp = ts; sts = m_mfxAllocator.Unlock(m_mfxAllocator.pthis, pSurface->Data.MemId, &(pSurface->Data)); MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); for (;;) { // Encode a frame asychronously (returns immediately) sts = m_pmfxENC->EncodeFrameAsync(NULL, pSurface, &m_pTaskPool[nTaskIdx].mfxBS, &m_pTaskPool[nTaskIdx].syncp); if (MFX_ERR_NONE < sts && !m_pTaskPool[nTaskIdx].syncp) { // Repeat the call if warning and no output if (MFX_WRN_DEVICE_BUSY == sts) MSDK_SLEEP(1); // Wait if device is busy, then repeat the same call } else if (MFX_ERR_NONE < sts && m_pTaskPool[nTaskIdx].syncp) { sts = MFX_ERR_NONE; // Ignore warnings if output is available break; } else if (MFX_ERR_NOT_ENOUGH_BUFFER == sts) { // Allocate more bitstream buffer memory here if needed... break; } else break; } return sts; }