diff --git a/cfg/sei_vui/display_overlays_info.cfg b/cfg/sei_vui/display_overlays_info.cfg new file mode 100644 index 0000000000000000000000000000000000000000..38a38fe69ff3a5772ed8a2162d5925ec36f3938f --- /dev/null +++ b/cfg/sei_vui/display_overlays_info.cfg @@ -0,0 +1,27 @@ +#========Display Overlays Information SEI message ===================== + +SEIDOIEnabled: 1 #Whether EOI SEI message will be generated. +SEIDOIId: 0 #The Identifier of the DOI SEI message +SEIDOICancelFlag: 0 #Whether the SEI cancel persistence of previous SEI. +SEIDOIPersistenceFlag: 1 #Does the SEI persist for one picture or till it is cancelled. +SEIDOINumDisplayOverlaysMinus2: 0 #Number of display overlays for which information is signalled in the SEI message. +SEIDOINuhLayerIdPresentFlag: 1 #Specifies that the doi_nuh_layer_id[ i ] syntax element is present in the SEI message. +SEIDOITargetPicSizePresentFlag: 1 #specifies that the doi_target_pic_width_minus1 and doi_target_pic_width_minus1 syntax elements are present. +SEIDOITargetPicWidthMinus1: 1279 +SEIDOITargetPicHeightMinus1: 719 +SEIDOIPicPartitionFlag: 1 #Specifies that display overlay components are coded as constituent rectangles/subpictures or in separated pictures. +SEIDOIPartitionTypeFlag: 1 #Specifies that display overlay components are coded as constituent rectangle (1) or subpictures (0) +SEIDOIPartitionIdLenMinus1: 3 #+1 specifies the length of doi partition syntax element +SEIDOIOffsetParamsPresentFlag: 1 #Specifies that offset parameters are present for the i-th display overlay. +SEIDOIOffsetParamsLengthMinus1: 10 #Specifies the length minus 1 of the doi_top_left_x[ i ] and doi_top_left_y[ i ], syntax elements in bits. +SEIDOIResamplingEnabledFlag: 0 #Specifies that display overlay components may be resampled in the target display picture. +SEIDOINuhLayerId0: 0 +SEIDOIPartitionId0: 0 +SEIDOIAlphaPresentFlag0: 0 +SEIDOINuhLayerId1: 1 +SEIDOIPartitionId1: 0 +SEIDOIAlphaPresentFlag1: 1 +SEIDOIAlphaNuhLayerId1: 1 +SEIDOIAlphaPartitionId1: 1 +SEIDOITopLeftX1: 0 +SEIDOITopLeftY1: 500 \ No newline at end of file diff --git a/doc/software-manual.tex b/doc/software-manual.tex index 8ceafa60fcb327a67b26bada0ddf43a35b3aa2aa..aaaeae5f57a13d9ce343ea8e25da053c4f3df47c 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -4002,6 +4002,7 @@ The table below lists the SEI messages defined for Version 1 and Range-Extension TBD & Packed Regions Info & Table \ref{tab:sei-pri}\\ TBD & Quality metric & Table \ref{tab:sei-qm}\\ TBD & Bitdepth Range Info & Table \ref{tab:sei-bri}\\ + TBD & Display Overlays Information & Table \ref{tab:sei-doi}\\ \end{SEIListTable} %% %% SEI messages @@ -6179,6 +6180,109 @@ Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries \\ \end{OptionTableNoShorthand} +\begin{OptionTableNoShorthand}{Display Overlays Information}{tab:sei-doi} + \Option{SEIDOIEnabled} & + \Default{false} & + Control generation of the Display Overlays Info SEI message. + \\ + \Option{SEIDOIId} & + \Default{0} & + Specifies the identifier of the DOI SEI message. + \\ + \Option{SEIDOICancelFlag} & + \Default{false} & + Specifies the persistence of any previous DOI SEI message in output order. + \\ + \Option{SEIDOIPersistenceFlag} & + \Default{false} & + Specifies the persistence of the DOI SEI message for the current layer. + \\ + \Option{SEIDOINumDisplayOverlaysMinus2} & + \Default{0} & + Specifies the number of display overlays minus 2 for which information is signalled in the SEI message. + \\ + \Option{SEIDOINuhLayerIdPresentFlag} & + \Default{false} & + Specifies that the doi_nuh_layer_id[ i ] syntax element is present in the SEI message. + \\ + \Option{SEIDOITargetPicSizePresentFlag} & + \Default{false} & + Specifies that the doi_target_pic_width_minus1 and doi_target_pic_width_minus1 syntax elements are present. + \\ + \Option{SEIDOITargetPicWidthMinus1} & + \Default{0} & + Indicates the width minus 1 of the target picture. + \\ + \Option{SEIDOITargetPicHeightMinus1} & + \Default{0} & + Indicates the height minus 1 of the target picture. + \\ + \Option{SEIDOIPicPartitionFlag} & + \Default{false} & + Specifies that display overlay components are coded as constituent rectangles or subpictures. + \\ + \Option{SEIDOIPartitionTypeFlag} & + \Default{false} & + Specifies that a display overlay component is coded as a constituent rectangle. + \\ + \Option{SEIDOIPartitionIdLenMinus1} & + \Default{0} & + Specifies the length minus 1 of the doi_partition_id[ i ] syntax elements. + \\ + \Option{SEIDOIOffsetParamsPresentFlag} & + \Default{false} & + Specifies that offset parameters are present for the i-th display overlay. + \\ + \Option{SEIDOIOffsetParamsLengthMinus1} & + \Default{0} & + Specifies the length minus 1 of the doi_top_left_x[ i ] and doi_top_left_y[ i ], syntax elements in bits. + \\ + \Option{SEIDOIResamplingEnabledFlag} & + \Default{false} & + Specifies that display overlay components may be resampled in the target display picture. + \\ + \Option{SEIDOISizeParamLengthMinus1} & + \Default{0} & + Specifies the length minus 1 of the doi_width_minus1[ i ] and doi_height_minus1[ i ] syntax elements in bits. + \\ + \Option{SEIDOINuhLayerId\emph{i}} & + \Default{0} & + Specifies the layer identifier of the texture component of the i-th display overlay. + \\ + \Option{SEIDOIPartitionId\emph{i}} & + \Default{0} & + Specifies that the texture component of the i-th display overlay is represented by the j-th constituent rectangle when cr_rect_id[ j ] equal doi_partition_id[ i ]. + \\ + \Option{SEIDOIAlphaPresentFlag\emph{i}} & + \Default{false} & + Specifies that an alpha component is provided for the i-th display overlay. + \\ + \Option{SEIDOIAlphaNuhLayerId\emph{i}} & + \Default{0} & + Specifies the layer identifier value of the alpha component of the i-th display overlay. + \\ + \Option{SEIDOIAlphaPartitionId\emph{i}} & + \Default{0} & + Specifies the cr_rect_id[ j ] of the alpha component of the i-th display overlay. + \\ + \Option{SEIDOITopLeftX\emph{i}} & + \Default{0} & + Specifies the horizontal positions of the top left corner of the i-th display overlay in the target display picture, in luma samples. + \\ + \Option{SEIDOITopLeftY\emph{i}} & + \Default{0} & + Specifies the vertical positions of the top left corner of the i-th display overlay in the target display picture, in luma samples. + \\ + \Option{SEIDOIWidthMinus1\emph{i}} & + \Default{} & + Specifies the width minus 1 in luma samples arrays of the i-th display overlay in the target display picture. + \\ + \Option{SEIDOIHeightMinus1\emph{i}} & + \Default{} & + Specifies the height minus 1 in luma samples arrays of the i-th display overlay in the target display picture. + \\ +\end{OptionTableNoShorthand} + \begin{OptionTableNoShorthand}{Phase indication}{tab:sei-phase-indication} \Option{SEIPhaseIndicationFullResolution} & \Default{false} & @@ -6907,6 +7011,18 @@ If no value is specified, the SEI message will not be output. Packed regions info output file name. If empty, no object information will be saved. \\ +\Option{SEIDOIId} & +%\ShortOption{\None} & +\Default{\NotSet} & +Specifies the DOI SEI id which should be used to generate output picture with overlay embedded. +\\ + +\Option{SEIDOIFilename} & +%\ShortOption{\None} & +\Default{\NotSet} & +DOI YUV output file name. If empty, no overlay is applied (ignore SEI message). +\\ + \end{OptionTableNoShorthand} diff --git a/source/App/DecoderApp/DecApp.cpp b/source/App/DecoderApp/DecApp.cpp index bb940b8fc813fcc2a9ccf19cd74ecb08cabf9074..273eea48743d7d65b66bcfa53e7e32df146940a9 100644 --- a/source/App/DecoderApp/DecApp.cpp +++ b/source/App/DecoderApp/DecApp.cpp @@ -63,6 +63,11 @@ DecApp::DecApp() { m_newCLVS[i] = true; } +#if JVET_AI0181 + m_doiSEIPelY = nullptr; + m_doiSEIPelU = nullptr; + m_doiSEIPelV = nullptr; +#endif } // ==================================================================================================================== @@ -81,6 +86,10 @@ uint32_t DecApp::decode() { int poc; PicList *pcListPic = nullptr; + +#if JVET_AI0181 + m_doiSEILastProcessedOverlay = -1; +#endif #if GREEN_METADATA_SEI_ENABLED FeatureCounterStruct featureCounter; @@ -1050,6 +1059,15 @@ void DecApp::xDestroyDecLib() recFile.second.close(); } } +#if JVET_AI0181 + if (!m_SEIDOIFileName.empty()) + { + for (auto& recFile: m_videoIOYuvSEIDOIFile) + { + recFile.second.close(); + } + } +#endif // destroy decoder class m_cDecLib.destroy(); @@ -1265,6 +1283,12 @@ void DecApp::xWriteOutput( PicList* pcListPic, uint32_t tId ) } } +#if JVET_AI0181 + if (!m_SEIDOIFileName.empty()) + { + xGenerateTargetPicture(pcPic); + } +#endif if (!m_shutterIntervalPostFileName.empty() && getShutterFilterFlag()) { @@ -1527,6 +1551,13 @@ void DecApp::xFlushOutput( PicList* pcListPic, const int layerId ) } } +#if JVET_AI0181 + if (!m_SEIDOIFileName.empty()) + { + xGenerateTargetPicture(pcPic); + } +#endif + if (!m_shutterIntervalPostFileName.empty() && getShutterFilterFlag()) { int blendingRatio = getBlendingRatio(); @@ -2156,3 +2187,289 @@ void DecApp::xUnpackOpacityLayer(Picture* pcPic) } #endif //! \} + +#if JVET_AI0181 +void DecApp::xGenerateTargetPicture(Picture* pcPic) +{ + SEIMessages seiListDOI = getSeisByType(pcPic->SEIs, SEI::PayloadType::DISPLAY_OVERLAYS_INFO); + CHECK(seiListDOI.empty(), "No DOI SEI have been received"); + bool seiDoiPresent = false; + SEIMessages seiListCR = getSeisByType(pcPic->SEIs, SEI::PayloadType::CONSTITUENT_RECTANGLES); + for (auto sei: seiListDOI) + { + auto doisei = (SEIDisplayOverlaysInfo*) sei; + if (doisei->m_doiSEIId == this->m_SEIDOIId) + { + seiDoiPresent = true; + int numOverlays = doisei->m_doiSEINumDisplayOverlaysMinus2 + 2; + int targetPicWidth = doisei->m_doiSEITargetPicWidthMinus1 + 1; + int targetPicHeight = doisei->m_doiSEITargetPicHeightMinus1 + 1; + // Create internal buffers + if (m_doiSEIPelY == nullptr) + { + m_doiSEIPelY = new Pel[targetPicWidth * targetPicHeight]; + m_doiSEIPelU = new Pel[(targetPicWidth >> 1) * (targetPicHeight >> 1)]; + m_doiSEIPelV = new Pel[(targetPicWidth >> 1) * (targetPicHeight >> 1)]; + } + for (int overlay_idx = this->m_doiSEILastProcessedOverlay + 1; overlay_idx < numOverlays; overlay_idx++) + { + if (doisei->m_doiSEIPicPartitionFlag == 1 && doisei->m_doiSEIPartitionTypeFlag == 1) + { + CHECK(seiListCR.empty(), "A constituent rectangles SEI is expected when doi_pic_partition_flag and " + "doi_pic_partition_type_flag are equal to 1"); + CHECK(doisei->m_doiSEIResamplingEnabledFlag, "Resampling is not implemented for DOI SEI."); + CHECK(overlay_idx != this->m_doiSEILastProcessedOverlay + 1, + "Coding of an overlay have been skipped, please constraint overlay to be processed in layer " + "ascending order"); + + if (doisei->m_doiSEINuhLayerId[overlay_idx] == pcPic->layerId) + { + // check CR + bool noCRforLayerId = true; + SEIConstituentRectangles* doicr; + for (auto sei: seiListCR) + { + doicr = (SEIConstituentRectangles*) sei; + if ((int) doicr->m_layerId == pcPic->layerId) + { + noCRforLayerId = false; + break; + } + } + CHECK(noCRforLayerId, "No CR SEI has been found for the current processed layer.") + + int cr_h = (doicr->m_rectSameSizeFlag + ? pcPic->cs->pps->getPicHeightInLumaSamples() / (doicr->m_numRowsMinus1 + 1) + : (1 << doicr->m_log2UnitSize) + * (doicr->m_rectHeightInUnitsMinus1[doisei->m_doiSEIPartitionId[overlay_idx]] + 1)); + int cr_w = (doicr->m_rectSameSizeFlag + ? pcPic->getPicWidthInLumaSamples() / (doicr->m_numColsMinus1 + 1) + : (1 << doicr->m_log2UnitSize) + * (doicr->m_rectWidthInUnitsMinus1[doisei->m_doiSEIPartitionId[overlay_idx]] + 1)); + + int x0_t = (overlay_idx > 0 ? doisei->m_doiSEITopLeftX[overlay_idx] : 0); + int y0_t = (overlay_idx > 0 ? doisei->m_doiSEITopLeftY[overlay_idx] : 0); + int x0_o = (doicr->m_rectSameSizeFlag + ? (doisei->m_doiSEIPartitionId[overlay_idx] % (doicr->m_numColsMinus1 + 1)) + * pcPic->cs->pps->getPicWidthInLumaSamples() / (doicr->m_numColsMinus1 + 1) + : doicr->m_rectTopLeftInUnitsX[overlay_idx] * (1 << doicr->m_log2UnitSize)); + int y0_o = (doicr->m_rectSameSizeFlag + ? (doisei->m_doiSEIPartitionId[overlay_idx] / (doicr->m_numColsMinus1 + 1)) + * pcPic->cs->pps->getPicHeightInLumaSamples() / (doicr->m_numRowsMinus1 + 1) + : doicr->m_rectTopLeftInUnitsY[overlay_idx] * (1 << doicr->m_log2UnitSize)); + int x_o = x0_o; + int y_o = y0_o; + int x0_a = 0; + int y0_a = 0; + if (doisei->m_doiSEIAlphaPresentFlag[overlay_idx]) + { + x0_a = (doicr->m_rectSameSizeFlag + ? (doisei->m_doiSEIAlphaPartitionId[overlay_idx] % (doicr->m_numColsMinus1 + 1)) + * pcPic->cs->pps->getPicWidthInLumaSamples() / (doicr->m_numColsMinus1 + 1) + : doicr->m_rectTopLeftInUnitsX[overlay_idx] * (1 << doicr->m_log2UnitSize)); + y0_a = (doicr->m_rectSameSizeFlag + ? (doisei->m_doiSEIAlphaPartitionId[overlay_idx] / (doicr->m_numColsMinus1 + 1)) + * pcPic->cs->pps->getPicHeightInLumaSamples() / (doicr->m_numRowsMinus1 + 1) + : doicr->m_rectTopLeftInUnitsY[overlay_idx] * (1 << doicr->m_log2UnitSize)); + } + int x_a = x0_a; + int y_a = y0_a; + + // Overlay Y component + for (int h_idx = y0_t; (h_idx < targetPicHeight) && ((h_idx - y0_t) < cr_h); h_idx++) + { + x_a = x0_a; + x_o = x0_o; + for (int w_idx = x0_t; (w_idx < targetPicWidth) && ((w_idx - x0_t) < cr_w); w_idx++) + { + if (doisei->m_doiSEIAlphaPresentFlag[overlay_idx]) + { + CHECK(doisei->m_doiSEIAlphaNuhLayerId[overlay_idx] != doisei->m_doiSEINuhLayerId[overlay_idx], + "Current implementation only sypports Texture and Alpha packed as two CR in the same " + "layer"); + float alpha = (float) pcPic->getRecoBuf().get(COMPONENT_Y).at(Position(x_o, y_o)) + / (1 << pcPic->m_bitDepths[(ChannelType) ChannelType::LUMA]); + float b = (float) pcPic->getRecoBuf().get(COMPONENT_Y).at(Position(x_o, y_o)); + float a = (float) m_doiSEIPelY[h_idx * targetPicWidth + w_idx]; + m_doiSEIPelY[h_idx * targetPicWidth + w_idx] = (uint16_t) (alpha * a + (1 - alpha) * b); + x_a++; + x_o++; + } + else + { + m_doiSEIPelY[h_idx * targetPicWidth + w_idx] = + pcPic->getRecoBuf().get(COMPONENT_Y).at(Position(x_o, y_o)); + x_o++; + } + } + y_a++; + y_o++; + } + + // Overlay U component + x0_t = (overlay_idx > 0 ? (doisei->m_doiSEITopLeftX[overlay_idx] >> 1) : 0); + y0_t = (overlay_idx > 0 ? (doisei->m_doiSEITopLeftY[overlay_idx] >> 1) : 0); + x0_o = (doicr->m_rectSameSizeFlag + ? (doisei->m_doiSEIPartitionId[overlay_idx] % (doicr->m_numColsMinus1 + 1)) + * (pcPic->cs->pps->getPicWidthInLumaSamples() >> 1) / (doicr->m_numColsMinus1 + 1) + : doicr->m_rectTopLeftInUnitsX[overlay_idx] * (1 << doicr->m_log2UnitSize)); + y0_o = (doicr->m_rectSameSizeFlag + ? (doisei->m_doiSEIPartitionId[overlay_idx] / (doicr->m_numColsMinus1 + 1)) + * (pcPic->cs->pps->getPicHeightInLumaSamples() >> 1) / (doicr->m_numRowsMinus1 + 1) + : doicr->m_rectTopLeftInUnitsY[overlay_idx] * (1 << doicr->m_log2UnitSize)); + x0_a = 0; + y0_a = 0; + x_o = x0_o; + y_o = y0_o; + if (doisei->m_doiSEIAlphaPresentFlag[overlay_idx]) + { + x0_a = (doicr->m_rectSameSizeFlag + ? (doisei->m_doiSEIAlphaPartitionId[overlay_idx] % (doicr->m_numColsMinus1 + 1)) + * (pcPic->cs->pps->getPicWidthInLumaSamples() >> 1) / (doicr->m_numColsMinus1 + 1) + : doicr->m_rectTopLeftInUnitsX[overlay_idx] * (1 << doicr->m_log2UnitSize)); + y0_a = (doicr->m_rectSameSizeFlag + ? (doisei->m_doiSEIAlphaPartitionId[overlay_idx] / (doicr->m_numColsMinus1 + 1)) + * (pcPic->cs->pps->getPicHeightInLumaSamples() >> 1) / (doicr->m_numRowsMinus1 + 1) + : doicr->m_rectTopLeftInUnitsY[overlay_idx] * (1 << doicr->m_log2UnitSize)); + } + x_a = x0_a; + y_a = y0_a; + for (int h_idx = y0_t; (h_idx < (targetPicHeight >> 1)) && ((h_idx - y0_t) < (cr_h >> 1)); h_idx++) + { + x_a = x0_a; + x_o = x0_o; + for (int w_idx = x0_t; (w_idx < (targetPicWidth >> 1)) && ((w_idx - x0_t) < (cr_w >> 1)); w_idx++) + { + if (doisei->m_doiSEIAlphaPresentFlag[overlay_idx]) + { + CHECK(doisei->m_doiSEIAlphaNuhLayerId[overlay_idx] != doisei->m_doiSEINuhLayerId[overlay_idx], + "Current implementation only sypports Texture and Alpha packed as two CR in the same " + "layer"); + float alpha = (float) pcPic->getRecoBuf().get(COMPONENT_Cb).at(Position(x_o, y_o)) + / (1 << pcPic->m_bitDepths[(ChannelType) ChannelType::CHROMA]); + float b = (float) pcPic->getRecoBuf().get(COMPONENT_Cb).at(Position(x_o, y_o)); + float a = (float) m_doiSEIPelU[h_idx * (targetPicWidth >> 1) + w_idx]; + m_doiSEIPelU[h_idx * (targetPicWidth >> 1) + w_idx] = (uint16_t) (alpha * a + (1 - alpha) * b); + x_a++; + x_o++; + } + else + { + m_doiSEIPelU[h_idx * (targetPicWidth >> 1) + w_idx] = + pcPic->getRecoBuf().get(COMPONENT_Cb).at(Position(x_o, y_o)); + x_o++; + } + } + y_a++; + y_o++; + } + + // Overlay V component + x0_t = (overlay_idx > 0 ? (doisei->m_doiSEITopLeftX[overlay_idx] >> 1) : 0); + y0_t = (overlay_idx > 0 ? (doisei->m_doiSEITopLeftY[overlay_idx] >> 1) : 0); + x0_o = (doicr->m_rectSameSizeFlag + ? (doisei->m_doiSEIPartitionId[overlay_idx] % (doicr->m_numColsMinus1 + 1)) + * (pcPic->cs->pps->getPicWidthInLumaSamples() >> 1) / (doicr->m_numColsMinus1 + 1) + : doicr->m_rectTopLeftInUnitsX[overlay_idx] * (1 << doicr->m_log2UnitSize)); + y0_o = (doicr->m_rectSameSizeFlag + ? (doisei->m_doiSEIPartitionId[overlay_idx] / (doicr->m_numColsMinus1 + 1)) + * (pcPic->cs->pps->getPicHeightInLumaSamples() >> 1) / (doicr->m_numRowsMinus1 + 1) + : doicr->m_rectTopLeftInUnitsY[overlay_idx] * (1 << doicr->m_log2UnitSize)); + x0_a = 0; + y0_a = 0; + x_o = x0_o; + y_o = y0_o; + if (doisei->m_doiSEIAlphaPresentFlag[overlay_idx]) + { + x0_a = (doicr->m_rectSameSizeFlag + ? (doisei->m_doiSEIAlphaPartitionId[overlay_idx] % (doicr->m_numColsMinus1 + 1)) + * (pcPic->cs->pps->getPicWidthInLumaSamples() >> 1) / (doicr->m_numColsMinus1 + 1) + : doicr->m_rectTopLeftInUnitsX[overlay_idx] * (1 << doicr->m_log2UnitSize)); + y0_a = (doicr->m_rectSameSizeFlag + ? (doisei->m_doiSEIAlphaPartitionId[overlay_idx] / (doicr->m_numColsMinus1 + 1)) + * (pcPic->cs->pps->getPicHeightInLumaSamples() >> 1) / (doicr->m_numRowsMinus1 + 1) + : doicr->m_rectTopLeftInUnitsY[overlay_idx] * (1 << doicr->m_log2UnitSize)); + } + x_a = x0_a; + y_a = y0_a; + + for (int h_idx = y0_t; (h_idx < (targetPicHeight >> 1)) && ((h_idx - y0_t) < (cr_h >> 1)); h_idx++) + { + x_a = x0_a; + x_o = x0_o; + for (int w_idx = x0_t; (w_idx < (targetPicWidth >> 1)) && ((w_idx - x0_t) < (cr_w >> 1)); w_idx++) + { + if (doisei->m_doiSEIAlphaPresentFlag[overlay_idx]) + { + CHECK(doisei->m_doiSEIAlphaNuhLayerId[overlay_idx] != doisei->m_doiSEINuhLayerId[overlay_idx], + "Current implementation only sypports Texture and Alpha packed as two CR in the same " + "layer"); + float alpha = (float) pcPic->getRecoBuf().get(COMPONENT_Cr).at(Position(x_o, y_o)) + / (1 << pcPic->m_bitDepths[(ChannelType) ChannelType::CHROMA]); + float b = (float) pcPic->getRecoBuf().get(COMPONENT_Cr).at(Position(x_o, y_o)); + float a = (float) m_doiSEIPelV[h_idx * (targetPicWidth >> 1) + w_idx]; + m_doiSEIPelV[h_idx * (targetPicWidth >> 1) + w_idx] = (uint16_t) (alpha * a + (1 - alpha) * b); + x_a++; + x_o++; + } + else + { + m_doiSEIPelV[h_idx * (targetPicWidth >> 1) + w_idx] = + pcPic->getRecoBuf().get(COMPONENT_Cr).at(Position(x_o, y_o)); + x_o++; + } + } + y_a++; + y_o++; + } + this->m_doiSEILastProcessedOverlay = overlay_idx; + } + } + else + { + CHECK(true, "Only constituent rectangles are implemented for DOI SEI."); + } + } + if (this->m_doiSEILastProcessedOverlay == numOverlays - 1) + { + // Writing output file + FILE* fptr = fopen(m_SEIDOIFileName.c_str(), "ab+"); + for (int r = 0; r < targetPicHeight; r++) + { + for (int c = 0; c < targetPicWidth; c++) + { + int16_t val = m_doiSEIPelY[r * targetPicWidth + c]; + fwrite(&val, sizeof(int16_t), 1, fptr); + } + } + for (int r = 0; r < (targetPicHeight >> 1); r++) + { + for (int c = 0; c < (targetPicWidth >> 1); c++) + { + int16_t val = m_doiSEIPelU[r * (targetPicWidth >> 1) + c]; + fwrite(&val, sizeof(int16_t), 1, fptr); + } + } + for (int r = 0; r < (targetPicHeight >> 1); r++) + { + for (int c = 0; c < (targetPicWidth >> 1); c++) + { + int16_t val = m_doiSEIPelV[r * (targetPicWidth >> 1) + c]; + fwrite(&val, sizeof(int16_t), 1, fptr); + } + } + fclose(fptr); + delete m_doiSEIPelY; + delete m_doiSEIPelU; + delete m_doiSEIPelV; + m_doiSEIPelY = nullptr; + m_doiSEIPelU = nullptr; + m_doiSEIPelV = nullptr; + this->m_doiSEILastProcessedOverlay = -1; + } + } + break; + } + CHECK(seiDoiPresent == false, "No SEI DOI messages are present for the requested DOI id"); +} +#endif \ No newline at end of file diff --git a/source/App/DecoderApp/DecApp.h b/source/App/DecoderApp/DecApp.h index 59846858e24206da8ae938b0ad15b4a340af1ae8..9fdcc8f789fbb9f60c0669937df289fae1d725bf 100644 --- a/source/App/DecoderApp/DecApp.h +++ b/source/App/DecoderApp/DecApp.h @@ -63,6 +63,14 @@ private: std::unordered_map<int, VideoIOYuv> m_cVideoIOYuvReconFile; ///< reconstruction YUV class std::unordered_map<int, VideoIOYuv> m_videoIOYuvSEIFGSFile; ///< reconstruction YUV with FGS class std::unordered_map<int, VideoIOYuv> m_cVideoIOYuvSEICTIFile; ///< reconstruction YUV with CTI class +#if JVET_AI0181 + std::unordered_map<int, VideoIOYuv> m_videoIOYuvSEIDOIFile; ///< reconstruction YUV with DOI class + int m_idxSEIDOI; ///< Index of the SEI DOI to be processed + int m_doiSEILastProcessedOverlay; ///< Index of the SEI DOI to be processed + Pel* m_doiSEIPelY; + Pel* m_doiSEIPelU; + Pel* m_doiSEIPelV; +#endif bool m_ShutterFilterEnable; ///< enable Post-processing with Shutter Interval SEI VideoIOYuv m_cTVideoIOYuvSIIPostFile; ///< post-filtered YUV class @@ -142,6 +150,9 @@ private: void xOutputPackedRegionsInfo(Picture* pcPic); void xOutputPackedRegionsInfoVector(FILE* fp, const char* paramName, const std::vector<uint32_t>& v); #endif +#if JVET_AI0181 + void xGenerateTargetPicture(Picture* pcPic); +#endif }; //! \} diff --git a/source/App/DecoderApp/DecAppCfg.cpp b/source/App/DecoderApp/DecAppCfg.cpp index 5a332537ff8263a225acb4ccd503497eebca7d79..117382ced85c3d29999af998d623d0b09b2f3826 100644 --- a/source/App/DecoderApp/DecAppCfg.cpp +++ b/source/App/DecoderApp/DecAppCfg.cpp @@ -114,6 +114,10 @@ bool DecAppCfg::parseCfg( int argc, char* argv[] ) #endif ("ClipOutputVideoToRec709Range", m_clipOutputVideoToRec709Range, false, "If true then clip output video to the Rec. 709 Range on saving") ("PYUV", m_packedYUVMode, false, "If true then output 10-bit and 12-bit YUV data as 5-byte and 3-byte (respectively) packed YUV data. Ignored for interlaced output.") +#if JVET_AI0181 + ("SEIDOIId", m_SEIDOIId, -1, "Specifies the DOI SEI id which should be used to generate output picture with overlay embedded.") + ("SEIDOIFilename", m_SEIDOIFileName, std::string(""), "DOI YUV output file name. If empty, no overlay is applied (ignore SEI message).\n") +#endif #if ENABLE_TRACING ("TraceChannelsList", bTracingChannelsList, false, "List all available tracing channels") ("TraceRule", sTracingRule, std::string(""), "Tracing rule (ex: \"D_CABAC:poc==8\" or \"D_REC_CB_LUMA:poc==8\")") @@ -289,6 +293,10 @@ DecAppCfg::DecAppCfg() , m_packedYUVMode(false) , m_statMode(0) , m_mctsCheck(false) +#if JVET_AI0181 + , m_SEIDOIId(-1) + , m_SEIDOIFileName() +#endif { m_outputBitDepth.fill(0); } diff --git a/source/App/DecoderApp/DecAppCfg.h b/source/App/DecoderApp/DecAppCfg.h index 5cdb8e3e8c51cfad17021a56c0b0253c75ce51ed..95911438a50b3c454dc015f3af551c8072d7298d 100644 --- a/source/App/DecoderApp/DecAppCfg.h +++ b/source/App/DecoderApp/DecAppCfg.h @@ -99,6 +99,10 @@ protected: std::string m_cacheCfgFile; ///< Config file of cache model int m_statMode; ///< Config statistic mode (0 - bit stat, 1 - tool stat, 3 - both) bool m_mctsCheck; +#if JVET_AI0181 + int m_SEIDOIId; // If != -1, specifies the DOI SEI id (doi_id) that should be targeted to reconstruct output layer + std::string m_SEIDOIFileName; ///< output file name for reconstructed sequence with display overlays +#endif #if GREEN_METADATA_SEI_ENABLED bool m_GMFA; std::string m_GMFAFile; diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 88eaaaae3d108704451cc9cdd5d9c25f27d0c002..ec04ed318a49bbe7deb98e63169b70b53bd3bea2 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -1508,6 +1508,77 @@ void EncApp::xInitLibCfg( int layerIdx ) m_cEncLib.setQmSEIMetricDescription(tmpMetricDescription); #endif +#if JVET_AI0181 + // Display overlays info + m_cEncLib.setDOISEIEnabled(m_doiSEIEnabled); + m_cEncLib.setDOISEIId(m_doiSEIId); + m_cEncLib.setDOISEICancelFlag(m_doiSEICancelFlag); + if (!m_doiSEICancelFlag) + { + m_cEncLib.setDOISEIPersistenceFlag(m_doiSEIPersistenceFlag); + m_cEncLib.setDOISEINumDisplayOverlaysMinus2(m_doiSEINumDisplayOverlaysMinus2); + m_cEncLib.setDOISEINuhLayerIdPresentFlag(m_doiSEINuhLayerIdPresentFlag); + m_cEncLib.setDOISEITargetPicSizePresentFlag(m_doiSEITargetPicSizePresentFlag); + if (m_doiSEITargetPicSizePresentFlag) + { + m_cEncLib.setDOISEITargetPicWidthMinus1(m_doiSEITargetPicWidthMinus1); + m_cEncLib.setDOISEITargetPicHeightMinus1(m_doiSEITargetPicHeightMinus1); + } + m_cEncLib.setDOISEIPicPartitionFlag(m_doiSEIPicPartitionFlag); + if (m_doiSEIPicPartitionFlag) + { + m_cEncLib.setDOISEIPartitionTypeFlag(m_doiSEIPartitionTypeFlag); + m_cEncLib.setDOISEIPartitionIdLenMinus1(m_doiSEIPartitionIdLenMinus1); + } + m_cEncLib.setDOISEIOffsetParamsPresentFlag(m_doiSEIOffsetParamsPresentFlag); + if (m_doiSEIOffsetParamsPresentFlag) + { + m_cEncLib.setDOISEIOffsetParamsLengthMinus1(m_doiSEIOffsetParamsLengthMinus1); + } + m_cEncLib.setDOISEIResamplingEnabledFlag(m_doiSEIResamplingEnabledFlag); + if (m_doiSEIResamplingEnabledFlag) + { + m_cEncLib.setDOISEISizeParamLengthMinus1(m_doiSEISizeParamLengthMinus1); + } + for (int i = 0; i < m_doiSEINumDisplayOverlaysMinus2 + 2; i++) + { + if (m_doiSEINuhLayerIdPresentFlag) + { + m_cEncLib.setDOISEINuhLayerId(m_doiSEINuhLayerId[i], i); + } + if (m_doiSEIPicPartitionFlag) + { + m_cEncLib.setDOISEIPartitionId(m_doiSEIPartitionId[i], i); + } + m_cEncLib.setDOISEIAlphaPresentFlag(m_doiSEIAlphaPresentFlag[i], i); + if (m_doiSEIAlphaPresentFlag[i]) + { + if (m_doiSEINuhLayerIdPresentFlag) + { + m_cEncLib.setDOISEIAlphaNuhLayerId(m_doiSEIAlphaNuhLayerId[i], i); + } + if (m_doiSEIPicPartitionFlag) + { + m_cEncLib.setDOISEIAlphaPartitionId(m_doiSEIAlphaPartitionId[i], i); + } + } + if (i > 0) + { + if (m_doiSEIOffsetParamsPresentFlag) + { + m_cEncLib.setDOISEITopLeftX(m_doiSEITopLeftX[i], i); + m_cEncLib.setDOISEITopLeftY(m_doiSEITopLeftY[i], i); + } + if (m_doiSEIResamplingEnabledFlag) + { + m_cEncLib.setDOISEIWidthMinus1(m_doiSEIWidthMinus1[i], i); + m_cEncLib.setDOISEIHeightMinus1(m_doiSEIHeightMinus1[i], i); + } + } + } + } +#endif + #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI m_cEncLib.setBriSEIEnabled(m_briSEIEnabled); m_cEncLib.setBriSEIOrigBitDepthMinus1(m_briSEIOrigBitDepthMinus1); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 231f7446b20c1c2c437af4b0b82686944102572b..56124fcd07f6c5c276e890c10904858b5ff5f5d1 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1810,6 +1810,33 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("SEIPRITargetRegionTopLeftX", cfg_priSEITargetRegionTopLeftX, cfg_priSEITargetRegionTopLeftX, "Specifies a list of horizontal top left postions in units of luma samples for the regions in reconstructed target picture") ("SEIPRITargetRegionTopLeftY", cfg_priSEITargetRegionTopLeftY, cfg_priSEITargetRegionTopLeftY, "Specifies a list of vertical top left postions in units of luma samples for the regions in reconstructed target picture") #endif +#if JVET_AI0181 + ("SEIDOIEnabled", m_doiSEIEnabled, false, "Control generation of the Display Overlays Info SEI message.") + ("SEIDOIId", m_doiSEIId, 0u, "Specifies the identifier of the DOI SEI message.") + ("SEIDOICancelFlag", m_doiSEICancelFlag, false, "Specifies the persistence of any previous DOI SEI message in output order.") + ("SEIDOIPersistenceFlag", m_doiSEIPersistenceFlag, false, "Specifies the persistence of the DOI SEI message for the current layer.") + ("SEIDOINumDisplayOverlaysMinus2", m_doiSEINumDisplayOverlaysMinus2, 0u, "Specifies the number of display overlays minus 2 for which information is signalled in the SEI message.") + ("SEIDOINuhLayerIdPresentFlag", m_doiSEINuhLayerIdPresentFlag, false, "Specifies that the doi_nuh_layer_id[ i ] syntax element is present in the SEI message.") + ("SEIDOITargetPicSizePresentFlag", m_doiSEITargetPicSizePresentFlag, false, "Specifies that the doi_target_pic_width_minus1 and doi_target_pic_width_minus1 syntax elements are present.") + ("SEIDOITargetPicWidthMinus1", m_doiSEITargetPicWidthMinus1, 0u, "Indicates the width minus 1 of the target picture.") + ("SEIDOITargetPicHeightMinus1", m_doiSEITargetPicHeightMinus1, 0u, "Indicates the height minus 1 of the target picture.") + ("SEIDOIPicPartitionFlag", m_doiSEIPicPartitionFlag, false, "Specifies that display overlay components are coded as constituent rectangles or subpictures.") + ("SEIDOIPartitionTypeFlag", m_doiSEIPartitionTypeFlag, false, "Specifies that a display overlay component is coded as a constituent rectangle.") + ("SEIDOIPartitionIdLenMinus1", m_doiSEIPartitionIdLenMinus1, 0u, "Specifies the length minus 1 of the doi_partition_id[ i ] syntax elements.") + ("SEIDOIOffsetParamsPresentFlag", m_doiSEIOffsetParamsPresentFlag, false, "Specifies that offset parameters are present for the i-th display overlay.") + ("SEIDOIOffsetParamsLengthMinus1", m_doiSEIOffsetParamsLengthMinus1, 0u, "Specifies the length minus 1 of the doi_top_left_x[ i ] and doi_top_left_y[ i ], syntax elements in bits.") + ("SEIDOIResamplingEnabledFlag", m_doiSEIResamplingEnabledFlag, false, "Specifies that display overlay components may be resampled in the target display picture.") + ("SEIDOISizeParamLengthMinus1", m_doiSEISizeParamLengthMinus1, 0u, "Specifies the length minus 1 of the doi_width_minus1[ i ] and doi_height_minus1[ i ] syntax elements in bits.") + ("SEIDOINuhLayerId%d", m_doiSEINuhLayerId, 0, MAX_DISPLAY_OVERLAYS, "Specifies the layer identifier of the texture component of the i-th display overlay.") + ("SEIDOIPartitionId%d", m_doiSEIPartitionId, 0, MAX_DISPLAY_OVERLAYS, "Specifies that the texture component of the i-th display overlay is represented by the j-th constituent rectangle when cr_rect_id[ j ] equal doi_partition_id[ i ].") + ("SEIDOIAlphaPresentFlag%d", m_doiSEIAlphaPresentFlag, 0, MAX_DISPLAY_OVERLAYS, "Specifies that an alpha component is provided for the i-th display overlay.") + ("SEIDOIAlphaNuhLayerId%d", m_doiSEIAlphaNuhLayerId, 0, MAX_DISPLAY_OVERLAYS, "Specifies the layer identifier value of the alpha component of the i-th display overlay.") + ("SEIDOIAlphaPartitionId%d", m_doiSEIAlphaPartitionId, 0, MAX_DISPLAY_OVERLAYS, "Specifies the cr_rect_id[ j ] of the alpha component of the i-th display overlay.") + ("SEIDOITopLeftX%d", m_doiSEITopLeftX, 0, MAX_DISPLAY_OVERLAYS, "Specifies the horizontal positions of the top left corner of the i-th display overlay in the target display picture, in luma samples.") + ("SEIDOITopLeftY%d", m_doiSEITopLeftY, 0, MAX_DISPLAY_OVERLAYS, "Specifies the vertical positions of the top left corner of the i-th display overlay in the target display picture, in luma samples.") + ("SEIDOIWidthMinus1%d", m_doiSEIWidthMinus1, 0, MAX_DISPLAY_OVERLAYS, "Specifies the width minus 1 in luma samples arrays of the i-th display overlay in the target display picture.") + ("SEIDOIHeightMinus1%d", m_doiSEIHeightMinus1, 0, MAX_DISPLAY_OVERLAYS, "Specifies the height minus 1 in luma samples arrays of the i-th display overlay in the target display picture.") +#endif ("DebugBitstream", m_decodeBitstreams[0], std::string( "" ), "Assume the frames up to POC DebugPOC will be the same as in this bitstream. Load those frames from the bitstream instead of encoding them." ) ("DebugPOC", m_switchPOC, -1, "If DebugBitstream is present, load frames up to this POC from this bitstream. Starting with DebugPOC, return to normal encoding." ) diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index fea11ff8442679e68fc859099062f95827287c55..c2ec29227c62ede60cb5ca5ac0312725f3ab5089 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -848,6 +848,35 @@ protected: std::string m_crSEIRectTypeDescription[MAX_RECT_TYPE_DESCRIPTIONS]; #endif +#if JVET_AI0181 + // Display overlays info + bool m_doiSEIEnabled; + uint32_t m_doiSEIId; + bool m_doiSEICancelFlag; + bool m_doiSEIPersistenceFlag; + uint32_t m_doiSEINumDisplayOverlaysMinus2; + bool m_doiSEINuhLayerIdPresentFlag; + bool m_doiSEITargetPicSizePresentFlag; + uint32_t m_doiSEITargetPicWidthMinus1; + uint32_t m_doiSEITargetPicHeightMinus1; + bool m_doiSEIPicPartitionFlag; + bool m_doiSEIPartitionTypeFlag; + uint32_t m_doiSEIPartitionIdLenMinus1; + bool m_doiSEIOffsetParamsPresentFlag; + uint32_t m_doiSEIOffsetParamsLengthMinus1; + bool m_doiSEIResamplingEnabledFlag; + uint32_t m_doiSEISizeParamLengthMinus1; + int m_doiSEINuhLayerId[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIPartitionId[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIAlphaPresentFlag[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIAlphaNuhLayerId[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIAlphaPartitionId[MAX_DISPLAY_OVERLAYS]; + int m_doiSEITopLeftX[MAX_DISPLAY_OVERLAYS]; + int m_doiSEITopLeftY[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIWidthMinus1[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIHeightMinus1[MAX_DISPLAY_OVERLAYS]; +#endif + bool m_constrainedRaslEncoding; bool m_sampleAspectRatioInfoSEIEnabled; diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 700d4520a98370a36abcb09dda0349309a644ac3..5b82d6d1e50de052f7fa7cbe658a9cfc96799aab 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -571,6 +571,9 @@ static constexpr int CBF_MASK_CBCR = CBF_MASK_CB | CBF_MASK_CR; // SEI and related constants // ==================================================================================================================== +#if JVET_AI0181 +static constexpr int MAX_DISPLAY_OVERLAYS = 32; +#endif static const uint32_t MAX_NNPFA_ID = 0xfffffffe; // Maximum supported nnpfa_id static const uint32_t MAX_NNPFC_ID = 0xfffffffe; // Maximum supported nnpfc_id static constexpr double SII_PF_W2 = 0.6; // weight for current picture diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp index f7e8a4b694413ef1a6f26d2958b576deaa0d16f5..4fd41f9408e3b547f1d0f8e5a6da97f65972e881 100644 --- a/source/Lib/CommonLib/SEI.cpp +++ b/source/Lib/CommonLib/SEI.cpp @@ -555,6 +555,9 @@ static const std::map<SEI::PayloadType, const char *> payloadTypeStrings = { #if JVET_AH0164_QUALITY_METRIC_SEI { SEI::PayloadType::QUALITY_METRIC, "Quality Metric" }, #endif +#if JVET_AI0181 + { SEI::PayloadType::DISPLAY_OVERLAYS_INFO, "Display overlays info" }, +#endif #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI { SEI::PayloadType::BITDEPTH_RANGE_INFO, "Bitdepth range information" }, #endif @@ -1404,6 +1407,37 @@ SEIQualityMetric::SEIQualityMetric(const SEIQualityMetric& sei) } #endif +#if JVET_AI0181 +SEIDisplayOverlaysInfo::SEIDisplayOverlaysInfo(const SEIDisplayOverlaysInfo& sei) +{ + m_doiSEIId = sei.m_doiSEIId; + m_doiSEICancelFlag = sei.m_doiSEICancelFlag; + m_doiSEIPersistenceFlag = sei.m_doiSEIPersistenceFlag; + m_doiSEINumDisplayOverlaysMinus2 = sei.m_doiSEINumDisplayOverlaysMinus2; + m_doiSEINuhLayerIdPresentFlag = sei.m_doiSEINuhLayerIdPresentFlag; + m_doiSEITargetPicSizePresentFlag = sei.m_doiSEITargetPicSizePresentFlag; + m_doiSEITargetPicWidthMinus1 = sei.m_doiSEITargetPicWidthMinus1; + m_doiSEITargetPicHeightMinus1 = sei.m_doiSEITargetPicHeightMinus1; + m_doiSEIPicPartitionFlag = sei.m_doiSEIPicPartitionFlag; + m_doiSEIPartitionTypeFlag = sei.m_doiSEIPartitionTypeFlag; + m_doiSEIPartitionIdLenMinus1 = sei.m_doiSEIPartitionIdLenMinus1; + m_doiSEIOffsetParamsPresentFlag = sei.m_doiSEIOffsetParamsPresentFlag; + m_doiSEIOffsetParamsLengthMinus1 = sei.m_doiSEIOffsetParamsLengthMinus1; + m_doiSEIResamplingEnabledFlag = sei.m_doiSEIResamplingEnabledFlag; + m_doiSEISizeParamLengthMinus1 = sei.m_doiSEISizeParamLengthMinus1; + + std::memcpy(m_doiSEINuhLayerId, sei.m_doiSEINuhLayerId, sizeof(sei.m_doiSEINuhLayerId)); + std::memcpy(m_doiSEIPartitionId, sei.m_doiSEIPartitionId, sizeof(sei.m_doiSEIPartitionId)); + std::memcpy(m_doiSEIAlphaPresentFlag, sei.m_doiSEIAlphaPresentFlag, sizeof(sei.m_doiSEIAlphaPresentFlag)); + std::memcpy(m_doiSEIAlphaNuhLayerId, sei.m_doiSEIAlphaNuhLayerId, sizeof(sei.m_doiSEIAlphaNuhLayerId)); + std::memcpy(m_doiSEIAlphaPartitionId, sei.m_doiSEIAlphaPartitionId, sizeof(sei.m_doiSEIAlphaPartitionId)); + std::memcpy(m_doiSEITopLeftX, sei.m_doiSEITopLeftX, sizeof(sei.m_doiSEITopLeftX)); + std::memcpy(m_doiSEITopLeftY, sei.m_doiSEITopLeftY, sizeof(sei.m_doiSEITopLeftY)); + std::memcpy(m_doiSEIWidthMinus1, sei.m_doiSEIWidthMinus1, sizeof(sei.m_doiSEIWidthMinus1)); + std::memcpy(m_doiSEIHeightMinus1, sei.m_doiSEIHeightMinus1, sizeof(sei.m_doiSEIHeightMinus1)); +} +#endif + #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI SEIBitdepthRangeInfo::SEIBitdepthRangeInfo(const SEIBitdepthRangeInfo& sei) { diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h index fe14a64a60221699b3e039abb987a398a5fc6a1e..01f9ef39dbd8fe4ad761e5cd58c09a7899e79bd3 100644 --- a/source/Lib/CommonLib/SEI.h +++ b/source/Lib/CommonLib/SEI.h @@ -126,8 +126,11 @@ public: #if JVET_AH0164_QUALITY_METRIC_SEI QUALITY_METRIC, // payload_type value TBD #endif +#if JVET_AI0181 + DISPLAY_OVERLAYS_INFO, +#endif #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI - BITDEPTH_RANGE_INFO, // payload_type value TBD + BITDEPTH_RANGE_INFO, // payload_type value TBD #endif }; @@ -1609,6 +1612,9 @@ public: CR_EMPTY = 255 }; +#if JVET_AI0181 + uint8_t m_layerId; +#endif uint32_t m_numRectsMinus1; bool m_rectIdPresentFlag; uint8_t m_rectIdLen; @@ -1728,32 +1734,71 @@ public: }; #endif +#if JVET_AI0181 +class SEIDisplayOverlaysInfo : public SEI +{ +public: + PayloadType payloadType() const { return PayloadType::DISPLAY_OVERLAYS_INFO; } + SEIDisplayOverlaysInfo() + : m_doiSEIId(false) + , m_doiSEICancelFlag(false) + , m_doiSEIPersistenceFlag(false) + , m_doiSEINumDisplayOverlaysMinus2(0) + , m_doiSEINuhLayerIdPresentFlag(false) + , m_doiSEIPicPartitionFlag(false) + , m_doiSEIPartitionTypeFlag(false) + , m_doiSEIPartitionIdLenMinus1(0) + , m_doiSEIOffsetParamsPresentFlag(false) + , m_doiSEIOffsetParamsLengthMinus1(0) + {} + SEIDisplayOverlaysInfo(const SEIDisplayOverlaysInfo& sei); + + virtual ~SEIDisplayOverlaysInfo() {} + + uint32_t m_doiSEIId; + bool m_doiSEICancelFlag; + bool m_doiSEIPersistenceFlag; + uint32_t m_doiSEINumDisplayOverlaysMinus2; + bool m_doiSEINuhLayerIdPresentFlag; + bool m_doiSEITargetPicSizePresentFlag; + uint32_t m_doiSEITargetPicWidthMinus1; + uint32_t m_doiSEITargetPicHeightMinus1; + bool m_doiSEIPicPartitionFlag; + bool m_doiSEIPartitionTypeFlag; + uint32_t m_doiSEIPartitionIdLenMinus1; + bool m_doiSEIOffsetParamsPresentFlag; + uint32_t m_doiSEIOffsetParamsLengthMinus1; + bool m_doiSEIResamplingEnabledFlag; + uint32_t m_doiSEISizeParamLengthMinus1; + int m_doiSEINuhLayerId[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIPartitionId[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIAlphaPresentFlag[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIAlphaNuhLayerId[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIAlphaPartitionId[MAX_DISPLAY_OVERLAYS]; + int m_doiSEITopLeftX[MAX_DISPLAY_OVERLAYS]; + int m_doiSEITopLeftY[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIWidthMinus1[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIHeightMinus1[MAX_DISPLAY_OVERLAYS]; +}; +#endif + #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI class SEIBitdepthRangeInfo : public SEI { public: PayloadType payloadType() const { return PayloadType::BITDEPTH_RANGE_INFO; } - SEIBitdepthRangeInfo() - : m_origBitDepthMinus1(9) - , m_numRangesMinus1(0) - , m_nuhLayerIdPresentFlag(false) - , m_picPartitionFlag(false) - , m_partitionTypeFlag(false) - , m_partitionIdLenMinus1(0) - , m_numBitsInRangeMinus1({9}) - , m_bitOffset({0}) - {} + SEIBitdepthRangeInfo() {} SEIBitdepthRangeInfo(const SEIBitdepthRangeInfo& sei); virtual ~SEIBitdepthRangeInfo() {} - uint32_t m_origBitDepthMinus1; - uint32_t m_numRangesMinus1; - bool m_nuhLayerIdPresentFlag; - bool m_picPartitionFlag; - bool m_partitionTypeFlag; - uint32_t m_partitionIdLenMinus1; + uint32_t m_origBitDepthMinus1; + uint32_t m_numRangesMinus1; + bool m_nuhLayerIdPresentFlag; + bool m_picPartitionFlag; + bool m_partitionTypeFlag; + uint32_t m_partitionIdLenMinus1; std::vector<uint32_t> m_nuhLayerId; std::vector<uint32_t> m_partitionId; std::vector<uint32_t> m_numBitsInRangeMinus1; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 13deb5ce29da61d59a7d014e03f79c447c15084f..012c8ed5f6b973ab3e27366c5bdec03da6c10b60 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -85,10 +85,13 @@ #define JVET_AH0164_QUALITY_METRIC_SEI 1 +#define JVET_AI0181 1 // JVET-AI0181: "AHG9: Display overlays information SEI" + #define JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI 1 //########### place macros to be be kept below this line ############### + #define GDR_ENABLED 1 #if GDR_ENABLED diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp index 5499dfc94b1293dbf23e8c84a816717a40ae463e..53ae3121380a2ae332f6908638ae4f6291fa563a 100644 --- a/source/Lib/DecoderLib/SEIread.cpp +++ b/source/Lib/DecoderLib/SEIread.cpp @@ -580,7 +580,11 @@ bool SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType #if JVET_AH0162_CONSTITUENT_RECTANGLES case SEI::PayloadType::CONSTITUENT_RECTANGLES: sei = new SEIConstituentRectangles(); +#if JVET_AI0181 + xParseSEIConstituentRectangles((SEIConstituentRectangles&) *sei,nuh_layer_id, payloadSize, pDecodedMessageOutputStream); +#else xParseSEIConstituentRectangles((SEIConstituentRectangles&) *sei, payloadSize, pDecodedMessageOutputStream); +#endif break; #endif #if JVET_AH0161_REGION_PACKING_INFORMATION_SEI @@ -589,6 +593,12 @@ bool SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType xParsePackedRegionsInfo((SEIPackedRegionsInfo &) *sei, payloadSize, pDecodedMessageOutputStream); break; #endif +#if JVET_AI0181 + case SEI::PayloadType::DISPLAY_OVERLAYS_INFO: + sei = new SEIDisplayOverlaysInfo; + xParseSEIDisplayOverlaysInfo((SEIDisplayOverlaysInfo&) *sei, payloadSize, pDecodedMessageOutputStream); + break; +#endif #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI case SEI::PayloadType::BITDEPTH_RANGE_INFO: sei = new SEIBitdepthRangeInfo; @@ -3920,8 +3930,14 @@ void SEIReader::xParseSEIXmpMetadata(SEIXmpMetadata &sei, uint32_t payLoadSize, #endif #if JVET_AH0162_CONSTITUENT_RECTANGLES +#if JVET_AI0181 +void SEIReader::xParseSEIConstituentRectangles(SEIConstituentRectangles& sei, int layerId, uint32_t payLoadSize,std::ostream* pDecodedMessageOutputStream) +{ + sei.m_layerId = layerId; +#else void SEIReader::xParseSEIConstituentRectangles(SEIConstituentRectangles& sei, uint32_t payLoadSize, std::ostream* pDecodedMessageOutputStream) { +#endif output_sei_message_header(sei, pDecodedMessageOutputStream, payLoadSize); uint32_t val; xReadCode(12, val, "cr_num_rects_minus1"); @@ -4270,6 +4286,129 @@ void SEIReader::xParseSEIQualityMetric(SEIQualityMetric& sei, uint32_t payLoadSi } #endif +#if JVET_AI0181 +void SEIReader::xParseSEIDisplayOverlaysInfo(SEIDisplayOverlaysInfo& sei, uint32_t payloadSize, + std::ostream* pDecodedMessageOutputStream) +{ + uint32_t val; + output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); + + sei_read_code(pDecodedMessageOutputStream, 6, val, "doi_id"); + sei.m_doiSEIId = val; + + sei_read_flag(pDecodedMessageOutputStream, val, "doi_cancel_flag"); + sei.m_doiSEICancelFlag = val; + + if (!sei.m_doiSEICancelFlag) + { + sei_read_flag(pDecodedMessageOutputStream, val, "doi_persistence_flag"); + sei.m_doiSEIPersistenceFlag = val; + + sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_num_display_overlays_minus2"); + sei.m_doiSEINumDisplayOverlaysMinus2 = val; + + sei_read_flag(pDecodedMessageOutputStream, val, "doi_nuh_layer_id_present_flag"); + sei.m_doiSEINuhLayerIdPresentFlag = val; + + sei_read_flag(pDecodedMessageOutputStream, val, "doi_target_pic_size_present_flag"); + sei.m_doiSEITargetPicSizePresentFlag = val; + + if (sei.m_doiSEITargetPicSizePresentFlag) + { + sei_read_code(pDecodedMessageOutputStream, 16, val, "doi_target_pic_width_minus1"); + sei.m_doiSEITargetPicWidthMinus1 = val; + + sei_read_code(pDecodedMessageOutputStream, 16, val, "doi_target_pic_height_minus1"); + sei.m_doiSEITargetPicHeightMinus1 = val; + } + + sei_read_flag(pDecodedMessageOutputStream, val, "doi_pic_partition_flag"); + sei.m_doiSEIPicPartitionFlag = val; + + if (sei.m_doiSEIPicPartitionFlag) + { + sei_read_flag(pDecodedMessageOutputStream, val, "doi_partition_type_flag"); + sei.m_doiSEIPartitionTypeFlag = val; + + sei_read_code(pDecodedMessageOutputStream, 4, val, "doi_partition_id_len_minus1"); + sei.m_doiSEIPartitionIdLenMinus1 = val; + } + + sei_read_flag(pDecodedMessageOutputStream, val, "doi_offset_params_present_flag"); + sei.m_doiSEIOffsetParamsPresentFlag = val; + + if (sei.m_doiSEIOffsetParamsPresentFlag) + { + sei_read_code(pDecodedMessageOutputStream, 4, val, "doi_offset_param_length_minus1"); + sei.m_doiSEIOffsetParamsLengthMinus1 = val; + } + + sei_read_flag(pDecodedMessageOutputStream, val, "doi_resampling_enabled_flag"); + sei.m_doiSEIResamplingEnabledFlag = val; + + if (sei.m_doiSEIResamplingEnabledFlag) + { + sei_read_code(pDecodedMessageOutputStream, 4, val, "doi_size_param_length_minus1"); + sei.m_doiSEISizeParamLengthMinus1 = val; + } + + for (int i = 0; i < sei.m_doiSEINumDisplayOverlaysMinus2 + 2; i++) + { + if (sei.m_doiSEINuhLayerIdPresentFlag) + { + sei_read_code(pDecodedMessageOutputStream, 6, val, "doi_nuh_layer_id[ i ]"); + sei.m_doiSEINuhLayerId[i] = val; + } + + if (sei.m_doiSEIPicPartitionFlag) + { + sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_partition_id[ i ]"); + sei.m_doiSEIPartitionId[i] = val; + } + + sei_read_flag(pDecodedMessageOutputStream, val, "doi_alpha_present_flag[ i ]"); + sei.m_doiSEIAlphaPresentFlag[i] = val; + + if (sei.m_doiSEIAlphaPresentFlag[i]) + { + if (sei.m_doiSEINuhLayerIdPresentFlag) + { + sei_read_code(pDecodedMessageOutputStream, 6, val, "doi_alpha_nuh_layer_id[ i ]"); + sei.m_doiSEIAlphaNuhLayerId[i] = val; + } + + if (sei.m_doiSEIPicPartitionFlag) + { + sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_alpha_partition_id[ i ]"); + sei.m_doiSEIAlphaPartitionId[i] = val; + } + } + + if (i > 0) + { + if (sei.m_doiSEIOffsetParamsPresentFlag) + { + sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_top_left_x[ i ]"); + sei.m_doiSEITopLeftX[i] = val; + + sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_top_left_y[ i ]"); + sei.m_doiSEITopLeftY[i] = val; + } + + if (sei.m_doiSEIResamplingEnabledFlag) + { + sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_width_minus1[ i ]"); + sei.m_doiSEIWidthMinus1[i] = val; + + sei_read_uvlc(pDecodedMessageOutputStream, val, "doi_height_minus1[ i ]"); + sei.m_doiSEIHeightMinus1[i] = val; + } + } + } + } +} +#endif + #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI void SEIReader::xParseSEIBitdepthRangeInfo(SEIBitdepthRangeInfo& sei, const uint32_t nuhLayerId, uint32_t payLoadSize, std::ostream *pDecodedMessageOutputStream) { diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h index f6f4d2c0cf633fcd41d126600410bd474165b05e..bc3ed52b74d1f07d569d8478069ef5c9ce243ec7 100644 --- a/source/Lib/DecoderLib/SEIread.h +++ b/source/Lib/DecoderLib/SEIread.h @@ -141,7 +141,15 @@ protected: #endif #if JVET_AH0162_CONSTITUENT_RECTANGLES +#if JVET_AI0181 + void xParseSEIConstituentRectangles(SEIConstituentRectangles& sei,int layerId, uint32_t payLoadSize,std::ostream* pDecodedMessageOutputStream); +#else void xParseSEIConstituentRectangles(SEIConstituentRectangles& sei, uint32_t payLoadSize, std::ostream *pDecodedMessageOutputStream); + #endif +#endif +#if JVET_AI0181 + void xParseSEIDisplayOverlaysInfo(SEIDisplayOverlaysInfo& sei, uint32_t payloadSize, + std::ostream* pDecodedMessageOutputStream); #endif #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index f38c90ee576f732d57073dbce745b3063f2e3ba0..d6edec90ccc71492b2b1f1b8fafc5a1258f012bb 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -1027,6 +1027,35 @@ protected: std::vector<std::array<uint32_t, 3>> m_qmSEIPicMetricValue; #endif +#if JVET_AI0181 + // Display overlays info + bool m_doiSEIEnabled; + uint32_t m_doiSEIId; + bool m_doiSEICancelFlag; + bool m_doiSEIPersistenceFlag; + uint32_t m_doiSEINumDisplayOverlaysMinus2; + bool m_doiSEINuhLayerIdPresentFlag; + bool m_doiSEITargetPicSizePresentFlag; + uint32_t m_doiSEITargetPicWidthMinus1; + uint32_t m_doiSEITargetPicHeightMinus1; + bool m_doiSEIPicPartitionFlag; + bool m_doiSEIPartitionTypeFlag; + uint32_t m_doiSEIPartitionIdLenMinus1; + bool m_doiSEIOffsetParamsPresentFlag; + uint32_t m_doiSEIOffsetParamsLengthMinus1; + bool m_doiSEIResamplingEnabledFlag; + uint32_t m_doiSEISizeParamLengthMinus1; + int m_doiSEINuhLayerId[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIPartitionId[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIAlphaPresentFlag[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIAlphaNuhLayerId[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIAlphaPartitionId[MAX_DISPLAY_OVERLAYS]; + int m_doiSEITopLeftX[MAX_DISPLAY_OVERLAYS]; + int m_doiSEITopLeftY[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIWidthMinus1[MAX_DISPLAY_OVERLAYS]; + int m_doiSEIHeightMinus1[MAX_DISPLAY_OVERLAYS]; +#endif + #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI bool m_briSEIEnabled; uint32_t m_briSEIOrigBitDepthMinus1; @@ -2958,6 +2987,60 @@ public: void setQmSEIPicMetricValue(std::vector<std::array<uint32_t, 3>> b) { m_qmSEIPicMetricValue = b; } #endif +#if JVET_AI0181 + // Display overlays info + void setDOISEIEnabled(bool b) { m_doiSEIEnabled = b; } + bool getDOISEIEnabled() { return m_doiSEIEnabled; } + void setDOISEIId(uint32_t v) { m_doiSEIId = v; } + uint32_t getDOISEIId() { return m_doiSEIId; } + void setDOISEICancelFlag(bool b) { m_doiSEICancelFlag = b; } + bool getDOISEICancelFlag() { return m_doiSEICancelFlag; } + void setDOISEIPersistenceFlag(bool b) { m_doiSEIPersistenceFlag = b; } + bool getDOISEIPersistenceFlag() { return m_doiSEIPersistenceFlag; } + void setDOISEINumDisplayOverlaysMinus2(uint32_t v) { m_doiSEINumDisplayOverlaysMinus2 = v; } + uint32_t getDOISEINumDisplayOverlaysMinus2() { return m_doiSEINumDisplayOverlaysMinus2; } + void setDOISEINuhLayerIdPresentFlag(bool b) { m_doiSEINuhLayerIdPresentFlag = b; } + bool getDOISEINuhLayerIdPresentFlag() { return m_doiSEINuhLayerIdPresentFlag; } + void setDOISEITargetPicSizePresentFlag(bool b) { m_doiSEITargetPicSizePresentFlag = b; } + bool getDOISEITargetPicSizePresentFlag() { return m_doiSEITargetPicSizePresentFlag; } + void setDOISEITargetPicWidthMinus1(uint32_t v) { m_doiSEITargetPicWidthMinus1 = v; } + uint32_t getDOISEITargetPicWidthMinus1() { return m_doiSEITargetPicWidthMinus1; } + void setDOISEITargetPicHeightMinus1(uint32_t v) { m_doiSEITargetPicHeightMinus1 = v; } + uint32_t getDOISEITargetPicHeightMinus1() { return m_doiSEITargetPicHeightMinus1; } + void setDOISEIPicPartitionFlag(bool b) { m_doiSEIPicPartitionFlag = b; } + bool getDOISEIPicPartitionFlag() { return m_doiSEIPicPartitionFlag; } + void setDOISEIPartitionTypeFlag(bool b) { m_doiSEIPartitionTypeFlag = b; } + bool getDOISEIPartitionTypeFlag() { return m_doiSEIPartitionTypeFlag; } + void setDOISEIPartitionIdLenMinus1(uint32_t v) { m_doiSEIPartitionIdLenMinus1 = v; } + uint32_t getDOISEIPartitionIdLenMinus1() { return m_doiSEIPartitionIdLenMinus1; } + void setDOISEIOffsetParamsPresentFlag(bool b) { m_doiSEIOffsetParamsPresentFlag = b; } + bool getDOISEIOffsetParamsPresentFlag() { return m_doiSEIOffsetParamsPresentFlag; } + void setDOISEIOffsetParamsLengthMinus1(uint32_t v) { m_doiSEIOffsetParamsLengthMinus1 = v; } + uint32_t getDOISEIOffsetParamsLengthMinus1() { return m_doiSEIOffsetParamsLengthMinus1; } + void setDOISEIResamplingEnabledFlag(bool b) { m_doiSEIResamplingEnabledFlag = b; } + bool getDOISEIResamplingEnabledFlag() { return m_doiSEIResamplingEnabledFlag; } + void setDOISEISizeParamLengthMinus1(uint32_t v) { m_doiSEISizeParamLengthMinus1 = v; } + uint32_t getDOISEISizeParamLengthMinus1() { return m_doiSEISizeParamLengthMinus1; } + void setDOISEINuhLayerId(uint32_t v, int i) { m_doiSEINuhLayerId[i] = v; } + uint32_t getDOISEINuhLayerId(int i) { return m_doiSEINuhLayerId[i]; } + void setDOISEIPartitionId(uint32_t v, int i) { m_doiSEIPartitionId[i] = v; } + uint32_t getDOISEIPartitionId(int i) { return m_doiSEIPartitionId[i]; } + void setDOISEIAlphaPresentFlag(bool v, int i) { m_doiSEIAlphaPresentFlag[i] = v; } + bool getDOISEIAlphaPresentFlag(int i) { return m_doiSEIAlphaPresentFlag[i]; } + void setDOISEIAlphaNuhLayerId(uint32_t v, int i) { m_doiSEIAlphaNuhLayerId[i] = v; } + int getDOISEIAlphaNuhLayerId(int i) { return m_doiSEIAlphaNuhLayerId[i]; } + void setDOISEIAlphaPartitionId(int v, int i) { m_doiSEIAlphaPartitionId[i] = v; } + int getDOISEIAlphaPartitionId(int i) { return m_doiSEIAlphaPartitionId[i]; } + void setDOISEITopLeftX(int v, int i) { m_doiSEITopLeftX[i] = v; } + int getDOISEITopLeftX(int i) { return m_doiSEITopLeftX[i]; } + void setDOISEITopLeftY(int v, int i) { m_doiSEITopLeftY[i] = v; } + int getDOISEITopLeftY(int i) { return m_doiSEITopLeftY[i]; } + void setDOISEIWidthMinus1(int v, int i) { m_doiSEIWidthMinus1[i] = v; } + int getDOISEIWidthMinus1(int i) { return m_doiSEIWidthMinus1[i]; } + void setDOISEIHeightMinus1(int v, int i) { m_doiSEIHeightMinus1[i] = v; } + int getDOISEIHeightMinus1(int i) { return m_doiSEIHeightMinus1[i]; } +#endif + #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI bool getBriSEIEnabled() const { return m_briSEIEnabled; } void setBriSEIEnabled(bool b) { m_briSEIEnabled = b; } diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index f632242a375a43e3df0b163dddd80056b3624885..94b705e7be9296964ea99559708b04f9d4be93d2 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -1131,6 +1131,15 @@ void EncGOP::xCreatePerPictureSEIMessages (int picInGOP, SEIMessages& seiMessage seiMessages.push_back(jfifSEI); } #endif + + #if JVET_AI0181 + if (m_pcCfg->getDOISEIEnabled()) + { + SEIDisplayOverlaysInfo* eoiSEI = new SEIDisplayOverlaysInfo; + m_seiEncoder.initSEIDisplayOverlaysInfo(eoiSEI); + seiMessages.push_back(eoiSEI); + } +#endif } void EncGOP::xCreateNNPostFilterCharacteristicsSEIMessages(SEIMessages& seiMessages) diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp index 27375bfcb7a45726994aa324b911d9bfcd35b53b..61fb7c2ffdd2c2e145c10b2826431559ea25e974 100644 --- a/source/Lib/EncoderLib/SEIEncoder.cpp +++ b/source/Lib/EncoderLib/SEIEncoder.cpp @@ -2058,6 +2058,106 @@ void SEIEncoder::initSEIPackedRegionsInfo(SEIPackedRegionsInfo* sei) } #endif +#if JVET_AI0181 + +void SEIEncoder::initSEIDisplayOverlaysInfo(SEIDisplayOverlaysInfo* sei) +{ + CHECK(!(m_isInitialized), "Unspecified error"); + CHECK(!(sei != nullptr), "Unspecified error"); + sei->m_doiSEIId = m_pcCfg->getDOISEIId(); + sei->m_doiSEICancelFlag = m_pcCfg->getDOISEICancelFlag(); + if (!sei->m_doiSEICancelFlag) + { + sei->m_doiSEIPersistenceFlag = m_pcCfg->getDOISEIPersistenceFlag(); + + sei->m_doiSEINumDisplayOverlaysMinus2 = m_pcCfg->getDOISEINumDisplayOverlaysMinus2(); + + sei->m_doiSEINuhLayerIdPresentFlag = m_pcCfg->getDOISEINuhLayerIdPresentFlag(); + + sei->m_doiSEITargetPicSizePresentFlag = m_pcCfg->getDOISEITargetPicSizePresentFlag(); + + if (sei->m_doiSEITargetPicSizePresentFlag) + { + sei->m_doiSEITargetPicWidthMinus1 = m_pcCfg->getDOISEITargetPicWidthMinus1(); + + sei->m_doiSEITargetPicHeightMinus1 = m_pcCfg->getDOISEITargetPicHeightMinus1(); + } + + sei->m_doiSEIPicPartitionFlag = m_pcCfg->getDOISEIPicPartitionFlag(); + + CHECK((sei->m_doiSEINuhLayerIdPresentFlag == 0) && (sei->m_doiSEIPicPartitionFlag == 0), + "It is a requirement of bitstream conformance that at least one of doi_nuh_layer_id_present_flag or " + "doi_pic_partition_flag shall be equal to 1."); + + if (sei->m_doiSEIPicPartitionFlag) + { + sei->m_doiSEIPartitionTypeFlag = m_pcCfg->getDOISEIPartitionTypeFlag(); + + sei->m_doiSEIPartitionIdLenMinus1 = m_pcCfg->getDOISEIPartitionIdLenMinus1(); + } + + sei->m_doiSEIOffsetParamsPresentFlag = m_pcCfg->getDOISEIOffsetParamsPresentFlag(); + + if (sei->m_doiSEIOffsetParamsPresentFlag) + { + sei->m_doiSEIOffsetParamsLengthMinus1 = m_pcCfg->getDOISEIOffsetParamsLengthMinus1(); + } + + sei->m_doiSEIResamplingEnabledFlag = m_pcCfg->getDOISEIResamplingEnabledFlag(); + + if (sei->m_doiSEIResamplingEnabledFlag) + { + sei->m_doiSEISizeParamLengthMinus1 = m_pcCfg->getDOISEISizeParamLengthMinus1(); + } + + for (int i = 0; i < sei->m_doiSEINumDisplayOverlaysMinus2 + 2; i++) + { + if (sei->m_doiSEINuhLayerIdPresentFlag) + { + sei->m_doiSEINuhLayerId[i] = m_pcCfg->getDOISEINuhLayerId(i); + } + + if (sei->m_doiSEIPicPartitionFlag) + { + sei->m_doiSEIPartitionId[i] = m_pcCfg->getDOISEIPartitionId(i); + } + + sei->m_doiSEIAlphaPresentFlag[i] = m_pcCfg->getDOISEIAlphaPresentFlag(i); + + if (sei->m_doiSEIAlphaPresentFlag[i]) + { + if (sei->m_doiSEINuhLayerIdPresentFlag) + { + sei->m_doiSEIAlphaNuhLayerId[i] = m_pcCfg->getDOISEIAlphaNuhLayerId(i); + } + + if (sei->m_doiSEIPicPartitionFlag) + { + sei->m_doiSEIAlphaPartitionId[i] = m_pcCfg->getDOISEIAlphaPartitionId(i); + } + } + + if (i > 0) + { + if (sei->m_doiSEIOffsetParamsPresentFlag) + { + sei->m_doiSEITopLeftX[i] = m_pcCfg->getDOISEITopLeftX(i); + + sei->m_doiSEITopLeftY[i] = m_pcCfg->getDOISEITopLeftY(i); + } + + if (sei->m_doiSEIResamplingEnabledFlag) + { + sei->m_doiSEIWidthMinus1[i] = m_pcCfg->getDOISEIWidthMinus1(i); + + sei->m_doiSEIHeightMinus1[i] = m_pcCfg->getDOISEIHeightMinus1(i); + } + } + } + } +} +#endif + #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI void SEIEncoder::initSEIBitdepthRangeInfo(SEIBitdepthRangeInfo* sei) { diff --git a/source/Lib/EncoderLib/SEIEncoder.h b/source/Lib/EncoderLib/SEIEncoder.h index 5fd894e856066c8c7ba964ce9c1be104c20115cf..6d9bfbf56035c9e371721bfbe8b8f1df81fcc630 100644 --- a/source/Lib/EncoderLib/SEIEncoder.h +++ b/source/Lib/EncoderLib/SEIEncoder.h @@ -130,6 +130,9 @@ public: #if JVET_AH0164_QUALITY_METRIC_SEI void initSEIQualityMetric(SEIQualityMetric *sei); #endif +#if JVET_AI0181 + void initSEIDisplayOverlaysInfo(SEIDisplayOverlaysInfo* sei); +#endif #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI void initSEIBitdepthRangeInfo(SEIBitdepthRangeInfo *sei); #endif diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp index f4981b81cf4a7eb7a2b698372e3aece6e0739270..c2c5a0d9fac599168d30029b552c91865d09bed4 100644 --- a/source/Lib/EncoderLib/SEIwrite.cpp +++ b/source/Lib/EncoderLib/SEIwrite.cpp @@ -198,6 +198,11 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI &sei, HRD &h xWriteSEIQualityMetric(*static_cast<const SEIQualityMetric *>(&sei)); break; #endif +#if JVET_AI0181 + case SEI::PayloadType::DISPLAY_OVERLAYS_INFO: + xWriteSEIDisplayOverlaysInfo(*static_cast<const SEIDisplayOverlaysInfo*>(&sei)); + break; +#endif #if JVET_AF0167_MULTI_PLANE_IMAGE_INFO_SEI case SEI::PayloadType::MULTIPLANE_IMAGE_INFO: xWriteSEIMultiplaneImageInfo(*static_cast<const SEIMultiplaneImageInfo*>(&sei)); @@ -2388,4 +2393,98 @@ void SEIWriter::xWriteSEIBitdepthRangeInfo(const SEIBitdepthRangeInfo& sei) } #endif +#if JVET_AI0181 +void SEIWriter::xWriteSEIDisplayOverlaysInfo(const SEIDisplayOverlaysInfo& sei) +{ + xWriteCode(sei.m_doiSEIId, 6, "doi_id"); + + xWriteFlag(sei.m_doiSEICancelFlag, "doi_cancel_flag"); + + if (!sei.m_doiSEICancelFlag) + { + xWriteFlag(sei.m_doiSEIPersistenceFlag, "doi_persistence_flag"); + + xWriteUvlc(sei.m_doiSEINumDisplayOverlaysMinus2, "doi_num_display_overlays_minus2"); + + xWriteFlag(sei.m_doiSEINuhLayerIdPresentFlag, "doi_nuh_layer_id_present_flag"); + + xWriteFlag(sei.m_doiSEITargetPicSizePresentFlag, "doi_target_pic_size_present_flag"); + + if (sei.m_doiSEITargetPicSizePresentFlag) + { + xWriteCode(sei.m_doiSEITargetPicWidthMinus1, 16, "doi_target_pic_width_minus1"); + + xWriteCode(sei.m_doiSEITargetPicHeightMinus1, 16, "doi_target_pic_height_minus1"); + } + + xWriteFlag(sei.m_doiSEIPicPartitionFlag, "doi_pic_partition_flag"); + + if (sei.m_doiSEIPicPartitionFlag) + { + xWriteFlag(sei.m_doiSEIPartitionTypeFlag, "doi_partition_type_flag"); + + xWriteCode(sei.m_doiSEIPartitionIdLenMinus1, 4, "doi_partition_id_len_minus1"); + } + + xWriteFlag(sei.m_doiSEIOffsetParamsPresentFlag, "doi_offset_params_present_flag"); + + if (sei.m_doiSEIOffsetParamsPresentFlag) + { + xWriteCode(sei.m_doiSEIOffsetParamsLengthMinus1, 4, "doi_offset_param_length_minus1"); + } + + xWriteFlag(sei.m_doiSEIResamplingEnabledFlag, "doi_resampling_enabled_flag"); + + if (sei.m_doiSEIResamplingEnabledFlag) + { + xWriteCode(sei.m_doiSEISizeParamLengthMinus1, 4, "doi_size_param_length_minus1"); + } + + for (int i = 0; i < sei.m_doiSEINumDisplayOverlaysMinus2 + 2; i++) + { + if (sei.m_doiSEINuhLayerIdPresentFlag) + { + xWriteCode(sei.m_doiSEINuhLayerId[i], 6, "doi_nuh_layer_id[ i ]"); + } + + if (sei.m_doiSEIPicPartitionFlag) + { + xWriteUvlc(sei.m_doiSEIPartitionId[i], "doi_partition_id[ i ]"); + } + + xWriteFlag(sei.m_doiSEIAlphaPresentFlag[i], "doi_alpha_present_flag[ i ]"); + + if (sei.m_doiSEIAlphaPresentFlag[i]) + { + if (sei.m_doiSEINuhLayerIdPresentFlag) + { + xWriteCode(sei.m_doiSEIAlphaNuhLayerId[i], 6, "doi_alpha_nuh_layer_id[ i ]"); + } + + if (sei.m_doiSEIPicPartitionFlag) + { + xWriteUvlc(sei.m_doiSEIAlphaPartitionId[i], "doi_alpha_partition_id[ i ]"); + } + } + + if (i > 0) + { + if (sei.m_doiSEIOffsetParamsPresentFlag) + { + xWriteUvlc(sei.m_doiSEITopLeftX[i], "doi_top_left_x[ i ]"); + + xWriteUvlc(sei.m_doiSEITopLeftY[i], "doi_top_left_y[ i ]"); + } + + if (sei.m_doiSEIResamplingEnabledFlag) + { + xWriteUvlc(sei.m_doiSEIWidthMinus1[i], "doi_width_minus1[ i ]"); + + xWriteUvlc(sei.m_doiSEIHeightMinus1[i], "doi_height_minus1[ i ]"); + } + } + } + } +} +#endif //! \} diff --git a/source/Lib/EncoderLib/SEIwrite.h b/source/Lib/EncoderLib/SEIwrite.h index b33b8f457ee52a31d30bc0aa80283c83c987ff54..4cbebc81af8e349f82ae9bdd22d3a7e1f18c3b8b 100644 --- a/source/Lib/EncoderLib/SEIwrite.h +++ b/source/Lib/EncoderLib/SEIwrite.h @@ -138,6 +138,9 @@ protected: #if JVET_AH0164_QUALITY_METRIC_SEI void xWriteSEIQualityMetric(const SEIQualityMetric& sei); #endif +#if JVET_AI0181 + void xWriteSEIDisplayOverlaysInfo(const SEIDisplayOverlaysInfo& sei); +#endif #if JVET_AI0182_BITDEPTH_RANGE_INFORMATION_SEI void xWriteSEIBitdepthRangeInfo(const SEIBitdepthRangeInfo& sei); #endif