1 /*
2 * Copyright (c) 2020, 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(CodechalHwInterface * hwInterface)36 HevcDecodeMemComp::HevcDecodeMemComp(CodechalHwInterface *hwInterface)
37 {
38     m_osInterface = hwInterface->GetOsInterface();
39 }
40 
SetRefSurfaceMask(HevcBasicFeature & hevcBasicFeature,const MHW_VDBOX_PIPE_BUF_ADDR_PARAMS & pipeBufAddrParams,MHW_VDBOX_SURFACE_PARAMS & refSurfaceParams)41 MOS_STATUS HevcDecodeMemComp::SetRefSurfaceMask(
42     HevcBasicFeature                     &hevcBasicFeature,
43     const MHW_VDBOX_PIPE_BUF_ADDR_PARAMS &pipeBufAddrParams,
44     MHW_VDBOX_SURFACE_PARAMS             &refSurfaceParams)
45 {
46     if (hevcBasicFeature.m_isSCCIBCMode)
47     {
48         HevcReferenceFrames &refFrames = hevcBasicFeature.m_refFrames;
49         DECODE_ASSERT(hevcBasicFeature.m_hevcPicParams != nullptr);
50         const std::vector<uint8_t> &activeRefList = refFrames.GetActiveReferenceList(*hevcBasicFeature.m_hevcPicParams);
51 
52         uint8_t IBCRefIdx = refFrames.m_IBCRefIdx;
53         DECODE_CHK_COND(activeRefList.size() <= IBCRefIdx, "Invalid IBC reference index.");
54         uint8_t IBCFrameIdx = activeRefList[IBCRefIdx];
55 
56         uint8_t skipMask = 0;
57         for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
58         {
59             if (pipeBufAddrParams.presReferences[i] == refFrames.GetReferenceByFrameIndex(IBCFrameIdx))
60             {
61                 skipMask |= (1 << i);
62             }
63         }
64         refSurfaceParams.mmcSkipMask = skipMask;
65         DECODE_NORMALMESSAGE("IBC ref index %d, MMC skip mask %d,", IBCRefIdx, skipMask);
66     }
67 
68     if (hevcBasicFeature.m_useDummyReference)
69     {
70         uint8_t skipMask = 0;
71         for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
72         {
73             if (hevcBasicFeature.m_dummyReferenceSlot[i])
74             {
75                 skipMask |= (1 << i);
76             }
77         }
78         refSurfaceParams.mmcSkipMask |= skipMask;
79     }
80 
81     return MOS_STATUS_SUCCESS;
82 }
83 
CheckReferenceList(HevcBasicFeature & hevcBasicFeature,MHW_VDBOX_PIPE_BUF_ADDR_PARAMS & pipeBufAddrParams)84 MOS_STATUS HevcDecodeMemComp::CheckReferenceList(
85     HevcBasicFeature &hevcBasicFeature, MHW_VDBOX_PIPE_BUF_ADDR_PARAMS &pipeBufAddrParams)
86 {
87     DECODE_FUNC_CALL();
88     DECODE_CHK_NULL(m_osInterface);
89 
90     // Disable MMC if self-reference is dectected (mainly for error concealment)
91     if (!hevcBasicFeature.m_refFrames.m_curIsIntra)
92     {
93         if (pipeBufAddrParams.PostDeblockSurfMmcState != MOS_MEMCOMP_DISABLED ||
94             pipeBufAddrParams.PreDeblockSurfMmcState  != MOS_MEMCOMP_DISABLED)
95         {
96             DECODE_ASSERT(hevcBasicFeature.m_hevcPicParams);
97             CODEC_HEVC_PIC_PARAMS &hevcPicParams = *(hevcBasicFeature.m_hevcPicParams);
98 
99             for (uint8_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
100             {
101                 if (hevcPicParams.CurrPic.FrameIdx == hevcPicParams.RefFrameList[i].FrameIdx)
102                 {
103                     DECODE_NORMALMESSAGE("Self-reference is detected for P/B frames!");
104                     pipeBufAddrParams.PostDeblockSurfMmcState = MOS_MEMCOMP_DISABLED;
105                     pipeBufAddrParams.PreDeblockSurfMmcState  = MOS_MEMCOMP_DISABLED;
106 
107                     // Decompress current frame to avoid green corruptions in this error handling case
108                     MOS_MEMCOMP_STATE mmcMode = MOS_MEMCOMP_DISABLED;
109                     MOS_SURFACE &destSurface  = hevcBasicFeature.m_destSurface;
110                     DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
111                         m_osInterface, &destSurface.OsResource, &mmcMode));
112                     if (mmcMode != MOS_MEMCOMP_DISABLED)
113                     {
114                         DECODE_CHK_STATUS(m_osInterface->pfnDecompResource(m_osInterface, &destSurface.OsResource));
115                     }
116 
117                     break;
118                 }
119             }
120         }
121     }
122 
123     // Do surface decompression to make sure the MMC states are consistent in the reference list
124     bool sameMmcStatus = true;
125     MOS_MEMCOMP_STATE mmcModePrev  = MOS_MEMCOMP_DISABLED;
126     for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
127     {
128         if (pipeBufAddrParams.presReferences[i] != nullptr)
129         {
130             MOS_MEMCOMP_STATE mmcMode = MOS_MEMCOMP_DISABLED;
131             DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
132                 m_osInterface, pipeBufAddrParams.presReferences[i], &mmcMode));
133 
134             if (i == 0)
135             {
136                 mmcModePrev = mmcMode;
137             }
138             else if (mmcModePrev != mmcMode)
139             {
140                 sameMmcStatus = false;
141                 break;
142             }
143         }
144     }
145 
146     if(!sameMmcStatus)
147     {
148         for (uint8_t i = 0; i < CODECHAL_MAX_CUR_NUM_REF_FRAME_HEVC; i++)
149         {
150             if (pipeBufAddrParams.presReferences[i] != nullptr)
151             {
152                 MOS_MEMCOMP_STATE mmcMode = MOS_MEMCOMP_DISABLED;
153                 DECODE_CHK_STATUS(m_osInterface->pfnGetMemoryCompressionMode(
154                     m_osInterface, pipeBufAddrParams.presReferences[i], &mmcMode));
155                 if(mmcMode != MOS_MEMCOMP_DISABLED)
156                 {
157                     m_osInterface->pfnDecompResource(m_osInterface, pipeBufAddrParams.presReferences[i]);
158                 }
159             }
160         }
161     }
162 
163     return MOS_STATUS_SUCCESS;
164 }
165 
166 }
167