1 /*
2 * Copyright (c) 2020-2022, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 
23 //!
24 //! \file     decode_hevc_mem_compression.cpp
25 //! \brief    Defines the common interface for Hevc decode mmc
26 //! \details  The mmc is to handle mmc operations,
27 //! including compression and decompressin of Hevc decode
28 //!
29 
30 #include "mos_defs.h"
31 #include "decode_hevc_mem_compression.h"
32 
33 namespace decode
34 {
35 
HevcDecodeMemComp(CodechalHwInterfaceNext * hwInterface)36 HevcDecodeMemComp::HevcDecodeMemComp(CodechalHwInterfaceNext *hwInterface)
37 {
38     if (hwInterface)
39     {
40         m_osInterface = hwInterface->GetOsInterface();
41     }
42 }
43 
SetRefSurfaceMask(HevcBasicFeature & hevcBasicFeature,const PMOS_RESOURCE * presReferences,uint8_t & mmcSkipMask)44 MOS_STATUS HevcDecodeMemComp::SetRefSurfaceMask(
45     HevcBasicFeature    &hevcBasicFeature,
46     const PMOS_RESOURCE *presReferences,
47     uint8_t             &mmcSkipMask)
48 {
49     if (hevcBasicFeature.m_isSCCIBCMode)
50     {
51         HevcReferenceFrames &refFrames = hevcBasicFeature.m_refFrames;
52         DECODE_ASSERT(hevcBasicFeature.m_hevcPicParams != nullptr);
53         const std::vector<uint8_t> &activeRefList = refFrames.GetActiveReferenceList(*hevcBasicFeature.m_hevcPicParams);
54 
55         uint8_t IBCRefIdx = refFrames.m_IBCRefIdx;
56         DECODE_CHK_COND(activeRefList.size() <= IBCRefIdx, "Invalid IBC reference index.");
57         uint8_t IBCFrameIdx = activeRefList[IBCRefIdx];
58 
59         uint8_t skipMask = 0;
60         for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
61         {
62             if (presReferences[i] == refFrames.GetReferenceByFrameIndex(IBCFrameIdx))
63             {
64                 skipMask |= (1 << i);
65             }
66         }
67         mmcSkipMask = skipMask;
68         DECODE_NORMALMESSAGE("IBC ref index %d, MMC skip mask %d,", IBCRefIdx, skipMask);
69     }
70 
71     MOS_MEMCOMP_STATE refMmcState = MOS_MEMCOMP_DISABLED;
72     uint8_t           skipMask    = 0;
73     for (uint16_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
74     {
75         if (presReferences[i] != nullptr)
76         {
77             DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
78                 m_osInterface, presReferences[i], &refMmcState));
79         }
80 
81         if (refMmcState == MOS_MEMCOMP_DISABLED)
82         {
83             skipMask |= (1 << i);
84         }
85     }
86     mmcSkipMask |= skipMask;
87     DECODE_NORMALMESSAGE("HEVC MMC skip mask %d\n", mmcSkipMask);
88 
89     return MOS_STATUS_SUCCESS;
90 }
91 
SetRefSurfaceCompressionFormat(HevcBasicFeature & hevcBasicFeature,const PMOS_RESOURCE * presReferences,uint32_t & mmcCompressionFormat)92 MOS_STATUS HevcDecodeMemComp::SetRefSurfaceCompressionFormat(
93     HevcBasicFeature    &hevcBasicFeature,
94     const PMOS_RESOURCE *presReferences,
95     uint32_t            &mmcCompressionFormat)
96 {
97     MOS_MEMCOMP_STATE refMmcState       = MOS_MEMCOMP_DISABLED;
98     uint32_t          compressionFormat = 0;
99     uint32_t          refcompressionFormat = 0;
100 
101     for (uint16_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
102     {
103         if (presReferences[i] != nullptr)
104         {
105             DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
106                 m_osInterface, presReferences[i], &refMmcState));
107 
108             if (refMmcState == MOS_MEMCOMP_MC || refMmcState == MOS_MEMCOMP_RC)
109             {
110                 DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionFormat(
111                     m_osInterface, presReferences[i], &compressionFormat));
112 
113                 refcompressionFormat = compressionFormat;
114             }
115         }
116     }
117     mmcCompressionFormat = refcompressionFormat;
118     DECODE_NORMALMESSAGE("HEVC reference surface compression format %d\n", mmcCompressionFormat);
119 
120     return MOS_STATUS_SUCCESS;
121 }
122 
CheckReferenceList(HevcBasicFeature & hevcBasicFeature,MOS_MEMCOMP_STATE & postDeblockSurfMmcState,MOS_MEMCOMP_STATE & preDeblockSurfMmcState,PMOS_RESOURCE * presReferences)123 MOS_STATUS HevcDecodeMemComp::CheckReferenceList(HevcBasicFeature &hevcBasicFeature,
124         MOS_MEMCOMP_STATE &postDeblockSurfMmcState,
125         MOS_MEMCOMP_STATE &preDeblockSurfMmcState,
126         PMOS_RESOURCE     *presReferences)
127 {
128     DECODE_FUNC_CALL();
129     DECODE_CHK_NULL(m_osInterface);
130 
131     // Disable MMC if self-reference is dectected (mainly for error concealment)
132     if (!hevcBasicFeature.m_refFrames.m_curIsIntra)
133     {
134         if (postDeblockSurfMmcState != MOS_MEMCOMP_DISABLED ||
135             preDeblockSurfMmcState  != MOS_MEMCOMP_DISABLED)
136         {
137             DECODE_ASSERT(hevcBasicFeature.m_hevcPicParams);
138             CODEC_HEVC_PIC_PARAMS &hevcPicParams = *(hevcBasicFeature.m_hevcPicParams);
139 
140             for (uint8_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
141             {
142                 if (hevcPicParams.CurrPic.FrameIdx == hevcPicParams.RefFrameList[i].FrameIdx)
143                 {
144                     DECODE_NORMALMESSAGE("Self-reference is detected for P/B frames!");
145                     postDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
146                     preDeblockSurfMmcState  = MOS_MEMCOMP_DISABLED;
147 
148                     // Decompress current frame to avoid green corruptions in this error handling case
149                     MOS_MEMCOMP_STATE mmcMode = MOS_MEMCOMP_DISABLED;
150                     MOS_SURFACE &destSurface  = hevcBasicFeature.m_destSurface;
151                     DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
152                         m_osInterface, &destSurface.OsResource, &mmcMode));
153                     if (mmcMode != MOS_MEMCOMP_DISABLED)
154                     {
155                         DECODE_CHK_STATUS(m_osInterface->pfnDecompResource(m_osInterface, &destSurface.OsResource));
156                     }
157 
158                     break;
159                 }
160             }
161         }
162     }
163 
164     // Do surface decompression to make sure the MMC states are consistent in the reference list
165     bool sameMmcStatus = true;
166     MOS_MEMCOMP_STATE mmcModePrev  = MOS_MEMCOMP_DISABLED;
167     for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
168     {
169         if (presReferences[i] != nullptr)
170         {
171             MOS_MEMCOMP_STATE mmcMode = MOS_MEMCOMP_DISABLED;
172             DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
173                 m_osInterface, presReferences[i], &mmcMode));
174 
175             if (i == 0)
176             {
177                 mmcModePrev = mmcMode;
178             }
179             else if (mmcModePrev != mmcMode)
180             {
181                 sameMmcStatus = false;
182                 break;
183             }
184         }
185     }
186 
187     if(!sameMmcStatus)
188     {
189         for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
190         {
191             if (presReferences[i] != nullptr)
192             {
193                 MOS_MEMCOMP_STATE mmcMode = MOS_MEMCOMP_DISABLED;
194                 DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
195                     m_osInterface, presReferences[i], &mmcMode));
196                 if(mmcMode != MOS_MEMCOMP_DISABLED)
197                 {
198                     m_osInterface->pfnDecompResource(m_osInterface, presReferences[i]);
199                 }
200             }
201         }
202     }
203 
204     return MOS_STATUS_SUCCESS;
205 }
206 
207 }
208