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_vp9.cpp
24 //! \brief    Impelements the public interface for CodecHal Media Memory Compression
25 //!
26 
27 #include "codechal_mmc_decode_vp9.h"
28 
CodechalMmcDecodeVp9(CodechalHwInterface * hwInterface,void * standardState)29 CodechalMmcDecodeVp9::CodechalMmcDecodeVp9(
30     CodechalHwInterface    *hwInterface,
31     void *standardState):
32     CodecHalMmcState(hwInterface)
33 {
34     CODECHAL_DECODE_FUNCTION_ENTER;
35 
36     m_vp9State = (CodechalDecodeVp9 *)standardState;
37     CODECHAL_HW_ASSERT(m_vp9State);
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 #if (_DEBUG || _RELEASE_INTERNAL)
61     m_compressibleId  = __MEDIA_USER_FEATURE_VALUE_MMC_DEC_RT_COMPRESSIBLE_ID;
62     m_compressModeId  = __MEDIA_USER_FEATURE_VALUE_MMC_DEC_RT_COMPRESSMODE_ID;
63 #endif
64 }
65 
SetPipeBufAddr(PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams,PMOS_COMMAND_BUFFER cmdBuffer)66 MOS_STATUS CodechalMmcDecodeVp9::SetPipeBufAddr(
67     PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams,
68     PMOS_COMMAND_BUFFER cmdBuffer)
69 {
70     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
71 
72     CODECHAL_DECODE_FUNCTION_ENTER;
73 
74     if (m_mmcEnabled &&
75         m_hcpMmcEnabled &&
76         m_vp9State->m_destSurface.bCompressible)
77     {
78         if ((m_10bitMmcEnabled && m_vp9State->m_destSurface.Format == Format_P010) ||
79             (m_vp9State->m_destSurface.Format == Format_NV12))
80         {
81             pipeBufAddrParams->PreDeblockSurfMmcState = MOS_MEMCOMP_HORIZONTAL;
82         }
83         else
84         {
85             pipeBufAddrParams->PreDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
86         }
87     }
88 
89     CODECHAL_DEBUG_TOOL(
90         m_vp9State->m_destSurface.MmcState = pipeBufAddrParams->PreDeblockSurfMmcState;)
91 
92     return eStatus;
93 }
94 
SetRefrenceSync(bool disableDecodeSyncLock,bool disableLockForTranscode)95 MOS_STATUS CodechalMmcDecodeVp9::SetRefrenceSync(
96     bool disableDecodeSyncLock,
97     bool disableLockForTranscode)
98 {
99     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
100 
101     CODECHAL_DECODE_FUNCTION_ENTER;
102 
103     // Check if reference surface needs to be synchronized in MMC case
104     if (m_mmcEnabled)
105     {
106         MOS_SYNC_PARAMS syncParams = g_cInitSyncParams;
107         syncParams.GpuContext = m_vp9State->GetVideoContext();
108         syncParams.bDisableDecodeSyncLock = disableDecodeSyncLock;
109         syncParams.bDisableLockForTranscode = disableLockForTranscode;
110 
111         if (m_vp9State->m_presLastRefSurface)
112         {
113             syncParams.presSyncResource = m_vp9State->m_presLastRefSurface;
114             syncParams.bReadOnly = true;
115 
116             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams));
117             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
118             m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
119         }
120 
121         if (m_vp9State->m_presGoldenRefSurface)
122         {
123             syncParams.presSyncResource = m_vp9State->m_presGoldenRefSurface;
124             syncParams.bReadOnly = true;
125 
126             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams));
127             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
128             m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
129         }
130 
131         if (m_vp9State->m_presAltRefSurface)
132         {
133             syncParams.presSyncResource = m_vp9State->m_presAltRefSurface;
134             syncParams.bReadOnly = true;
135 
136             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams));
137             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
138             m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
139         }
140     }
141 
142     return eStatus;
143 }
144 
CheckReferenceList(PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams)145 MOS_STATUS CodechalMmcDecodeVp9::CheckReferenceList(
146         PMHW_VDBOX_PIPE_BUF_ADDR_PARAMS pipeBufAddrParams)
147 {
148     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
149 
150     CODECHAL_DECODE_FUNCTION_ENTER;
151 
152     CODECHAL_DECODE_CHK_NULL_RETURN(pipeBufAddrParams);
153     CODECHAL_DECODE_CHK_NULL_RETURN(m_vp9State->m_vp9PicParams);
154     auto picParams = m_vp9State->m_vp9PicParams;
155 
156     MOS_MEMCOMP_STATE mmcMode;
157 
158     // Disable MMC if self-reference is dectected for P/B frames (mainly for error concealment)
159     if (((pipeBufAddrParams->PostDeblockSurfMmcState != MOS_MEMCOMP_DISABLED) ||
160         (pipeBufAddrParams->PreDeblockSurfMmcState != MOS_MEMCOMP_DISABLED)) &&
161         (picParams->PicFlags.fields.frame_type != CODEC_VP9_KEY_FRAME &&
162         !picParams->PicFlags.fields.intra_only))
163     {
164         bool selfReference = false;
165         if ((picParams->CurrPic.FrameIdx == picParams->RefFrameList[picParams->PicFlags.fields.LastRefIdx].FrameIdx)   ||
166             (picParams->CurrPic.FrameIdx == picParams->RefFrameList[picParams->PicFlags.fields.GoldenRefIdx].FrameIdx) ||
167             (picParams->CurrPic.FrameIdx == picParams->RefFrameList[picParams->PicFlags.fields.AltRefIdx].FrameIdx))
168         {
169             selfReference = true;
170         }
171 
172         if (selfReference)
173         {
174             pipeBufAddrParams->PostDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
175             pipeBufAddrParams->PreDeblockSurfMmcState  = MOS_MEMCOMP_DISABLED;
176             CODECHAL_DECODE_ASSERTMESSAGE("Self-reference is detected for P/B frames!");
177 
178             // Decompress current frame to avoid green corruptions in this error handling case
179             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetMemoryCompressionMode(
180                 m_osInterface,
181                 &m_vp9State->m_destSurface.OsResource,
182                 &mmcMode));
183             if (mmcMode != MOS_MEMCOMP_DISABLED)
184             {
185                 m_osInterface->pfnDecompResource(m_osInterface, &m_vp9State->m_destSurface.OsResource);
186             }
187         }
188     }
189 
190     // Do surface decompression to make sure the MMC states are consistent in the reference list
191     MOS_MEMCOMP_STATE mmcModePrev = MOS_MEMCOMP_DISABLED;
192     bool sameMmcStatus = true;
193     bool firstRefPic = true;
194     for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_VP9; i++)
195     {
196         if (pipeBufAddrParams->presReferences[i])
197         {
198             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetMemoryCompressionMode(
199                 m_osInterface,
200                 pipeBufAddrParams->presReferences[i],
201                 &mmcMode));
202             if (firstRefPic)
203             {
204                 mmcModePrev = mmcMode;
205                 firstRefPic = false;
206             }
207             else if (mmcModePrev != mmcMode)
208             {
209                 sameMmcStatus = false;
210                 break;
211             }
212         }
213     }
214 
215     if(!sameMmcStatus)
216     {
217         for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_VP9; i++)
218         {
219             if (pipeBufAddrParams->presReferences[i])
220             {
221                 CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetMemoryCompressionMode(
222                     m_osInterface,
223                     pipeBufAddrParams->presReferences[i],
224                     &mmcMode));
225                 if(mmcMode != MOS_MEMCOMP_DISABLED)
226                 {
227                     m_osInterface->pfnDecompResource(
228                         m_osInterface,
229                         pipeBufAddrParams->presReferences[i]);
230                 }
231             }
232         }
233     }
234 
235     return eStatus;
236 }
237