1 /*
2 * Copyright (c) 2018-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 //! \file     encode_hevc_vdenc_weighted_prediction.cpp
24 //! \brief    Implemetation for hevc weighted prediction feature
25 //!
26 
27 #include "encode_hevc_vdenc_weighted_prediction.h"
28 #include "encode_hevc_vdenc_feature_manager.h"
29 namespace encode
30 {
HevcVdencWeightedPred(MediaFeatureManager * featureManager,EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,void * constSettings)31     HevcVdencWeightedPred::HevcVdencWeightedPred(
32         MediaFeatureManager *featureManager,
33         EncodeAllocator *allocator,
34         CodechalHwInterfaceNext *hwInterface,
35         void *constSettings) :
36         MediaFeature(constSettings)
37     {
38         ENCODE_CHK_NULL_NO_STATUS_RETURN(featureManager);
39 
40         m_basicFeature = dynamic_cast<HevcBasicFeature *>(featureManager->GetFeature(FeatureIDs::basicFeature));
41         ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
42     }
43 
Update(void * params)44     MOS_STATUS HevcVdencWeightedPred::Update(void *params)
45     {
46         ENCODE_FUNC_CALL();
47         ENCODE_CHK_NULL_RETURN(params);
48 
49         EncoderParams *encodeParams = (EncoderParams *)params;
50 
51         auto hevcPicParams = static_cast<PCODEC_HEVC_ENCODE_PICTURE_PARAMS>(encodeParams->pPicParams);
52         ENCODE_CHK_NULL_RETURN(hevcPicParams);
53 
54         m_hevcSliceParams = static_cast<PCODEC_HEVC_ENCODE_SLICE_PARAMS>(encodeParams->pSliceParams);
55         ENCODE_CHK_NULL_RETURN(m_hevcSliceParams);
56 
57         if (hevcPicParams->weighted_pred_flag || hevcPicParams->weighted_bipred_flag)
58         {
59             m_enabled = true;
60         }
61 
62         m_bEnableGPUWeightedPrediction = m_enabled && hevcPicParams->bEnableGPUWeightedPrediction;
63 
64         return MOS_STATUS_SUCCESS;
65     }
66 
SetHucBrcUpdateDmemBuffer(bool isFirstPass,VdencHevcHucBrcUpdateDmem & dmem)67     MOS_STATUS HevcVdencWeightedPred::SetHucBrcUpdateDmemBuffer(
68         bool isFirstPass,
69         VdencHevcHucBrcUpdateDmem &dmem)
70     {
71         ENCODE_FUNC_CALL();
72 
73         // 1: BRC (including ACQP), 2: Weighted prediction (should not be enabled in first pass)
74         // 01: BRC, 10: WP never used,  11: BRC + WP
75         dmem.OpMode_U8 = (m_bEnableGPUWeightedPrediction && !isFirstPass) ? 3 : 1;
76 
77         if (m_enabled)
78         {
79             dmem.LumaLog2WeightDenom_S8   = 6;
80             dmem.ChromaLog2WeightDenom_S8 = 6;
81         }
82 
83         return MOS_STATUS_SUCCESS;
84     }
85 
SetHucBrcUpdateConstData(const CODEC_HEVC_ENCODE_SLICE_PARAMS & hevcSliceParams,uint32_t sliceIndex,uint32_t weightOffsetStateCmdSize,uint32_t & sliceLocation,VdencHevcHucBrcConstantData & constantData)86     MOS_STATUS HevcVdencWeightedPred::SetHucBrcUpdateConstData(
87         const CODEC_HEVC_ENCODE_SLICE_PARAMS &hevcSliceParams,
88         uint32_t sliceIndex,
89         uint32_t weightOffsetStateCmdSize,
90         uint32_t &sliceLocation,
91         VdencHevcHucBrcConstantData &constantData)
92     {
93         ENCODE_FUNC_CALL();
94 
95         uint32_t sliceType = hevcSliceParams.slice_type;
96 
97         if (m_enabled)
98         {
99             // 1st HCP_WEIGHTOFFSET_STATE cmd - P & B
100             if (sliceType == encodeHevcPSlice || sliceType == encodeHevcBSlice)
101             {
102                 // HCP_WEIGHTOFFSET_L0 starts in byte from beginning of the SLB.
103                 // 0xFFFF means unavailable in SLB
104                 constantData.Slice[sliceIndex].HcpWeightOffsetL0_StartInBytes =
105                     (uint16_t)sliceLocation;
106                 sliceLocation += weightOffsetStateCmdSize;
107             }
108 
109             // 2nd HCP_WEIGHTOFFSET_STATE cmd - B
110             if (sliceType == encodeHevcBSlice)
111             {
112                 // HCP_WEIGHTOFFSET_L1 starts in byte from beginning of the SLB.
113                 // 0xFFFF means unavailable in SLB
114                 constantData.Slice[sliceIndex].HcpWeightOffsetL1_StartInBytes =
115                     (uint16_t)sliceLocation;
116                 sliceLocation += weightOffsetStateCmdSize;
117             }
118 
119             constantData.Slice[sliceIndex].WeightTable_StartInBits =
120                 (uint16_t)hevcSliceParams.PredWeightTableBitOffset;
121             constantData.Slice[sliceIndex].WeightTable_EndInBits =
122                 (uint16_t)(hevcSliceParams.PredWeightTableBitOffset +
123                           (hevcSliceParams.PredWeightTableBitLength));
124         }
125         else
126         {
127             // 0xFFFF means unavailable in SLB
128             constantData.Slice[sliceIndex].HcpWeightOffsetL0_StartInBytes = 0xFFFF;
129             constantData.Slice[sliceIndex].HcpWeightOffsetL1_StartInBytes = 0xFFFF;
130 
131             // number of bits from beginning of slice header, 0xffff means not awailable
132             constantData.Slice[sliceIndex].WeightTable_StartInBits = 0xFFFF;
133             constantData.Slice[sliceIndex].WeightTable_EndInBits   = 0xFFFF;
134         }
135         return MOS_STATUS_SUCCESS;
136     }
137 
MHW_SETPAR_DECL_SRC(VDENC_WEIGHTSOFFSETS_STATE,HevcVdencWeightedPred)138     MHW_SETPAR_DECL_SRC(VDENC_WEIGHTSOFFSETS_STATE, HevcVdencWeightedPred)
139     {
140         params.denomLuma = 1;
141 
142         if (m_enabled)
143         {
144             char    lumaWeights[2][CODEC_MAX_NUM_REF_FRAME_HEVC];
145             int16_t lumaOffsets[2][CODEC_MAX_NUM_REF_FRAME_HEVC];
146             char    chromaWeights[2][CODEC_MAX_NUM_REF_FRAME_HEVC][2];
147             int16_t chromaOffsets[2][CODEC_MAX_NUM_REF_FRAME_HEVC][2];
148 
149             params.denomLuma   = 1 << (m_hevcSliceParams->luma_log2_weight_denom);
150             params.denomChroma = 1 << (m_hevcSliceParams->luma_log2_weight_denom + m_hevcSliceParams->delta_chroma_log2_weight_denom);
151 
152             for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
153             {
154                 // Luma offset
155                 lumaOffsets[0][i] = (int16_t)m_hevcSliceParams->luma_offset[0][i];
156                 lumaOffsets[1][i] = (int16_t)m_hevcSliceParams->luma_offset[1][i];
157 
158                 // Cb offset
159                 chromaOffsets[0][i][0] = (int16_t)m_hevcSliceParams->chroma_offset[0][i][0];
160                 chromaOffsets[1][i][0] = (int16_t)m_hevcSliceParams->chroma_offset[1][i][0];
161 
162                 // Cr offset
163                 chromaOffsets[0][i][1] = (int16_t)m_hevcSliceParams->chroma_offset[0][i][1];
164                 chromaOffsets[1][i][1] = (int16_t)m_hevcSliceParams->chroma_offset[1][i][1];
165             }
166 
167             // Luma Weight
168             ENCODE_CHK_STATUS_MESSAGE_RETURN(MOS_SecureMemcpy(&lumaWeights[0], sizeof(lumaWeights[0]), &m_hevcSliceParams->delta_luma_weight[0], sizeof(m_hevcSliceParams->delta_luma_weight[0])), "Failed to copy luma weight 0 memory.");
169 
170             ENCODE_CHK_STATUS_MESSAGE_RETURN(MOS_SecureMemcpy(&lumaWeights[1], sizeof(lumaWeights[1]), &m_hevcSliceParams->delta_luma_weight[1], sizeof(m_hevcSliceParams->delta_luma_weight[1])), "Failed to copy luma weight 1 memory.");
171 
172             // Chroma Weight
173             ENCODE_CHK_STATUS_MESSAGE_RETURN(MOS_SecureMemcpy(&chromaWeights[0], sizeof(chromaWeights[0]), &m_hevcSliceParams->delta_chroma_weight[0], sizeof(m_hevcSliceParams->delta_chroma_weight[0])), "Failed to copy chroma weight 0 memory.");
174 
175             ENCODE_CHK_STATUS_MESSAGE_RETURN(MOS_SecureMemcpy(&chromaWeights[1], sizeof(chromaWeights[1]), &m_hevcSliceParams->delta_chroma_weight[1], sizeof(m_hevcSliceParams->delta_chroma_weight[1])), "Failed to copy chroma weight 1 memory.");
176 
177             if (m_basicFeature->m_ref.IsLowDelay())
178             {
179                 lumaWeights[1][0] = lumaWeights[0][0];
180                 lumaOffsets[1][0] = lumaOffsets[0][0];
181 
182                 chromaWeights[1][0][0] = chromaWeights[0][0][0];
183                 chromaOffsets[1][0][0] = chromaOffsets[0][0][0];
184 
185                 chromaWeights[1][0][1] = chromaWeights[0][0][1];
186                 chromaOffsets[1][0][1] = chromaOffsets[0][0][1];
187             }
188 
189             for (auto i = 0; i < 3; i++)
190             {
191                 params.offsetsLuma[0][i] = lumaOffsets[0][i];
192                 params.offsetsLuma[1][i] = lumaOffsets[1][i];
193                 params.weightsLuma[0][i] = lumaWeights[0][i];
194                 params.weightsLuma[1][i] = lumaWeights[1][i];
195 
196                 params.offsetsChroma[0][i][0] = chromaOffsets[0][i][0];
197                 params.offsetsChroma[1][i][0] = chromaOffsets[1][i][0];
198                 params.offsetsChroma[0][i][1] = chromaOffsets[0][i][1];
199                 params.offsetsChroma[1][i][1] = chromaOffsets[1][i][1];
200 
201                 params.weightsChroma[0][i][0] = chromaWeights[0][i][0];
202                 params.weightsChroma[1][i][0] = chromaWeights[1][i][0];
203                 params.weightsChroma[0][i][1] = chromaWeights[0][i][1];
204                 params.weightsChroma[1][i][1] = chromaWeights[1][i][1];
205             }
206         }
207 
208         return MOS_STATUS_SUCCESS;
209     }
210 
MHW_SETPAR_DECL_SRC(HCP_WEIGHTOFFSET_STATE,HevcVdencWeightedPred)211     MHW_SETPAR_DECL_SRC(HCP_WEIGHTOFFSET_STATE, HevcVdencWeightedPred)
212     {
213         ENCODE_FUNC_CALL();
214 
215         if (!m_enabled)
216         {
217             return MOS_STATUS_SUCCESS;
218         }
219 
220         ENCODE_CHK_NULL_RETURN(m_hevcSliceParams);
221 
222         PCODEC_HEVC_ENCODE_SLICE_PARAMS pEncodeHevcSliceParams = &m_basicFeature->m_hevcSliceParams[m_basicFeature->m_curNumSlices];
223 
224         for (auto k = 0; k < 2; k++)  // k=0: LIST_0, k=1: LIST_1
225         {
226             // LUMA, Chroma offset
227             for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
228             {
229                 params.LumaOffsets[k][i] = pEncodeHevcSliceParams->luma_offset[k][i];
230                 // Cb, Cr
231                 for (auto j = 0; j < 2; j++)
232                 {
233                     params.ChromaOffsets[k][i][j] = pEncodeHevcSliceParams->chroma_offset[k][i][j];
234                 }
235             }
236 
237             // LUMA Weight
238             ENCODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(
239                 &params.LumaWeights[k],
240                 sizeof(params.LumaWeights[k]),
241                 &pEncodeHevcSliceParams->delta_luma_weight[k],
242                 sizeof(pEncodeHevcSliceParams->delta_luma_weight[k])));
243 
244             // Chroma Weight
245             for (auto i = 0; i < CODEC_MAX_NUM_REF_FRAME_HEVC; i++)
246             {
247                 for (auto j = 0; j < 2; j++)
248                 {
249                     params.ChromaWeights[k][i][j] = pEncodeHevcSliceParams->delta_chroma_weight[k][i][j];
250                 }
251             }
252         }
253         return MOS_STATUS_SUCCESS;
254     }
255 
MHW_SETPAR_DECL_SRC(VDENC_HEVC_VP9_TILE_SLICE_STATE,HevcVdencWeightedPred)256     MHW_SETPAR_DECL_SRC(VDENC_HEVC_VP9_TILE_SLICE_STATE, HevcVdencWeightedPred)
257     {
258         auto hevcFeature = dynamic_cast<HevcBasicFeature *>(m_basicFeature);
259         ENCODE_CHK_NULL_RETURN(hevcFeature);
260 
261         params.log2WeightDenomLuma = params.hevcVp9Log2WeightDenomLuma = m_enabled ? (m_bEnableGPUWeightedPrediction ? 6 : hevcFeature->m_hevcSliceParams->luma_log2_weight_denom) : 0;
262         params.log2WeightDenomChroma                                   = m_enabled ? (m_bEnableGPUWeightedPrediction ? 6 : hevcFeature->m_hevcSliceParams->luma_log2_weight_denom + hevcFeature->m_hevcSliceParams->delta_chroma_log2_weight_denom) : 0;
263 
264         return MOS_STATUS_SUCCESS;
265     }
266 }  // namespace encode
267