diff options
Diffstat (limited to 'tinyDAV/src/codecs/h264/tdav_codec_h264_intel.cxx')
-rwxr-xr-x | tinyDAV/src/codecs/h264/tdav_codec_h264_intel.cxx | 3383 |
1 files changed, 1593 insertions, 1790 deletions
diff --git a/tinyDAV/src/codecs/h264/tdav_codec_h264_intel.cxx b/tinyDAV/src/codecs/h264/tdav_codec_h264_intel.cxx index 49f9e1c..7ef6b2c 100755 --- a/tinyDAV/src/codecs/h264/tdav_codec_h264_intel.cxx +++ b/tinyDAV/src/codecs/h264/tdav_codec_h264_intel.cxx @@ -76,9 +76,9 @@ static mfxIMPL __IntelDefaultImpl = MFX_IMPL_AUTO_ANY #if INTEL_DX11_D3D -| MFX_IMPL_VIA_D3D11 + | MFX_IMPL_VIA_D3D11 #endif -; + ; static mfxVersion __IntelDefaultVer = { 0, 1 }; // TODO: Test against FFmpeg, CUDA, OpenH264 and Microsoft implementations @@ -87,40 +87,39 @@ static mfxVersion __IntelDefaultVer = { 0, 1 }; class IntelCodecEncoder; class IntelCodecDecoder; -typedef struct tdav_codec_h264_intel_s -{ - TDAV_DECLARE_CODEC_H264_COMMON; +typedef struct tdav_codec_h264_intel_s { + TDAV_DECLARE_CODEC_H264_COMMON; - MFXVideoSession* mfxSession; + MFXVideoSession* mfxSession; - // DX11_D3D + // DX11_D3D #if INTEL_DX11_D3D - mfxFrameAllocResponse D3D11SavedAllocResponses[2/*Encode=0, Decode=1*/]; - mfxFrameAllocator D3D11Allocator; - - CComPtr<ID3D11Device> pD3D11Device; - CComPtr<ID3D11DeviceContext> pD3D11Ctx; - CComPtr<IDXGIAdapter>pAdapter; - CComPtr<IDXGIFactory1> pDXGIFactory; - CComPtr<IDXGIAdapter> hAdapter; + mfxFrameAllocResponse D3D11SavedAllocResponses[2/*Encode=0, Decode=1*/]; + mfxFrameAllocator D3D11Allocator; + + CComPtr<ID3D11Device> pD3D11Device; + CComPtr<ID3D11DeviceContext> pD3D11Ctx; + CComPtr<IDXGIAdapter>pAdapter; + CComPtr<IDXGIFactory1> pDXGIFactory; + CComPtr<IDXGIAdapter> hAdapter; #endif - // Encoder - struct{ - IntelCodecEncoder *pInst; - int64_t frame_count; - tsk_bool_t force_idr; - int rotation; - int neg_width; - int neg_height; - int neg_fps; - int max_bitrate_bps; - } encoder; - - // decoder - struct{ - IntelCodecDecoder *pInst; - } decoder; + // Encoder + struct { + IntelCodecEncoder *pInst; + int64_t frame_count; + tsk_bool_t force_idr; + int rotation; + int neg_width; + int neg_height; + int neg_fps; + int max_bitrate_bps; + } encoder; + + // decoder + struct { + IntelCodecDecoder *pInst; + } decoder; } tdav_codec_h264_intel_t; @@ -140,19 +139,19 @@ static int tdav_codec_h264_intel_close_decoder(tdav_codec_h264_intel_t* self); #define D3D11_WILL_WRITE 0x2000 typedef struct { - mfxMemId memId; - mfxMemId memIdStage; - mfxU16 rw; + mfxMemId memId; + mfxMemId memIdStage; + mfxU16 rw; } CustomMemId; const struct { - mfxIMPL impl; // actual implementation - mfxU32 adapterID; // device adapter number + mfxIMPL impl; // actual implementation + mfxU32 adapterID; // device adapter number } implTypes[] = { - { MFX_IMPL_HARDWARE, 0 }, - { MFX_IMPL_HARDWARE2, 1 }, - { MFX_IMPL_HARDWARE3, 2 }, - { MFX_IMPL_HARDWARE4, 3 } + { MFX_IMPL_HARDWARE, 0 }, + { MFX_IMPL_HARDWARE2, 1 }, + { MFX_IMPL_HARDWARE3, 2 }, + { MFX_IMPL_HARDWARE4, 3 } }; static mfxStatus D3D11_CreateHWDevice(mfxHDL pthis, mfxSession session, mfxHDL* deviceHandle, HWND hWnd); @@ -174,245 +173,225 @@ static mfxStatus D3D11_SimpleFree(mfxHDL pthis, mfxFrameAllocResponse *response) class IntelCodec { protected: - IntelCodec(MFXVideoSession* pSession) - : m_bOpened(false) - , m_pSession(pSession) - , n_nNumSurfaces(0) - , m_nSurfaceWidth(0) - , m_nSurfaceHeight(0) - , m_nSurfaceBitsPerPixel(0) - , m_nSurfaceSize(0) - , m_pSurfaceBuffers(NULL) - , m_ppSurfacePtrs(NULL) - { - memset(&m_sBitstream, 0, sizeof(m_sBitstream)); - memset(&m_sParamReq, 0, sizeof(m_sParamReq)); - memset(&m_sParamSel, 0, sizeof(m_sParamSel)); - memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest)); - } + IntelCodec(MFXVideoSession* pSession) + : m_bOpened(false) + , m_pSession(pSession) + , n_nNumSurfaces(0) + , m_nSurfaceWidth(0) + , m_nSurfaceHeight(0) + , m_nSurfaceBitsPerPixel(0) + , m_nSurfaceSize(0) + , m_pSurfaceBuffers(NULL) + , m_ppSurfacePtrs(NULL) { + memset(&m_sBitstream, 0, sizeof(m_sBitstream)); + memset(&m_sParamReq, 0, sizeof(m_sParamReq)); + memset(&m_sParamSel, 0, sizeof(m_sParamSel)); + memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest)); + } public: - virtual ~IntelCodec() - { - Close(); - } - virtual mfxStatus Open(struct tdav_codec_h264_intel_s* pWrappedCodec) = 0; + virtual ~IntelCodec() { + Close(); + } + virtual mfxStatus Open(struct tdav_codec_h264_intel_s* pWrappedCodec) = 0; - virtual mfxStatus Close() - { - DeAllocSurfaces(); - DeAllocateBitstream(); + virtual mfxStatus Close() { + DeAllocSurfaces(); + DeAllocateBitstream(); - memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest)); + memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest)); - m_bOpened = false; + m_bOpened = false; - return MFX_ERR_NONE; - } + return MFX_ERR_NONE; + } protected: - int GetFreeSurfaceIndex() - { - if (m_ppSurfacePtrs) - { - for (mfxU16 i = 0; i < n_nNumSurfaces; i++) - { - if (0 == m_ppSurfacePtrs[i]->Data.Locked) - { - return i; - } - } - } - return MFX_ERR_NOT_FOUND; - } - - mfxStatus ReadPlaneData(mfxU16 w, mfxU16 h, mfxU8 *buf, mfxU8 *ptr, mfxU16 pitch, mfxU16 offset, const mfxU8* &src) - { - for (mfxU16 i = 0; i < h; i++) - { - memcpy(buf, src, w); - src += w; - - for (mfxU16 j = 0; j < w; j++) - ptr[i * pitch + j * 2 + offset] = buf[j]; - } - return MFX_ERR_NONE; - } - - mfxStatus LoadRawFrame(int nSurfaceIndex, const mfxU8* src) - { - mfxFrameSurface1* pSurface = (m_ppSurfacePtrs && nSurfaceIndex >= 0 && nSurfaceIndex < n_nNumSurfaces) ? m_ppSurfacePtrs[nSurfaceIndex] : NULL; - if (!pSurface) - { - INTEL_DEBUG_ERROR("Failed to find surface at index=%d", nSurfaceIndex); - return MFX_ERR_NOT_FOUND; - } - - mfxStatus sts = MFX_ERR_NONE; - mfxU16 w, h, i, pitch; - mfxU8 *ptr; - mfxFrameInfo* pInfo = &pSurface->Info; - mfxFrameData* pData = &pSurface->Data; - - if (pInfo->CropH > 0 && pInfo->CropW > 0) { - w = pInfo->CropW; - h = pInfo->CropH; - } - else { - w = pInfo->Width; - h = pInfo->Height; - } - - pitch = pData->Pitch; - ptr = pData->Y + pInfo->CropX + pInfo->CropY * pData->Pitch; - - // read luminance plane - for (i = 0; i < h; i++) - { - memcpy(ptr + i * pitch, src, w); - src += w; - } - - mfxU8 buf[2048]; // maximum supported chroma width for nv12 - w /= 2; - h /= 2; - ptr = pData->UV + pInfo->CropX + (pInfo->CropY / 2) * pitch; - if (w > 2048) - return MFX_ERR_UNSUPPORTED; - - // load U - sts = ReadPlaneData(w, h, buf, ptr, pitch, 0, src); - if (MFX_ERR_NONE != sts) return sts; - // load V - sts = ReadPlaneData(w, h, buf, ptr, pitch, 1, src); - if (MFX_ERR_NONE != sts) return sts; - - return MFX_ERR_NONE; - } - - virtual mfxStatus AllocSurfaces(mfxU16 nNumSurfaces, mfxU16 nSurfaceWidth, mfxU16 nSurfaceHeight, const mfxFrameInfo* pcFrameInfo) - { - mfxStatus status = MFX_ERR_UNKNOWN; - - INTEL_DEBUG_INFO("Alloc surfaces: num=%u, width=%u, height=%u", nNumSurfaces, nSurfaceWidth, nSurfaceHeight); - - DeAllocSurfaces(); - - n_nNumSurfaces = nNumSurfaces; - m_nSurfaceWidth = (mfxU16)INTEL_ALIGN32(nSurfaceWidth); - m_nSurfaceHeight = (mfxU16)INTEL_ALIGN32(nSurfaceHeight); - m_nSurfaceBitsPerPixel = 12; // NV12 format is a 12 bits per pixel format - m_nSurfaceSize = m_nSurfaceWidth * m_nSurfaceHeight * m_nSurfaceBitsPerPixel / 8; + int GetFreeSurfaceIndex() { + if (m_ppSurfacePtrs) { + for (mfxU16 i = 0; i < n_nNumSurfaces; i++) { + if (0 == m_ppSurfacePtrs[i]->Data.Locked) { + return i; + } + } + } + return MFX_ERR_NOT_FOUND; + } + + mfxStatus ReadPlaneData(mfxU16 w, mfxU16 h, mfxU8 *buf, mfxU8 *ptr, mfxU16 pitch, mfxU16 offset, const mfxU8* &src) { + for (mfxU16 i = 0; i < h; i++) { + memcpy(buf, src, w); + src += w; + + for (mfxU16 j = 0; j < w; j++) { + ptr[i * pitch + j * 2 + offset] = buf[j]; + } + } + return MFX_ERR_NONE; + } + + mfxStatus LoadRawFrame(int nSurfaceIndex, const mfxU8* src) { + mfxFrameSurface1* pSurface = (m_ppSurfacePtrs && nSurfaceIndex >= 0 && nSurfaceIndex < n_nNumSurfaces) ? m_ppSurfacePtrs[nSurfaceIndex] : NULL; + if (!pSurface) { + INTEL_DEBUG_ERROR("Failed to find surface at index=%d", nSurfaceIndex); + return MFX_ERR_NOT_FOUND; + } + + mfxStatus sts = MFX_ERR_NONE; + mfxU16 w, h, i, pitch; + mfxU8 *ptr; + mfxFrameInfo* pInfo = &pSurface->Info; + mfxFrameData* pData = &pSurface->Data; + + if (pInfo->CropH > 0 && pInfo->CropW > 0) { + w = pInfo->CropW; + h = pInfo->CropH; + } + else { + w = pInfo->Width; + h = pInfo->Height; + } + + pitch = pData->Pitch; + ptr = pData->Y + pInfo->CropX + pInfo->CropY * pData->Pitch; + + // read luminance plane + for (i = 0; i < h; i++) { + memcpy(ptr + i * pitch, src, w); + src += w; + } + + mfxU8 buf[2048]; // maximum supported chroma width for nv12 + w /= 2; + h /= 2; + ptr = pData->UV + pInfo->CropX + (pInfo->CropY / 2) * pitch; + if (w > 2048) { + return MFX_ERR_UNSUPPORTED; + } + + // load U + sts = ReadPlaneData(w, h, buf, ptr, pitch, 0, src); + if (MFX_ERR_NONE != sts) { + return sts; + } + // load V + sts = ReadPlaneData(w, h, buf, ptr, pitch, 1, src); + if (MFX_ERR_NONE != sts) { + return sts; + } + + return MFX_ERR_NONE; + } + + virtual mfxStatus AllocSurfaces(mfxU16 nNumSurfaces, mfxU16 nSurfaceWidth, mfxU16 nSurfaceHeight, const mfxFrameInfo* pcFrameInfo) { + mfxStatus status = MFX_ERR_UNKNOWN; + + INTEL_DEBUG_INFO("Alloc surfaces: num=%u, width=%u, height=%u", nNumSurfaces, nSurfaceWidth, nSurfaceHeight); + + DeAllocSurfaces(); + + n_nNumSurfaces = nNumSurfaces; + m_nSurfaceWidth = (mfxU16)INTEL_ALIGN32(nSurfaceWidth); + m_nSurfaceHeight = (mfxU16)INTEL_ALIGN32(nSurfaceHeight); + m_nSurfaceBitsPerPixel = 12; // NV12 format is a 12 bits per pixel format + m_nSurfaceSize = m_nSurfaceWidth * m_nSurfaceHeight * m_nSurfaceBitsPerPixel / 8; #if !INTEL_DX11_D3D - if (!(m_pSurfaceBuffers = (mfxU8 *)new mfxU8[m_nSurfaceSize * n_nNumSurfaces])) - { - INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); - } + if (!(m_pSurfaceBuffers = (mfxU8 *)new mfxU8[m_nSurfaceSize * n_nNumSurfaces])) { + INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); + } #endif - if (!(m_ppSurfacePtrs = new mfxFrameSurface1*[n_nNumSurfaces])) - { - INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); - } - for (mfxU16 i = 0; i < n_nNumSurfaces; i++) - { - if (!(m_ppSurfacePtrs[i] = new mfxFrameSurface1)) - { - INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); - } - memset(m_ppSurfacePtrs[i], 0, sizeof(mfxFrameSurface1)); - memcpy(&(m_ppSurfacePtrs[i]->Info), pcFrameInfo, sizeof(mfxFrameInfo)); + if (!(m_ppSurfacePtrs = new mfxFrameSurface1*[n_nNumSurfaces])) { + INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); + } + for (mfxU16 i = 0; i < n_nNumSurfaces; i++) { + if (!(m_ppSurfacePtrs[i] = new mfxFrameSurface1)) { + INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); + } + memset(m_ppSurfacePtrs[i], 0, sizeof(mfxFrameSurface1)); + memcpy(&(m_ppSurfacePtrs[i]->Info), pcFrameInfo, sizeof(mfxFrameInfo)); #if INTEL_DX11_D3D - m_ppSurfacePtrs[i]->Data.MemId = m_sD3D11Response.mids[i]; // MID (memory id) represent one D3D NV12 surface + m_ppSurfacePtrs[i]->Data.MemId = m_sD3D11Response.mids[i]; // MID (memory id) represent one D3D NV12 surface #else - m_ppSurfacePtrs[i]->Data.Y = &m_pSurfaceBuffers[m_nSurfaceSize * i]; - m_ppSurfacePtrs[i]->Data.U = m_ppSurfacePtrs[i]->Data.Y + m_nSurfaceWidth * m_nSurfaceHeight; - m_ppSurfacePtrs[i]->Data.V = m_ppSurfacePtrs[i]->Data.U + 1; - m_ppSurfacePtrs[i]->Data.Pitch = m_nSurfaceWidth; + m_ppSurfacePtrs[i]->Data.Y = &m_pSurfaceBuffers[m_nSurfaceSize * i]; + m_ppSurfacePtrs[i]->Data.U = m_ppSurfacePtrs[i]->Data.Y + m_nSurfaceWidth * m_nSurfaceHeight; + m_ppSurfacePtrs[i]->Data.V = m_ppSurfacePtrs[i]->Data.U + 1; + m_ppSurfacePtrs[i]->Data.Pitch = m_nSurfaceWidth; #endif - } + } - return MFX_ERR_NONE; + return MFX_ERR_NONE; - bail: - DeAllocSurfaces(); - return status; - } +bail: + DeAllocSurfaces(); + return status; + } - mfxStatus AllocateBitstream(mfxU32 nMaxLength) - { - DeAllocateBitstream(); + mfxStatus AllocateBitstream(mfxU32 nMaxLength) { + DeAllocateBitstream(); - m_sBitstream.MaxLength = nMaxLength; - if (!(m_sBitstream.Data = new mfxU8[nMaxLength])) - { - INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); - } + m_sBitstream.MaxLength = nMaxLength; + if (!(m_sBitstream.Data = new mfxU8[nMaxLength])) { + INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); + } - return MFX_ERR_NONE; + return MFX_ERR_NONE; - bail: - return MFX_ERR_MEMORY_ALLOC; - } +bail: + return MFX_ERR_MEMORY_ALLOC; + } private: - mfxStatus DeAllocSurfaces() - { - if (m_ppSurfacePtrs) - { - for (mfxU16 i = 0; i < n_nNumSurfaces; i++) - { - if (m_ppSurfacePtrs[i]) - { - delete m_ppSurfacePtrs[i]; - } - } - delete[] m_ppSurfacePtrs; - m_ppSurfacePtrs = NULL; - } - n_nNumSurfaces = 0; - - if (m_pSurfaceBuffers) - { - delete[] m_pSurfaceBuffers; - m_pSurfaceBuffers = NULL; - } - - m_nSurfaceWidth = 0; - m_nSurfaceHeight = 0; - m_nSurfaceBitsPerPixel = 0; - m_nSurfaceSize = 0; - - return MFX_ERR_NONE; - } - - mfxStatus DeAllocateBitstream() - { - if (m_sBitstream.Data) - { - delete[]m_sBitstream.Data; - } - memset(&m_sBitstream, 0, sizeof(m_sBitstream)); - - return MFX_ERR_NONE; - } + mfxStatus DeAllocSurfaces() { + if (m_ppSurfacePtrs) { + for (mfxU16 i = 0; i < n_nNumSurfaces; i++) { + if (m_ppSurfacePtrs[i]) { + delete m_ppSurfacePtrs[i]; + } + } + delete[] m_ppSurfacePtrs; + m_ppSurfacePtrs = NULL; + } + n_nNumSurfaces = 0; + + if (m_pSurfaceBuffers) { + delete[] m_pSurfaceBuffers; + m_pSurfaceBuffers = NULL; + } + + m_nSurfaceWidth = 0; + m_nSurfaceHeight = 0; + m_nSurfaceBitsPerPixel = 0; + m_nSurfaceSize = 0; + + return MFX_ERR_NONE; + } + + mfxStatus DeAllocateBitstream() { + if (m_sBitstream.Data) { + delete[]m_sBitstream.Data; + } + memset(&m_sBitstream, 0, sizeof(m_sBitstream)); + + return MFX_ERR_NONE; + } protected: - bool m_bOpened; - MFXVideoSession* m_pSession; - mfxU16 n_nNumSurfaces; - mfxU16 m_nSurfaceWidth; - mfxU16 m_nSurfaceHeight; - mfxU8 m_nSurfaceBitsPerPixel; - mfxU32 m_nSurfaceSize; - mfxU8* m_pSurfaceBuffers; // mfxU8[]; - mfxFrameSurface1** m_ppSurfacePtrs; // mfxFrameSurface1[] - mfxBitstream m_sBitstream; - mfxVideoParam m_sParamReq; // requested params - mfxVideoParam m_sParamSel; // selected params - mfxFrameAllocRequest m_sAllocRequest; + bool m_bOpened; + MFXVideoSession* m_pSession; + mfxU16 n_nNumSurfaces; + mfxU16 m_nSurfaceWidth; + mfxU16 m_nSurfaceHeight; + mfxU8 m_nSurfaceBitsPerPixel; + mfxU32 m_nSurfaceSize; + mfxU8* m_pSurfaceBuffers; // mfxU8[]; + mfxFrameSurface1** m_ppSurfacePtrs; // mfxFrameSurface1[] + mfxBitstream m_sBitstream; + mfxVideoParam m_sParamReq; // requested params + mfxVideoParam m_sParamSel; // selected params + mfxFrameAllocRequest m_sAllocRequest; #if INTEL_DX11_D3D - mfxFrameAllocResponse m_sD3D11Response; + mfxFrameAllocResponse m_sD3D11Response; #endif }; @@ -423,349 +402,315 @@ protected: class IntelCodecEncoder : public IntelCodec { public: - IntelCodecEncoder(MFXVideoSession* pSession) - : IntelCodec(pSession) - , m_Inst(*pSession) - { - memset(&m_sFrameCtrl, 0, sizeof(m_sFrameCtrl)); - } - virtual ~IntelCodecEncoder() - { - Close(); - } - - virtual mfxStatus Close() - { - m_Inst.Close(); - memset(&m_sFrameCtrl, 0, sizeof(m_sFrameCtrl)); - return IntelCodec::Close(); - } - - mfxStatus Reset() - { - if (m_bOpened) - { - return m_Inst.Reset(&m_sParamSel); - } - return MFX_ERR_NONE; - } - - mfxStatus Open(struct tdav_codec_h264_intel_s* pWrappedCodec) - { - int32_t max_bw_kpbs; - tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec; - mfxStatus status = MFX_ERR_UNKNOWN; - mfxU16 uSelWidth, uSelHeight; - - pWrappedCodec->encoder.neg_width = (pWrappedCodec->encoder.rotation == 90 || pWrappedCodec->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.height : TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.width; - pWrappedCodec->encoder.neg_height = (pWrappedCodec->encoder.rotation == 90 || pWrappedCodec->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.width : TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.height; - pWrappedCodec->encoder.neg_fps = TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.fps; - max_bw_kpbs = TSK_CLAMP( - 0, - tmedia_get_video_bandwidth_kbps_2(pWrappedCodec->encoder.neg_width, pWrappedCodec->encoder.neg_height, pWrappedCodec->encoder.neg_fps), - TMEDIA_CODEC(pWrappedCodec)->bandwidth_max_upload - ); - pWrappedCodec->encoder.max_bitrate_bps = (max_bw_kpbs * 1024); - - INTEL_DEBUG_INFO("neg_width=%d, neg_height=%d, neg_fps=%d, max_bitrate_bps=%d", - pWrappedCodec->encoder.neg_width, - pWrappedCodec->encoder.neg_height, - pWrappedCodec->encoder.neg_fps, - pWrappedCodec->encoder.max_bitrate_bps - ); - - // Initialize encoder parameters - memset(&m_sParamReq, 0, sizeof(m_sParamReq)); - m_sParamReq.mfx.CodecId = MFX_CODEC_AVC; - m_sParamReq.mfx.CodecProfile = pWrappedCodecCommon->profile == profile_idc_main ? MFX_PROFILE_AVC_MAIN : MFX_PROFILE_AVC_BASELINE; - m_sParamReq.mfx.CodecLevel = (mfxU16)pWrappedCodecCommon->level; - // TODO: Update "CodecProfile" based on "common->profile_iop" - m_sParamReq.mfx.TargetUsage = MFX_TARGETUSAGE_BALANCED; - m_sParamReq.mfx.TargetKbps = max_bw_kpbs; - m_sParamReq.mfx.RateControlMethod = MFX_RATECONTROL_CBR; - m_sParamReq.mfx.IdrInterval = (pWrappedCodec->encoder.neg_fps * INTEL_H264_GOP_SIZE_IN_SECONDS); - m_sParamReq.mfx.FrameInfo.FrameRateExtN = pWrappedCodec->encoder.neg_fps; - m_sParamReq.mfx.FrameInfo.FrameRateExtD = 1; - m_sParamReq.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12; - m_sParamReq.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; - m_sParamReq.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; - m_sParamReq.mfx.FrameInfo.CropX = 0; - m_sParamReq.mfx.FrameInfo.CropY = 0; - m_sParamReq.mfx.FrameInfo.CropW = pWrappedCodec->encoder.neg_width; - m_sParamReq.mfx.FrameInfo.CropH = pWrappedCodec->encoder.neg_height; - m_sParamReq.mfx.FrameInfo.Width = INTEL_ALIGN16(pWrappedCodec->encoder.neg_width); // must be a multiple of 16 - m_sParamReq.mfx.FrameInfo.Height = INTEL_ALIGN16(pWrappedCodec->encoder.neg_height); // must be a multiple of 16 + IntelCodecEncoder(MFXVideoSession* pSession) + : IntelCodec(pSession) + , m_Inst(*pSession) { + memset(&m_sFrameCtrl, 0, sizeof(m_sFrameCtrl)); + } + virtual ~IntelCodecEncoder() { + Close(); + } + + virtual mfxStatus Close() { + m_Inst.Close(); + memset(&m_sFrameCtrl, 0, sizeof(m_sFrameCtrl)); + return IntelCodec::Close(); + } + + mfxStatus Reset() { + if (m_bOpened) { + return m_Inst.Reset(&m_sParamSel); + } + return MFX_ERR_NONE; + } + + mfxStatus Open(struct tdav_codec_h264_intel_s* pWrappedCodec) { + int32_t max_bw_kpbs; + tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec; + mfxStatus status = MFX_ERR_UNKNOWN; + mfxU16 uSelWidth, uSelHeight; + + pWrappedCodec->encoder.neg_width = (pWrappedCodec->encoder.rotation == 90 || pWrappedCodec->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.height : TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.width; + pWrappedCodec->encoder.neg_height = (pWrappedCodec->encoder.rotation == 90 || pWrappedCodec->encoder.rotation == 270) ? TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.width : TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.height; + pWrappedCodec->encoder.neg_fps = TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.fps; + max_bw_kpbs = TSK_CLAMP( + 0, + tmedia_get_video_bandwidth_kbps_2(pWrappedCodec->encoder.neg_width, pWrappedCodec->encoder.neg_height, pWrappedCodec->encoder.neg_fps), + TMEDIA_CODEC(pWrappedCodec)->bandwidth_max_upload + ); + pWrappedCodec->encoder.max_bitrate_bps = (max_bw_kpbs * 1024); + + INTEL_DEBUG_INFO("neg_width=%d, neg_height=%d, neg_fps=%d, max_bitrate_bps=%d", + pWrappedCodec->encoder.neg_width, + pWrappedCodec->encoder.neg_height, + pWrappedCodec->encoder.neg_fps, + pWrappedCodec->encoder.max_bitrate_bps + ); + + // Initialize encoder parameters + memset(&m_sParamReq, 0, sizeof(m_sParamReq)); + m_sParamReq.mfx.CodecId = MFX_CODEC_AVC; + m_sParamReq.mfx.CodecProfile = pWrappedCodecCommon->profile == profile_idc_main ? MFX_PROFILE_AVC_MAIN : MFX_PROFILE_AVC_BASELINE; + m_sParamReq.mfx.CodecLevel = (mfxU16)pWrappedCodecCommon->level; + // TODO: Update "CodecProfile" based on "common->profile_iop" + m_sParamReq.mfx.TargetUsage = MFX_TARGETUSAGE_BALANCED; + m_sParamReq.mfx.TargetKbps = max_bw_kpbs; + m_sParamReq.mfx.RateControlMethod = MFX_RATECONTROL_CBR; + m_sParamReq.mfx.IdrInterval = (pWrappedCodec->encoder.neg_fps * INTEL_H264_GOP_SIZE_IN_SECONDS); + m_sParamReq.mfx.FrameInfo.FrameRateExtN = pWrappedCodec->encoder.neg_fps; + m_sParamReq.mfx.FrameInfo.FrameRateExtD = 1; + m_sParamReq.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12; + m_sParamReq.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; + m_sParamReq.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + m_sParamReq.mfx.FrameInfo.CropX = 0; + m_sParamReq.mfx.FrameInfo.CropY = 0; + m_sParamReq.mfx.FrameInfo.CropW = pWrappedCodec->encoder.neg_width; + m_sParamReq.mfx.FrameInfo.CropH = pWrappedCodec->encoder.neg_height; + m_sParamReq.mfx.FrameInfo.Width = INTEL_ALIGN16(pWrappedCodec->encoder.neg_width); // must be a multiple of 16 + m_sParamReq.mfx.FrameInfo.Height = INTEL_ALIGN16(pWrappedCodec->encoder.neg_height); // must be a multiple of 16 #if INTEL_DX11_D3D - m_sParamReq.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY; + m_sParamReq.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY; #else - m_sParamReq.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY; + m_sParamReq.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY; #endif - memset(&m_sOpt2MaxFrameSize, 0, sizeof(m_sOpt2MaxFrameSize)); - m_sOpt2MaxFrameSize.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; - m_sOpt2MaxFrameSize.Header.BufferSz = sizeof(m_sOpt2MaxFrameSize); - m_sOpt2MaxFrameSize.MaxSliceSize = (H264_RTP_PAYLOAD_SIZE - 100); - m_sOpt2MaxFrameSize.RepeatPPS = MFX_CODINGOPTION_OFF; - m_pExtendedBuffers[0] = (mfxExtBuffer*)&m_sOpt2MaxFrameSize; + memset(&m_sOpt2MaxFrameSize, 0, sizeof(m_sOpt2MaxFrameSize)); + m_sOpt2MaxFrameSize.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; + m_sOpt2MaxFrameSize.Header.BufferSz = sizeof(m_sOpt2MaxFrameSize); + m_sOpt2MaxFrameSize.MaxSliceSize = (H264_RTP_PAYLOAD_SIZE - 100); + m_sOpt2MaxFrameSize.RepeatPPS = MFX_CODINGOPTION_OFF; + m_pExtendedBuffers[0] = (mfxExtBuffer*)&m_sOpt2MaxFrameSize; #if INTEL_ENABLE_REALTIME - m_sParamReq.AsyncDepth = 1; // limits internal frame buffering - m_sParamReq.mfx.GopRefDist = 1; // No B-Frames - m_sParamReq.mfx.NumRefFrame = 1; - memset(&m_sOptLowLatency, 0, sizeof(m_sOptLowLatency)); - m_sOptLowLatency.Header.BufferId = MFX_EXTBUFF_CODING_OPTION; - m_sOptLowLatency.Header.BufferSz = sizeof(m_sOptLowLatency); - m_sOptLowLatency.MaxDecFrameBuffering = 1; - m_pExtendedBuffers[1] = (mfxExtBuffer*)&m_sOptLowLatency; - m_sParamReq.NumExtParam = 2; + m_sParamReq.AsyncDepth = 1; // limits internal frame buffering + m_sParamReq.mfx.GopRefDist = 1; // No B-Frames + m_sParamReq.mfx.NumRefFrame = 1; + memset(&m_sOptLowLatency, 0, sizeof(m_sOptLowLatency)); + m_sOptLowLatency.Header.BufferId = MFX_EXTBUFF_CODING_OPTION; + m_sOptLowLatency.Header.BufferSz = sizeof(m_sOptLowLatency); + m_sOptLowLatency.MaxDecFrameBuffering = 1; + m_pExtendedBuffers[1] = (mfxExtBuffer*)&m_sOptLowLatency; + m_sParamReq.NumExtParam = 2; #else - m_sParamReq.NumExtParam = 1; + m_sParamReq.NumExtParam = 1; #endif - m_sParamReq.ExtParam = m_pExtendedBuffers; - - // Check parameters - status = m_Inst.Query(&m_sParamReq, &m_sParamReq); - if (status != MFX_ERR_NONE && status != MFX_WRN_INCOMPATIBLE_VIDEO_PARAM /* Best one will be selected by the encoder */) { - INTEL_CHECK_STATUS(status); - } - if (m_sOpt2MaxFrameSize.MaxSliceSize == 0) - { - INTEL_DEBUG_INFO("The encoder doesn't support setting 'MaxSliceSize' :("); - } - - // Query number required surfaces for encoder - memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest)); - INTEL_CHECK_STATUS(status = m_Inst.QueryIOSurf(&m_sParamReq, &m_sAllocRequest)); - INTEL_DEBUG_INFO("nEncSurfNum = %hu", m_sAllocRequest.NumFrameSuggested); + m_sParamReq.ExtParam = m_pExtendedBuffers; + + // Check parameters + status = m_Inst.Query(&m_sParamReq, &m_sParamReq); + if (status != MFX_ERR_NONE && status != MFX_WRN_INCOMPATIBLE_VIDEO_PARAM /* Best one will be selected by the encoder */) { + INTEL_CHECK_STATUS(status); + } + if (m_sOpt2MaxFrameSize.MaxSliceSize == 0) { + INTEL_DEBUG_INFO("The encoder doesn't support setting 'MaxSliceSize' :("); + } + + // Query number required surfaces for encoder + memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest)); + INTEL_CHECK_STATUS(status = m_Inst.QueryIOSurf(&m_sParamReq, &m_sAllocRequest)); + INTEL_DEBUG_INFO("nEncSurfNum = %hu", m_sAllocRequest.NumFrameSuggested); #if INTEL_DX11_D3D - m_sAllocRequest.Type |= D3D11_WILL_WRITE; // Hint to DX11 memory handler that application will write data to input surfaces + m_sAllocRequest.Type |= D3D11_WILL_WRITE; // Hint to DX11 memory handler that application will write data to input surfaces #endif - // Allocate surfaces for encoder + // Allocate surfaces for encoder #if INTEL_DX11_D3D - INTEL_CHECK_STATUS(status = pWrappedCodec->D3D11Allocator.Alloc(pWrappedCodec->D3D11Allocator.pthis, &m_sAllocRequest, &m_sD3D11Response)); - if (m_sD3D11Response.NumFrameActual == 0) - { - INTEL_CHECK_STATUS(status = MFX_ERR_UNKNOWN); - } - INTEL_CHECK_STATUS(status = AllocSurfaces(m_sD3D11Response.NumFrameActual, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo)); + INTEL_CHECK_STATUS(status = pWrappedCodec->D3D11Allocator.Alloc(pWrappedCodec->D3D11Allocator.pthis, &m_sAllocRequest, &m_sD3D11Response)); + if (m_sD3D11Response.NumFrameActual == 0) { + INTEL_CHECK_STATUS(status = MFX_ERR_UNKNOWN); + } + INTEL_CHECK_STATUS(status = AllocSurfaces(m_sD3D11Response.NumFrameActual, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo)); #else - INTEL_CHECK_STATUS(status = AllocSurfaces(m_sAllocRequest.NumFrameSuggested, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo)); + INTEL_CHECK_STATUS(status = AllocSurfaces(m_sAllocRequest.NumFrameSuggested, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo)); #endif - // Initialize the Media SDK encoder - status = m_Inst.Init(&m_sParamReq); - if (status != MFX_ERR_NONE && status != MFX_WRN_PARTIAL_ACCELERATION) { - INTEL_CHECK_STATUS(status); - } - INTEL_DEBUG_INFO("Encoder->Init() returned: %d", status); - - // Retrieve video parameters selected by encoder. - memset(&m_sParamSel, 0, sizeof(m_sParamSel)); - INTEL_CHECK_STATUS(status = m_Inst.GetVideoParam(&m_sParamSel)); - INTEL_DEBUG_INFO("sel_width=%u.crop=%u, sel_height=%u.crop=%u, sel_fps=%u/%u", - m_sParamSel.mfx.FrameInfo.Width, m_sParamSel.mfx.FrameInfo.CropW, - m_sParamSel.mfx.FrameInfo.Height, m_sParamSel.mfx.FrameInfo.CropH, - m_sParamReq.mfx.FrameInfo.FrameRateExtN, - m_sParamReq.mfx.FrameInfo.FrameRateExtD - ); - if (m_sParamSel.mfx.FrameInfo.CropW > 0 && m_sParamSel.mfx.FrameInfo.CropH > 0) - { - uSelWidth = m_sParamSel.mfx.FrameInfo.CropW; - uSelHeight = m_sParamSel.mfx.FrameInfo.CropH; - } - else - { - uSelWidth = m_sParamSel.mfx.FrameInfo.Width; - uSelHeight = m_sParamSel.mfx.FrameInfo.Height; - } - if (pWrappedCodec->encoder.neg_width != uSelWidth || pWrappedCodec->encoder.neg_height != uSelHeight) { - INTEL_DEBUG_INFO("Encoder neg size <> sel size: %dx%d<>%dx%d", pWrappedCodec->encoder.neg_width, pWrappedCodec->encoder.neg_height, uSelWidth, uSelHeight); - pWrappedCodec->encoder.neg_width = uSelWidth; - pWrappedCodec->encoder.neg_height = uSelHeight; - TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.width = pWrappedCodec->encoder.neg_width; - TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.height = pWrappedCodec->encoder.neg_height; - } - - // Allocate BitStream - INTEL_CHECK_STATUS(status = AllocateBitstream(m_sParamSel.mfx.BufferSizeInKB * 1000)); - - m_bOpened = true; - return MFX_ERR_NONE; - - bail: - Close(); - return status; - } - - mfxStatus UpdateBandwidth(bool bUp, mfxU16 max) - { - if (bUp) - { - m_sParamSel.mfx.TargetKbps = TSK_CLAMP(0, (mfxU16)((m_sParamSel.mfx.TargetKbps * 3) >> 1), max); - } - else - { - m_sParamSel.mfx.TargetKbps = TSK_CLAMP(0, (mfxU16)((m_sParamSel.mfx.TargetKbps << 1) / 3), max); - } - m_sParamReq.mfx.TargetKbps = m_sParamSel.mfx.TargetKbps; - INTEL_DEBUG_INFO("Setting new target bandwidth to %ukbps", m_sParamSel.mfx.TargetKbps); - return m_Inst.Reset(&m_sParamSel); - } - - mfxStatus SetMaxBandwidth(mfxU16 max) - { - m_sParamSel.mfx.TargetKbps = TSK_CLAMP(0, m_sParamSel.mfx.TargetKbps, max); - m_sParamReq.mfx.TargetKbps = m_sParamSel.mfx.TargetKbps; - INTEL_DEBUG_INFO("Setting new target bandwidth to %ukbps", m_sParamSel.mfx.TargetKbps); - return m_Inst.Reset(&m_sParamSel); - } - - mfxStatus Encode(struct tmedia_codec_s* pWrappedCodec, const mfxU8* pcInDataPtr, mfxU32 nInDataSize) - { - tdav_codec_h264_intel_t* pWrappedCodecH264 = (tdav_codec_h264_intel_t*)pWrappedCodec; - tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec; - mfxU32 nInDataXSize; - tsk_bool_t bSendIDR; - int nEncSurfIdx = 0; - mfxSyncPoint syncp; - mfxStatus status = MFX_ERR_UNKNOWN; - - if (!pWrappedCodec || !pcInDataPtr || !nInDataSize) { - INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR); - } - - if (!m_bOpened) { - INTEL_CHECK_STATUS(MFX_ERR_NOT_INITIALIZED); - } - - nInDataXSize = (pWrappedCodecH264->encoder.neg_width * pWrappedCodecH264->encoder.neg_height * 3) >> 1; - if (nInDataXSize != nInDataSize) - { - /* guard */ - INTEL_DEBUG_ERROR("Invalid size: %u<>%u", nInDataXSize, nInDataSize); - goto bail; - } - - bSendIDR = (pWrappedCodecH264->encoder.frame_count++ == 0 || pWrappedCodecH264->encoder.force_idr); - - nEncSurfIdx = GetFreeSurfaceIndex(); - if (MFX_ERR_NOT_FOUND == nEncSurfIdx) - { - INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); - } - - // Surface locking required when read/write D3D surfaces + // Initialize the Media SDK encoder + status = m_Inst.Init(&m_sParamReq); + if (status != MFX_ERR_NONE && status != MFX_WRN_PARTIAL_ACCELERATION) { + INTEL_CHECK_STATUS(status); + } + INTEL_DEBUG_INFO("Encoder->Init() returned: %d", status); + + // Retrieve video parameters selected by encoder. + memset(&m_sParamSel, 0, sizeof(m_sParamSel)); + INTEL_CHECK_STATUS(status = m_Inst.GetVideoParam(&m_sParamSel)); + INTEL_DEBUG_INFO("sel_width=%u.crop=%u, sel_height=%u.crop=%u, sel_fps=%u/%u", + m_sParamSel.mfx.FrameInfo.Width, m_sParamSel.mfx.FrameInfo.CropW, + m_sParamSel.mfx.FrameInfo.Height, m_sParamSel.mfx.FrameInfo.CropH, + m_sParamReq.mfx.FrameInfo.FrameRateExtN, + m_sParamReq.mfx.FrameInfo.FrameRateExtD + ); + if (m_sParamSel.mfx.FrameInfo.CropW > 0 && m_sParamSel.mfx.FrameInfo.CropH > 0) { + uSelWidth = m_sParamSel.mfx.FrameInfo.CropW; + uSelHeight = m_sParamSel.mfx.FrameInfo.CropH; + } + else { + uSelWidth = m_sParamSel.mfx.FrameInfo.Width; + uSelHeight = m_sParamSel.mfx.FrameInfo.Height; + } + if (pWrappedCodec->encoder.neg_width != uSelWidth || pWrappedCodec->encoder.neg_height != uSelHeight) { + INTEL_DEBUG_INFO("Encoder neg size <> sel size: %dx%d<>%dx%d", pWrappedCodec->encoder.neg_width, pWrappedCodec->encoder.neg_height, uSelWidth, uSelHeight); + pWrappedCodec->encoder.neg_width = uSelWidth; + pWrappedCodec->encoder.neg_height = uSelHeight; + TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.width = pWrappedCodec->encoder.neg_width; + TMEDIA_CODEC_VIDEO(pWrappedCodec)->out.height = pWrappedCodec->encoder.neg_height; + } + + // Allocate BitStream + INTEL_CHECK_STATUS(status = AllocateBitstream(m_sParamSel.mfx.BufferSizeInKB * 1000)); + + m_bOpened = true; + return MFX_ERR_NONE; + +bail: + Close(); + return status; + } + + mfxStatus UpdateBandwidth(bool bUp, mfxU16 max) { + if (bUp) { + m_sParamSel.mfx.TargetKbps = TSK_CLAMP(0, (mfxU16)((m_sParamSel.mfx.TargetKbps * 3) >> 1), max); + } + else { + m_sParamSel.mfx.TargetKbps = TSK_CLAMP(0, (mfxU16)((m_sParamSel.mfx.TargetKbps << 1) / 3), max); + } + m_sParamReq.mfx.TargetKbps = m_sParamSel.mfx.TargetKbps; + INTEL_DEBUG_INFO("Setting new target bandwidth to %ukbps", m_sParamSel.mfx.TargetKbps); + return m_Inst.Reset(&m_sParamSel); + } + + mfxStatus SetMaxBandwidth(mfxU16 max) { + m_sParamSel.mfx.TargetKbps = TSK_CLAMP(0, m_sParamSel.mfx.TargetKbps, max); + m_sParamReq.mfx.TargetKbps = m_sParamSel.mfx.TargetKbps; + INTEL_DEBUG_INFO("Setting new target bandwidth to %ukbps", m_sParamSel.mfx.TargetKbps); + return m_Inst.Reset(&m_sParamSel); + } + + mfxStatus Encode(struct tmedia_codec_s* pWrappedCodec, const mfxU8* pcInDataPtr, mfxU32 nInDataSize) { + tdav_codec_h264_intel_t* pWrappedCodecH264 = (tdav_codec_h264_intel_t*)pWrappedCodec; + tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec; + mfxU32 nInDataXSize; + tsk_bool_t bSendIDR; + int nEncSurfIdx = 0; + mfxSyncPoint syncp; + mfxStatus status = MFX_ERR_UNKNOWN; + + if (!pWrappedCodec || !pcInDataPtr || !nInDataSize) { + INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR); + } + + if (!m_bOpened) { + INTEL_CHECK_STATUS(MFX_ERR_NOT_INITIALIZED); + } + + nInDataXSize = (pWrappedCodecH264->encoder.neg_width * pWrappedCodecH264->encoder.neg_height * 3) >> 1; + if (nInDataXSize != nInDataSize) { + /* guard */ + INTEL_DEBUG_ERROR("Invalid size: %u<>%u", nInDataXSize, nInDataSize); + goto bail; + } + + bSendIDR = (pWrappedCodecH264->encoder.frame_count++ == 0 || pWrappedCodecH264->encoder.force_idr); + + nEncSurfIdx = GetFreeSurfaceIndex(); + if (MFX_ERR_NOT_FOUND == nEncSurfIdx) { + INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); + } + + // Surface locking required when read/write D3D surfaces #if INTEL_DX11_D3D - INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Lock(pWrappedCodecH264->D3D11Allocator.pthis, m_ppSurfacePtrs[nEncSurfIdx]->Data.MemId, &(m_ppSurfacePtrs[nEncSurfIdx]->Data))); + INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Lock(pWrappedCodecH264->D3D11Allocator.pthis, m_ppSurfacePtrs[nEncSurfIdx]->Data.MemId, &(m_ppSurfacePtrs[nEncSurfIdx]->Data))); #endif - INTEL_CHECK_STATUS(status = LoadRawFrame(nEncSurfIdx, pcInDataPtr)); + INTEL_CHECK_STATUS(status = LoadRawFrame(nEncSurfIdx, pcInDataPtr)); #if INTEL_DX11_D3D - INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Unlock(pWrappedCodecH264->D3D11Allocator.pthis, m_ppSurfacePtrs[nEncSurfIdx]->Data.MemId, &(m_ppSurfacePtrs[nEncSurfIdx]->Data))); + INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Unlock(pWrappedCodecH264->D3D11Allocator.pthis, m_ppSurfacePtrs[nEncSurfIdx]->Data.MemId, &(m_ppSurfacePtrs[nEncSurfIdx]->Data))); #endif - m_sFrameCtrl.FrameType = bSendIDR ? (MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF | MFX_FRAMETYPE_IDR) : MFX_FRAMETYPE_UNKNOWN; - - // - // Stage 1: Main encoding loop - // - do - { - for (;;) - { - // Encode a frame asychronously (returns immediately) - status = m_Inst.EncodeFrameAsync(&m_sFrameCtrl, m_ppSurfacePtrs[nEncSurfIdx], &m_sBitstream, &syncp); - - if (MFX_ERR_NONE < status && !syncp) // Repeat the call if warning and no output - { - if (MFX_WRN_DEVICE_BUSY == status) - { - tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call - } - } - else if (MFX_ERR_NONE < status && syncp) - { - status = MFX_ERR_NONE; // Ignore warnings if output is available - break; - } - else if (MFX_ERR_NOT_ENOUGH_BUFFER == status) - { - // Allocate more bitstream buffer memory here if needed... - break; - } - else - { - if (status != MFX_ERR_MORE_DATA) - { - INTEL_CHECK_STATUS(status); - } - break; - } - } - if (MFX_ERR_NONE == status) - { - INTEL_CHECK_STATUS(m_pSession->SyncOperation(syncp, 60000)); // Synchronize. Wait until encoded frame is ready - if (m_sBitstream.DataLength > 0) - { - tdav_codec_h264_rtp_encap(pWrappedCodecCommon, (const uint8_t*)(m_sBitstream.Data + m_sBitstream.DataOffset), (tsk_size_t)m_sBitstream.DataLength); - m_sBitstream.DataLength = 0; - pWrappedCodecH264->encoder.force_idr = tsk_false; // reset - } - } - } while (0); - - // - // Stage 2: Retrieve the buffered encoded frames - // - while (MFX_ERR_NONE <= status) - { - for (;;) - { - // Encode a frame asychronously (returns immediately) - status = m_Inst.EncodeFrameAsync(&m_sFrameCtrl, NULL, &m_sBitstream, &syncp); - - if (MFX_ERR_NONE < status && !syncp) // Repeat the call if warning and no output - { - if (MFX_WRN_DEVICE_BUSY == status) - { - tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call - } - } - else if (MFX_ERR_NONE < status && syncp) - { - status = MFX_ERR_NONE; // Ignore warnings if output is available - break; - } - else - { - break; - } - } - - if (MFX_ERR_NONE == status) - { - INTEL_CHECK_STATUS(m_pSession->SyncOperation(syncp, 60000)); // Synchronize. Wait until encoded frame is - if (m_sBitstream.DataLength > 0) - { - tdav_codec_h264_rtp_encap(pWrappedCodecCommon, (const uint8_t*)(m_sBitstream.Data + m_sBitstream.DataOffset), (tsk_size_t)m_sBitstream.DataLength); - m_sBitstream.DataLength = 0; - pWrappedCodecH264->encoder.force_idr = tsk_false; // reset - } - } - } - - bail: - return MFX_ERR_NONE; - } + m_sFrameCtrl.FrameType = bSendIDR ? (MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF | MFX_FRAMETYPE_IDR) : MFX_FRAMETYPE_UNKNOWN; + + // + // Stage 1: Main encoding loop + // + do { + for (;;) { + // Encode a frame asychronously (returns immediately) + status = m_Inst.EncodeFrameAsync(&m_sFrameCtrl, m_ppSurfacePtrs[nEncSurfIdx], &m_sBitstream, &syncp); + + if (MFX_ERR_NONE < status && !syncp) { // Repeat the call if warning and no output + if (MFX_WRN_DEVICE_BUSY == status) { + tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call + } + } + else if (MFX_ERR_NONE < status && syncp) { + status = MFX_ERR_NONE; // Ignore warnings if output is available + break; + } + else if (MFX_ERR_NOT_ENOUGH_BUFFER == status) { + // Allocate more bitstream buffer memory here if needed... + break; + } + else { + if (status != MFX_ERR_MORE_DATA) { + INTEL_CHECK_STATUS(status); + } + break; + } + } + if (MFX_ERR_NONE == status) { + INTEL_CHECK_STATUS(m_pSession->SyncOperation(syncp, 60000)); // Synchronize. Wait until encoded frame is ready + if (m_sBitstream.DataLength > 0) { + tdav_codec_h264_rtp_encap(pWrappedCodecCommon, (const uint8_t*)(m_sBitstream.Data + m_sBitstream.DataOffset), (tsk_size_t)m_sBitstream.DataLength); + m_sBitstream.DataLength = 0; + pWrappedCodecH264->encoder.force_idr = tsk_false; // reset + } + } + } + while (0); + + // + // Stage 2: Retrieve the buffered encoded frames + // + while (MFX_ERR_NONE <= status) { + for (;;) { + // Encode a frame asychronously (returns immediately) + status = m_Inst.EncodeFrameAsync(&m_sFrameCtrl, NULL, &m_sBitstream, &syncp); + + if (MFX_ERR_NONE < status && !syncp) { // Repeat the call if warning and no output + if (MFX_WRN_DEVICE_BUSY == status) { + tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call + } + } + else if (MFX_ERR_NONE < status && syncp) { + status = MFX_ERR_NONE; // Ignore warnings if output is available + break; + } + else { + break; + } + } + + if (MFX_ERR_NONE == status) { + INTEL_CHECK_STATUS(m_pSession->SyncOperation(syncp, 60000)); // Synchronize. Wait until encoded frame is + if (m_sBitstream.DataLength > 0) { + tdav_codec_h264_rtp_encap(pWrappedCodecCommon, (const uint8_t*)(m_sBitstream.Data + m_sBitstream.DataOffset), (tsk_size_t)m_sBitstream.DataLength); + m_sBitstream.DataLength = 0; + pWrappedCodecH264->encoder.force_idr = tsk_false; // reset + } + } + } + +bail: + return MFX_ERR_NONE; + } private: - MFXVideoENCODE m_Inst; - mfxEncodeCtrl m_sFrameCtrl; - mfxExtCodingOption m_sOptLowLatency; - mfxExtCodingOption2 m_sOpt2MaxFrameSize; - mfxExtBuffer* m_pExtendedBuffers[2]; // Not allocated + MFXVideoENCODE m_Inst; + mfxEncodeCtrl m_sFrameCtrl; + mfxExtCodingOption m_sOptLowLatency; + mfxExtCodingOption2 m_sOpt2MaxFrameSize; + mfxExtBuffer* m_pExtendedBuffers[2]; // Not allocated }; @@ -775,253 +720,222 @@ private: class IntelCodecDecoder : public IntelCodec { public: - IntelCodecDecoder(MFXVideoSession* pSession) - : IntelCodec(pSession) - , m_Inst(*pSession) - , m_pAccumulatorPtr(NULL) - , m_nAccumulatorSize(0) - , m_nAccumulatorPos(0) - , m_bInit(false) - { - - } - virtual ~IntelCodecDecoder() - { - Close(); - } - - virtual mfxStatus Close() - { - m_Inst.Close(); - TSK_FREE(m_pAccumulatorPtr); - m_nAccumulatorSize = 0; - m_nAccumulatorPos = 0; - m_bInit = false; - return IntelCodec::Close(); - } - - mfxStatus Open(struct tdav_codec_h264_intel_s* pWrappedCodec) - { - tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec; - - INTEL_DEBUG_INFO("Decoder.Open width=%d, height=%d, fps=%d", - TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.width, - TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.height, - TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.fps - ); - - // Allocation will be done each time we decode the SPS:PPS header - - m_bOpened = true; - return MFX_ERR_NONE; - } - - mfxU32 Decode(struct tmedia_codec_s* pWrappedCodec, const mfxU8* pcInDataPtr, mfxU32 nInDataSize, void **ppOutDataPtr, tsk_size_t *pOutDataMaxSize, const trtp_rtp_header_t* pcRtpHdr) - { - mfxU32 nRetSize = 0, nOutXSize; - mfxStatus status = MFX_ERR_NONE; - tsk_bool_t append_scp, end_of_unit; - tsk_bool_t sps_or_pps; - const uint8_t* pay_ptr = tsk_null; - tsk_size_t pay_size = 0, size_to_copy = 0; - bool bGotFrame = false; - mfxFrameSurface1* pmfxOutSurface = NULL; - static const tsk_size_t xmax_size = (3840 * 2160 * 3) >> 3; // >>3 instead of >>1 (not an error) - static tsk_size_t start_code_prefix_size = sizeof(H264_START_CODE_PREFIX); - - tdav_codec_h264_intel_t* pWrappedCodecH264 = (tdav_codec_h264_intel_t*)pWrappedCodec; - tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec; - - if (!pWrappedCodec || !pcInDataPtr || !nInDataSize || !ppOutDataPtr) - { - INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR); - } - //INTEL_DEBUG_INFO("Size=%u", nInDataSize); - if (!m_bOpened) - { - INTEL_CHECK_STATUS(MFX_ERR_NOT_INITIALIZED); - } - - - /* 5.3. NAL Unit Octet Usage - +---------------+ - |0|1|2|3|4|5|6|7| - +-+-+-+-+-+-+-+-+ - |F|NRI| Type | - +---------------+ - */ - if (pcInDataPtr[0] & 0x80) // F ?== 1 - { - /* reset accumulator */ - m_nAccumulatorPos = 0; - INTEL_CHECK_STATUS(status = MFX_ERR_UNDEFINED_BEHAVIOR); - } - - // New frame? - if (m_nLastRtpTimestamp != pcRtpHdr->timestamp) - { - m_nAccumulatorPos = 0; - m_nLastRtpTimestamp = pcRtpHdr->timestamp; - } - - /* get payload */ - if ((tdav_codec_h264_get_pay(pcInDataPtr, nInDataSize, (const void**)&pay_ptr, &pay_size, &append_scp, &end_of_unit) != 0) || !pay_ptr || !pay_size) - { - INTEL_BREAK("Depayloader failed to get H.264 content"); - } + IntelCodecDecoder(MFXVideoSession* pSession) + : IntelCodec(pSession) + , m_Inst(*pSession) + , m_pAccumulatorPtr(NULL) + , m_nAccumulatorSize(0) + , m_nAccumulatorPos(0) + , m_bInit(false) { + + } + virtual ~IntelCodecDecoder() { + Close(); + } + + virtual mfxStatus Close() { + m_Inst.Close(); + TSK_FREE(m_pAccumulatorPtr); + m_nAccumulatorSize = 0; + m_nAccumulatorPos = 0; + m_bInit = false; + return IntelCodec::Close(); + } + + mfxStatus Open(struct tdav_codec_h264_intel_s* pWrappedCodec) { + tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec; + + INTEL_DEBUG_INFO("Decoder.Open width=%d, height=%d, fps=%d", + TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.width, + TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.height, + TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.fps + ); + + // Allocation will be done each time we decode the SPS:PPS header + + m_bOpened = true; + return MFX_ERR_NONE; + } + + mfxU32 Decode(struct tmedia_codec_s* pWrappedCodec, const mfxU8* pcInDataPtr, mfxU32 nInDataSize, void **ppOutDataPtr, tsk_size_t *pOutDataMaxSize, const trtp_rtp_header_t* pcRtpHdr) { + mfxU32 nRetSize = 0, nOutXSize; + mfxStatus status = MFX_ERR_NONE; + tsk_bool_t append_scp, end_of_unit; + tsk_bool_t sps_or_pps; + const uint8_t* pay_ptr = tsk_null; + tsk_size_t pay_size = 0, size_to_copy = 0; + bool bGotFrame = false; + mfxFrameSurface1* pmfxOutSurface = NULL; + static const tsk_size_t xmax_size = (3840 * 2160 * 3) >> 3; // >>3 instead of >>1 (not an error) + static tsk_size_t start_code_prefix_size = sizeof(H264_START_CODE_PREFIX); + + tdav_codec_h264_intel_t* pWrappedCodecH264 = (tdav_codec_h264_intel_t*)pWrappedCodec; + tdav_codec_h264_common_t* pWrappedCodecCommon = (tdav_codec_h264_common_t*)pWrappedCodec; + + if (!pWrappedCodec || !pcInDataPtr || !nInDataSize || !ppOutDataPtr) { + INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR); + } + //INTEL_DEBUG_INFO("Size=%u", nInDataSize); + if (!m_bOpened) { + INTEL_CHECK_STATUS(MFX_ERR_NOT_INITIALIZED); + } + + + /* 5.3. NAL Unit Octet Usage + +---------------+ + |0|1|2|3|4|5|6|7| + +-+-+-+-+-+-+-+-+ + |F|NRI| Type | + +---------------+ + */ + if (pcInDataPtr[0] & 0x80) { // F ?== 1 + /* reset accumulator */ + m_nAccumulatorPos = 0; + INTEL_CHECK_STATUS(status = MFX_ERR_UNDEFINED_BEHAVIOR); + } + + // New frame? + if (m_nLastRtpTimestamp != pcRtpHdr->timestamp) { + m_nAccumulatorPos = 0; + m_nLastRtpTimestamp = pcRtpHdr->timestamp; + } + + /* get payload */ + if ((tdav_codec_h264_get_pay(pcInDataPtr, nInDataSize, (const void**)&pay_ptr, &pay_size, &append_scp, &end_of_unit) != 0) || !pay_ptr || !pay_size) { + INTEL_BREAK("Depayloader failed to get H.264 content"); + } #if 1 // TODO: MSDK cannot decode slices - end_of_unit = pcRtpHdr->marker; + end_of_unit = pcRtpHdr->marker; #endif - //append_scp = tsk_true; - size_to_copy = pay_size + (append_scp ? start_code_prefix_size : 0); - // whether it's SPS or PPS (append_scp is false for subsequent FUA chuncks) - sps_or_pps = append_scp && pay_ptr && ((pay_ptr[0] & 0x1F) == 7 || (pay_ptr[0] & 0x1F) == 8); - - // start-accumulator - if (!m_pAccumulatorPtr) - { - if (size_to_copy > xmax_size) - { - INTEL_DEBUG_ERROR("%u too big to contain valid encoded data. xmax_size=%u", size_to_copy, xmax_size); - m_nAccumulatorPos = 0; - return 0; - } - if (!(m_pAccumulatorPtr = (mfxU8*)tsk_calloc(size_to_copy, sizeof(mfxU8)))) - { - INTEL_DEBUG_ERROR("Failed to allocated new buffer"); - m_nAccumulatorPos = 0; - return 0; - } - m_nAccumulatorSize = (mfxU32)size_to_copy; - } - if ((m_nAccumulatorPos + size_to_copy) >= xmax_size) - { - INTEL_DEBUG_ERROR("BufferOverflow"); - m_nAccumulatorPos = 0; - return 0; - } - if ((m_nAccumulatorPos + size_to_copy) > m_nAccumulatorSize) - { - if (!(m_pAccumulatorPtr = (mfxU8*)tsk_realloc(m_pAccumulatorPtr, (m_nAccumulatorPos + size_to_copy)))) - { - INTEL_DEBUG_ERROR("Failed to reallocated new buffer"); - m_nAccumulatorPos = 0; - m_nAccumulatorSize = 0; - return 0; - } - m_nAccumulatorSize = (mfxU32)(m_nAccumulatorPos + size_to_copy); - } - - if (append_scp) - { - memcpy(&m_pAccumulatorPtr[m_nAccumulatorPos], H264_START_CODE_PREFIX, start_code_prefix_size); - m_nAccumulatorPos += (mfxU32)start_code_prefix_size; - } - memcpy(&m_pAccumulatorPtr[m_nAccumulatorPos], pay_ptr, pay_size); - m_nAccumulatorPos += (mfxU32)pay_size; - // end-accumulator - - if (/*rtp_hdr->marker*/end_of_unit) - { - /* decode the picture */ - mfxU32 nOutWidth, nOutHeight; - - // Decode a Unit - status = DecodeFrame(pWrappedCodecH264, m_pAccumulatorPtr, m_nAccumulatorPos, !!sps_or_pps, &pmfxOutSurface, bGotFrame); - if (status != MFX_ERR_NONE) - { - INTEL_DEBUG_WARN("DecodeFrame failed: %d", status); - goto bail; - } - - // Do we have a complete frame? - if (!bGotFrame || !pmfxOutSurface) - { - goto bail; - } + //append_scp = tsk_true; + size_to_copy = pay_size + (append_scp ? start_code_prefix_size : 0); + // whether it's SPS or PPS (append_scp is false for subsequent FUA chuncks) + sps_or_pps = append_scp && pay_ptr && ((pay_ptr[0] & 0x1F) == 7 || (pay_ptr[0] & 0x1F) == 8); + + // start-accumulator + if (!m_pAccumulatorPtr) { + if (size_to_copy > xmax_size) { + INTEL_DEBUG_ERROR("%u too big to contain valid encoded data. xmax_size=%u", size_to_copy, xmax_size); + m_nAccumulatorPos = 0; + return 0; + } + if (!(m_pAccumulatorPtr = (mfxU8*)tsk_calloc(size_to_copy, sizeof(mfxU8)))) { + INTEL_DEBUG_ERROR("Failed to allocated new buffer"); + m_nAccumulatorPos = 0; + return 0; + } + m_nAccumulatorSize = (mfxU32)size_to_copy; + } + if ((m_nAccumulatorPos + size_to_copy) >= xmax_size) { + INTEL_DEBUG_ERROR("BufferOverflow"); + m_nAccumulatorPos = 0; + return 0; + } + if ((m_nAccumulatorPos + size_to_copy) > m_nAccumulatorSize) { + if (!(m_pAccumulatorPtr = (mfxU8*)tsk_realloc(m_pAccumulatorPtr, (m_nAccumulatorPos + size_to_copy)))) { + INTEL_DEBUG_ERROR("Failed to reallocated new buffer"); + m_nAccumulatorPos = 0; + m_nAccumulatorSize = 0; + return 0; + } + m_nAccumulatorSize = (mfxU32)(m_nAccumulatorPos + size_to_copy); + } + + if (append_scp) { + memcpy(&m_pAccumulatorPtr[m_nAccumulatorPos], H264_START_CODE_PREFIX, start_code_prefix_size); + m_nAccumulatorPos += (mfxU32)start_code_prefix_size; + } + memcpy(&m_pAccumulatorPtr[m_nAccumulatorPos], pay_ptr, pay_size); + m_nAccumulatorPos += (mfxU32)pay_size; + // end-accumulator + + if (/*rtp_hdr->marker*/end_of_unit) { + /* decode the picture */ + mfxU32 nOutWidth, nOutHeight; + + // Decode a Unit + status = DecodeFrame(pWrappedCodecH264, m_pAccumulatorPtr, m_nAccumulatorPos, !!sps_or_pps, &pmfxOutSurface, bGotFrame); + if (status != MFX_ERR_NONE) { + INTEL_DEBUG_WARN("DecodeFrame failed: %d", status); + goto bail; + } + + // Do we have a complete frame? + if (!bGotFrame || !pmfxOutSurface) { + goto bail; + } #if INTEL_DX11_D3D - INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Lock(pWrappedCodecH264->D3D11Allocator.pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data))); + INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Lock(pWrappedCodecH264->D3D11Allocator.pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data))); #endif - if (!pmfxOutSurface->Data.Y || !pmfxOutSurface->Data.U || !pmfxOutSurface->Data.V) - { + if (!pmfxOutSurface->Data.Y || !pmfxOutSurface->Data.U || !pmfxOutSurface->Data.V) { #if INTEL_DX11_D3D - INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Unlock(pWrappedCodecH264->D3D11Allocator.pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data))); + INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Unlock(pWrappedCodecH264->D3D11Allocator.pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data))); #endif - goto bail; - } - - if (pmfxOutSurface->Info.CropW > 0 && pmfxOutSurface->Info.CropH > 0) - { - nOutWidth = pmfxOutSurface->Info.CropW; - nOutHeight = pmfxOutSurface->Info.CropH; - } - else - { - nOutWidth = pmfxOutSurface->Info.Width; - nOutHeight = pmfxOutSurface->Info.Height; - } - - nOutXSize = (nOutWidth * nOutHeight * 3) >> 1; // I420 - /* IDR ? */ - if (((pay_ptr[0] & 0x1F) == 0x05) && TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback) - { - INTEL_DEBUG_INFO("Decoded H.264 IDR"); - TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.type = tmedia_video_decode_result_type_idr; - TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.proto_hdr = pcRtpHdr; - TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback(&TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result); - } - /* fill out */ - if (*pOutDataMaxSize < nOutXSize) - { - if ((*ppOutDataPtr = tsk_realloc(*ppOutDataPtr, nOutXSize))) - { - *pOutDataMaxSize = nOutXSize; - } - else - { - *pOutDataMaxSize = 0; - return 0; - } - } - TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.width = nOutWidth; - TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.height = nOutHeight; - - /* layout picture */ - INTEL_CHECK_STATUS(status = IntelCodecDecoder::LayoutPicture(pmfxOutSurface, (mfxU8 *)*ppOutDataPtr)); - nRetSize = nOutXSize; + goto bail; + } + + if (pmfxOutSurface->Info.CropW > 0 && pmfxOutSurface->Info.CropH > 0) { + nOutWidth = pmfxOutSurface->Info.CropW; + nOutHeight = pmfxOutSurface->Info.CropH; + } + else { + nOutWidth = pmfxOutSurface->Info.Width; + nOutHeight = pmfxOutSurface->Info.Height; + } + + nOutXSize = (nOutWidth * nOutHeight * 3) >> 1; // I420 + /* IDR ? */ + if (((pay_ptr[0] & 0x1F) == 0x05) && TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback) { + INTEL_DEBUG_INFO("Decoded H.264 IDR"); + TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.type = tmedia_video_decode_result_type_idr; + TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.proto_hdr = pcRtpHdr; + TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback(&TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result); + } + /* fill out */ + if (*pOutDataMaxSize < nOutXSize) { + if ((*ppOutDataPtr = tsk_realloc(*ppOutDataPtr, nOutXSize))) { + *pOutDataMaxSize = nOutXSize; + } + else { + *pOutDataMaxSize = 0; + return 0; + } + } + TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.width = nOutWidth; + TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.height = nOutHeight; + + /* layout picture */ + INTEL_CHECK_STATUS(status = IntelCodecDecoder::LayoutPicture(pmfxOutSurface, (mfxU8 *)*ppOutDataPtr)); + nRetSize = nOutXSize; #if INTEL_DX11_D3D - INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Unlock(pWrappedCodecH264->D3D11Allocator.pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data))); + INTEL_CHECK_STATUS(status = pWrappedCodecH264->D3D11Allocator.Unlock(pWrappedCodecH264->D3D11Allocator.pthis, pmfxOutSurface->Data.MemId, &(pmfxOutSurface->Data))); #endif - } // else if(rtp_hdr->marker) - - bail: - if (end_of_unit) - { - /* reset accumulator */ - m_nAccumulatorPos = 0; - } - - if (status != MFX_ERR_NONE) - { - INTEL_DEBUG_INFO("Failed to decode the buffer with error code =%d, size=%u, append=%s", status, m_nAccumulatorPos, append_scp ? "yes" : "no"); - if (TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback) - { - TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.type = tmedia_video_decode_result_type_error; - TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.proto_hdr = pcRtpHdr; - TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback(&TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result); - } - } - return nRetSize; - } + } // else if(rtp_hdr->marker) + +bail: + if (end_of_unit) { + /* reset accumulator */ + m_nAccumulatorPos = 0; + } + + if (status != MFX_ERR_NONE) { + INTEL_DEBUG_INFO("Failed to decode the buffer with error code =%d, size=%u, append=%s", status, m_nAccumulatorPos, append_scp ? "yes" : "no"); + if (TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback) { + TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.type = tmedia_video_decode_result_type_error; + TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result.proto_hdr = pcRtpHdr; + TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.callback(&TMEDIA_CODEC_VIDEO(pWrappedCodec)->in.result); + } + } + return nRetSize; + } private: #if 0 - static mfxStatus WriteSection(mfxU8* plane, mfxU16 factor, mfxU16 chunksize, mfxFrameInfo *pInfo, mfxFrameData *pData, mfxU32 i, mfxU32 j, mfxU8 *pDstPtr) - { - memcpy(pDstPtr, plane + (pInfo->CropY * pData->Pitch / factor + pInfo->CropX) + i * pData->Pitch + j, chunksize); - return MFX_ERR_NONE; - } + static mfxStatus WriteSection(mfxU8* plane, mfxU16 factor, mfxU16 chunksize, mfxFrameInfo *pInfo, mfxFrameData *pData, mfxU32 i, mfxU32 j, mfxU8 *pDstPtr) { + memcpy(pDstPtr, plane + (pInfo->CropY * pData->Pitch / factor + pInfo->CropX) + i * pData->Pitch + j, chunksize); + return MFX_ERR_NONE; + } #else #define WriteSection(_plane, _factor, _chunksize, _pInfo, _pData, _i, _j, _pDstPtr) \ memcpy((_pDstPtr), (_plane) + ((_pInfo)->CropY * (_pData)->Pitch / (_factor) + (_pInfo)->CropX) + (_i) * (_pData)->Pitch + (_j), (_chunksize)) @@ -1029,447 +943,391 @@ private: *(_pDstPtr) = *((_plane) + ((_pInfo)->CropY * (_pData)->Pitch / (_factor) + (_pInfo)->CropX) + (_i) * (_pData)->Pitch + (_j)); #endif - static mfxStatus LayoutPicture(mfxFrameSurface1 *pSurface, mfxU8 *pDstPtr) - { + static mfxStatus LayoutPicture(mfxFrameSurface1 *pSurface, mfxU8 *pDstPtr) { #if 1 // ->YUV420 - mfxFrameInfo *pInfo = &pSurface->Info; - mfxFrameData *pData = &pSurface->Data; - mfxU32 i, j, h, w; - - if (pSurface->Info.CropW > 0 && pSurface->Info.CropH > 0) - { - w = pSurface->Info.CropW; - h = pSurface->Info.CropH; - } - else - { - w = pSurface->Info.Width; - h = pSurface->Info.Height; - } - - for (i = 0; i < h; i++) - { - WriteSection(pData->Y, 1, w, pInfo, pData, i, 0, pDstPtr); - pDstPtr += w; - } - - h >>= 1; - for (i = 0; i < h; i++) - { - for (j = 0; j < w; j += 2) - { - WriteSection1(pData->UV, 2, pInfo, pData, i, j, pDstPtr); - pDstPtr += 1; - } - } - - for (i = 0; i < h; i++) - { - for (j = 1; j < w; j += 2) - { - WriteSection1(pData->UV, 2, pInfo, pData, i, j, pDstPtr); - pDstPtr += 1; - } - } + mfxFrameInfo *pInfo = &pSurface->Info; + mfxFrameData *pData = &pSurface->Data; + mfxU32 i, j, h, w; + + if (pSurface->Info.CropW > 0 && pSurface->Info.CropH > 0) { + w = pSurface->Info.CropW; + h = pSurface->Info.CropH; + } + else { + w = pSurface->Info.Width; + h = pSurface->Info.Height; + } + + for (i = 0; i < h; i++) { + WriteSection(pData->Y, 1, w, pInfo, pData, i, 0, pDstPtr); + pDstPtr += w; + } + + h >>= 1; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j += 2) { + WriteSection1(pData->UV, 2, pInfo, pData, i, j, pDstPtr); + pDstPtr += 1; + } + } + + for (i = 0; i < h; i++) { + for (j = 1; j < w; j += 2) { + WriteSection1(pData->UV, 2, pInfo, pData, i, j, pDstPtr); + pDstPtr += 1; + } + } #elif 1 // ->NV12 - mfxFrameInfo *pInfo = &pSurface->Info; - mfxFrameData *pData = &pSurface->Data; - mfxU32 i, j, h, w; - - if (pSurface->Info.CropW > 0 && pSurface->Info.CropH > 0) - { - w = pSurface->Info.CropW; - h = pSurface->Info.CropH; - } - else - { - w = pSurface->Info.Width; - h = pSurface->Info.Height; - } - - for (i = 0; i < h; i++) - { - WriteSection(pData->Y, 1, w, pInfo, pData, i, 0, pDstPtr); - pDstPtr += w; - } - - h >>= 1; - for (i = 0; i < h; i++) - { - for (j = 0; j < w; j += 2) - { - WriteSection1(pData->UV, 2, pInfo, pData, i, j, &pDstPtr[0]); - WriteSection1(pData->UV, 2, pInfo, pData, i, j + 1, &pDstPtr[1]); - pDstPtr += 2; - } - } + mfxFrameInfo *pInfo = &pSurface->Info; + mfxFrameData *pData = &pSurface->Data; + mfxU32 i, j, h, w; + + if (pSurface->Info.CropW > 0 && pSurface->Info.CropH > 0) { + w = pSurface->Info.CropW; + h = pSurface->Info.CropH; + } + else { + w = pSurface->Info.Width; + h = pSurface->Info.Height; + } + + for (i = 0; i < h; i++) { + WriteSection(pData->Y, 1, w, pInfo, pData, i, 0, pDstPtr); + pDstPtr += w; + } + + h >>= 1; + for (i = 0; i < h; i++) { + for (j = 0; j < w; j += 2) { + WriteSection1(pData->UV, 2, pInfo, pData, i, j, &pDstPtr[0]); + WriteSection1(pData->UV, 2, pInfo, pData, i, j + 1, &pDstPtr[1]); + pDstPtr += 2; + } + } #endif - return MFX_ERR_NONE; - } - - mfxStatus DecodeFrame(struct tdav_codec_h264_intel_s* pWrappedCodec, const mfxU8* pcInDataPtr, mfxU32 nInDataSize, bool bSpsOrPps, mfxFrameSurface1** ppmfxOutSurface, bool &bGotFrame) - { - mfxStatus status = MFX_ERR_NONE; - int nSurfaceIndex; - mfxSyncPoint syncp; - bGotFrame = false; - *ppmfxOutSurface = NULL; - mfxFrameSurface1* pmfxOutSurface = NULL; - -#if 0 - if (!bSpsOrPps && !m_bInit) - { - INTEL_CHECK_STATUS(status = MFX_ERR_NOT_INITIALIZED); - } + return MFX_ERR_NONE; + } + + mfxStatus DecodeFrame(struct tdav_codec_h264_intel_s* pWrappedCodec, const mfxU8* pcInDataPtr, mfxU32 nInDataSize, bool bSpsOrPps, mfxFrameSurface1** ppmfxOutSurface, bool &bGotFrame) { + mfxStatus status = MFX_ERR_NONE; + int nSurfaceIndex; + mfxSyncPoint syncp; + bGotFrame = false; + *ppmfxOutSurface = NULL; + mfxFrameSurface1* pmfxOutSurface = NULL; + +#if 0 + if (!bSpsOrPps && !m_bInit) { + INTEL_CHECK_STATUS(status = MFX_ERR_NOT_INITIALIZED); + } #endif - if (m_sBitstream.DataLength < nInDataSize) - { - INTEL_CHECK_STATUS(status = AllocateBitstream(nInDataSize)); - } - memcpy(m_sBitstream.Data, pcInDataPtr, nInDataSize); - m_sBitstream.DataOffset = 0; - m_sBitstream.DataLength = nInDataSize; - m_sBitstream.DataFlag = MFX_BITSTREAM_COMPLETE_FRAME; - - if (bSpsOrPps || !m_bInit) - { - memset(&m_sParamReq, 0, sizeof(m_sParamReq)); - m_sParamReq.mfx.CodecId = MFX_CODEC_AVC; - m_sParamReq.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12; - m_sParamReq.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; + if (m_sBitstream.DataLength < nInDataSize) { + INTEL_CHECK_STATUS(status = AllocateBitstream(nInDataSize)); + } + memcpy(m_sBitstream.Data, pcInDataPtr, nInDataSize); + m_sBitstream.DataOffset = 0; + m_sBitstream.DataLength = nInDataSize; + m_sBitstream.DataFlag = MFX_BITSTREAM_COMPLETE_FRAME; + + if (bSpsOrPps || !m_bInit) { + memset(&m_sParamReq, 0, sizeof(m_sParamReq)); + m_sParamReq.mfx.CodecId = MFX_CODEC_AVC; + m_sParamReq.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12; + m_sParamReq.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420; #if INTEL_DX11_D3D - m_sParamReq.IOPattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY; + m_sParamReq.IOPattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY; #else - m_sParamReq.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; + m_sParamReq.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; #endif - m_sParamReq.AsyncDepth = 1; // Low latency: limits internal frame buffering - - status = m_Inst.DecodeHeader(&m_sBitstream, &m_sParamReq); - if (status == MFX_WRN_PARTIAL_ACCELERATION) - { - status = MFX_ERR_NONE; - } - INTEL_CHECK_STATUS(status); - - memcpy(&m_sParamSel, &m_sParamReq, sizeof(m_sParamSel)); - - // Check parameters - status = m_Inst.Query(&m_sParamReq, &m_sParamReq); - if (status != MFX_ERR_NONE && status != MFX_WRN_INCOMPATIBLE_VIDEO_PARAM /* Best one will be selected by the encoder */) - { - INTEL_CHECK_STATUS(status); - } - - // Query number required surfaces for encoder - memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest)); - INTEL_CHECK_STATUS(status = m_Inst.QueryIOSurf(&m_sParamReq, &m_sAllocRequest)); + m_sParamReq.AsyncDepth = 1; // Low latency: limits internal frame buffering + + status = m_Inst.DecodeHeader(&m_sBitstream, &m_sParamReq); + if (status == MFX_WRN_PARTIAL_ACCELERATION) { + status = MFX_ERR_NONE; + } + INTEL_CHECK_STATUS(status); + + memcpy(&m_sParamSel, &m_sParamReq, sizeof(m_sParamSel)); + + // Check parameters + status = m_Inst.Query(&m_sParamReq, &m_sParamReq); + if (status != MFX_ERR_NONE && status != MFX_WRN_INCOMPATIBLE_VIDEO_PARAM /* Best one will be selected by the encoder */) { + INTEL_CHECK_STATUS(status); + } + + // Query number required surfaces for encoder + memset(&m_sAllocRequest, 0, sizeof(m_sAllocRequest)); + INTEL_CHECK_STATUS(status = m_Inst.QueryIOSurf(&m_sParamReq, &m_sAllocRequest)); #if INTEL_DX11_D3D - m_sAllocRequest.Type |= D3D11_WILL_READ; // Hint to DX11 memory handler that application will read data from output surfaces + m_sAllocRequest.Type |= D3D11_WILL_READ; // Hint to DX11 memory handler that application will read data from output surfaces #endif - // Allocate surfaces for decoder + // Allocate surfaces for decoder #if INTEL_DX11_D3D - INTEL_CHECK_STATUS(status = pWrappedCodec->D3D11Allocator.Alloc(pWrappedCodec->D3D11Allocator.pthis, &m_sAllocRequest, &m_sD3D11Response)); - if (m_sD3D11Response.NumFrameActual == 0) - { - INTEL_CHECK_STATUS(status = MFX_ERR_UNKNOWN); - } - INTEL_DEBUG_INFO("nEncSurfNum = %hu", m_sD3D11Response.NumFrameActual); - INTEL_CHECK_STATUS(status = AllocSurfaces(m_sD3D11Response.NumFrameActual, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo)); + INTEL_CHECK_STATUS(status = pWrappedCodec->D3D11Allocator.Alloc(pWrappedCodec->D3D11Allocator.pthis, &m_sAllocRequest, &m_sD3D11Response)); + if (m_sD3D11Response.NumFrameActual == 0) { + INTEL_CHECK_STATUS(status = MFX_ERR_UNKNOWN); + } + INTEL_DEBUG_INFO("nEncSurfNum = %hu", m_sD3D11Response.NumFrameActual); + INTEL_CHECK_STATUS(status = AllocSurfaces(m_sD3D11Response.NumFrameActual, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo)); #else - INTEL_DEBUG_INFO("nEncSurfNum = %hu", m_sAllocRequest.NumFrameSuggested); - INTEL_CHECK_STATUS(status = AllocSurfaces(m_sAllocRequest.NumFrameSuggested, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo)); -#endif - // Initialize the Media SDK decoder - status = m_Inst.Init(&m_sParamReq); - if (status != MFX_ERR_NONE && status != MFX_WRN_PARTIAL_ACCELERATION) - { - INTEL_CHECK_STATUS(status); - } - INTEL_DEBUG_INFO("Decoder->Init() returned: %d", status); - - m_bInit = true; - } - - // - // Stage 1: Main decoding loop - // - while (MFX_ERR_NONE <= status || MFX_ERR_MORE_DATA == status || MFX_ERR_MORE_SURFACE == status) - { - if (MFX_WRN_DEVICE_BUSY == status) - { - tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call to DecodeFrameAsync - } - - if (MFX_ERR_MORE_DATA == status) - { - return MFX_ERR_NONE; - } - - if (MFX_ERR_MORE_SURFACE == status || MFX_ERR_NONE == status) - { - nSurfaceIndex = GetFreeSurfaceIndex(); // Find free frame surface - if (MFX_ERR_NOT_FOUND == nSurfaceIndex) - { - INTEL_CHECK_STATUS((status = 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 - status = m_Inst.DecodeFrameAsync(&m_sBitstream, m_ppSurfacePtrs[nSurfaceIndex], &pmfxOutSurface, &syncp); - - // Ignore warnings if output is available, - // if no output and no action required just repeat the DecodeFrameAsync call - if (MFX_ERR_NONE < status && syncp) - { - status = MFX_ERR_NONE; - } - - if (MFX_ERR_NONE == status) - { - status = m_pSession->SyncOperation(syncp, 60000); // Synchronize. Wait until decoded frame is ready - } - - if (MFX_ERR_NONE == status) - { - bGotFrame = true; - if (pmfxOutSurface) - { - *ppmfxOutSurface = pmfxOutSurface; - } - } - } - - // - // Stage 2: Retrieve the buffered decoded frames - // - while (MFX_ERR_NONE <= status || MFX_ERR_MORE_SURFACE == status) - { - if (MFX_WRN_DEVICE_BUSY == status) - { - tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call to DecodeFrameAsync - } - - nSurfaceIndex = GetFreeSurfaceIndex(); // Find free frame surface - if (MFX_ERR_NOT_FOUND == nSurfaceIndex) - { - INTEL_CHECK_STATUS((status = MFX_ERR_MEMORY_ALLOC)); - } - - // Decode a frame asychronously (returns immediately) - status = m_Inst.DecodeFrameAsync(NULL, m_ppSurfacePtrs[nSurfaceIndex], ppmfxOutSurface, &syncp); - - // Ignore warnings if output is available, - // if no output and no action required just repeat the DecodeFrameAsync call - if (MFX_ERR_NONE < status && syncp) - { - status = MFX_ERR_NONE; - } - - if (MFX_ERR_NONE == status) - { - status = m_pSession->SyncOperation(syncp, 60000); // Synchronize. Waits until decoded frame is ready - } - - if (MFX_ERR_NONE == status) - { - bGotFrame = true; - if (pmfxOutSurface) - { - *ppmfxOutSurface = pmfxOutSurface; - } - } - } - - status = MFX_ERR_NONE; - - bail: - return status; - } + INTEL_DEBUG_INFO("nEncSurfNum = %hu", m_sAllocRequest.NumFrameSuggested); + INTEL_CHECK_STATUS(status = AllocSurfaces(m_sAllocRequest.NumFrameSuggested, m_sAllocRequest.Info.Width, m_sAllocRequest.Info.Height, &m_sParamReq.mfx.FrameInfo)); +#endif + // Initialize the Media SDK decoder + status = m_Inst.Init(&m_sParamReq); + if (status != MFX_ERR_NONE && status != MFX_WRN_PARTIAL_ACCELERATION) { + INTEL_CHECK_STATUS(status); + } + INTEL_DEBUG_INFO("Decoder->Init() returned: %d", status); + + m_bInit = true; + } + + // + // Stage 1: Main decoding loop + // + while (MFX_ERR_NONE <= status || MFX_ERR_MORE_DATA == status || MFX_ERR_MORE_SURFACE == status) { + if (MFX_WRN_DEVICE_BUSY == status) { + tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call to DecodeFrameAsync + } + + if (MFX_ERR_MORE_DATA == status) { + return MFX_ERR_NONE; + } + + if (MFX_ERR_MORE_SURFACE == status || MFX_ERR_NONE == status) { + nSurfaceIndex = GetFreeSurfaceIndex(); // Find free frame surface + if (MFX_ERR_NOT_FOUND == nSurfaceIndex) { + INTEL_CHECK_STATUS((status = 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 + status = m_Inst.DecodeFrameAsync(&m_sBitstream, m_ppSurfacePtrs[nSurfaceIndex], &pmfxOutSurface, &syncp); + + // Ignore warnings if output is available, + // if no output and no action required just repeat the DecodeFrameAsync call + if (MFX_ERR_NONE < status && syncp) { + status = MFX_ERR_NONE; + } + + if (MFX_ERR_NONE == status) { + status = m_pSession->SyncOperation(syncp, 60000); // Synchronize. Wait until decoded frame is ready + } + + if (MFX_ERR_NONE == status) { + bGotFrame = true; + if (pmfxOutSurface) { + *ppmfxOutSurface = pmfxOutSurface; + } + } + } + + // + // Stage 2: Retrieve the buffered decoded frames + // + while (MFX_ERR_NONE <= status || MFX_ERR_MORE_SURFACE == status) { + if (MFX_WRN_DEVICE_BUSY == status) { + tsk_thread_sleep(1); // Wait if device is busy, then repeat the same call to DecodeFrameAsync + } + + nSurfaceIndex = GetFreeSurfaceIndex(); // Find free frame surface + if (MFX_ERR_NOT_FOUND == nSurfaceIndex) { + INTEL_CHECK_STATUS((status = MFX_ERR_MEMORY_ALLOC)); + } + + // Decode a frame asychronously (returns immediately) + status = m_Inst.DecodeFrameAsync(NULL, m_ppSurfacePtrs[nSurfaceIndex], ppmfxOutSurface, &syncp); + + // Ignore warnings if output is available, + // if no output and no action required just repeat the DecodeFrameAsync call + if (MFX_ERR_NONE < status && syncp) { + status = MFX_ERR_NONE; + } + + if (MFX_ERR_NONE == status) { + status = m_pSession->SyncOperation(syncp, 60000); // Synchronize. Waits until decoded frame is ready + } + + if (MFX_ERR_NONE == status) { + bGotFrame = true; + if (pmfxOutSurface) { + *ppmfxOutSurface = pmfxOutSurface; + } + } + } + + status = MFX_ERR_NONE; + +bail: + return status; + } private: - mfxU8 *m_pAccumulatorPtr; - mfxU32 m_nAccumulatorSize; - mfxU32 m_nAccumulatorPos; - mfxU32 m_nLastRtpTimestamp; - MFXVideoDECODE m_Inst; - bool m_bInit; + mfxU8 *m_pAccumulatorPtr; + mfxU32 m_nAccumulatorSize; + mfxU32 m_nAccumulatorPos; + mfxU32 m_nLastRtpTimestamp; + MFXVideoDECODE m_Inst; + bool m_bInit; }; /* ============ H.264 Base/Main Profile X.X Plugin interface functions ================= */ static int tdav_codec_h264_intel_set(tmedia_codec_t* self, const tmedia_param_t* param) { - tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self; - if (param->value_type == tmedia_pvt_int32) - { - if (tsk_striequals(param->key, "action")) - { - tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value); - switch (action) { - case tmedia_codec_action_encode_idr: - { - h264->encoder.force_idr = tsk_true; - return 0; - } - case tmedia_codec_action_bw_up: - case tmedia_codec_action_bw_down: - { - if (self->opened) - { - INTEL_CHECK_STATUS(h264->encoder.pInst->UpdateBandwidth(action == tmedia_codec_action_bw_up, TMEDIA_CODEC(h264)->bandwidth_max_upload)); - } - break; - } - } - } - else if (tsk_striequals(param->key, "bw_kbps")) // both up and down (from the SDP) - { - int32_t max_bw_userdefine = tmedia_defaults_get_bandwidth_video_upload_max(); - int32_t max_bw_new = *((int32_t*)param->value); - if (max_bw_userdefine > 0) - { - // do not use more than what the user defined in it's configuration - TMEDIA_CODEC(h264)->bandwidth_max_upload = TSK_MIN(max_bw_new, max_bw_userdefine); - } - else - { - TMEDIA_CODEC(h264)->bandwidth_max_upload = max_bw_new; - } - INTEL_DEBUG_INFO("bandwidth-max-upload=%d", TMEDIA_CODEC(h264)->bandwidth_max_upload); - if (self->opened) - { - INTEL_CHECK_STATUS(h264->encoder.pInst->SetMaxBandwidth(TMEDIA_CODEC(h264)->bandwidth_max_upload)); - } - return 0; - } - else if (tsk_striequals(param->key, "bandwidth-max-upload")) - { - int32_t bw_max_upload = *((int32_t*)param->value); - TSK_DEBUG_INFO("OpenH264 codec: bandwidth-max-upload=%d", bw_max_upload); - TMEDIA_CODEC(h264)->bandwidth_max_upload = bw_max_upload; - if (self->opened) - { - INTEL_CHECK_STATUS(h264->encoder.pInst->SetMaxBandwidth(TMEDIA_CODEC(h264)->bandwidth_max_upload)); - } - return 0; - } - else if (tsk_striequals(param->key, "rotation")) - { - int rotation = *((int32_t*)param->value); - if (h264->encoder.rotation != rotation) - { - if (self->opened) - { - int ret; - h264->encoder.rotation = rotation; - if ((ret = tdav_codec_h264_intel_close_encoder(h264))) - { - return ret; - } - if ((ret = tdav_codec_h264_intel_open_encoder(h264))) - { - return ret; - } - } - } - return 0; - } - } + tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self; + if (param->value_type == tmedia_pvt_int32) { + if (tsk_striequals(param->key, "action")) { + tmedia_codec_action_t action = (tmedia_codec_action_t)TSK_TO_INT32((uint8_t*)param->value); + switch (action) { + case tmedia_codec_action_encode_idr: { + h264->encoder.force_idr = tsk_true; + return 0; + } + case tmedia_codec_action_bw_up: + case tmedia_codec_action_bw_down: { + if (self->opened) { + INTEL_CHECK_STATUS(h264->encoder.pInst->UpdateBandwidth(action == tmedia_codec_action_bw_up, TMEDIA_CODEC(h264)->bandwidth_max_upload)); + } + break; + } + } + } + else if (tsk_striequals(param->key, "bw_kbps")) { // both up and down (from the SDP) + int32_t max_bw_userdefine = tmedia_defaults_get_bandwidth_video_upload_max(); + int32_t max_bw_new = *((int32_t*)param->value); + if (max_bw_userdefine > 0) { + // do not use more than what the user defined in it's configuration + TMEDIA_CODEC(h264)->bandwidth_max_upload = TSK_MIN(max_bw_new, max_bw_userdefine); + } + else { + TMEDIA_CODEC(h264)->bandwidth_max_upload = max_bw_new; + } + INTEL_DEBUG_INFO("bandwidth-max-upload=%d", TMEDIA_CODEC(h264)->bandwidth_max_upload); + if (self->opened) { + INTEL_CHECK_STATUS(h264->encoder.pInst->SetMaxBandwidth(TMEDIA_CODEC(h264)->bandwidth_max_upload)); + } + return 0; + } + else if (tsk_striequals(param->key, "bandwidth-max-upload")) { + int32_t bw_max_upload = *((int32_t*)param->value); + TSK_DEBUG_INFO("OpenH264 codec: bandwidth-max-upload=%d", bw_max_upload); + TMEDIA_CODEC(h264)->bandwidth_max_upload = bw_max_upload; + if (self->opened) { + INTEL_CHECK_STATUS(h264->encoder.pInst->SetMaxBandwidth(TMEDIA_CODEC(h264)->bandwidth_max_upload)); + } + return 0; + } + else if (tsk_striequals(param->key, "rotation")) { + int rotation = *((int32_t*)param->value); + if (h264->encoder.rotation != rotation) { + if (self->opened) { + int ret; + h264->encoder.rotation = rotation; + if ((ret = tdav_codec_h264_intel_close_encoder(h264))) { + return ret; + } + if ((ret = tdav_codec_h264_intel_open_encoder(h264))) { + return ret; + } + } + } + return 0; + } + } bail: - return -1; + return -1; } static int tdav_codec_h264_intel_open(tmedia_codec_t* self) { - int ret; - tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self; + int ret; + tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self; - if (!h264) { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!h264) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - /* the caller (base class) already checked that the codec is not opened */ + /* the caller (base class) already checked that the codec is not opened */ - // Encoder - if ((ret = tdav_codec_h264_intel_open_encoder(h264))) { - return ret; - } + // Encoder + if ((ret = tdav_codec_h264_intel_open_encoder(h264))) { + return ret; + } - // Decoder - if ((ret = tdav_codec_h264_intel_open_decoder(h264))) { - return ret; - } + // Decoder + if ((ret = tdav_codec_h264_intel_open_decoder(h264))) { + return ret; + } - return 0; + return 0; } static int tdav_codec_h264_intel_close(tmedia_codec_t* self) { - tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self; + tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self; - if (!h264) - { - INTEL_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!h264) { + INTEL_DEBUG_ERROR("Invalid parameter"); + return -1; + } - /* the caller (base class) alreasy checked that the codec is opened */ + /* the caller (base class) alreasy checked that the codec is opened */ - // Encoder - tdav_codec_h264_intel_close_encoder(h264); + // Encoder + tdav_codec_h264_intel_close_encoder(h264); - // Decoder - tdav_codec_h264_intel_close_decoder(h264); + // Decoder + tdav_codec_h264_intel_close_decoder(h264); - return 0; + return 0; } static tsk_size_t tdav_codec_h264_intel_encode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size) { - tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self; - (void)(out_data); - (void)(out_max_size); - - if (!h264 || !h264->encoder.pInst) - { - INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR); - } - INTEL_CHECK_STATUS(h264->encoder.pInst->Encode(self, (const mfxU8*)in_data, (mfxU32)in_size)); + tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self; + (void)(out_data); + (void)(out_max_size); + + if (!h264 || !h264->encoder.pInst) { + INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR); + } + INTEL_CHECK_STATUS(h264->encoder.pInst->Encode(self, (const mfxU8*)in_data, (mfxU32)in_size)); bail: - return 0; + return 0; } static tsk_size_t tdav_codec_h264_intel_decode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr) { - tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self; + tdav_codec_h264_intel_t* h264 = (tdav_codec_h264_intel_t*)self; - if (!h264 || !h264->decoder.pInst) - { - INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR); - } - return (tsk_size_t)h264->decoder.pInst->Decode(self, (const mfxU8*)in_data, (mfxU32)in_size, out_data, out_max_size, (const trtp_rtp_header_t*)proto_hdr); + if (!h264 || !h264->decoder.pInst) { + INTEL_CHECK_STATUS(MFX_ERR_NULL_PTR); + } + return (tsk_size_t)h264->decoder.pInst->Decode(self, (const mfxU8*)in_data, (mfxU32)in_size, out_data, out_max_size, (const trtp_rtp_header_t*)proto_hdr); bail: - return 0; + return 0; } static tsk_bool_t tdav_codec_h264_intel_sdp_att_match(const tmedia_codec_t* self, const char* att_name, const char* att_value) { - return tdav_codec_h264_common_sdp_att_match((tdav_codec_h264_common_t*)self, att_name, att_value); + return tdav_codec_h264_common_sdp_att_match((tdav_codec_h264_common_t*)self, att_name, att_value); } static char* tdav_codec_h264_intel_sdp_att_get(const tmedia_codec_t* self, const char* att_name) { - char* att = tdav_codec_h264_common_sdp_att_get((const tdav_codec_h264_common_t*)self, att_name); - if (att && tsk_striequals(att_name, "fmtp")) { - tsk_strcat(&att, "; impl=intel"); - } - return att; + char* att = tdav_codec_h264_common_sdp_att_get((const tdav_codec_h264_common_t*)self, att_name); + if (att && tsk_striequals(att_name, "fmtp")) { + tsk_strcat(&att, "; impl=intel"); + } + return att; } /* ============ H.264 Base Profile Plugin interface ================= */ @@ -1477,63 +1335,61 @@ static char* tdav_codec_h264_intel_sdp_att_get(const tmedia_codec_t* self, const /* constructor */ static tsk_object_t* tdav_codec_h264_intel_base_ctor(tsk_object_t * self, va_list * app) { - tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self; - if (h264) { - /* init base: called by tmedia_codec_create() */ - /* init self */ - if (tdav_codec_h264_intel_init(h264, profile_idc_baseline) != 0) { - return tsk_null; - } - } - return self; + tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self; + if (h264) { + /* init base: called by tmedia_codec_create() */ + /* init self */ + if (tdav_codec_h264_intel_init(h264, profile_idc_baseline) != 0) { + return tsk_null; + } + } + return self; } /* destructor */ static tsk_object_t* tdav_codec_h264_intel_base_dtor(tsk_object_t * self) { - tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self; - if (h264) { - /* deinit base */ - tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self)); - /* deinit self */ - tdav_codec_h264_intel_deinit(h264); - } - - return self; + tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self; + if (h264) { + /* deinit base */ + tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self)); + /* deinit self */ + tdav_codec_h264_intel_deinit(h264); + } + + return self; } /* object definition */ -static const tsk_object_def_t tdav_codec_h264_intel_base_def_s = -{ - sizeof(tdav_codec_h264_intel_t), - tdav_codec_h264_intel_base_ctor, - tdav_codec_h264_intel_base_dtor, - tmedia_codec_cmp, +static const tsk_object_def_t tdav_codec_h264_intel_base_def_s = { + sizeof(tdav_codec_h264_intel_t), + tdav_codec_h264_intel_base_ctor, + tdav_codec_h264_intel_base_dtor, + tmedia_codec_cmp, }; /* plugin definition*/ -static const tmedia_codec_plugin_def_t tdav_codec_h264_intel_base_plugin_def_s = -{ - &tdav_codec_h264_intel_base_def_s, - - tmedia_video, - tmedia_codec_id_h264_bp, - "H264", - "H264 Base Profile (Intel Media SDK)", - TMEDIA_CODEC_FORMAT_H264_BP, - tsk_true, - 90000, // rate - - /* audio */ - { 0 }, - - /* video (width, height, fps) */ - { 176, 144, 0 }, // fps is @deprecated - - tdav_codec_h264_intel_set, - tdav_codec_h264_intel_open, - tdav_codec_h264_intel_close, - tdav_codec_h264_intel_encode, - tdav_codec_h264_intel_decode, - tdav_codec_h264_intel_sdp_att_match, - tdav_codec_h264_intel_sdp_att_get +static const tmedia_codec_plugin_def_t tdav_codec_h264_intel_base_plugin_def_s = { + &tdav_codec_h264_intel_base_def_s, + + tmedia_video, + tmedia_codec_id_h264_bp, + "H264", + "H264 Base Profile (Intel Media SDK)", + TMEDIA_CODEC_FORMAT_H264_BP, + tsk_true, + 90000, // rate + + /* audio */ + { 0 }, + + /* video (width, height, fps) */ + { 176, 144, 0 }, // fps is @deprecated + + tdav_codec_h264_intel_set, + tdav_codec_h264_intel_open, + tdav_codec_h264_intel_close, + tdav_codec_h264_intel_encode, + tdav_codec_h264_intel_decode, + tdav_codec_h264_intel_sdp_att_match, + tdav_codec_h264_intel_sdp_att_get }; const tmedia_codec_plugin_def_t *tdav_codec_h264_intel_base_plugin_def_t = &tdav_codec_h264_intel_base_plugin_def_s; @@ -1543,64 +1399,61 @@ const tmedia_codec_plugin_def_t *tdav_codec_h264_intel_base_plugin_def_t = &tdav /* constructor */ static tsk_object_t* tdav_codec_h264_intel_main_ctor(tsk_object_t * self, va_list * app) { - tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self; - if (h264) { - /* init main: called by tmedia_codec_create() */ - /* init self */ - if (tdav_codec_h264_intel_init(h264, profile_idc_main) != 0) { - return tsk_null; - } - } - return self; + tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self; + if (h264) { + /* init main: called by tmedia_codec_create() */ + /* init self */ + if (tdav_codec_h264_intel_init(h264, profile_idc_main) != 0) { + return tsk_null; + } + } + return self; } /* destructor */ static tsk_object_t* tdav_codec_h264_intel_main_dtor(tsk_object_t * self) { - tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self; - if (h264) - { - /* deinit main */ - tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self)); - /* deinit self */ - tdav_codec_h264_intel_deinit(h264); - } - - return self; + tdav_codec_h264_intel_t *h264 = (tdav_codec_h264_intel_t*)self; + if (h264) { + /* deinit main */ + tdav_codec_h264_common_deinit(TDAV_CODEC_H264_COMMON(self)); + /* deinit self */ + tdav_codec_h264_intel_deinit(h264); + } + + return self; } /* object definition */ -static const tsk_object_def_t tdav_codec_h264_intel_main_def_s = -{ - sizeof(tdav_codec_h264_intel_t), - tdav_codec_h264_intel_main_ctor, - tdav_codec_h264_intel_main_dtor, - tmedia_codec_cmp, +static const tsk_object_def_t tdav_codec_h264_intel_main_def_s = { + sizeof(tdav_codec_h264_intel_t), + tdav_codec_h264_intel_main_ctor, + tdav_codec_h264_intel_main_dtor, + tmedia_codec_cmp, }; /* plugin definition*/ -static const tmedia_codec_plugin_def_t tdav_codec_h264_intel_main_plugin_def_s = -{ - &tdav_codec_h264_intel_main_def_s, - - tmedia_video, - tmedia_codec_id_h264_mp, - "H264", - "H264 main Profile (Intel Media SDK)", - TMEDIA_CODEC_FORMAT_H264_MP, - tsk_true, - 90000, // rate - - /* audio */ - { 0 }, - - /* video (width, height, fps) */ - { 176, 144, 0 }, // fps is @deprecated - - tdav_codec_h264_intel_set, - tdav_codec_h264_intel_open, - tdav_codec_h264_intel_close, - tdav_codec_h264_intel_encode, - tdav_codec_h264_intel_decode, - tdav_codec_h264_intel_sdp_att_match, - tdav_codec_h264_intel_sdp_att_get +static const tmedia_codec_plugin_def_t tdav_codec_h264_intel_main_plugin_def_s = { + &tdav_codec_h264_intel_main_def_s, + + tmedia_video, + tmedia_codec_id_h264_mp, + "H264", + "H264 main Profile (Intel Media SDK)", + TMEDIA_CODEC_FORMAT_H264_MP, + tsk_true, + 90000, // rate + + /* audio */ + { 0 }, + + /* video (width, height, fps) */ + { 176, 144, 0 }, // fps is @deprecated + + tdav_codec_h264_intel_set, + tdav_codec_h264_intel_open, + tdav_codec_h264_intel_close, + tdav_codec_h264_intel_encode, + tdav_codec_h264_intel_decode, + tdav_codec_h264_intel_sdp_att_match, + tdav_codec_h264_intel_sdp_att_get }; const tmedia_codec_plugin_def_t *tdav_codec_h264_intel_main_plugin_def_t = &tdav_codec_h264_intel_main_plugin_def_s; @@ -1608,171 +1461,158 @@ const tmedia_codec_plugin_def_t *tdav_codec_h264_intel_main_plugin_def_t = &tdav static int tdav_codec_h264_intel_open_encoder(tdav_codec_h264_intel_t* self) { - if (self->encoder.pInst) - { - INTEL_BREAK("Already initialized"); - } + if (self->encoder.pInst) { + INTEL_BREAK("Already initialized"); + } - if (!(self->encoder.pInst = new IntelCodecEncoder(self->mfxSession))) - { - INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); - } - INTEL_CHECK_STATUS(self->encoder.pInst->Open(self)); + if (!(self->encoder.pInst = new IntelCodecEncoder(self->mfxSession))) { + INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); + } + INTEL_CHECK_STATUS(self->encoder.pInst->Open(self)); - return 0; + return 0; bail: - if (self->encoder.pInst) - { - delete self->encoder.pInst, self->encoder.pInst = NULL; - } - return -1; + if (self->encoder.pInst) { + delete self->encoder.pInst, self->encoder.pInst = NULL; + } + return -1; } static int tdav_codec_h264_intel_close_encoder(tdav_codec_h264_intel_t* self) { - if (self) - { - if (self->encoder.pInst) - { - delete self->encoder.pInst; - self->encoder.pInst = NULL; - } - self->encoder.frame_count = 0; - } - return 0; + if (self) { + if (self->encoder.pInst) { + delete self->encoder.pInst; + self->encoder.pInst = NULL; + } + self->encoder.frame_count = 0; + } + return 0; } int tdav_codec_h264_intel_open_decoder(tdav_codec_h264_intel_t* self) { - if (self->decoder.pInst) - { - INTEL_BREAK("Already initialized"); - } + if (self->decoder.pInst) { + INTEL_BREAK("Already initialized"); + } - if (!(self->decoder.pInst = new IntelCodecDecoder(self->mfxSession))) - { - INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); - } - INTEL_CHECK_STATUS(self->decoder.pInst->Open(self)); + if (!(self->decoder.pInst = new IntelCodecDecoder(self->mfxSession))) { + INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); + } + INTEL_CHECK_STATUS(self->decoder.pInst->Open(self)); - return 0; + return 0; bail: - if (self->decoder.pInst) - { - delete self->decoder.pInst, self->decoder.pInst = NULL; - } - return -1; + if (self->decoder.pInst) { + delete self->decoder.pInst, self->decoder.pInst = NULL; + } + return -1; } static int tdav_codec_h264_intel_close_decoder(tdav_codec_h264_intel_t* self) { - if (self) - { - if (self->decoder.pInst) - { - delete self->decoder.pInst; - self->decoder.pInst = NULL; - } - } - return 0; + if (self) { + if (self->decoder.pInst) { + delete self->decoder.pInst; + self->decoder.pInst = NULL; + } + } + return 0; } static int tdav_codec_h264_intel_init(tdav_codec_h264_intel_t* self, profile_idc_t profile) { - int ret = -1; - level_idc_t level; - tdav_codec_h264_common_t* common = (tdav_codec_h264_common_t*)self; + int ret = -1; + level_idc_t level; + tdav_codec_h264_common_t* common = (tdav_codec_h264_common_t*)self; #if INTEL_DX11_D3D - mfxHDL deviceHandle = NULL; + mfxHDL deviceHandle = NULL; #endif - if (!self) { - TSK_DEBUG_ERROR("Invalid parameter"); - goto bail; - } - - if ((ret = tdav_codec_h264_common_init(common))) { - TSK_DEBUG_ERROR("tdav_codec_h264_intel_common_init() faile with error code=%d", ret); - goto bail; - } - - if ((ret = tdav_codec_h264_common_level_from_size(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, &level))) { - TSK_DEBUG_ERROR("Failed to find level for size=[%u, %u]", TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height); - goto bail; - } - - if (/*MFUtils::IsLowLatencyH264SupportsMaxSliceSize()*/0) { // TODO: MSDK doesn't support PM=0. Neg. PM=1 but try to do the best to produce SingleNalUnits - common->pack_mode_local = H264_PACKETIZATION_MODE; - } - else { - common->pack_mode_local = Non_Interleaved_Mode; - } - common->profile = profile; - common->level = level; + if (!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + goto bail; + } + + if ((ret = tdav_codec_h264_common_init(common))) { + TSK_DEBUG_ERROR("tdav_codec_h264_intel_common_init() faile with error code=%d", ret); + goto bail; + } + + if ((ret = tdav_codec_h264_common_level_from_size(TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height, &level))) { + TSK_DEBUG_ERROR("Failed to find level for size=[%u, %u]", TMEDIA_CODEC_VIDEO(self)->out.width, TMEDIA_CODEC_VIDEO(self)->out.height); + goto bail; + } + + if (/*MFUtils::IsLowLatencyH264SupportsMaxSliceSize()*/0) { // TODO: MSDK doesn't support PM=0. Neg. PM=1 but try to do the best to produce SingleNalUnits + common->pack_mode_local = H264_PACKETIZATION_MODE; + } + else { + common->pack_mode_local = Non_Interleaved_Mode; + } + common->profile = profile; + common->level = level; #if 0 - // A.2.1.1 Constrained Baseline profile - // Conformance of a bitstream to the Constrained Baseline profile is indicated by profile_idc being equal to 66 with - // constraint_set1_flag being equal to 1. - common->profile_iop = 0xe0; // "constraint_set0_flag=1 and constraint_set1_flag=1" -> Constrained Baseline profile + // A.2.1.1 Constrained Baseline profile + // Conformance of a bitstream to the Constrained Baseline profile is indicated by profile_idc being equal to 66 with + // constraint_set1_flag being equal to 1. + common->profile_iop = 0xe0; // "constraint_set0_flag=1 and constraint_set1_flag=1" -> Constrained Baseline profile #endif - TMEDIA_CODEC_VIDEO(self)->in.max_mbps = TMEDIA_CODEC_VIDEO(self)->out.max_mbps = H264_MAX_MBPS * 1000; - TMEDIA_CODEC_VIDEO(self)->in.max_br = TMEDIA_CODEC_VIDEO(self)->out.max_br = H264_MAX_BR * 1000; + TMEDIA_CODEC_VIDEO(self)->in.max_mbps = TMEDIA_CODEC_VIDEO(self)->out.max_mbps = H264_MAX_MBPS * 1000; + TMEDIA_CODEC_VIDEO(self)->in.max_br = TMEDIA_CODEC_VIDEO(self)->out.max_br = H264_MAX_BR * 1000; - TMEDIA_CODEC_VIDEO(self)->in.chroma = tmedia_chroma_yuv420p; // decoded - TMEDIA_CODEC_VIDEO(self)->out.chroma = tmedia_chroma_yuv420p; // encoded + TMEDIA_CODEC_VIDEO(self)->in.chroma = tmedia_chroma_yuv420p; // decoded + TMEDIA_CODEC_VIDEO(self)->out.chroma = tmedia_chroma_yuv420p; // encoded - if (!self->mfxSession && !(self->mfxSession = new MFXVideoSession())) - { - INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); - } - INTEL_CHECK_STATUS(self->mfxSession->Init(__IntelDefaultImpl, &__IntelDefaultVer)); + if (!self->mfxSession && !(self->mfxSession = new MFXVideoSession())) { + INTEL_CHECK_STATUS(MFX_ERR_MEMORY_ALLOC); + } + INTEL_CHECK_STATUS(self->mfxSession->Init(__IntelDefaultImpl, &__IntelDefaultVer)); #if INTEL_DX11_D3D - // Create DirectX device context - INTEL_CHECK_STATUS(D3D11_CreateHWDevice(self, *self->mfxSession, &deviceHandle, NULL)); - - // Provide device manager to Media SDK - INTEL_CHECK_STATUS(self->mfxSession->SetHandle(MFX_HANDLE_D3D11_DEVICE, deviceHandle)); - - self->D3D11Allocator.Alloc = D3D11_SimpleAlloc; - self->D3D11Allocator.Free = D3D11_SimpleFree; - self->D3D11Allocator.Lock = D3D11_SimpleLock; - self->D3D11Allocator.Unlock = D3D11_SimpleUnlock; - self->D3D11Allocator.GetHDL = D3D11_SimpleGethdl; - self->D3D11Allocator.pthis = self; - - // Since we are using video memory we must provide Media SDK with an external allocator - INTEL_CHECK_STATUS(self->mfxSession->SetFrameAllocator(&self->D3D11Allocator)); + // Create DirectX device context + INTEL_CHECK_STATUS(D3D11_CreateHWDevice(self, *self->mfxSession, &deviceHandle, NULL)); + + // Provide device manager to Media SDK + INTEL_CHECK_STATUS(self->mfxSession->SetHandle(MFX_HANDLE_D3D11_DEVICE, deviceHandle)); + + self->D3D11Allocator.Alloc = D3D11_SimpleAlloc; + self->D3D11Allocator.Free = D3D11_SimpleFree; + self->D3D11Allocator.Lock = D3D11_SimpleLock; + self->D3D11Allocator.Unlock = D3D11_SimpleUnlock; + self->D3D11Allocator.GetHDL = D3D11_SimpleGethdl; + self->D3D11Allocator.pthis = self; + + // Since we are using video memory we must provide Media SDK with an external allocator + INTEL_CHECK_STATUS(self->mfxSession->SetFrameAllocator(&self->D3D11Allocator)); #endif /* INTEL_DX11_D3D */ - ret = 0; + ret = 0; bail: - return ret; + return ret; } static int tdav_codec_h264_intel_deinit(tdav_codec_h264_intel_t* self) { - if (!self) - { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if (!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - tdav_codec_h264_intel_close((tmedia_codec_t*)self); + tdav_codec_h264_intel_close((tmedia_codec_t*)self); - if (self->mfxSession) - { - delete self->mfxSession, self->mfxSession = NULL; - } + if (self->mfxSession) { + delete self->mfxSession, self->mfxSession = NULL; + } #if INTEL_DX11_D3D - D3D11_CleanupHWDevice(self); + D3D11_CleanupHWDevice(self); #endif /* INTEL_DX11_D3D */ - return 0; + return 0; } @@ -1780,40 +1620,36 @@ static int tdav_codec_h264_intel_deinit(tdav_codec_h264_intel_t* self) static IDXGIAdapter* D3D11_GetIntelDeviceAdapterHandle(mfxHDL _pthis, mfxSession session) { - mfxU32 adapterNum = 0; - mfxIMPL impl; - tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; - - MFXQueryIMPL(session, &impl); - - mfxIMPL baseImpl = MFX_IMPL_BASETYPE(impl); // Extract Media SDK base implementation type - - // get corresponding adapter number - for (mfxU8 i = 0; i < sizeof(implTypes) / sizeof(implTypes[0]); i++) - { - if (implTypes[i].impl == baseImpl) - { - adapterNum = implTypes[i].adapterID; - break; - } - } - - HRESULT hres = CreateDXGIFactory(__uuidof(IDXGIFactory2), (void**)(&pthis->pDXGIFactory)); - if (FAILED(hres)) - { - INTEL_DEBUG_ERROR("CreateDXGIFactory failed: %ld", hres); - return NULL; - } - - IDXGIAdapter* adapter = NULL; - hres = pthis->pDXGIFactory->EnumAdapters(adapterNum, &adapter); - if (FAILED(hres)) - { - INTEL_DEBUG_ERROR("EnumAdapters failed: %ld", hres); - return NULL; - } - - return adapter; + mfxU32 adapterNum = 0; + mfxIMPL impl; + tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; + + MFXQueryIMPL(session, &impl); + + mfxIMPL baseImpl = MFX_IMPL_BASETYPE(impl); // Extract Media SDK base implementation type + + // get corresponding adapter number + for (mfxU8 i = 0; i < sizeof(implTypes) / sizeof(implTypes[0]); i++) { + if (implTypes[i].impl == baseImpl) { + adapterNum = implTypes[i].adapterID; + break; + } + } + + HRESULT hres = CreateDXGIFactory(__uuidof(IDXGIFactory2), (void**)(&pthis->pDXGIFactory)); + if (FAILED(hres)) { + INTEL_DEBUG_ERROR("CreateDXGIFactory failed: %ld", hres); + return NULL; + } + + IDXGIAdapter* adapter = NULL; + hres = pthis->pDXGIFactory->EnumAdapters(adapterNum, &adapter); + if (FAILED(hres)) { + INTEL_DEBUG_ERROR("EnumAdapters failed: %ld", hres); + return NULL; + } + + return adapter; } // Create DirectX 11 device context @@ -1826,394 +1662,361 @@ static IDXGIAdapter* D3D11_GetIntelDeviceAdapterHandle(mfxHDL _pthis, mfxSession // - For switchable graphics solutions (mobile) make sure that Intel device is the active device static mfxStatus D3D11_CreateHWDevice(mfxHDL _pthis, mfxSession session, mfxHDL* deviceHandle, HWND hWnd) { - hWnd; // Window handle not required by DX11 since we do not showcase rendering. - - HRESULT hres = S_OK; - tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; - - static D3D_FEATURE_LEVEL FeatureLevels[] = { - D3D_FEATURE_LEVEL_11_1, - D3D_FEATURE_LEVEL_11_0, - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0 - }; - D3D_FEATURE_LEVEL pFeatureLevelsOut; - - pthis->hAdapter = D3D11_GetIntelDeviceAdapterHandle(_pthis, session); - if (NULL == pthis->hAdapter) - { - INTEL_DEBUG_ERROR("D3D11_GetIntelDeviceAdapterHandle failed"); - return MFX_ERR_DEVICE_FAILED; - } - - hres = D3D11CreateDevice(pthis->hAdapter, - D3D_DRIVER_TYPE_UNKNOWN, - NULL, - 0, - FeatureLevels, - (sizeof(FeatureLevels) / sizeof(FeatureLevels[0])), - D3D11_SDK_VERSION, - &pthis->pD3D11Device, - &pFeatureLevelsOut, - &pthis->pD3D11Ctx); - if (FAILED(hres)) - { - INTEL_DEBUG_ERROR("D3D11CreateDevice failed: %ld", hres); - return MFX_ERR_DEVICE_FAILED; - } - - // turn on multithreading for the DX11 cntext - CComQIPtr<ID3D10Multithread> p_mt(pthis->pD3D11Ctx); - if (p_mt) - { - p_mt->SetMultithreadProtected(true); - } - else - { - INTEL_DEBUG_ERROR("Failed to create ID3D10Multithread object"); - return MFX_ERR_DEVICE_FAILED; - } - - *deviceHandle = (mfxHDL)pthis->pD3D11Device; - return MFX_ERR_NONE; + hWnd; // Window handle not required by DX11 since we do not showcase rendering. + + HRESULT hres = S_OK; + tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; + + static D3D_FEATURE_LEVEL FeatureLevels[] = { + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0 + }; + D3D_FEATURE_LEVEL pFeatureLevelsOut; + + pthis->hAdapter = D3D11_GetIntelDeviceAdapterHandle(_pthis, session); + if (NULL == pthis->hAdapter) { + INTEL_DEBUG_ERROR("D3D11_GetIntelDeviceAdapterHandle failed"); + return MFX_ERR_DEVICE_FAILED; + } + + hres = D3D11CreateDevice(pthis->hAdapter, + D3D_DRIVER_TYPE_UNKNOWN, + NULL, + 0, + FeatureLevels, + (sizeof(FeatureLevels) / sizeof(FeatureLevels[0])), + D3D11_SDK_VERSION, + &pthis->pD3D11Device, + &pFeatureLevelsOut, + &pthis->pD3D11Ctx); + if (FAILED(hres)) { + INTEL_DEBUG_ERROR("D3D11CreateDevice failed: %ld", hres); + return MFX_ERR_DEVICE_FAILED; + } + + // turn on multithreading for the DX11 cntext + CComQIPtr<ID3D10Multithread> p_mt(pthis->pD3D11Ctx); + if (p_mt) { + p_mt->SetMultithreadProtected(true); + } + else { + INTEL_DEBUG_ERROR("Failed to create ID3D10Multithread object"); + return MFX_ERR_DEVICE_FAILED; + } + + *deviceHandle = (mfxHDL)pthis->pD3D11Device; + return MFX_ERR_NONE; } static void D3D11_CleanupHWDevice(mfxHDL _pthis) { - tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; - pthis->pD3D11Device = NULL; - pthis->pDXGIFactory = NULL; - pthis->pD3D11Ctx = NULL; - pthis->hAdapter = NULL; - pthis->pAdapter = NULL; + tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; + pthis->pD3D11Device = NULL; + pthis->pDXGIFactory = NULL; + pthis->pD3D11Ctx = NULL; + pthis->hAdapter = NULL; + pthis->pAdapter = NULL; } static void D3D11_SetHWDeviceContext(mfxHDL _pthis, CComPtr<ID3D11DeviceContext> devCtx) { - tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; - pthis->pD3D11Ctx = devCtx; - devCtx->GetDevice(&pthis->pD3D11Device); + tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; + pthis->pD3D11Ctx = devCtx; + devCtx->GetDevice(&pthis->pD3D11Device); } // Intel Media SDK memory allocator entrypoints.... // - A slightly different allocation procedure is used for encode, decode and VPP static mfxStatus _D3D11_SimpleAlloc(mfxHDL _pthis, mfxFrameAllocRequest *request, mfxFrameAllocResponse *response) { - HRESULT hRes; - tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; - - // Determine surface format (current simple implementation only supports NV12 and RGB4(32)) - DXGI_FORMAT format; - if (MFX_FOURCC_NV12 == request->Info.FourCC) - { - format = DXGI_FORMAT_NV12; - } - else if (MFX_FOURCC_RGB4 == request->Info.FourCC) - { - format = DXGI_FORMAT_B8G8R8A8_UNORM; - } - else - { - format = DXGI_FORMAT_P8; - } - - // Allocate custom container to keep texture and stage buffers for each surface - // Container also stores the intended read and/or write operation. - CustomMemId** mids = new CustomMemId *[request->NumFrameSuggested]; - if (!mids) return MFX_ERR_MEMORY_ALLOC; - for (int i = 0; i < request->NumFrameSuggested; i++) - { - mids[i] = new CustomMemId; - memset(mids[i], 0, sizeof(CustomMemId)); - mids[i]->rw = request->Type & 0xF000; // Set intended read/write operation - } - - request->Type = request->Type & 0x0FFF; - - // because P8 data (bitstream) for h264 encoder should be allocated by CreateBuffer() - // but P8 data (MBData) for MPEG2 encoder should be allocated by CreateTexture2D() - if (request->Info.FourCC == MFX_FOURCC_P8) - { - D3D11_BUFFER_DESC desc = { 0 }; - - desc.ByteWidth = request->Info.Width * request->Info.Height; - desc.Usage = D3D11_USAGE_STAGING; - desc.BindFlags = 0; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - desc.MiscFlags = 0; - desc.StructureByteStride = 0; - - ID3D11Buffer * buffer = 0; - hRes = pthis->pD3D11Device->CreateBuffer(&desc, 0, &buffer); - if (FAILED(hRes)) - { - INTEL_DEBUG_ERROR("CreateBuffer failed:%ld", hRes); - return MFX_ERR_MEMORY_ALLOC; - } - - mids[0]->memId = reinterpret_cast<ID3D11Texture2D *>(buffer); - } - else - { - D3D11_TEXTURE2D_DESC desc = { 0 }; - - desc.Width = request->Info.Width; - desc.Height = request->Info.Height; - desc.MipLevels = 1; - desc.ArraySize = 1; // number of subresources is 1 in this case - desc.Format = format; - desc.SampleDesc.Count = 1; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_DECODER; - desc.MiscFlags = 0; - - if ((MFX_MEMTYPE_FROM_VPPIN & request->Type) && - (DXGI_FORMAT_B8G8R8A8_UNORM == desc.Format)) - { - desc.BindFlags = D3D11_BIND_RENDER_TARGET; - if (desc.ArraySize > 2) - return MFX_ERR_MEMORY_ALLOC; - } - - if ((MFX_MEMTYPE_FROM_VPPOUT & request->Type) || - (MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & request->Type)) - { - desc.BindFlags = D3D11_BIND_RENDER_TARGET; - if (desc.ArraySize > 2) - { - return MFX_ERR_MEMORY_ALLOC; - } - } - - if (DXGI_FORMAT_P8 == desc.Format) - desc.BindFlags = 0; - - ID3D11Texture2D* pTexture2D; - - // Create surface textures - for (size_t i = 0; i < request->NumFrameSuggested / desc.ArraySize; i++) - { - hRes = pthis->pD3D11Device->CreateTexture2D(&desc, NULL, &pTexture2D); - - if (FAILED(hRes)) - { - INTEL_DEBUG_ERROR("CreateTexture2D failed:%ld", hRes); - return MFX_ERR_MEMORY_ALLOC; - } - - mids[i]->memId = pTexture2D; - } - - desc.ArraySize = 1; - desc.Usage = D3D11_USAGE_STAGING; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ /*| D3D11_CPU_ACCESS_WRITE*/; - desc.BindFlags = 0; - desc.MiscFlags = 0; - - // Create surface staging textures - for (size_t i = 0; i < request->NumFrameSuggested; i++) - { - hRes = pthis->pD3D11Device->CreateTexture2D(&desc, NULL, &pTexture2D); - - if (FAILED(hRes)) - { - INTEL_DEBUG_ERROR("CreateTexture2D failed:%ld", hRes); - return MFX_ERR_MEMORY_ALLOC; - } - - mids[i]->memIdStage = pTexture2D; - } - } - - response->mids = (mfxMemId*)mids; - response->NumFrameActual = request->NumFrameSuggested; - - return MFX_ERR_NONE; + HRESULT hRes; + tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; + + // Determine surface format (current simple implementation only supports NV12 and RGB4(32)) + DXGI_FORMAT format; + if (MFX_FOURCC_NV12 == request->Info.FourCC) { + format = DXGI_FORMAT_NV12; + } + else if (MFX_FOURCC_RGB4 == request->Info.FourCC) { + format = DXGI_FORMAT_B8G8R8A8_UNORM; + } + else { + format = DXGI_FORMAT_P8; + } + + // Allocate custom container to keep texture and stage buffers for each surface + // Container also stores the intended read and/or write operation. + CustomMemId** mids = new CustomMemId *[request->NumFrameSuggested]; + if (!mids) { + return MFX_ERR_MEMORY_ALLOC; + } + for (int i = 0; i < request->NumFrameSuggested; i++) { + mids[i] = new CustomMemId; + memset(mids[i], 0, sizeof(CustomMemId)); + mids[i]->rw = request->Type & 0xF000; // Set intended read/write operation + } + + request->Type = request->Type & 0x0FFF; + + // because P8 data (bitstream) for h264 encoder should be allocated by CreateBuffer() + // but P8 data (MBData) for MPEG2 encoder should be allocated by CreateTexture2D() + if (request->Info.FourCC == MFX_FOURCC_P8) { + D3D11_BUFFER_DESC desc = { 0 }; + + desc.ByteWidth = request->Info.Width * request->Info.Height; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + desc.MiscFlags = 0; + desc.StructureByteStride = 0; + + ID3D11Buffer * buffer = 0; + hRes = pthis->pD3D11Device->CreateBuffer(&desc, 0, &buffer); + if (FAILED(hRes)) { + INTEL_DEBUG_ERROR("CreateBuffer failed:%ld", hRes); + return MFX_ERR_MEMORY_ALLOC; + } + + mids[0]->memId = reinterpret_cast<ID3D11Texture2D *>(buffer); + } + else { + D3D11_TEXTURE2D_DESC desc = { 0 }; + + desc.Width = request->Info.Width; + desc.Height = request->Info.Height; + desc.MipLevels = 1; + desc.ArraySize = 1; // number of subresources is 1 in this case + desc.Format = format; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_DECODER; + desc.MiscFlags = 0; + + if ((MFX_MEMTYPE_FROM_VPPIN & request->Type) && + (DXGI_FORMAT_B8G8R8A8_UNORM == desc.Format)) { + desc.BindFlags = D3D11_BIND_RENDER_TARGET; + if (desc.ArraySize > 2) { + return MFX_ERR_MEMORY_ALLOC; + } + } + + if ((MFX_MEMTYPE_FROM_VPPOUT & request->Type) || + (MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & request->Type)) { + desc.BindFlags = D3D11_BIND_RENDER_TARGET; + if (desc.ArraySize > 2) { + return MFX_ERR_MEMORY_ALLOC; + } + } + + if (DXGI_FORMAT_P8 == desc.Format) { + desc.BindFlags = 0; + } + + ID3D11Texture2D* pTexture2D; + + // Create surface textures + for (size_t i = 0; i < request->NumFrameSuggested / desc.ArraySize; i++) { + hRes = pthis->pD3D11Device->CreateTexture2D(&desc, NULL, &pTexture2D); + + if (FAILED(hRes)) { + INTEL_DEBUG_ERROR("CreateTexture2D failed:%ld", hRes); + return MFX_ERR_MEMORY_ALLOC; + } + + mids[i]->memId = pTexture2D; + } + + desc.ArraySize = 1; + desc.Usage = D3D11_USAGE_STAGING; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ /*| D3D11_CPU_ACCESS_WRITE*/; + desc.BindFlags = 0; + desc.MiscFlags = 0; + + // Create surface staging textures + for (size_t i = 0; i < request->NumFrameSuggested; i++) { + hRes = pthis->pD3D11Device->CreateTexture2D(&desc, NULL, &pTexture2D); + + if (FAILED(hRes)) { + INTEL_DEBUG_ERROR("CreateTexture2D failed:%ld", hRes); + return MFX_ERR_MEMORY_ALLOC; + } + + mids[i]->memIdStage = pTexture2D; + } + } + + response->mids = (mfxMemId*)mids; + response->NumFrameActual = request->NumFrameSuggested; + + return MFX_ERR_NONE; } static mfxStatus D3D11_SimpleAlloc(mfxHDL _pthis, mfxFrameAllocRequest *request, mfxFrameAllocResponse *response) { - tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; - mfxStatus sts = MFX_ERR_NONE; - int idx = (MFX_MEMTYPE_FROM_DECODE & request->Type) ? 1 : 0; - - if (request->NumFrameSuggested <= pthis->D3D11SavedAllocResponses[idx].NumFrameActual && - MFX_MEMTYPE_EXTERNAL_FRAME & request->Type && - MFX_MEMTYPE_FROM_DECODE & request->Type && - pthis->D3D11SavedAllocResponses[idx].NumFrameActual != 0) - { - // Memory for this request was already allocated during manual allocation stage. Return saved response - // When decode acceleration device (DXVA) is created it requires a list of d3d surfaces to be passed. - // Therefore Media SDK will ask for the surface info/mids again at Init() stage, thus requiring us to return the saved response - // (No such restriction applies to Encode or VPP) - - *response = pthis->D3D11SavedAllocResponses[idx]; - } - else - { - sts = _D3D11_SimpleAlloc(_pthis, request, response); - pthis->D3D11SavedAllocResponses[idx] = *response; - } - - return sts; + tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; + mfxStatus sts = MFX_ERR_NONE; + int idx = (MFX_MEMTYPE_FROM_DECODE & request->Type) ? 1 : 0; + + if (request->NumFrameSuggested <= pthis->D3D11SavedAllocResponses[idx].NumFrameActual && + MFX_MEMTYPE_EXTERNAL_FRAME & request->Type && + MFX_MEMTYPE_FROM_DECODE & request->Type && + pthis->D3D11SavedAllocResponses[idx].NumFrameActual != 0) { + // Memory for this request was already allocated during manual allocation stage. Return saved response + // When decode acceleration device (DXVA) is created it requires a list of d3d surfaces to be passed. + // Therefore Media SDK will ask for the surface info/mids again at Init() stage, thus requiring us to return the saved response + // (No such restriction applies to Encode or VPP) + + *response = pthis->D3D11SavedAllocResponses[idx]; + } + else { + sts = _D3D11_SimpleAlloc(_pthis, request, response); + pthis->D3D11SavedAllocResponses[idx] = *response; + } + + return sts; } static mfxStatus D3D11_SimpleLock(mfxHDL _pthis, mfxMemId mid, mfxFrameData *ptr) { - HRESULT hRes = S_OK; - tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; - - D3D11_TEXTURE2D_DESC desc = { 0 }; - D3D11_MAPPED_SUBRESOURCE lockedRect = { 0 }; - - CustomMemId* memId = (CustomMemId*)mid; - ID3D11Texture2D* pSurface = (ID3D11Texture2D *)memId->memId; - ID3D11Texture2D* pStage = (ID3D11Texture2D *)memId->memIdStage; - - D3D11_MAP mapType = D3D11_MAP_READ; - UINT mapFlags = D3D11_MAP_FLAG_DO_NOT_WAIT; - - if (NULL == pStage) - { - hRes = pthis->pD3D11Ctx->Map(pSurface, 0, mapType, mapFlags, &lockedRect); - desc.Format = DXGI_FORMAT_P8; - } - else - { - pSurface->GetDesc(&desc); - - // copy data only in case of user wants o read from stored surface - if (memId->rw & D3D11_WILL_READ) - { - pthis->pD3D11Ctx->CopySubresourceRegion(pStage, 0, 0, 0, 0, pSurface, 0, NULL); - } - - do - { - hRes = pthis->pD3D11Ctx->Map(pStage, 0, mapType, mapFlags, &lockedRect); - if (S_OK != hRes && DXGI_ERROR_WAS_STILL_DRAWING != hRes) - { - return MFX_ERR_LOCK_MEMORY; - } - } while (DXGI_ERROR_WAS_STILL_DRAWING == hRes); - } - - if (FAILED(hRes)) - { - return MFX_ERR_LOCK_MEMORY; - } - - switch (desc.Format) - { - case DXGI_FORMAT_NV12: - ptr->Pitch = (mfxU16)lockedRect.RowPitch; - ptr->Y = (mfxU8 *)lockedRect.pData; - ptr->U = (mfxU8 *)lockedRect.pData + desc.Height * lockedRect.RowPitch; - ptr->V = ptr->U + 1; - break; - case DXGI_FORMAT_B8G8R8A8_UNORM: - ptr->Pitch = (mfxU16)lockedRect.RowPitch; - ptr->B = (mfxU8 *)lockedRect.pData; - ptr->G = ptr->B + 1; - ptr->R = ptr->B + 2; - ptr->A = ptr->B + 3; - break; - case DXGI_FORMAT_P8: - ptr->Pitch = (mfxU16)lockedRect.RowPitch; - ptr->Y = (mfxU8 *)lockedRect.pData; - ptr->U = 0; - ptr->V = 0; - break; - default: - return MFX_ERR_LOCK_MEMORY; - } - - return MFX_ERR_NONE; + HRESULT hRes = S_OK; + tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; + + D3D11_TEXTURE2D_DESC desc = { 0 }; + D3D11_MAPPED_SUBRESOURCE lockedRect = { 0 }; + + CustomMemId* memId = (CustomMemId*)mid; + ID3D11Texture2D* pSurface = (ID3D11Texture2D *)memId->memId; + ID3D11Texture2D* pStage = (ID3D11Texture2D *)memId->memIdStage; + + D3D11_MAP mapType = D3D11_MAP_READ; + UINT mapFlags = D3D11_MAP_FLAG_DO_NOT_WAIT; + + if (NULL == pStage) { + hRes = pthis->pD3D11Ctx->Map(pSurface, 0, mapType, mapFlags, &lockedRect); + desc.Format = DXGI_FORMAT_P8; + } + else { + pSurface->GetDesc(&desc); + + // copy data only in case of user wants o read from stored surface + if (memId->rw & D3D11_WILL_READ) { + pthis->pD3D11Ctx->CopySubresourceRegion(pStage, 0, 0, 0, 0, pSurface, 0, NULL); + } + + do { + hRes = pthis->pD3D11Ctx->Map(pStage, 0, mapType, mapFlags, &lockedRect); + if (S_OK != hRes && DXGI_ERROR_WAS_STILL_DRAWING != hRes) { + return MFX_ERR_LOCK_MEMORY; + } + } + while (DXGI_ERROR_WAS_STILL_DRAWING == hRes); + } + + if (FAILED(hRes)) { + return MFX_ERR_LOCK_MEMORY; + } + + switch (desc.Format) { + case DXGI_FORMAT_NV12: + ptr->Pitch = (mfxU16)lockedRect.RowPitch; + ptr->Y = (mfxU8 *)lockedRect.pData; + ptr->U = (mfxU8 *)lockedRect.pData + desc.Height * lockedRect.RowPitch; + ptr->V = ptr->U + 1; + break; + case DXGI_FORMAT_B8G8R8A8_UNORM: + ptr->Pitch = (mfxU16)lockedRect.RowPitch; + ptr->B = (mfxU8 *)lockedRect.pData; + ptr->G = ptr->B + 1; + ptr->R = ptr->B + 2; + ptr->A = ptr->B + 3; + break; + case DXGI_FORMAT_P8: + ptr->Pitch = (mfxU16)lockedRect.RowPitch; + ptr->Y = (mfxU8 *)lockedRect.pData; + ptr->U = 0; + ptr->V = 0; + break; + default: + return MFX_ERR_LOCK_MEMORY; + } + + return MFX_ERR_NONE; } static mfxStatus D3D11_SimpleUnlock(mfxHDL _pthis, mfxMemId mid, mfxFrameData *ptr) { - tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; - - CustomMemId* memId = (CustomMemId*)mid; - ID3D11Texture2D* pSurface = (ID3D11Texture2D *)memId->memId; - ID3D11Texture2D* pStage = (ID3D11Texture2D *)memId->memIdStage; - - if (NULL == pStage) - { - pthis->pD3D11Ctx->Unmap(pSurface, 0); - } - else - { - pthis->pD3D11Ctx->Unmap(pStage, 0); - // copy data only in case of user wants to write to stored surface - if (memId->rw & D3D11_WILL_WRITE) - { - pthis->pD3D11Ctx->CopySubresourceRegion(pSurface, 0, 0, 0, 0, pStage, 0, NULL); - } - } - - if (ptr) - { - ptr->Pitch = 0; - ptr->U = ptr->V = ptr->Y = 0; - ptr->A = ptr->R = ptr->G = ptr->B = 0; - } - - return MFX_ERR_NONE; + tdav_codec_h264_intel_t* pthis = (tdav_codec_h264_intel_t*)_pthis; + + CustomMemId* memId = (CustomMemId*)mid; + ID3D11Texture2D* pSurface = (ID3D11Texture2D *)memId->memId; + ID3D11Texture2D* pStage = (ID3D11Texture2D *)memId->memIdStage; + + if (NULL == pStage) { + pthis->pD3D11Ctx->Unmap(pSurface, 0); + } + else { + pthis->pD3D11Ctx->Unmap(pStage, 0); + // copy data only in case of user wants to write to stored surface + if (memId->rw & D3D11_WILL_WRITE) { + pthis->pD3D11Ctx->CopySubresourceRegion(pSurface, 0, 0, 0, 0, pStage, 0, NULL); + } + } + + if (ptr) { + ptr->Pitch = 0; + ptr->U = ptr->V = ptr->Y = 0; + ptr->A = ptr->R = ptr->G = ptr->B = 0; + } + + return MFX_ERR_NONE; } static mfxStatus D3D11_SimpleGethdl(mfxHDL _pthis, mfxMemId mid, mfxHDL *handle) { - _pthis; - if (NULL == handle) - { - return MFX_ERR_INVALID_HANDLE; - } + _pthis; + if (NULL == handle) { + return MFX_ERR_INVALID_HANDLE; + } - mfxHDLPair* pPair = (mfxHDLPair*)handle; - CustomMemId* memId = (CustomMemId*)mid; + mfxHDLPair* pPair = (mfxHDLPair*)handle; + CustomMemId* memId = (CustomMemId*)mid; - pPair->first = memId->memId; // surface texture - pPair->second = 0; + pPair->first = memId->memId; // surface texture + pPair->second = 0; - return MFX_ERR_NONE; + return MFX_ERR_NONE; } static mfxStatus D3D11_SimpleFree(mfxHDL _pthis, mfxFrameAllocResponse *response) { - _pthis; - if (NULL == response) - { - return MFX_ERR_NULL_PTR; - } - - if (response->mids) - { - for (mfxU32 i = 0; i < response->NumFrameActual; i++) - { - if (response->mids[i]) - { - CustomMemId* mid = (CustomMemId*)response->mids[i]; - ID3D11Texture2D* pSurface = (ID3D11Texture2D *)mid->memId; - ID3D11Texture2D* pStage = (ID3D11Texture2D *)mid->memIdStage; - if (pSurface) - { - pSurface->Release(); - } - if (pStage) - { - pStage->Release(); - } - delete mid; - } - } - } - - delete[] response->mids; - response->mids = 0; - - return MFX_ERR_NONE; + _pthis; + if (NULL == response) { + return MFX_ERR_NULL_PTR; + } + + if (response->mids) { + for (mfxU32 i = 0; i < response->NumFrameActual; i++) { + if (response->mids[i]) { + CustomMemId* mid = (CustomMemId*)response->mids[i]; + ID3D11Texture2D* pSurface = (ID3D11Texture2D *)mid->memId; + ID3D11Texture2D* pStage = (ID3D11Texture2D *)mid->memIdStage; + if (pSurface) { + pSurface->Release(); + } + if (pStage) { + pStage->Release(); + } + delete mid; + } + } + } + + delete[] response->mids; + response->mids = 0; + + return MFX_ERR_NONE; } #endif /* INTEL_DX11_D3D */ |