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_roi_strategy.h
24 //! \brief    Defines of the ROI strategy
25 //!
26 
27 #ifndef __CODECHAL_HEVC_VDENC_ROI_STRATEGY_H__
28 #define __CODECHAL_HEVC_VDENC_ROI_STRATEGY_H__
29 
30 #include "encode_recycle_resource.h"
31 #include "encode_hevc_basic_feature.h"
32 #include "encode_hevc_brc.h"
33 #include "encode_hevc_vdenc_roi_overlap.h"
34 #include "encode_hevc_vdenc_const_settings.h"
35 #include "mhw_vdbox_huc_itf.h"
36 
37 namespace encode
38 {
39 struct HevcVdencStreamInState
40 {
41     // DWORD 0
42     union
43     {
44         struct
45         {
46             uint32_t RoiCtrl : MOS_BITFIELD_RANGE(0, 7);
47             uint32_t MaxTuSize : MOS_BITFIELD_RANGE(8, 9);
48             uint32_t MaxCuSize : MOS_BITFIELD_RANGE(10, 11);
49             uint32_t NumImePredictors : MOS_BITFIELD_RANGE(12, 15);
50             uint32_t Reserved_0 : MOS_BITFIELD_RANGE(16, 20);
51             uint32_t ForceQPDelta : MOS_BITFIELD_BIT(21);
52             uint32_t PaletteDisable : MOS_BITFIELD_BIT(22);
53             uint32_t Reserved_1 : MOS_BITFIELD_BIT(23);
54             uint32_t PuTypeCtrl : MOS_BITFIELD_RANGE(24, 31);
55         };
56         uint32_t Value;
57     } DW0;
58 
59     // DWORD 1-4
60     union
61     {
62         struct
63         {
64             uint32_t ForceMvX : MOS_BITFIELD_RANGE(0, 15);
65             uint32_t ForceMvY : MOS_BITFIELD_RANGE(16, 31);
66         };
67         uint32_t Value;
68     } DW1[4];
69 
70     // DWORD 5
71     union
72     {
73         struct
74         {
75             uint32_t Reserved : MOS_BITFIELD_RANGE(0, 31);
76         };
77         uint32_t Value;
78     } DW5;
79 
80     // DWORD 6
81     union
82     {
83         struct
84         {
85             uint32_t ForceRefIdx : MOS_BITFIELD_RANGE(0, 15);  //4-bits per 16x16 block
86             uint32_t NumMergeCandidateCu8x8 : MOS_BITFIELD_RANGE(16, 19);
87             uint32_t NumMergeCandidateCu16x16 : MOS_BITFIELD_RANGE(20, 23);
88             uint32_t NumMergeCandidateCu32x32 : MOS_BITFIELD_RANGE(24, 27);
89             uint32_t NumMergeCandidateCu64x64 : MOS_BITFIELD_RANGE(28, 31);
90         };
91         uint32_t Value;
92     } DW6;
93 
94     // DWORD 7
95     union
96     {
97         struct
98         {
99             uint32_t SegID : MOS_BITFIELD_RANGE(0, 15);  //4-bits per 16x16 block
100             uint32_t QpEnable : MOS_BITFIELD_RANGE(16, 19);
101             uint32_t SegIDEnable : MOS_BITFIELD_RANGE(20, 20);
102             uint32_t Reserved : MOS_BITFIELD_RANGE(21, 22);
103             uint32_t ForceRefIdEnable : MOS_BITFIELD_RANGE(23, 23);
104             uint32_t ImePredictorSelect : MOS_BITFIELD_RANGE(24, 31);
105         };
106         uint32_t Value;
107     } DW7;
108 
109     // DWORD 8-11
110     union
111     {
112         struct
113         {
114             uint32_t ImePredictorMvX : MOS_BITFIELD_RANGE(0, 15);
115             uint32_t ImePredictorMvY : MOS_BITFIELD_RANGE(16, 31);
116         };
117         uint32_t Value;
118     } DW8[4];
119 
120     // DWORD 12
121     union
122     {
123         struct
124         {
125             uint32_t ImePredictorRefIdx : MOS_BITFIELD_RANGE(0, 15);  //4-bits per 16x16 block
126             uint32_t Reserved : MOS_BITFIELD_RANGE(16, 31);
127         };
128         uint32_t Value;
129     } DW12;
130 
131     // DWORD 13
132     union
133     {
134         struct
135         {
136             uint32_t PanicModeLCUThreshold : MOS_BITFIELD_RANGE(0, 15);
137             uint32_t Reserved : MOS_BITFIELD_RANGE(16, 31);
138         };
139         uint32_t Value;
140     } DW13;
141 
142     // DWORD 14
143     union
144     {
145         struct
146         {
147             uint32_t ForceQp_0 : MOS_BITFIELD_RANGE(0, 7);
148             uint32_t ForceQp_1 : MOS_BITFIELD_RANGE(8, 15);
149             uint32_t ForceQp_2 : MOS_BITFIELD_RANGE(16, 23);
150             uint32_t ForceQp_3 : MOS_BITFIELD_RANGE(24, 31);
151         };
152         uint32_t Value;
153     } DW14;
154 
155     // DWORD 15
156     union
157     {
158         struct
159         {
160             uint32_t Reserved : MOS_BITFIELD_RANGE(0, 31);
161         };
162         uint32_t Value;
163     } DW15;
164 
165     inline bool operator==(const HevcVdencStreamInState &ps) const
166     {
167         if ((this->DW0.Value == ps.DW0.Value) &&
168             (this->DW1[0].Value == ps.DW1[0].Value) &&
169             this->DW1[1].Value == ps.DW1[1].Value &&
170             this->DW1[2].Value == ps.DW1[2].Value &&
171             this->DW1[3].Value == ps.DW1[3].Value &&
172             this->DW5.Value == ps.DW5.Value &&
173             this->DW6.Value == ps.DW6.Value &&
174             this->DW7.Value == ps.DW7.Value &&
175             this->DW8[0].Value == ps.DW8[0].Value &&
176             this->DW8[1].Value == ps.DW8[1].Value &&
177             this->DW8[2].Value == ps.DW8[2].Value &&
178             this->DW8[3].Value == ps.DW8[3].Value &&
179             this->DW12.Value == ps.DW12.Value &&
180             this->DW13.Value == ps.DW13.Value &&
181             this->DW14.Value == ps.DW14.Value &&
182             this->DW15.Value == ps.DW15.Value)
183             return true;
184         return false;
185     }
186 };
187 //!
188 //! \struct    DeltaQpForRoi
189 //! \brief     This struct is defined for BRC Update HUC kernel
190 //!            region 10 - Delta Qp for ROI Buffer
191 //!
192 struct DeltaQpForRoi
193 {
194     int8_t iDeltaQp;
195 };
196 
197 using SeqParams      = CODEC_HEVC_ENCODE_SEQUENCE_PARAMS;
198 using PicParams      = CODEC_HEVC_ENCODE_PICTURE_PARAMS;
199 using SlcParams      = CODEC_HEVC_ENCODE_SLICE_PARAMS;
200 using StreamInParams = mhw::vdbox::vdenc::_MHW_PAR_T(VDENC_STREAMIN_STATE);
201 using UintVector     = std::vector<uint32_t>;
202 
203 //!
204 //! \class    RoiStrategy
205 //!
206 //! \brief    Base class of Native ROI. ForceQP ROI, HuC based ForceQP ROI and
207 //!           Dirty ROI.
208 //!
209 //! \detail   This class provided unified interface of all ROI, and implemented
210 //!           some common functions which will be used by the sub classes.
211 //!
212 class RoiStrategy : public mhw::vdbox::huc::Itf::ParSetting
213 {
214 public:
RoiStrategy(EncodeAllocator * allocator,MediaFeatureManager * featureManager,PMOS_INTERFACE osInterface)215     RoiStrategy(EncodeAllocator *allocator,
216         MediaFeatureManager *featureManager,
217         PMOS_INTERFACE osInterface) :
218         m_allocator(allocator),
219         m_featureManager(featureManager),
220         m_osInterface(osInterface)
221     {
222         ENCODE_CHK_NULL_NO_STATUS_RETURN(m_featureManager);
223         ENCODE_CHK_NULL_NO_STATUS_RETURN(m_osInterface);
224 
225         m_basicFeature = dynamic_cast<HevcBasicFeature *>(m_featureManager->GetFeature(FeatureIDs::basicFeature));
226         ENCODE_CHK_NULL_NO_STATUS_RETURN(m_basicFeature);
227 
228         m_recycle = m_basicFeature->m_recycleBuf;
229     }
230 
~RoiStrategy()231     virtual ~RoiStrategy() {}
232 
233     //!
234     //! \brief    Prepare parameters
235     //!
236     //! \param    [in] hevcSeqParams
237     //!           pointer of sequence parameters
238     //! \param    [in] hevcPicParams
239     //!           pointer of picture parameters
240     //! \param    [in] hevcSlcParams
241     //!           pointer of slice parameters
242     //! \return   MOS_STATUS
243     //!           MOS_STATUS_SUCCESS if success, else fail reason
244     //!
245     virtual MOS_STATUS PrepareParams(
246         SeqParams *hevcSeqParams,
247         PicParams *hevcPicParams,
248         SlcParams *hevcSlcParams);
249 
250     //!
251     //! \brief    Setup the ROI regione
252     //!
253     //! \param    [in] overlap
254     //!           Overlap between ROI and dirty ROI
255     //! \return   MOS_STATUS
256     //!           MOS_STATUS_SUCCESS if success, else fail reason
257     //!
258     virtual MOS_STATUS SetupRoi(RoiOverlap &overlap);
259 
260     //!
261     //! \brief    Write the Streamin data according to marker.
262     //! \param    [in] lcuIndex
263     //!           Index of LCU
264     //! \param    [in] marker
265     //!           overlap marker
266     //! \param    [in] roiRegionIndex
267     //!           Index of ROI region
268     //! \param    [out] streamInBuffer
269     //!           Streamin buffer
270     //! \return   MOS_STATUS
271     //!           MOS_STATUS_SUCCESS if success, else fail reason
272     //!
273     virtual MOS_STATUS WriteStreaminData(uint32_t lcuIndex,
274         RoiOverlap::OverlapMarker marker,
275         uint32_t roiRegionIndex,
276         uint8_t *streamInBuffer);
277 
278     //!
279     //! \brief    Set VDENC_PIPE_BUF_ADDR parameters
280     //!
281     //! \param    [in] streamIn
282     //!           Stream in buffer
283     //! \param    [out] PipeBufAddrParams
284     //!           Pipe buf addr parameters
285     //!
286     //! \return   void
287     //!
SetVdencPipeBufAddrParams(PMOS_RESOURCE streamin,MHW_VDBOX_PIPE_BUF_ADDR_PARAMS & pipeBufAddrParams)288     virtual void SetVdencPipeBufAddrParams(PMOS_RESOURCE streamin,
289         MHW_VDBOX_PIPE_BUF_ADDR_PARAMS &pipeBufAddrParams)
290     {
291         pipeBufAddrParams.presVdencStreamInBuffer = streamin;
292         return;
293     }
294 
295     //!
296     //! \brief    Get stream in buffer
297     //!
298     //! \return   PMOS_RESOURCE
299     //!           Stream in buffer
300     //!
GetStreamInBuf()301     virtual PMOS_RESOURCE GetStreamInBuf() const { return nullptr; }
302 
303     //!
304     //! \brief    Setup HuC BRC init/reset parameters
305     //!
306     //! \param    [out] hucVdencBrcInitDmem
307     //!           pointer of PCODECHAL_VDENC_HEVC_HUC_BRC_INIT_DMEM_G12
308     //! \return   MOS_STATUS
309     //!           MOS_STATUS_SUCCESS if success, else fail reason
310     //!
SetDmemHuCBrcInitReset(VdencHevcHucBrcInitDmem * hucVdencBrcInitDmem)311     virtual MOS_STATUS SetDmemHuCBrcInitReset(
312         VdencHevcHucBrcInitDmem *hucVdencBrcInitDmem)
313     {
314         return MOS_STATUS_SUCCESS;
315     }
316 
SetFeatureSetting(HevcVdencFeatureSettings * settings)317     void SetFeatureSetting(HevcVdencFeatureSettings *settings) { m_FeatureSettings = settings; }
318 
319 protected:
320     //!
321     //! \brief    Calculate X/Y offsets for zigzag scan within 64 LCU
322     //!
323     //! \param    [in] streamInWidth
324     //!           StreamInWidth, location of top left corner
325     //! \param    [in] x
326     //!           Position X
327     //! \param    [in] y
328     //!           Position Y
329     //! \param    [out] offset
330     //!           Offsets into the stream-in surface
331     //! \param    [out] xyOffset
332     //!           XY Offsets into the stream-in surface
333     //!
334     //! \return   void
335     //!
336     void StreaminZigZagToLinearMap(
337         uint32_t  streamInWidth,
338         uint32_t  x,
339         uint32_t  y,
340         uint32_t *offset,
341         uint32_t *xyOffset);
342 
343     //!
344     //! \brief    Calculate X/Y position for linear scan in current frame
345     //!
346     //! \param    [in] streamInWidth
347     //!           StreamInWidth, location of top left corner
348     //! \param    [in] lcuIndex
349     //!           Index for 32x32 cu in current frame
350     //! \param    [out] x
351     //!           Position X
352     //! \param    [out] y
353     //!           Position Y
354     //!
355     //! \return   void
356     //!
357     void ZigZagToRaster(
358         uint32_t  streamInWidth,
359         uint32_t  lcuIndex,
360         uint32_t  &x,
361         uint32_t  &y);
362 
363     //!
364     //! \brief    Get LCUs' index In ROI region
365     //!
366     //! \param    [in] streamInWidth
367     //!           StreamInWidth, location of top left corner
368     //! \param    [in] top
369     //!           top of the ROI region
370     //! \param    [in] bottom
371     //!           bottom of the ROI region
372     //! \param    [in] left
373     //!           left of the ROI region
374     //! \param    [in] bottom
375     //!           right of the ROI region
376     //! \param    [out] lcuVector
377     //!           vector of LCUs' index
378     //!
379     //! \return   void
380     //!
381     void GetLCUsInRoiRegion(
382         uint32_t    streamInWidth,
383         uint32_t    top,
384         uint32_t    bottom,
385         uint32_t    left,
386         uint32_t    right,
387         UintVector &lcuVector);
388 
389     //!
390     //! \brief    Get LCUs' index In ROI region in Tile
391     //!
392     //! \param    [in] streamInWidth
393     //!           StreamInWidth, location of top left corner
394     //! \param    [in] top
395     //!           top of the ROI region
396     //! \param    [in] bottom
397     //!           bottom of the ROI region
398     //! \param    [in] left
399     //!           left of the ROI region
400     //! \param    [in] bottom
401     //!           right of the ROI region
402     //! \param    [out] lcuVector
403     //!           vector of LCUs' index
404     //!
405     //! \return   void
406     //!
407     void GetLCUsInRoiRegionForTile(
408         uint32_t    streamInWidth,
409         uint32_t    top,
410         uint32_t    bottom,
411         uint32_t    left,
412         uint32_t    right,
413         UintVector &lcuVector);
414 
415     //!
416     //! \brief    Setup stream-in data per region
417     //!
418     //! \param    [in] lcuVector
419     //!                vector of LCUs' index
420     //! \param    [in] streaminParams
421     //!                 pointer to MHW_VDBOX_VDENC_STREAMIN_STATE_PARAMS
422     //! \param    [out] streaminData
423     //!                 pointer to streaminData
424     //!
425     //! \return   void
426     //!
427     void SetStreaminDataPerRegion(
428         const UintVector &lcuVector,
429         StreamInParams *streaminParams,
430         void *streaminData);
431 
432     //!
433     //! \brief    Write out stream-in data for each LCU
434     //!
435     //! \param    [in] streaminParams
436     //!           Params to write into stream in surface
437     //! \param    [out] streaminData
438     //!           Pointer to streaminData
439     //!
440     //! \return   void
441     //!
442     void SetStreaminDataPerLcu(
443         StreamInParams *streaminParams,
444         void *streaminData);
445 
446     //!
447     //! \brief    Set streamin parameter according to the TU
448     //!
449     //! \param    [in] cu64Align
450     //!           Whether CU is 64 aligned
451     //! \param    [out] streaminDataParams
452     //!           Streamin data parameters
453     //!
454     //! \return   void
455     //!
456     virtual void SetStreaminParamByTU(
457         bool cu64Align,
458         StreamInParams &streaminDataParams);
459 
460     //!
461     //! \brief    Set the ROI ctrol mode(Native/ForceQP)
462     //!
463     //! \param    [in] roiCtrl
464     //!           ROI control
465     //! \param    [in] forceQp
466     //!           force QP value
467     //! \param    [out] streaminDataParams
468     //!           Streamin data parameters
469     //!
470     //! \return   void
471     //!
SetRoiCtrlMode(uint32_t lcuIndex,uint32_t regionIndex,StreamInParams & streaminParams)472     virtual void SetRoiCtrlMode(
473         uint32_t lcuIndex,
474         uint32_t regionIndex,
475         StreamInParams &streaminParams) {}
476 
477     //!
478     //! \brief    Set ROI Control/Force QP Data per LCU
479     //!
480     //! \param    [in] streaminDataParams
481     //!           Streamin data parameters
482     //! \param    [out] data
483     //!           Streamin data
484     //!
485     //! \return   void
486     //!
SetQpRoiCtrlPerLcu(StreamInParams * streaminParams,HevcVdencStreamInState * data)487     virtual void SetQpRoiCtrlPerLcu(
488         StreamInParams *streaminParams,
489         HevcVdencStreamInState *data) {}
490 
491     static constexpr uint8_t m_maxNumRoi             = 16;  //!< VDEnc maximum number of ROI supported
492     static constexpr uint8_t m_maxNumNativeRoi       = 3;   //!< Number of native ROI supported by VDEnc HW
493     static constexpr uint8_t m_imgStateImePredictors = 8;   //!< Number of predictors for IME
494 
495     uint8_t    m_numRoi      = 0;           //!< Number of ROI
496     CODEC_ROI  *m_roiRegions = nullptr;     //!< ROI regions
497 
498     uint8_t m_targetUsage = 0;              //!< Target Usage
499 
500     int8_t m_qpY          = 0;
501     int8_t m_sliceQpDelta = 0;
502 
503     uint8_t m_numDistinctDeltaQp = 0;
504     int8_t *m_roiDistinctDeltaQp = nullptr;
505 
506     bool     m_isTileModeEnabled  = false;
507     uint32_t m_minCodingBlockSize = 0;
508 
509     EncodeAllocator *m_allocator    = nullptr;
510     RecycleResource *m_recycle      = nullptr;
511     HevcBasicFeature *m_basicFeature = nullptr;
512     MediaFeatureManager *m_featureManager = nullptr;
513     HevcVdencFeatureSettings *m_FeatureSettings = nullptr;
514     PMOS_INTERFACE m_osInterface = nullptr;
515 
516 MEDIA_CLASS_DEFINE_END(encode__RoiStrategy)
517 };
518 
519 //!
520 //! \class    RoiStrategyFactory
521 //!
522 //! \brief    This is help class to create ROI and Dirty ROI
523 //!
524 //! \detail   At the same time, Navtive ROI,
525 //!           ForceQP ROI and Huc based ForceQP, we can only use one of them in
526 //!           one frame, which we can treat them as traditional ROI. Different
527 //!           with traditional ROI, dirty ROI can exist with them simultaneously.
528 //!           We should create traditinal ROI and dirty ROI seperately if they
529 //!           exist in the same time.
530 //!
531 class RoiStrategyFactory
532 {
533 public:
534     //!
535     //! \brief    Create ROIs, include Native ROI, ForceQP ROI, Huc based ROI and
536     //!           dirty ROI according to the input parameters
537     //!
538     //! \param    [in] allocator
539     //!           Encode allocator
540     //! \param    [in] recycle
541     //!           Recycle buffer
542     //! \param    [in] params
543     //!           Encode parameters
544     //! \param    [in] isDirtyRoi
545     //!           Whether is dirty ROI or not.
546     //! \param    [in] isNativeRoi
547     //!           Whether is native ROI or not.
548     //!
549     //! \return   RoiStrategy *
550     //!           Pointer of RoiStrategy
551     //!
552     RoiStrategy *CreateStrategy(
553         EncodeAllocator     *allocator,
554         MediaFeatureManager *featureManager,
555         PMOS_INTERFACE       m_osInterface,
556         bool                 isArb,
557         bool                 isDirtyRoi,
558         bool                 isNativeRoi,
559         bool                 isQPMap = false);
560 
561     //!
562     //! \brief    Create ROIs, include force delta qp ROI,
563     //!
564     //!
565     //! \param    [in] allocator
566     //!           Encode allocator
567     //! \param    [in] featureManager
568     //!           Media feature manager.
569     //!
570     //! \return   RoiStrategy *
571     //!           Pointer of RoiStrategy
572     //!
573     RoiStrategy *CreateStrategyForceDeltaQP(
574         EncodeAllocator *allocator,
575         MediaFeatureManager *featureManager,
576         PMOS_INTERFACE m_osInterface);
577 
578     ~RoiStrategyFactory();
579 
580     //!
581     //! \brief    Get dirty ROI for current frame
582     //!
583     //! \return   RoiStrategy *
584     //!           Pointer of RoiStrategy
585     //!
GetDirtyRoi()586     RoiStrategy *GetDirtyRoi() const { return m_dirtyRoi; }
587     //!
588     //! \brief    Get traditional ROI for current frame
589     //!
590     //! \return   RoiStrategy *
591     //!           Pointer of RoiStrategy
592     //!
GetRoi()593     RoiStrategy *GetRoi() const { return m_currentRoi; }
594 
595 private:
596     RoiStrategy *m_nativeRoi  = nullptr;
597     RoiStrategy *m_arbRoi  = nullptr;
598     RoiStrategy *m_forceQpRoi = nullptr;
599     RoiStrategy *m_hucForceQpRoi = nullptr;
600     RoiStrategy *m_currentRoi = nullptr;
601     RoiStrategy *m_dirtyRoi   = nullptr;
602     RoiStrategy *m_QPMapROI  = nullptr;
603     RoiStrategy *m_deltaQpRoi = nullptr;
604 
605 MEDIA_CLASS_DEFINE_END(encode__RoiStrategyFactory)
606 };
607 
608 }  // namespace encode
609 #endif  //<! __CODECHAL_HEVC_VDENC_ROI_STRATEGY_H__
610