1 // Copyright (c) 2017 Intel Corporation
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 
21 #ifndef __MFX_MPEG2_ENCODE_HW_UTILS_H__
22 #define __MFX_MPEG2_ENCODE_HW_UTILS_H__
23 
24 #include "mfx_common.h"
25 
26 
27 #if defined (MFX_ENABLE_MPEG2_VIDEO_ENCODE)
28 
29 #include "mfxvideo++int.h"
30 #include "mfx_frames.h"
31 #include "mfx_mpeg2_enc_common_hw.h"
32 #include "umc_mpeg2_brc.h"
33 #include "mfx_brc_common.h"
34 #include "umc_video_brc.h"
35 #include "mfx_enc_common.h"
36 
37 namespace MPEG2EncoderHW
38 {
39     enum HW_MODE
40     {
41         FULL_ENCODE,
42         HYBRID_ENCODE,
43         UNSUPPORTED
44     };
45     class EncoderBase
46     {
47     public:
48         // Destructor
49         virtual
~EncoderBase(void)50             ~EncoderBase(void) {}
51 
52         virtual
53             mfxStatus Init(mfxVideoParam *par) = 0;
54         virtual
55             mfxStatus Reset(mfxVideoParam *par) = 0;
56         virtual
57             mfxStatus Close(void) = 0;
58 
59         virtual
60             mfxStatus GetVideoParam(mfxVideoParam *par) = 0;
61         virtual
62             mfxStatus GetEncodeStat(mfxEncodeStat *stat) = 0;
63         virtual
64             mfxStatus EncodeFrameCheck(mfxEncodeCtrl *ctrl,
65             mfxFrameSurface1 *surface,
66             mfxBitstream *bs,
67             mfxFrameSurface1 **reordered_surface,
68             mfxEncodeInternalParams *pInternalParams,
69             MFX_ENTRY_POINT *pEntryPoint) = 0;
70         virtual
EncodeFrameCheck(mfxEncodeCtrl * ctrl,mfxFrameSurface1 * surface,mfxBitstream * bs,mfxFrameSurface1 ** reordered_surface,mfxEncodeInternalParams * pInternalParams,MFX_ENTRY_POINT pEntryPoints[],mfxU32 & numEntryPoints)71             mfxStatus EncodeFrameCheck(mfxEncodeCtrl *ctrl,
72             mfxFrameSurface1 *surface,
73             mfxBitstream *bs,
74             mfxFrameSurface1 **reordered_surface,
75             mfxEncodeInternalParams *pInternalParams,
76             MFX_ENTRY_POINT pEntryPoints[],
77             mfxU32 &numEntryPoints)
78         {
79             mfxStatus mfxRes;
80 
81             // call the overweighted version
82             mfxRes = EncodeFrameCheck(ctrl, surface, bs, reordered_surface, pInternalParams, pEntryPoints);
83             numEntryPoints = 1;
84 
85             return mfxRes;
86         }
87         virtual
88             mfxStatus EncodeFrameCheck(mfxEncodeCtrl *ctrl, mfxFrameSurface1 *surface, mfxBitstream *bs, mfxFrameSurface1 **reordered_surface, mfxEncodeInternalParams *pInternalParams) = 0;
89         virtual
90             mfxStatus EncodeFrame(mfxEncodeCtrl *ctrl, mfxEncodeInternalParams *pInternalParams, mfxFrameSurface1 *surface, mfxBitstream *bs) = 0;
91         virtual
92             mfxStatus CancelFrame(mfxEncodeCtrl *ctrl, mfxEncodeInternalParams *pInternalParams, mfxFrameSurface1 *surface, mfxBitstream *bs) = 0;
93         virtual
94             mfxTaskThreadingPolicy GetThreadingPolicy(void) = 0;
95 
96     };
97     class FramesSet
98     {
99     public:
100         mfxFrameSurface1    *m_pInputFrame;
101         mfxFrameSurface1    *m_pRefFrame[2];
102         mfxFrameSurface1    *m_pRawFrame[2];
103         mfxFrameSurface1    *m_pRecFrame;
104         mfxU32               m_nFrame;
105         mfxU32               m_nRefFrame[2];
106         mfxI32               m_nLastRefBeforeIntra;
107         mfxI32               m_nLastRef;
108     public:
109         FramesSet();
110         void Reset();
111         mfxStatus ReleaseFrames(VideoCORE* pCore);
112         mfxStatus LockRefFrames(VideoCORE* pCore);
LockFrames(VideoCORE * pCore)113         inline mfxStatus LockFrames(VideoCORE* pCore)
114         {
115             if (m_pInputFrame)
116             {
117                 MFX_CHECK_STS (pCore->IncreaseReference(&m_pInputFrame->Data));
118             }
119             if (m_pRecFrame)
120             {
121                 MFX_CHECK_STS (pCore->IncreaseReference(&m_pRecFrame->Data));
122             }
123             return LockRefFrames(pCore);
124         }
125     };
126     mfxStatus CheckHwCaps(  VideoCORE* core,
127                             mfxVideoParam const * par,
128                             mfxExtCodingOption const * ext = 0,
129                             ENCODE_CAPS*  pCaps = 0);
130 
131     HW_MODE GetHwEncodeMode(ENCODE_CAPS &caps);
132 
133     mfxStatus ApplyTargetUsage(mfxVideoParamEx_MPEG2* par);
134 
135     mfxExtCodingOptionSPSPPS* GetExtCodingOptionsSPSPPS(mfxExtBuffer** ebuffers,
136                                                         mfxU32 nbuffers);
137     mfxStatus CheckExtendedBuffers (mfxVideoParam* par);
138 
139     mfxStatus UnlockFrames   (MFXGOP* pGOP, MFXWaitingList* pWaitingList, VideoCORE* pcore);
140 
141     mfxStatus FillMFXFrameParams(mfxFrameParamMPEG2*     pFrameParams,
142                               mfxU8 frameType,
143                               mfxVideoParamEx_MPEG2 *pExParams,
144                               mfxU16 surface_pict_struct,
145                               bool bBackwOnly,
146                               bool bFwdOnly);
147 
148 
149     class ControllerBase
150     {
151     private:
152         VideoCORE*                      m_pCore;
153         mfxU32                          m_nEncodeCalls;
154         mfxU32                          m_nFrameInGOP;
155 
156         MFXGOP*                         m_pGOP;
157         MFXWaitingList*                 m_pWaitingList;
158         mfxI32                          m_InputFrameOrder;
159         mfxI32                          m_OutputFrameOrder;
160         mfxU64                          m_BitstreamLen;
161         mfxVideoParamEx_MPEG2           m_VideoParamsEx;
162 
163         InputSurfaces                   m_InputSurfaces;
164 
165         mfxU16                          m_InitWidth;
166         mfxU16                          m_InitHeight;
167         bool                            m_bInitialized;
168         bool                            m_bAVBR_WA;
169 
170     protected:
is_initialized()171         inline bool is_initialized ()
172         {return m_bInitialized;}
173 
174     public:
175 
176         ControllerBase(VideoCORE *core, bool bAVBR_WA = false);
~ControllerBase()177         ~ControllerBase()
178         {
179             Close();
180         }
181         mfxStatus Close(void);
182         mfxStatus Reset(mfxVideoParam *par, bool bAllowRawFrames);
183         mfxStatus GetVideoParam(mfxVideoParam *par);
184         mfxStatus GetFrameParam(mfxFrameParam *par);
185         mfxStatus GetEncodeStat(mfxEncodeStat *stat);
186         mfxStatus EncodeFrameCheck(mfxEncodeCtrl *ctrl,
187             mfxFrameSurface1 *surface,
188             mfxBitstream *bs,
189             mfxFrameSurface1 **reordered_surface,
190             mfxEncodeInternalParams *pInternalParams);
191 
192         static mfxStatus
193             Query(VideoCORE *core, mfxVideoParam *in, mfxVideoParam *out, bool bAVBR_WA = false);
194         static mfxStatus
195             QueryIOSurf  (VideoCORE *core, mfxVideoParam *par, mfxFrameAllocRequest *request);
196 
197         mfxStatus ReorderFrame(mfxEncodeInternalParams *pInInternalParams, mfxFrameSurface1 *in,
198             mfxEncodeInternalParams *pOutInternalParams, mfxFrameSurface1 **out);
199 
200         mfxStatus CheckNextFrame(mfxEncodeInternalParams *pOutInternalParams, mfxFrameSurface1 **out);
201 
202         mfxStatus CheckFrameType   (mfxEncodeInternalParams *pInternalParams);
203 
isHWInput()204         inline bool isHWInput () {return !m_InputSurfaces.isSysMemFrames();}
isOpaq()205         inline bool isOpaq() { return m_InputSurfaces.isOpaq(); }
206 
GetInputFrameType()207         inline mfxU16 GetInputFrameType()
208         {
209             return (mfxU16)( MFX_MEMTYPE_EXTERNAL_FRAME |
210                             (m_InputSurfaces.isSysMemFrames() ? MFX_MEMTYPE_SYSTEM_MEMORY : MFX_MEMTYPE_DXVA2_DECODER_TARGET)|
211                              MFX_MEMTYPE_FROM_ENCODE);
212         }
213 
isRawFrames()214         inline bool isRawFrames()
215         {return m_VideoParamsEx.bRawFrames;}
216 
getVideoParamsEx()217         inline mfxVideoParamEx_MPEG2* getVideoParamsEx()
218         {return &m_VideoParamsEx;}
219 
GetFrameNumber()220         inline mfxI32 GetFrameNumber()
221         { return m_OutputFrameOrder; }
222 
FinishFrame(mfxU32 frameSize)223         inline void FinishFrame(mfxU32 frameSize)
224         {
225             m_OutputFrameOrder ++;
226             m_BitstreamLen = m_BitstreamLen + frameSize;
227         }
GetOutputFrameOrder()228         mfxI32 GetOutputFrameOrder ()
229         {
230             return m_OutputFrameOrder;
231         }
232 
SetAllocResponse(mfxFrameAllocResponse * pAR,bool bHW)233         inline void SetAllocResponse(mfxFrameAllocResponse* pAR, bool bHW)
234         {
235             if (bHW)
236                 m_VideoParamsEx.pRecFramesResponse_hw = pAR;
237             else
238                 m_VideoParamsEx.pRecFramesResponse_sw = pAR;
239         }
240 
GetOriginalSurface(mfxFrameSurface1 * surface)241         mfxFrameSurface1 *GetOriginalSurface(mfxFrameSurface1 *surface)
242         {
243             return m_InputSurfaces.GetOriginalSurface(surface);
244         }
245 
GetOpaqSurface(mfxFrameSurface1 * surface)246         mfxFrameSurface1 *GetOpaqSurface(mfxFrameSurface1 *surface)
247         {
248             return m_InputSurfaces.GetOpaqSurface(surface);
249         }
250 
251 
252     }; // class ControllerBase
253 
254 
255     class MPEG2BRC_HW
256     {
257     private:
258         UMC::VideoBrc*   m_pBRC;
259         mfxU32           m_bConstantQuant;
260         mfxU32           m_MinFrameSizeBits[3];
261         mfxU32           m_MinFieldSizeBits[3];
262         VideoCORE*       m_pCore;
263         mfxU32           m_FirstGopSize;
264         mfxU32           m_GopSize;
265         mfxU32           m_bufferSizeInKB;
266         mfxI32           m_InputBitsPerFrame;
267         bool             m_bLimitedMode;
268 
269     protected:
270 
271         void QuantIntoScaleTypeAndCode (int32_t quant_value, int32_t &q_scale_type, int32_t &quantiser_scale_code);
ScaleTypeAndCodeIntoQuant(int32_t q_scale_type,int32_t quantiser_scale_code)272         inline int32_t ScaleTypeAndCodeIntoQuant (int32_t q_scale_type, int32_t quantiser_scale_code)
273         {
274             static int32_t Val_QScale[2][32] =
275             {
276                 /* linear q_scale */
277                 {0,  2,  4,  6,  8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
278                 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62},
279                 /* non-linear q_scale */
280                 {0, 1,  2,  3,  4,  5,  6,  7,  8, 10, 12, 14, 16, 18, 20, 22,
281                 24, 28, 32, 36, 40, 44, 48, 52, 56, 64, 72, 80, 88, 96,104,112}};
282 
283                 return Val_QScale[q_scale_type][quantiser_scale_code];
284         }
285 
286 
287         int32_t ChangeQuant(int32_t quant_value_old, int32_t quant_value_new);
288 
289     public:
MPEG2BRC_HW(VideoCORE * pCore)290         MPEG2BRC_HW(VideoCORE* pCore)
291         {
292             m_pCore          = pCore;
293             m_pBRC           = 0;
294             m_bConstantQuant = 0;
295             m_MinFrameSizeBits [0] = 0;
296             m_MinFrameSizeBits [1] = 0;
297             m_MinFrameSizeBits [2] = 0;
298 
299             m_MinFieldSizeBits [0] = 0;
300             m_MinFieldSizeBits [1] = 0;
301             m_MinFieldSizeBits [2] = 0;
302 
303             m_FirstGopSize = 0;
304             m_GopSize = 0;
305             m_bufferSizeInKB = 0;
306             m_InputBitsPerFrame = 0;
307             m_bLimitedMode = 0;
308 
309         }
~MPEG2BRC_HW()310         ~MPEG2BRC_HW ()
311         {
312             Close();
313         }
314         mfxStatus Init(mfxVideoParam* par);
315 
Reset(mfxVideoParam * par)316         inline mfxStatus Reset(mfxVideoParam* par)
317         {
318             return Init(par);
319         }
320         void Close ();
321 
322         mfxStatus StartNewFrame(const mfxFrameParamMPEG2 *pFrameParams, mfxI32 recode);
323         mfxStatus SetQuantDCPredAndDelay(mfxFrameParamMPEG2 *pFrameParams, mfxU8 *pQuant);
324 
325         mfxStatus UpdateBRC(const mfxFrameParamMPEG2 *pParams, mfxBitstream* pBitsream, mfxU32 bitsize, mfxU32 numEncodedFrame, bool bNotEnoughBuffer ,mfxI32 &recode);
SetQuant(mfxU32 Quant,mfxU32 FrameType)326         inline void SetQuant(mfxU32 Quant, mfxU32 FrameType)
327         {
328             if (m_pBRC && m_bConstantQuant)
329             {
330                 if (Quant > 0)
331                 {
332                     if  (FrameType & MFX_FRAMETYPE_I)
333                         m_pBRC->SetQP(Quant, UMC::I_PICTURE);
334                     else if  (FrameType & MFX_FRAMETYPE_P)
335                         m_pBRC->SetQP(Quant, UMC::P_PICTURE);
336                     else if  (FrameType & MFX_FRAMETYPE_B)
337                         m_pBRC->SetQP(Quant, UMC::B_PICTURE);
338                 }
339             }
340         }
341 
IsSkipped(mfxI32 & recode)342         inline bool   IsSkipped (mfxI32 &recode)
343         {
344             if (m_bLimitedMode && recode == 0)
345             {
346                 recode = UMC::BRC_EXT_FRAMESKIP;
347                 return true;
348             }
349             else if (m_bLimitedMode)
350             {
351                 return true;
352             }
353             return false;
354         }
355     private:
356         // Declare private copy constructor to avoid accidental assignment
357         // and klocwork complaining.
358         MPEG2BRC_HW(const MPEG2BRC_HW &);
359         MPEG2BRC_HW & operator = (const MPEG2BRC_HW &);
360     };
361 
362     enum TaskStatus
363     {
364         NOT_STARTED = 0,
365         INPUT_READY = 1,
366         ENC_STARTED = 2,
367         ENC_READY   = 3,
368     };
369     class FrameStore
370     {
371     private:
372         FrameStore(const FrameStore&);      // non-copyable
373         void operator=(const FrameStore&);  // non-copyable
374 
375         mfxU16                  m_InputType;
376         bool                    m_bHWFrames;
377 
378         mfxFrameSurface1        *m_pRefFrame[2];
379         mfxFrameSurface1        *m_pRawFrame[2];
380         mfxU32                  m_nRefFrame[2];
381 
382         mfxFrameSurface1        *m_pRefFramesStore;   // reference frames
383         mfxFrameSurface1        *m_pInputFramesStore; // input frames in case of system memory
384         mfxU32                  m_nRefFrames;
385         mfxU32                  m_nInputFrames;
386         VideoCORE*              m_pCore;
387         mfxFrameAllocRequest    m_RefRequest;
388         mfxFrameAllocResponse   m_RefResponse;
389         mfxFrameAllocRequest    m_InputRequest;
390         mfxFrameAllocResponse   m_InputResponse;
391         mfxU32                  m_nFrame;
392         mfxI32                  m_nLastRefBeforeIntra;
393         mfxI32                  m_nLastRef;
394         bool                    m_bRawFrame;
395 
396     protected:
397         mfxStatus ReleaseFrames();
398         mfxStatus GetInternalRefFrame(mfxFrameSurface1** ppFrame);
399         mfxStatus GetInternalInputFrame(mfxFrameSurface1** ppFrame);
400 
401     public:
402 
FrameStore(VideoCORE * pCore)403         FrameStore(VideoCORE* pCore)
404         {
405             m_InputType    = 0;
406             m_bHWFrames    = false;
407 
408             memset (m_pRefFrame,0,sizeof(mfxFrameSurface1*)*2);
409             memset (m_pRawFrame,0,sizeof(mfxFrameSurface1*)*2);
410             memset (m_nRefFrame,0,sizeof(mfxU32)*2);
411 
412             m_pRefFramesStore = 0;
413             m_pInputFramesStore = 0;
414             m_nRefFrames = 0;
415             m_nInputFrames = 0;
416 
417             m_nFrame = 0;
418             m_nRefFrame[0] = 0;
419             m_nRefFrame[1] = 0;
420             m_nLastRefBeforeIntra = -1;
421             m_nLastRef = -1;
422 
423             memset(&m_RefRequest, 0,  sizeof(mfxFrameAllocRequest));
424             memset(&m_RefResponse, 0, sizeof(mfxFrameAllocResponse));
425             memset(&m_InputRequest, 0,  sizeof(mfxFrameAllocRequest));
426             memset(&m_InputResponse, 0, sizeof(mfxFrameAllocResponse));
427 
428             m_bRawFrame = 0;
429             m_pCore = pCore;
430         }
431 
~FrameStore()432         ~FrameStore()
433         {
434             Close();
435         }
436 
437         inline mfxStatus Reset(bool bRawFrame, mfxU16 InputFrameType, bool bHWFrames, mfxU32 nTasks, mfxFrameInfo* pFrameInfo, bool bProtected = false)
438         {
439             return Init(bRawFrame, InputFrameType, bHWFrames, nTasks, pFrameInfo, bProtected);
440         }
441 
442         mfxStatus Init(bool bRawFrame, mfxU16 InputFrameType, bool bHWFrames, mfxU32 mTasks, mfxFrameInfo* pFrameInfo, bool bProtected = false);
443 
444         mfxStatus NextFrame(mfxFrameSurface1 *pInputFrame, mfxU32 nFrame, mfxU16 frameType, mfxU32 intFlags, FramesSet *pFrames);
445 
446         mfxStatus Close();
447 
GetFrameAllocResponse()448         inline mfxFrameAllocResponse* GetFrameAllocResponse()
449         {
450             return  &m_RefResponse;
451         }
452     };
453 
454     class EncodeFrameTask
455     {
456     public:
457         TaskStatus          m_taskStatus;
458         mfxFrameParamMPEG2  m_FrameParams;
459         mfxBitstream*       m_pBitstream;
460         FramesSet           m_Frames;
461         VideoCORE*          m_pCore;
462         mfxU32              m_nFrameOrder;
463         mfxEncodeInternalParams
464                             m_sEncodeInternalParams;
465         mfxU32              m_FeedbackNumber;
466         mfxU32              m_BitstreamFrameNumber;
467 
468     protected:
469         inline
Reset()470         void Reset()
471         {
472             memset(&m_FrameParams,0,sizeof(mfxFrameParamMPEG2));
473             memset(&m_sEncodeInternalParams, 0, sizeof(mfxEncodeInternalParams));
474             m_pBitstream = 0;
475             m_pCore = 0;
476             m_nFrameOrder = 0;
477             m_taskStatus = NOT_STARTED;
478             m_Frames.Reset();
479             m_FeedbackNumber = 0;
480             m_BitstreamFrameNumber = 0;
481         }
482 
483     public:
EncodeFrameTask()484         EncodeFrameTask()
485         {
486             Reset();
487         }
488         inline
Reset(VideoCORE * pCore)489         mfxStatus Reset(VideoCORE* pCore)
490         {
491             mfxStatus sts = MFX_ERR_NONE;
492             sts = m_Frames.ReleaseFrames(m_pCore);
493             Reset();
494             m_pCore = pCore;
495             return sts;
496         }
497         inline
Close()498         mfxStatus Close()
499         {
500             mfxStatus sts = MFX_ERR_NONE;
501             sts = m_Frames.ReleaseFrames(m_pCore);
502             Reset();
503             return sts;
504         }
505 
506         inline
SetFrames(FramesSet * pFrames,mfxEncodeInternalParams * pEncodeInternalParams)507         void SetFrames(FramesSet *pFrames,
508                        mfxEncodeInternalParams* pEncodeInternalParams)
509         {
510             m_Frames = *pFrames;
511             m_sEncodeInternalParams = *pEncodeInternalParams;
512         }
513         inline
FillFrameParams(mfxU8 frameType,mfxVideoParamEx_MPEG2 * pExParams,mfxU16 surface_pict_struct,bool bBackwOnly,bool bFwdOnly,bool bAddSH,bool bAddEOS)514             mfxStatus FillFrameParams (mfxU8 frameType, mfxVideoParamEx_MPEG2 *pExParams, mfxU16 surface_pict_struct, bool bBackwOnly, bool bFwdOnly, bool bAddSH, bool bAddEOS)
515         {
516             mfxStatus sts = MFX_ERR_NONE;
517             sts = FillMFXFrameParams(&m_FrameParams, frameType, pExParams, surface_pict_struct, bBackwOnly, bFwdOnly);
518             MFX_CHECK_STS(sts);
519             m_FrameParams.TemporalReference = (mfxU16)(m_Frames.m_nFrame - m_Frames.m_nLastRefBeforeIntra - 1);
520             m_FrameParams.ExtraFlags = (mfxU16)(( bAddSH ? MFX_IFLAG_ADD_HEADER:0)| (bAddEOS ? MFX_IFLAG_ADD_EOS:0)); // those values are not declared
521             return sts;
522         }
523     };
524 
525 }
526 
527 
528 #endif // MFX_ENABLE_MPEG2_VIDEO_ENCODE
529 #endif
530