From cd6d4c892ad596fec8db1f96c53ee2819d83051b Mon Sep 17 00:00:00 2001 From: "Shiryaeva, Ekaterina" Date: Wed, 25 Jan 2023 15:47:38 +0100 Subject: [PATCH] [sample_encode] Added segmentation support for VP9e --- samples/sample_common/include/sample_utils.h | 3 + .../sample_encode/include/pipeline_encode.h | 6 ++ samples/sample_encode/src/pipeline_encode.cpp | 71 +++++++++++++++++++ samples/sample_encode/src/sample_encode.cpp | 29 ++++++++ 4 files changed, 109 insertions(+) diff --git a/samples/sample_common/include/sample_utils.h b/samples/sample_common/include/sample_utils.h index 0bcf02e798..6c84458237 100644 --- a/samples/sample_common/include/sample_utils.h +++ b/samples/sample_common/include/sample_utils.h @@ -435,6 +435,9 @@ template<>struct mfx_ext_buffer_id { template<>struct mfx_ext_buffer_id { enum {id = MFX_EXTBUFF_VP9_PARAM}; }; +template<>struct mfx_ext_buffer_id { + enum {id = MFX_EXTBUFF_VP9_SEGMENTATION}; +}; template<>struct mfx_ext_buffer_id { enum {id = MFX_EXTBUFF_VIDEO_SIGNAL_INFO}; }; diff --git a/samples/sample_encode/include/pipeline_encode.h b/samples/sample_encode/include/pipeline_encode.h index de02122e33..405d111c3e 100644 --- a/samples/sample_encode/include/pipeline_encode.h +++ b/samples/sample_encode/include/pipeline_encode.h @@ -239,6 +239,12 @@ struct sInputParams mfxI16 DeblockingBetaOffset; #endif + mfxU16 nVp9Segments; + mfxI16 vp9SegmentationQIDelta[8]; + mfxU16 vp9SegmentationBlockSize; + //mfxU8* vp9SegmentationMap; + //msdk_char* vp9SegmMapPath; + }; diff --git a/samples/sample_encode/src/pipeline_encode.cpp b/samples/sample_encode/src/pipeline_encode.cpp index b0cac12aa7..902f183650 100644 --- a/samples/sample_encode/src/pipeline_encode.cpp +++ b/samples/sample_encode/src/pipeline_encode.cpp @@ -75,6 +75,58 @@ void UnlockPreEncAuxBuffer(PreEncAuxBuffer* pBuff) msdk_atomic_dec16(&pBuff->Locked); } +mfxStatus ParseSegmentMap(/*msdk_char* fname,*/ + mfxU16 frameWidth, + mfxU16 frameHeight, + mfxExtVP9Segmentation* pSeg, + mfxU8** segmentIds) { + if (segmentIds == nullptr) + return MFX_ERR_UNKNOWN; + + //umc_file* parFile = umc_file_fopen(fname, VM_STRING("r")); + //MFX_CHECK(parFile != 0); + + mfxU16 defaultSize = MFX_VP9_SEGMENT_ID_BLOCK_SIZE_16x16; + + mfxU16 blockSize = pSeg->SegmentIdBlockSize > 0 ? pSeg->SegmentIdBlockSize : defaultSize; + mfxU16 mapWidth = (frameWidth + (blockSize - 1)) / blockSize; + mfxU16 mapHeight = (frameHeight + (blockSize - 1)) / blockSize; + pSeg->NumSegmentIdAlloc = (mfxU32)(mapWidth * mapHeight); + mfxU8* buffer = new mfxU8[pSeg->NumSegmentIdAlloc]; + *segmentIds = buffer; + + bool isInvalid = false; + //int bufSize = sizeof(vm_char) * (mapWidth + blockSize); + //vm_char* sbuf = new vm_char[bufSize]; + + for (mfxU16 i = 0; !isInvalid && i < mapHeight; ++i) { + //vm_char* pStr = nullptr; + + //pStr = umc_file_fgets(sbuf, bufSize, parFile); + + //if (!pStr) + // break; + + for (mfxU16 j = 0; j < mapWidth; ++j) { + //buffer[i * mapWidth + j] = pStr[j] - '0'; + buffer[i * mapWidth + j] = i % 8; + if (buffer[i * mapWidth + j] >= pSeg->NumSegments) { + isInvalid = true; + break; + } + } + } + + //delete[] sbuf; + //umc_file_close(parFile); + + if (isInvalid) + return MFX_ERR_UNKNOWN; + else + return MFX_ERR_NONE; +} + + CEncTaskPool::CEncTaskPool() { @@ -587,6 +639,25 @@ mfxStatus CEncodingPipeline::InitMfxEncParams(sInputParams *pInParams) } #endif } + + if (pInParams->nVp9Segments && m_mfxEncParams.mfx.CodecId == MFX_CODEC_VP9) + { + auto vp9SegmParam = m_mfxEncParams.AddExtBuffer(); + vp9SegmParam->NumSegments = pInParams->nVp9Segments; + for (int i = 0; i < pInParams->nVp9Segments; i++) { + vp9SegmParam->Segment[i].QIndexDelta = pInParams->vp9SegmentationQIDelta[i]; + vp9SegmParam->Segment[i].FeatureEnabled = MFX_VP9_SEGMENT_FEATURE_QINDEX; + } + vp9SegmParam->SegmentIdBlockSize = pInParams->vp9SegmentationBlockSize; + //vp9SegmParam->SegmentId = pInParams->vp9SegmentationMap; + MSDK_CHECK_STATUS(ParseSegmentMap(/*pInParams->vp9SegmMapPath,*/ + pInParams->nDstWidth, + pInParams->nDstHeight, + vp9SegmParam, + &vp9SegmParam->SegmentId), + "error: vp9 segm map is invalid !"); + } + if (*pInParams->uSEI && (pInParams->CodecId == MFX_CODEC_AVC || pInParams->CodecId == MFX_CODEC_HEVC)) { auto pl = new mfxPayload; diff --git a/samples/sample_encode/src/sample_encode.cpp b/samples/sample_encode/src/sample_encode.cpp index e4a5a7c5cb..3b9dbb55ad 100644 --- a/samples/sample_encode/src/sample_encode.cpp +++ b/samples/sample_encode/src/sample_encode.cpp @@ -417,6 +417,35 @@ mfxStatus ParseAdditionalParams(msdk_char *strInput[], mfxU8 nArgNum, mfxU8& i, } } #endif + else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-vp9SegmentationBlockSize"))) { + VAL_CHECK(i + 1 >= nArgNum, i, strInput[i]); + if (MFX_ERR_NONE != msdk_opt_read(strInput[++i], pParams->vp9SegmentationBlockSize)) { + msdk_printf(MSDK_STRING("error: Set size of block (NxN) for segmentation map: 8, 16, 32, 64.\n")); + pParams->vp9SegmentationBlockSize = 64; + } + } + else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-vp9SegmentationQIDelta"))) { + VAL_CHECK(i + 8 >= nArgNum, i, strInput[i]); + + pParams->nVp9Segments = 1; + + for (mfxU16 t = 0; t < 8; t++) { + if (MFX_ERR_NONE != msdk_opt_read(strInput[++i], pParams->vp9SegmentationQIDelta[t])) { + msdk_printf(MSDK_STRING( + "error: Array of 8 digits containing quantization index deltas for 8 possible segments, each value [-255..255], 0 - disabled (default).\n")); + pParams->vp9SegmentationQIDelta[t] = 0; + } + if (pParams->vp9SegmentationQIDelta[t] != 0) pParams->nVp9Segments = t + 1; + } + } + //else if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-vp9SegmentationMap"))) { + // VAL_CHECK(i + 1 >= nArgNum, i, strInput[i]); + + // pParams->vp9SegmMapPath = strInput[++i]; + // if (!pParams->vp9SegmMapPath) { + // msdk_printf(MSDK_STRING("error: vp9SegmentationMap is not provided!!.\n")); + // } + //} else { return MFX_ERR_NOT_FOUND;