1 /*
2 * Copyright (c) 2017, 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 //! \file     codechal_mmc_decode_hevc.cpp
24 //! \brief    Impelements the public interface for CodecHal Media Memory Compression
25 //!
26 
27 #include "codechal_mmc_decode_hevc.h"
28 
CodechalMmcDecodeHevc(CodechalHwInterface * hwInterface,void * standardState)29 CodechalMmcDecodeHevc::CodechalMmcDecodeHevc(
30     CodechalHwInterface    *hwInterface,
31     void *standardState):
32     CodecHalMmcState(hwInterface)
33 {
34     CODECHAL_DECODE_FUNCTION_ENTER;
35 
36     m_hevcState = (CodechalDecodeHevc *)standardState;
37     CODECHAL_HW_ASSERT(m_hevcState);
38 
39     CODECHAL_HW_ASSERT(hwInterface);
40     CODECHAL_HW_ASSERT(hwInterface->GetSkuTable());
41     if (MEDIA_IS_SKU(hwInterface->GetSkuTable(), FtrMemoryCompression))
42     {
43         MOS_USER_FEATURE_VALUE_DATA userFeatureData;
44         MOS_ZeroMemory(&userFeatureData, sizeof(userFeatureData));
45         userFeatureData.i32Data = m_mmcEnabled;
46         userFeatureData.i32DataFlag = MOS_USER_FEATURE_VALUE_DATA_FLAG_CUSTOM_DEFAULT_VALUE_TYPE;
47 
48         MOS_UserFeature_ReadValue_ID(
49             nullptr,
50             __MEDIA_USER_FEATURE_VALUE_DECODE_MMC_ENABLE_ID,
51             &userFeatureData);
52         m_mmcEnabled = (userFeatureData.i32Data) ? true : false;
53 
54         MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData;
55         MOS_ZeroMemory(&userFeatureWriteData, sizeof(userFeatureWriteData));
56         userFeatureWriteData.Value.i32Data = m_mmcEnabled;
57         userFeatureWriteData.ValueID = __MEDIA_USER_FEATURE_VALUE_DECODE_MMC_IN_USE_ID;
58         MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1);
59     }
60 
61 #if (_DEBUG || _RELEASE_INTERNAL)
62     m_compressibleId  = __MEDIA_USER_FEATURE_VALUE_MMC_DEC_RT_COMPRESSIBLE_ID;
63     m_compressModeId  = __MEDIA_USER_FEATURE_VALUE_MMC_DEC_RT_COMPRESSMODE_ID;
64 #endif
65 }
66 
SetPipeBufAddr(PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams,PMOS_COMMAND_BUFFER cmdBuffer)67 MOS_STATUS CodechalMmcDecodeHevc::SetPipeBufAddr(
68     PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams,
69     PMOS_COMMAND_BUFFER cmdBuffer)
70 {
71     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
72 
73     CODECHAL_DECODE_FUNCTION_ENTER;
74 
75     pipeBufAddrParams->PreDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
76 
77     if (m_mmcEnabled &&
78         m_hcpMmcEnabled &&
79         m_hevcState->m_destSurface.bCompressible)
80     {
81         if ((m_10bitMmcEnabled && m_hevcState->m_destSurface.Format == Format_P010) ||
82             (m_hevcState->m_destSurface.Format == Format_NV12) ||
83             (m_hevcState->m_destSurface.Format == Format_YUY2))
84         {
85             pipeBufAddrParams->PreDeblockSurfMmcState = MOS_MEMCOMP_HORIZONTAL;
86         }
87     }
88 
89     CODECHAL_DEBUG_TOOL(
90         m_hevcState->m_destSurface.MmcState = pipeBufAddrParams->PreDeblockSurfMmcState;)
91 
92     return eStatus;
93 }
94 
SetRefrenceSync(bool disableDecodeSyncLock,bool disableLockForTranscode)95 MOS_STATUS CodechalMmcDecodeHevc::SetRefrenceSync(
96     bool disableDecodeSyncLock,
97     bool disableLockForTranscode)
98 {
99     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
100 
101     CODECHAL_DECODE_FUNCTION_ENTER;
102 
103     CODECHAL_DECODE_CHK_NULL_RETURN(m_hevcState->m_hevcPicParams);
104 
105     // Check if reference surface needs to be synchronized in MMC case
106     if (m_mmcEnabled &&
107         !CodecHal_PictureIsField(m_hevcState->m_hevcPicParams->CurrPic))
108     {
109         MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
110         syncParams.GpuContext = m_hevcState->GetVideoContext();
111         syncParams.bDisableDecodeSyncLock = disableDecodeSyncLock;
112         syncParams.bDisableLockForTranscode = disableLockForTranscode;
113 
114         for (uint32_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
115         {
116             if (m_hevcState->m_presReferences[i])
117             {
118                 syncParams.presSyncResource = m_hevcState->m_presReferences[i];
119                 syncParams.bReadOnly        = true;
120 
121                 CODECHAL_DECODE_CHK_STATUS_RETURN(
122                     m_osInterface->pfnPerformOverlaySync(
123                         m_osInterface,
124                         &syncParams));
125                 CODECHAL_DECODE_CHK_STATUS_RETURN(
126                     m_osInterface->pfnResourceWait(
127                         m_osInterface,
128                         &syncParams));
129                 m_osInterface->pfnSetResourceSyncTag(
130                     m_osInterface,
131                     &syncParams);
132             }
133         }
134     }
135 
136     return eStatus;
137 }
138 
CheckReferenceList(PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams)139 MOS_STATUS CodechalMmcDecodeHevc::CheckReferenceList(
140         PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams)
141 {
142     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
143 
144     CODECHAL_DECODE_FUNCTION_ENTER;
145 
146     CODECHAL_DECODE_CHK_NULL_RETURN(pipeBufAddrParams);
147     CODECHAL_DECODE_CHK_NULL_RETURN(m_hevcState->m_hevcPicParams);
148 
149     MOS_MEMCOMP_STATE mmcMode;
150     bool selfReference = false;
151 
152     // Disable MMC if self-reference is dectected (mainly for error concealment)
153     if (((pipeBufAddrParams->PostDeblockSurfMmcState != MOS_MEMCOMP_DISABLED) ||
154             (pipeBufAddrParams->PreDeblockSurfMmcState != MOS_MEMCOMP_DISABLED)) &&
155         !m_hevcState->m_curPicIntra)
156     {
157         for (int i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
158         {
159             if (m_hevcState->m_hevcPicParams->CurrPic.FrameIdx == m_hevcState->m_hevcPicParams->RefFrameList[i].FrameIdx)
160             {
161                 selfReference = true;
162                 break;
163             }
164         }
165 
166         if (selfReference)
167         {
168             pipeBufAddrParams->PostDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
169             pipeBufAddrParams->PreDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
170             CODECHAL_DECODE_NORMALMESSAGE("Self-reference is detected for P/B frames!");
171 
172             // Decompress current frame to avoid green corruptions in this error handling case
173             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetMemoryCompressionMode(
174                 m_osInterface,
175                 &m_hevcState->m_destSurface.OsResource,
176                 &mmcMode));
177             if (mmcMode != MOS_MEMCOMP_DISABLED)
178             {
179                 CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnDecompResource(
180                     m_osInterface,
181                     &m_hevcState->m_destSurface.OsResource));
182             }
183         }
184     }
185 
186     // Do surface decompression to make sure the MMC states are consistent in the reference list
187     MOS_MEMCOMP_STATE mmcModePrev = MOS_MEMCOMP_DISABLED;
188     bool sameMmcStatus = true;
189     bool firstRefPic = true;
190     for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
191     {
192         if (m_hevcState->m_presReferences[i])
193         {
194             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetMemoryCompressionMode(
195                 m_osInterface,
196                 m_hevcState->m_presReferences[i],
197                 &mmcMode));
198             if (firstRefPic)
199             {
200                 mmcModePrev = mmcMode;
201                 firstRefPic = false;
202             }
203             else if (mmcModePrev != mmcMode)
204             {
205                 sameMmcStatus = false;
206                 break;
207             }
208         }
209     }
210 
211     if(!sameMmcStatus)
212     {
213         for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
214         {
215             if (m_hevcState->m_presReferences[i])
216             {
217                 CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetMemoryCompressionMode(
218                     m_osInterface,
219                     m_hevcState->m_presReferences[i],
220                     &mmcMode));
221                 if(mmcMode != MOS_MEMCOMP_DISABLED)
222                 {
223                     m_osInterface->pfnDecompResource(
224                         m_osInterface,
225                         m_hevcState->m_presReferences[i]);
226                 }
227             }
228         }
229     }
230     return eStatus;
231 }
232