1 /*
2 * Copyright (c) 2021-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_vp9_mem_compression.cpp
25 //! \brief    Defines the common interface for Vp9 decode mmc
26 //! \details  The mmc is to handle mmc operations,
27 //! including compression and decompressin of Vp9 decode
28 //!
29 
30 #include "mos_defs.h"
31 #include "decode_utils.h"
32 #include "decode_vp9_mem_compression.h"
33 
34 namespace decode
35 {
Vp9DecodeMemComp(CodechalHwInterfaceNext * hwInterface)36 Vp9DecodeMemComp::Vp9DecodeMemComp(CodechalHwInterfaceNext *hwInterface)
37 {
38     m_osInterface = hwInterface->GetOsInterface();
39 }
40 
CheckReferenceList(Vp9BasicFeature & vp9BasicFeature,MOS_MEMCOMP_STATE & postDeblockSurfMmcState,MOS_MEMCOMP_STATE & preDeblockSurfMmcState,PMOS_RESOURCE * presReferences)41 MOS_STATUS Vp9DecodeMemComp::CheckReferenceList(Vp9BasicFeature &vp9BasicFeature,
42     MOS_MEMCOMP_STATE &postDeblockSurfMmcState,
43     MOS_MEMCOMP_STATE &preDeblockSurfMmcState,
44     PMOS_RESOURCE     *presReferences)
45 {
46     DECODE_FUNC_CALL();
47     DECODE_CHK_NULL(m_osInterface);
48     MOS_MEMCOMP_STATE mmcMode;
49 
50     //Disable MMC if self-reference is detected (mainly for error concealment)
51     if ((postDeblockSurfMmcState != MOS_MEMCOMP_DISABLED) ||
52         (preDeblockSurfMmcState != MOS_MEMCOMP_DISABLED))
53     {
54         DECODE_ASSERT(vp9BasicFeature.m_vp9PicParams);
55         auto &vp9PicParams = *(vp9BasicFeature.m_vp9PicParams);
56 
57         if (vp9PicParams.PicFlags.fields.frame_type != CODEC_VP9_KEY_FRAME &&
58             !vp9PicParams.PicFlags.fields.intra_only)
59         {
60             bool selfReference = false;
61             if ((vp9PicParams.CurrPic.FrameIdx == vp9PicParams.RefFrameList[vp9PicParams.PicFlags.fields.LastRefIdx].FrameIdx) ||
62                 (vp9PicParams.CurrPic.FrameIdx == vp9PicParams.RefFrameList[vp9PicParams.PicFlags.fields.GoldenRefIdx].FrameIdx) ||
63                 (vp9PicParams.CurrPic.FrameIdx == vp9PicParams.RefFrameList[vp9PicParams.PicFlags.fields.AltRefIdx].FrameIdx))
64             {
65                 selfReference = true;
66             }
67 
68             if (selfReference)
69             {
70                 postDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
71                 preDeblockSurfMmcState  = MOS_MEMCOMP_DISABLED;
72                 DECODE_NORMALMESSAGE("Self-reference is detected for P/B frames!");
73 
74                 // Decompress current frame to avoid green corruptions in this error handling case
75                 MOS_SURFACE &destSurface = vp9BasicFeature.m_destSurface;
76                 DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
77                     m_osInterface, &destSurface.OsResource, &mmcMode));
78                 if (mmcMode != MOS_MEMCOMP_DISABLED)
79                 {
80                     DECODE_CHK_STATUS(m_osInterface->pfnDecompResource(m_osInterface, &destSurface.OsResource));
81                 }
82             }
83         }
84     }
85 
86     // Do surface decompression to make sure the MMC states are consistent in the reference list
87     MOS_MEMCOMP_STATE mmcModePrev   = MOS_MEMCOMP_DISABLED;
88     bool              sameMmcStatus = true;
89     bool              firstRefPic   = true;
90     for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_VP9; i++)
91     {
92         if (presReferences[i])
93         {
94             DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
95                 m_osInterface,
96                 presReferences[i],
97                 &mmcMode));
98             if (firstRefPic)
99             {
100                 mmcModePrev = mmcMode;
101                 firstRefPic = false;
102             }
103             else if (mmcModePrev != mmcMode)
104             {
105                 sameMmcStatus = false;
106                 break;
107             }
108         }
109     }
110 
111     if (!sameMmcStatus)
112     {
113         for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_VP9; i++)
114         {
115             if (presReferences[i])
116             {
117                 DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
118                     m_osInterface,
119                     presReferences[i],
120                     &mmcMode));
121                 if (mmcMode != MOS_MEMCOMP_DISABLED)
122                 {
123                     m_osInterface->pfnDecompResource(
124                         m_osInterface,
125                         presReferences[i]);
126                 }
127             }
128         }
129     }
130     return MOS_STATUS_SUCCESS;
131 }
132 
SetRefSurfaceMask(Vp9BasicFeature & vp9BasicFeature,MHW_VDBOX_SURFACE_PARAMS refSurfaceParams[])133 MOS_STATUS Vp9DecodeMemComp::SetRefSurfaceMask(
134     Vp9BasicFeature         &vp9BasicFeature,
135     MHW_VDBOX_SURFACE_PARAMS refSurfaceParams[])
136 {
137     m_skipMask = 0xf8;
138     for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_VP9; i++)
139     {
140         if (refSurfaceParams[i].mmcState == MOS_MEMCOMP_DISABLED)
141         {
142             m_skipMask |= (1 << i);
143         }
144     }
145     DECODE_NORMALMESSAGE("MMC skip mask is %d,", m_skipMask);
146     for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_VP9; i++)
147     {
148         refSurfaceParams[i].mmcState    = MOS_MEMCOMP_MC;
149         refSurfaceParams[i].mmcSkipMask = m_skipMask;
150     }
151 
152     return MOS_STATUS_SUCCESS;
153 }
154 
SetRefSurfaceMask(Vp9BasicFeature & vp9BasicFeature,mhw::vdbox::hcp::HCP_SURFACE_STATE_PAR refSurfaceParams[])155 MOS_STATUS Vp9DecodeMemComp::SetRefSurfaceMask(
156     Vp9BasicFeature                       &vp9BasicFeature,
157     mhw::vdbox::hcp::HCP_SURFACE_STATE_PAR refSurfaceParams[])
158 {
159     m_skipMask = 0xf8;
160     for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_VP9; i++)
161     {
162         if (refSurfaceParams[i].mmcState == MOS_MEMCOMP_DISABLED)
163         {
164             m_skipMask |= (1 << i);
165         }
166     }
167     DECODE_NORMALMESSAGE("MMC skip mask is %d,", m_skipMask);
168     for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_VP9; i++)
169     {
170         refSurfaceParams[i].mmcState    = MOS_MEMCOMP_MC;
171         refSurfaceParams[i].mmcSkipMask = m_skipMask;
172     }
173 
174     return MOS_STATUS_SUCCESS;
175 }
176 
SetRefSurfaceCompressionFormat(Vp9BasicFeature & vp9BasicFeature,MHW_VDBOX_SURFACE_PARAMS refSurfaceParams[])177 MOS_STATUS Vp9DecodeMemComp::SetRefSurfaceCompressionFormat(
178     Vp9BasicFeature         &vp9BasicFeature,
179     MHW_VDBOX_SURFACE_PARAMS refSurfaceParams[])
180 {
181     uint32_t compressionFormat = 0;
182     for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_VP9; i++)
183     {
184         if (refSurfaceParams[i].mmcState == MOS_MEMCOMP_MC || refSurfaceParams[i].mmcState == MOS_MEMCOMP_RC)
185         {
186             compressionFormat = refSurfaceParams[i].dwCompressionFormat;
187         }
188     }
189 
190     for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_VP9; i++)
191     {
192         refSurfaceParams[i].dwCompressionFormat = compressionFormat;
193     }
194 
195     DECODE_NORMALMESSAGE("Reference surfaces compression format is %d,", compressionFormat);
196 
197     return MOS_STATUS_SUCCESS;
198 }
199 
200 }  // namespace decode
201