1 /*
2 * Copyright (c) 2018-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 //! \file     encode_basic_feature.cpp
24 //! \brief    Defines the common interface for encode basic feature
25 //!
26 
27 #include "encode_basic_feature.h"
28 #include "encode_utils.h"
29 #include "encode_allocator.h"
30 #include "mos_interface.h"
31 #include "codec_def_common_encode.h"
32 #include "codec_def_encode_vp9.h"
33 #include "codec_def_encode_hevc.h"
34 
35 namespace encode
36 {
EncodeBasicFeature(EncodeAllocator * allocator,CodechalHwInterfaceNext * hwInterface,TrackedBuffer * trackedBuf,RecycleResource * recycleBuf)37 EncodeBasicFeature::EncodeBasicFeature(
38     EncodeAllocator *allocator,
39     CodechalHwInterfaceNext *hwInterface,
40     TrackedBuffer *trackedBuf,
41     RecycleResource *recycleBuf):
42     MediaFeature(hwInterface ? hwInterface->GetOsInterface() : nullptr),
43     m_trackedBuf(trackedBuf),
44     m_recycleBuf(recycleBuf),
45     m_allocator(allocator)
46 {
47     if(hwInterface)
48     {
49         m_osInterface = hwInterface->GetOsInterface();
50     }
51 
52 }
53 
Init(void * setting)54 MOS_STATUS EncodeBasicFeature::Init(void *setting)
55 {
56     ENCODE_FUNC_CALL();
57     ENCODE_CHK_NULL_RETURN(setting);
58 
59     CodechalSetting *codecSettings = (CodechalSetting*)setting;
60     m_standard = codecSettings->standard;
61     m_mode = codecSettings->mode;
62     m_codecFunction = codecSettings->codecFunction;
63 
64     m_is10Bit       = codecSettings->lumaChromaDepth == CODECHAL_LUMA_CHROMA_DEPTH_10_BITS ? true : false;
65     m_chromaFormat  = codecSettings->chromaFormat;
66     m_bitDepth      = codecSettings->lumaChromaDepth == CODECHAL_LUMA_CHROMA_DEPTH_8_BITS ?
67                         8 : (codecSettings->lumaChromaDepth == CODECHAL_LUMA_CHROMA_DEPTH_10_BITS ? 10 : 12);
68     m_standard      = codecSettings->standard;
69 
70     m_oriFrameWidth   = codecSettings->width;
71     m_oriFrameHeight  = codecSettings->height;
72     m_picWidthInMb    = (uint16_t)CODECHAL_GET_WIDTH_IN_MACROBLOCKS(m_oriFrameWidth);
73     m_picHeightInMb   = (uint16_t)CODECHAL_GET_HEIGHT_IN_MACROBLOCKS(m_oriFrameHeight);
74     m_frameWidth      = m_picWidthInMb * CODECHAL_MACROBLOCK_WIDTH;
75     m_frameHeight     = m_picHeightInMb * CODECHAL_MACROBLOCK_HEIGHT;
76 
77     m_currOriginalPic.PicFlags = PICTURE_INVALID;
78     m_currOriginalPic.FrameIdx = 0;
79     m_currOriginalPic.PicEntry = 0;
80 
81     //RCPanic settings
82     MediaUserSetting::Value outValue;
83     ReadUserSetting(
84         m_userSettingPtr,
85         outValue,
86         "RC Panic Mode",
87         MediaUserSetting::Group::Sequence);
88     m_panicEnable = outValue.Get<bool>();
89 
90     ReadUserSetting(
91         m_userSettingPtr,
92         outValue,
93         "HEVC Encode Enable HW Stitch",
94         MediaUserSetting::Group::Sequence);
95     m_enableTileStitchByHW = outValue.Get<bool>();
96 
97     return MOS_STATUS_SUCCESS;
98 }
99 
Update(void * params)100 MOS_STATUS EncodeBasicFeature::Update(void *params)
101 {
102     ENCODE_FUNC_CALL();
103     ENCODE_CHK_NULL_RETURN(params);
104     ENCODE_CHK_NULL_RETURN(m_allocator);
105 
106     EncoderParams* encodeParams = (EncoderParams*)params;
107 
108     m_newSeq                = encodeParams->bNewSeq;           // used by all except JPEG
109     m_mbDataBufferSize      = encodeParams->dwMbDataBufferSize;// used by all except JPEG
110     m_newVuiData            = encodeParams->bNewVuiData;       // used by AVC and MPEG2
111     m_picQuant              = encodeParams->bPicQuant ;        // used by AVC and MPEG2
112     m_newQmatrixData        = encodeParams->bNewQmatrixData;   // used by AVC and MPEG2
113     m_numSlices             = encodeParams->dwNumSlices;       // used by all except VP9
114     m_slcData               = (PCODEC_ENCODER_SLCDATA)(encodeParams->pSlcHeaderData);// used by AVC, MPEG2, and HEVC
115 
116     ENCODE_CHK_NULL_RETURN(encodeParams->psRawSurface);
117     m_rawSurface           = *(encodeParams->psRawSurface);           // used by all
118     m_allocator->GetSurfaceInfo(&m_rawSurface);
119     ENCODE_CHK_STATUS_RETURN(m_allocator->UpdateResourceUsageType(&m_rawSurface.OsResource, MOS_HW_RESOURCE_USAGE_ENCODE_INPUT_RAW));
120 
121     ENCODE_CHK_NULL_RETURN(encodeParams->presBitstreamBuffer);
122     m_resBitstreamBuffer    = *(encodeParams->presBitstreamBuffer);   // used by all
123 
124     m_resMetadataBuffer    = (encodeParams->presMetadataBuffer);
125     m_metaDataOffset       = encodeParams->metaDataOffset;
126 
127     // Get resource details of the bitstream resource
128     MOS_SURFACE bsSurface;
129     MOS_ZeroMemory(&bsSurface, sizeof(bsSurface));
130     bsSurface.OsResource = m_resBitstreamBuffer;
131     m_allocator->GetSurfaceInfo(&bsSurface);
132     ENCODE_CHK_STATUS_RETURN(m_allocator->UpdateResourceUsageType(&m_resBitstreamBuffer, MOS_HW_RESOURCE_USAGE_ENCODE_OUTPUT_BITSTREAM));
133 
134     m_bitstreamSize = encodeParams->dwBitstreamSize = bsSurface.dwHeight * bsSurface.dwWidth;
135 
136     if (Mos_ResourceIsNull(&m_rawSurface.OsResource))
137     {
138         ENCODE_ASSERTMESSAGE("Raw surface is nullptr!");
139         return MOS_STATUS_INVALID_PARAMETER;
140     }
141 
142 #if (_DEBUG || _RELEASE_INTERNAL)
143     ReportUserSettingForDebug(
144         m_userSettingPtr,
145         "Encode Raw Surface Tile",
146         m_rawSurface.TileType,
147         MediaUserSetting::Group::Sequence);
148 #endif
149 
150     m_rawSurfaceToEnc     =
151     m_rawSurfaceToPak     = &m_rawSurface;
152 
153     if (encodeParams->psReconSurface != nullptr)
154     {
155         m_reconSurface     = *(encodeParams->psReconSurface);         // used by all except JPEG
156         ENCODE_CHK_STATUS_RETURN(m_allocator->GetSurfaceInfo(&m_reconSurface));
157         ENCODE_CHK_STATUS_RETURN(m_allocator->UpdateResourceUsageType(&m_reconSurface.OsResource, MOS_HW_RESOURCE_USAGE_ENCODE_OUTPUT_PICTURE));
158     }
159 
160     if (encodeParams->pBSBuffer != nullptr)
161     {
162         m_bsBuffer          = *(encodeParams->pBSBuffer);              // used by all except VP9
163     }
164 
165     m_mbDisableSkipMapEnabled          = encodeParams->bMbDisableSkipMapEnabled;
166     m_mbQpDataEnabled                  = encodeParams->bMbQpDataEnabled;
167 
168     if (encodeParams->bMbQpDataEnabled && encodeParams->psMbQpDataSurface != nullptr)
169     {
170         m_mbQpDataSurface = *(encodeParams->psMbQpDataSurface);
171         ENCODE_CHK_STATUS_RETURN(m_allocator->GetSurfaceInfo(&m_mbQpDataSurface));
172     }
173 
174     if (encodeParams->psMbDisableSkipMapSurface != nullptr)
175     {
176         m_mbDisableSkipMapSurface = *(encodeParams->psMbDisableSkipMapSurface);
177         ENCODE_CHK_STATUS_RETURN(m_allocator->GetSurfaceInfo(&m_mbDisableSkipMapSurface));
178     }
179 
180     m_slcData               =
181         (PCODEC_ENCODER_SLCDATA)(encodeParams->pSlcHeaderData);             // used by AVC, MPEG2, and HEVC
182 
183     m_newSeqHeader = encodeParams->newSeqHeader;
184     m_newPpsHeader = encodeParams->newPpsHeader;
185 
186     if (CodecHalUsesVideoEngine(m_codecFunction))
187     {
188         //UpdateBitstreamSize()
189         // Get resource details of the bitstream resource
190         MOS_SURFACE details;
191         MOS_ZeroMemory(&details, sizeof(details));
192         details.Format = Format_Invalid;
193         ENCODE_CHK_STATUS_RETURN(
194             m_osInterface->pfnGetResourceInfo(m_osInterface, &m_resBitstreamBuffer, &details));
195         m_bitstreamSize = details.dwHeight * details.dwWidth;
196     }
197 
198     // check output Chroma format
199     UpdateFormat(params);
200 
201     m_predicationNotEqualZero              = encodeParams->m_predicationNotEqualZero;
202     m_predicationEnabled                   = encodeParams->m_predicationEnabled;
203     m_setMarkerEnabled                     = encodeParams->m_setMarkerEnabled;
204     m_predicationResOffset                 = encodeParams->m_predicationResOffset;
205     m_presPredication                      = encodeParams->m_presPredication;
206     m_tempPredicationBuffer                = encodeParams->m_tempPredicationBuffer;
207 
208     if (m_predicationBuffer == nullptr && m_predicationEnabled)
209     {
210         // initiate allocation parameters and lock flags
211         MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
212         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
213         allocParamsForBufferLinear.Type         = MOS_GFXRES_BUFFER;
214         allocParamsForBufferLinear.TileType     = MOS_TILE_LINEAR;
215         allocParamsForBufferLinear.Format       = Format_Buffer;
216         allocParamsForBufferLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
217         allocParamsForBufferLinear.dwBytes      = sizeof(uint32_t);
218         allocParamsForBufferLinear.pBufName     = "PredicationBuffer";
219         m_predicationBuffer                     = m_allocator->AllocateResource(allocParamsForBufferLinear, false);
220     }
221 
222     return MOS_STATUS_SUCCESS;
223 }
224 
UpdateFormat(void * params)225 MOS_STATUS EncodeBasicFeature::UpdateFormat(void *params)
226 {
227     ENCODE_FUNC_CALL();
228     ENCODE_CHK_NULL_RETURN(params);
229     EncoderParams* encodeParams = (EncoderParams*)params;
230 
231     PCODEC_VP9_ENCODE_SEQUENCE_PARAMS vp9SeqParams = nullptr;
232     PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams = nullptr;
233 
234         // check output Chroma format
235     switch (m_standard)
236     {
237     case CODECHAL_HEVC:
238         hevcSeqParams =  static_cast<PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams);
239         ENCODE_CHK_NULL_RETURN(hevcSeqParams);
240         m_outputChromaFormat = hevcSeqParams->chroma_format_idc;
241         break;
242 
243     case CODECHAL_VP9:
244         // check output Chroma format
245         vp9SeqParams = static_cast<PCODEC_VP9_ENCODE_SEQUENCE_PARAMS>(encodeParams->pSeqParams);
246         if (VP9_ENCODED_CHROMA_FORMAT_YUV420 == vp9SeqParams->SeqFlags.fields.EncodedFormat)
247         {
248             m_outputChromaFormat = HCP_CHROMA_FORMAT_YUV420;
249         }
250         else if (VP9_ENCODED_CHROMA_FORMAT_YUV422 == vp9SeqParams->SeqFlags.fields.EncodedFormat)
251         {
252             m_outputChromaFormat = HCP_CHROMA_FORMAT_YUV422;
253         }
254         else if (VP9_ENCODED_CHROMA_FORMAT_YUV444 == vp9SeqParams->SeqFlags.fields.EncodedFormat)
255         {
256             m_outputChromaFormat = HCP_CHROMA_FORMAT_YUV444;
257         }
258         else
259         {
260             ENCODE_ASSERTMESSAGE("Invalid output chromat format in VP9 Seq param!");
261             return MOS_STATUS_INVALID_PARAMETER;
262         }
263         break;
264 
265     default:
266         break;
267     }
268 
269     if (m_outputChromaFormat == HCP_CHROMA_FORMAT_YUV422)
270     {
271         if (Format_YUY2 != m_reconSurface.Format && Format_Y216 != m_reconSurface.Format)
272         {
273             ENCODE_ASSERTMESSAGE("Recon surface format is not correct!");
274             return MOS_STATUS_INVALID_PARAMETER;
275         }
276         else if (m_reconSurface.dwHeight < m_oriFrameHeight * 2 ||
277                  m_reconSurface.dwWidth < m_oriFrameWidth / 2)
278         {
279             ENCODE_ASSERTMESSAGE("Recon surface allocation size is not correct!");
280             return MOS_STATUS_INVALID_PARAMETER;
281         }
282     }
283     return MOS_STATUS_SUCCESS;
284 }
285 
UpdateTrackedBufferParameters()286 MOS_STATUS EncodeBasicFeature::UpdateTrackedBufferParameters()
287 {
288     ENCODE_CHK_NULL_RETURN(m_trackedBuf);
289 
290     MOS_ALLOC_GFXRES_PARAMS allocParamsForLinear;
291     MOS_ZeroMemory(&allocParamsForLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
292     allocParamsForLinear.Type = MOS_GFXRES_BUFFER;
293     allocParamsForLinear.TileType = MOS_TILE_LINEAR;
294     allocParamsForLinear.Format   = Format_Buffer;
295 
296     MOS_ALLOC_GFXRES_PARAMS allocParamsForBuffer2D;
297     MOS_ZeroMemory(&allocParamsForBuffer2D, sizeof(MOS_ALLOC_GFXRES_PARAMS));
298     allocParamsForBuffer2D.Type     = MOS_GFXRES_2D;
299     allocParamsForBuffer2D.TileType = MOS_TILE_Y;
300     allocParamsForBuffer2D.Format   = Format_NV12;
301     allocParamsForBuffer2D.Flags.bNotLockable = allocParamsForLinear.Flags.bNotLockable
302         = ((m_standard == CODECHAL_AV1) && !m_lockableResource);
303 
304     if (m_mbCodeSize > 0 && !m_isMbCodeRegistered)
305     {
306         allocParamsForLinear.pBufName = "mbCodeBuffer";
307         // Must reserve at least 8 cachelines after MI_BATCH_BUFFER_END_CMD since HW prefetch max 8 cachelines from BB everytime
308         // + 8 * CODECHAL_CACHELINE_SIZE is inherient from legacy code
309         allocParamsForLinear.dwBytes = m_mbCodeSize + 8 * CODECHAL_CACHELINE_SIZE;
310         allocParamsForLinear.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_NOCACHE;
311         ENCODE_CHK_STATUS_RETURN(m_trackedBuf->RegisterParam(encode::BufferType::mbCodedBuffer, allocParamsForLinear));
312     }
313 
314     if (m_mvDataSize > 0)
315     {
316         allocParamsForLinear.pBufName = "mvDataBuffer";
317         allocParamsForLinear.dwBytes  = m_mvDataSize;
318         ENCODE_CHK_STATUS_RETURN(m_trackedBuf->RegisterParam(encode::BufferType::mvDataBuffer, allocParamsForLinear));
319     }
320 
321     if (m_downscaledWidth4x > 0 && m_downscaledHeight4x > 0)
322     {
323         allocParamsForBuffer2D.dwWidth  = m_downscaledWidth4x;
324         allocParamsForBuffer2D.dwHeight = m_downscaledHeight4x;
325         allocParamsForBuffer2D.pBufName = "4xDSSurface";
326         allocParamsForBuffer2D.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
327         ENCODE_CHK_STATUS_RETURN(m_trackedBuf->RegisterParam(encode::BufferType::ds4xSurface, allocParamsForBuffer2D));
328 
329         allocParamsForBuffer2D.dwWidth  = m_downscaledWidth4x >> 1;
330         allocParamsForBuffer2D.dwHeight = MOS_ALIGN_CEIL(m_downscaledHeight4x >> 1, MOS_YTILE_H_ALIGNMENT) << 1;
331         allocParamsForBuffer2D.pBufName = "8xDSSurface";
332         allocParamsForBuffer2D.ResUsageType = MOS_HW_RESOURCE_USAGE_ENCODE_INTERNAL_READ_WRITE_CACHE;
333         ENCODE_CHK_STATUS_RETURN(m_trackedBuf->RegisterParam(encode::BufferType::ds8xSurface, allocParamsForBuffer2D));
334     }
335 
336     return MOS_STATUS_SUCCESS;
337 }
338 
Reset(CODEC_REF_LIST * refList)339 MOS_STATUS EncodeBasicFeature::Reset(CODEC_REF_LIST *refList)
340 {
341     ENCODE_CHK_NULL_RETURN(refList);
342     ENCODE_CHK_NULL_RETURN(m_trackedBuf);
343 
344     m_trackedBuf->Release(refList);
345     return MOS_STATUS_SUCCESS;
346 }
347 }  // namespace encode
348