1 // Copyright (c) 2018-2020 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 #include "mfx_common.h"
21 #ifdef MFX_ENABLE_H264_VIDEO_ENCODE_HW
22 
23 #include <vector>
24 #include <list>
25 #include <memory>
26 #include <algorithm> /* for std::find_if on Linux/Android */
27 #include <mfx_brc_common.h>
28 
29 #include "mfx_h264_encode_struct_vaapi.h"
30 #include "umc_mutex.h"
31 #include "umc_event.h"
32 #include "umc_h264_brc.h"
33 #include "mfx_h264_enc_common_hw.h"
34 #include "mfx_ext_buffers.h"
35 #include "mfx_h264_encode_interface.h"
36 #include "mfx_h264_encode_cm.h"
37 #include "vm_time.h"
38 #include "asc.h"
39 
40 #ifdef MFX_ENABLE_MCTF_IN_AVC
41 #include "cmvm.h"
42 #include "mctf_common.h"
43 #endif
44 
45 #ifndef _MFX_H264_ENCODE_HW_UTILS_H_
46 #define _MFX_H264_ENCODE_HW_UTILS_H_
47 
48 #if defined(AS_H264LA_PLUGIN) && defined(MFX_ENABLE_ENCTOOLS)
49 #undef MFX_ENABLE_ENCTOOLS
50 #endif
51 
52 #define bRateControlLA(RCMethod) ((RCMethod == MFX_RATECONTROL_LA)||(RCMethod == MFX_RATECONTROL_LA_ICQ)||(RCMethod == MFX_RATECONTROL_LA_EXT)||(RCMethod == MFX_RATECONTROL_LA_HRD))
53 #define bIntRateControlLA(RCMethod) ((RCMethod == MFX_RATECONTROL_LA)||(RCMethod == MFX_RATECONTROL_LA_ICQ)||(RCMethod == MFX_RATECONTROL_LA_HRD))
54 
55 inline constexpr
hasSupportVME(eMFXHWType platform)56 bool hasSupportVME(eMFXHWType platform)
57 {
58     return
59            (platform <= MFX_HW_ADL_S
60         &&  platform != MFX_HW_JSL
61         &&  platform != MFX_HW_EHL
62         );
63 }
64 
65 #define MFX_H264ENC_HW_TASK_TIMEOUT 2000
66 
67 #define MFX_ARRAY_SIZE(ARR) (sizeof(ARR)/sizeof(ARR[0]))
68 const int MFX_MAX_DIRTY_RECT_COUNT = MFX_ARRAY_SIZE(mfxExtDirtyRect::Rect);
69 const int MFX_MAX_MOVE_RECT_COUNT = MFX_ARRAY_SIZE(mfxExtMoveRect::Rect);
70 const int DEFAULT_PPYR_INTERVAL = 3;
71 
72 
73 namespace MfxHwH264Encode
74 {
75     struct VmeData;
76 
77     enum {
78         STAGE_QP   = 0xf00000,
79         STAGE_ENC1 = 0x0f0000,
80         STAGE_PAK1 = 0x00f000,
81         STAGE_ENC2 = 0x000f00,
82         STAGE_PAK2 = 0x0000f0,
83         STAGE_ENC  = STAGE_ENC1 | STAGE_ENC2,
84         STAGE_PAK  = STAGE_PAK1 | STAGE_PAK2,
85         STAGE_ALL  = 0xffffff
86     };
87 
88     static const mfxU16 MFX_MEMTYPE_SYS_INT =
89         MFX_MEMTYPE_FROM_ENCODE | MFX_MEMTYPE_SYSTEM_MEMORY | MFX_MEMTYPE_INTERNAL_FRAME;
90 
91     static const mfxU16 MFX_MEMTYPE_SYS_EXT =
92         MFX_MEMTYPE_FROM_ENCODE | MFX_MEMTYPE_SYSTEM_MEMORY | MFX_MEMTYPE_EXTERNAL_FRAME;
93 
94     static const mfxU16 MFX_MEMTYPE_D3D_INT =
95         MFX_MEMTYPE_FROM_ENCODE | MFX_MEMTYPE_DXVA2_DECODER_TARGET | MFX_MEMTYPE_INTERNAL_FRAME;
96 
97     static const mfxU16 MFX_MEMTYPE_D3D_EXT =
98         MFX_MEMTYPE_FROM_ENCODE | MFX_MEMTYPE_DXVA2_DECODER_TARGET | MFX_MEMTYPE_EXTERNAL_FRAME;
99 
100 
101     mfxU16 CalcNumFrameMin(const MfxHwH264Encode::MfxVideoParam &par, MFX_ENCODE_CAPS const & hwCaps);
102 
103     enum
104     {
105         TFIELD = 0,
106         BFIELD = 1
107     };
108 
109     enum
110     {
111         ENC = 0,
112         DISP = 1
113     };
114 
115     /*
116         NAL unit types for internal usage
117     */
118     enum {
119         NALU_NON_IDR = 1,
120         NALU_IDR = 5,
121         NALU_SEI = 6,
122         NALU_SPS = 7,
123         NALU_PPS = 8,
124         NALU_AUD = 9,
125         NALU_PREFIX = 14,
126         NALU_CODED_SLICE_EXT = 20,
127     };
128 
129 
130     class DdiTask;
131 
132     struct mfxExtAvcSeiBufferingPeriod
133     {
134         mfxU8  seq_parameter_set_id;
135         mfxU8  nal_cpb_cnt;
136         mfxU8  vcl_cpb_cnt;
137         mfxU8  initial_cpb_removal_delay_length;
138         mfxU32 nal_initial_cpb_removal_delay[32];
139         mfxU32 nal_initial_cpb_removal_delay_offset[32];
140         mfxU32 vcl_initial_cpb_removal_delay[32];
141         mfxU32 vcl_initial_cpb_removal_delay_offset[32];
142     };
143 
144     struct mfxExtAvcSeiPicTiming
145     {
146         mfxU8  cpb_dpb_delays_present_flag;
147         mfxU8  cpb_removal_delay_length;
148         mfxU8  dpb_output_delay_length;
149         mfxU8  pic_struct_present_flag;
150         mfxU8  time_offset_length;
151 
152         mfxU32 cpb_removal_delay;
153         mfxU32 dpb_output_delay;
154         mfxU8  pic_struct;
155         mfxU8  ct_type;
156     };
157 
158     struct mfxExtAvcSeiDecRefPicMrkRep
159     {
160         mfxU8  original_idr_flag;
161         mfxU16 original_frame_num;
162         mfxU8  original_field_info_present_flag;
163         mfxU8  original_field_pic_flag;
164         mfxU8  original_bottom_field_flag;
165         mfxU8  no_output_of_prior_pics_flag;
166         mfxU8  long_term_reference_flag;
167         mfxU8  adaptive_ref_pic_marking_mode_flag;
168         mfxU32 num_mmco_entries;                // number of currently valid mmco, value pairs
169         mfxU8  mmco[32];                        // memory management control operation id
170         mfxU32 value[64];                       // operation-dependent data, max 2 per operation
171     };
172 
173     struct mfxExtAvcSeiRecPoint
174     {
175         mfxU16 recovery_frame_cnt;
176         mfxU8  exact_match_flag;
177         mfxU8  broken_link_flag;
178         mfxU8  changing_slice_group_idc;
179     };
180 
181 
182     template <typename T> struct Pair
183     {
184         T top;
185         T bot;
186 
PairPair187         Pair()
188             : top()
189             , bot()
190         {
191         }
192 
PairPair193         template<typename U> Pair(Pair<U> const & pair)
194             : top(static_cast<T>(pair.top))
195             , bot(static_cast<T>(pair.bot))
196         {
197         }
198 
PairPair199         template<typename U> explicit Pair(U const & value)
200             : top(static_cast<T>(value))
201             , bot(static_cast<T>(value))
202         {
203         }
204 
PairPair205         template<typename U> Pair(U const & t, U const & b)
206             : top(static_cast<T>(t))
207             , bot(static_cast<T>(b))
208         {
209         }
210 
211         template<typename U>
212         Pair<T> & operator =(Pair<U> const & pair)
213         {
214             Pair<T> tmp(pair);
215             std::swap(*this, tmp);
216             return *this;
217         }
218 
219         T & operator[] (mfxU32 parity)
220         {
221             assert(parity < 2);
222             return (&top)[parity & 1];
223         }
224 
225         T const & operator[] (mfxU32 parity) const
226         {
227             assert(parity < 2);
228             return (&top)[parity & 1];
229         }
230     };
231 
MakePair(T const & top,T const & bot)232     template <class T> Pair<T> MakePair(T const & top, T const & bot)
233     {
234         return Pair<T>(top, bot);
235     }
236 
237     template <class T> bool operator ==(Pair<T> const & l, Pair<T> const & r)
238     {
239         return l.top == r.top && l.bot == r.bot;
240     }
241 
242     typedef Pair<mfxU8>  PairU8;
243     typedef Pair<mfxU16> PairU16;
244     typedef Pair<mfxU32> PairU32;
245     typedef Pair<mfxI32> PairI32;
246 
247     void PrepareSeiMessage(
248         DdiTask const &               task,
249         mfxU32                        nalHrdBpPresentFlag,
250         mfxU32                        vclHrdBpPresentFlag,
251         mfxU32                        seqParameterSetId,
252         mfxExtAvcSeiBufferingPeriod & msg);
253 
254     void PrepareSeiMessage(
255         DdiTask const &                task,
256         mfxU32                         fieldId,
257         mfxU32                         cpbDpbDelaysPresentFlag,
258         mfxExtAvcSeiPicTiming &        msg);
259 
260     void PrepareSeiMessage(
261         DdiTask const &               task,
262         mfxU32                        fieldId,
263         mfxU32                        frame_mbs_only_flag,
264         mfxExtAvcSeiDecRefPicMrkRep & msg);
265 
266     void PrepareSeiMessage(
267         MfxVideoParam const &   par,
268         mfxExtAvcSeiRecPoint &  msg);
269 
270     mfxU32 CalculateSeiSize( mfxExtAvcSeiRecPoint const & msg);
271     mfxU32 CalculateSeiSize( mfxExtAvcSeiDecRefPicMrkRep const & msg);
272 
273 // MVC BD {
274     mfxU32 CalculateSeiSize( mfxExtAvcSeiBufferingPeriod const & msg);
275     mfxU32 CalculateSeiSize(
276         mfxExtPictureTimingSEI const & extPt,
277         mfxExtAvcSeiPicTiming const & msg);
278 // MVC BD }
279 
280     mfxStatus CheckBeforeCopy(
281         mfxExtMVCSeqDesc &       dst,
282         mfxExtMVCSeqDesc const & src);
283 
284     mfxStatus CheckBeforeCopyQueryLike(
285         mfxExtMVCSeqDesc &       dst,
286         mfxExtMVCSeqDesc const & src);
287 
288     void Copy(
289         mfxExtMVCSeqDesc &       dst,
290         mfxExtMVCSeqDesc const & src);
291 
292     void FastCopyBufferVid2Sys(
293         void *       dstSys,
294         void const * srcVid,
295         mfxI32       bytes);
296 
297     void FastCopyBufferSys2Vid(
298         void *       dstSys,
299         void const * srcVid,
300         mfxI32       bytes);
301 
302     PairU8 ExtendFrameType(
303         mfxU32 type);
304 
305     mfxU8 CalcTemporalLayerIndex(
306         MfxVideoParam const & video,
307         mfxI32                frameOrder);
308 
309     bool CheckSubMbPartition(
310         mfxExtCodingOptionDDI const * extDdi,
311         mfxU8                         frameType);
312 
313     mfxU8 GetPFrameLevel(
314         mfxU32 i,
315         mfxU32 num);
316 
317     mfxU8 PLayer(
318         MfxVideoParam const & par,
319         mfxU32                order);
320 
321     mfxU8 GetQpValue(
322         DdiTask const &       task,
323         MfxVideoParam const & par,
324         mfxU32                frameType);
325 
326     PairU16 GetPicStruct(
327         MfxVideoParam const & video,
328         mfxU16                runtPs);
329 
330     PairU16 GetPicStruct(
331         MfxVideoParam const & video,
332         DdiTask const &       task);
333 
334     bool isBitstreamUpdateRequired(MfxVideoParam const & video,
335         MFX_ENCODE_CAPS caps,
336         eMFXHWType platform);
337     // Helper which checks number of allocated frames and auto-free.
338     enum
339     {
340         H264_FRAME_FLAG_SKIPPED = 1,
341         H264_FRAME_FLAG_READY = 2
342     };
343 
344     class MfxFrameAllocResponse : public mfxFrameAllocResponse
345     {
346     public:
347         MfxFrameAllocResponse();
348 
349         ~MfxFrameAllocResponse();
350 
351         mfxStatus Alloc(
352             VideoCORE *            core,
353             mfxFrameAllocRequest & req,
354             bool isCopyRequired = true,
355             bool isAllFramesRequired = false);
356 
357         mfxStatus Alloc(
358             VideoCORE *            core,
359             mfxFrameAllocRequest & req,
360             mfxFrameSurface1 **    opaqSurf,
361             mfxU32                 numOpaqSurf);
362 
363         mfxStatus AllocCmBuffers(
364             CmDevice *             device,
365             mfxFrameAllocRequest & req);
366 
367         mfxStatus AllocCmBuffersUp(
368             CmDevice *             device,
369             mfxFrameAllocRequest & req);
370 
371         mfxStatus AllocCmSurfaces(
372             CmDevice *             device,
373             mfxFrameAllocRequest & req);
374 
375         mfxStatus AllocCmSurfacesUP(
376             CmDevice *             device,
377             mfxFrameAllocRequest & req);
378         mfxStatus AllocFrames(
379             VideoCORE *            core,
380             mfxFrameAllocRequest & req);
381         mfxStatus UpdateResourcePointers(
382             mfxU32                 idxScd,
383             void *                 memY,
384             void *                 gpuSurf);
385 
386         void * GetSysmemBuffer(mfxU32 idx);
387 
388         mfxU32 Lock(mfxU32 idx);
389 
390         void Unlock();
391 
392         mfxU32 Unlock(mfxU32 idx);
393 
394         mfxU32 Locked(mfxU32 idx) const;
395 
396         void   ClearFlag(mfxU32 idx);
397         void   SetFlag(mfxU32 idx, mfxU32 flag);
398         mfxU32 GetFlag(mfxU32 idx) const;
399     private:
400         MfxFrameAllocResponse(MfxFrameAllocResponse const &);
401         MfxFrameAllocResponse & operator =(MfxFrameAllocResponse const &);
402 
403         static void DestroyBuffer     (CmDevice * device, void * p);
404         static void DestroySurface    (CmDevice * device, void * p);
405         static void DestroySurface2DUP(CmDevice * device, void * p);
406         static void DestroyBufferUp   (CmDevice * device, void * p);
407 
408         void (*m_cmDestroy)(CmDevice *, void *);
409 
410         VideoCORE * m_core;
411         CmDevice *  m_cmDevice;
412         mfxU16      m_numFrameActualReturnedByAllocFrames;
413 
414         std::vector<mfxFrameAllocResponse> m_responseQueue;
415         std::vector<mfxMemId>              m_mids;
416         std::vector<mfxU32>                m_locked;
417         std::vector<mfxU32>                m_flag;
418         std::vector<void *>                m_sysmems;
419     };
420 
421     mfxU32 FindFreeResourceIndex(
422         MfxFrameAllocResponse const & pool,
423         mfxU32                        startingFrom = 0);
424 
425     mfxMemId AcquireResource(
426         MfxFrameAllocResponse & pool,
427         mfxU32                  index);
428 
429     mfxMemId AcquireResource(
430         MfxFrameAllocResponse & pool);
431 
432     mfxHDLPair AcquireResourceUp(
433         MfxFrameAllocResponse & pool,
434         mfxU32                  index);
435 
436     mfxHDLPair AcquireResourceUp(
437         MfxFrameAllocResponse & pool);
438 
439     void ReleaseResource(
440         MfxFrameAllocResponse & pool,
441         mfxMemId                mid);
442 
443     // add hwType param
444     mfxStatus CheckEncodeFrameParam(
445         MfxVideoParam const &      video,
446         mfxEncodeCtrl *            ctrl,
447         mfxFrameSurface1 *         surface,
448         mfxBitstream *             bs,
449         bool                       isExternalFrameAllocator,
450         MFX_ENCODE_CAPS const &    caps,
451         eMFXHWType                 hwType = MFX_HW_UNKNOWN);
452 
Clear(std::vector<T> & v)453     template<typename T> void Clear(std::vector<T> & v)
454     {
455         std::vector<T>().swap(v);
456     }
457 
458 
459     template<class T, mfxU32 N>
460     struct FixedArray
461     {
FixedArrayFixedArray462         FixedArray()
463             : m_numElem(0)
464         {
465         }
466 
FixedArrayFixedArray467         explicit FixedArray(T fillVal)
468             : m_numElem(0)
469         {
470             Fill(fillVal);
471         }
472 
PushBackFixedArray473         void PushBack(T const & val)
474         {
475             assert(m_numElem < N);
476             m_arr[m_numElem] = val;
477             m_numElem++;
478         }
479 
PushFrontFixedArray480         void PushFront(T const val)
481         {
482             assert(m_numElem < N);
483             std::copy(m_arr, m_arr + m_numElem, m_arr + 1);
484             m_arr[0] = val;
485             m_numElem++;
486         }
487 
EraseFixedArray488         void Erase(T * p)
489         {
490             assert(p >= m_arr && p <= m_arr + m_numElem);
491 
492             m_numElem = mfxU32(
493                 std::copy(p + 1, m_arr + m_numElem, p) - m_arr);
494         }
495 
EraseFixedArray496         void Erase(T * b, T * e)
497         {
498             assert(b <= e);
499             assert(b >= m_arr && b <= m_arr + m_numElem);
500             assert(e >= m_arr && e <= m_arr + m_numElem);
501 
502             m_numElem = mfxU32(
503                 std::copy(e, m_arr + m_numElem, b) - m_arr);
504         }
505 
506         void Resize(mfxU32 size, T fillVal = T())
507         {
508             assert(size <= N);
509             for (mfxU32 i = m_numElem ; i < size; ++i)
510                 m_arr[i] = fillVal;
511             m_numElem = size;
512         }
513 
BeginFixedArray514         T * Begin()
515         {
516             return m_arr;
517         }
518 
BeginFixedArray519         T const * Begin() const
520         {
521             return m_arr;
522         }
523 
EndFixedArray524         T * End()
525         {
526             return m_arr + m_numElem;
527         }
528 
EndFixedArray529         T const * End() const
530         {
531             return m_arr + m_numElem;
532         }
533 
BackFixedArray534         T & Back()
535         {
536             assert(m_numElem > 0);
537             return m_arr[m_numElem - 1];
538         }
539 
BackFixedArray540         T const & Back() const
541         {
542             assert(m_numElem > 0);
543             return m_arr[m_numElem - 1];
544         }
545 
SizeFixedArray546         mfxU32 Size() const
547         {
548             return m_numElem;
549         }
550 
CapacityFixedArray551         mfxU32 Capacity() const
552         {
553             return N;
554         }
555 
556         T & operator[](mfxU32 idx)
557         {
558             assert(idx < N);
559             return m_arr[idx];
560         }
561 
562         T const & operator[](mfxU32 idx) const
563         {
564             assert(idx < N);
565             return m_arr[idx];
566         }
567 
FillFixedArray568         void Fill(T val)
569         {
570             for (mfxU32 i = 0; i < N; i++)
571             {
572                 m_arr[i] = val;
573             }
574         }
575 
576         template<mfxU32 M>
577         bool operator==(const FixedArray<T, M>& r) const
578         {
579             assert(Size() <= N);
580             assert(r.Size() <= M);
581 
582             if (Size() != r.Size())
583             {
584                 return false;
585             }
586 
587             for (mfxU32 i = 0; i < Size(); i++)
588             {
589                 if (m_arr[i] != r[i])
590                 {
591                     return false;
592                 }
593             }
594 
595             return true;
596         }
597 
598     private:
599         T      m_arr[N];
600         mfxU32 m_numElem;
601     };
602 
603     struct BiFrameLocation
604     {
BiFrameLocationBiFrameLocation605         BiFrameLocation() { Zero(*this); }
606 
607         mfxU32 miniGopCount;    // sequence of B frames between I/P frames
608         mfxU32 encodingOrder;   // number within mini-GOP (in encoding order)
609         mfxU16 refFrameFlag;    // MFX_FRAMETYPE_REF if B frame is reference
610         mfxU32 level;           // level of pyramid
611     };
612 
613     class FrameTypeGenerator
614     {
615     public:
616         FrameTypeGenerator();
617 
618         void Init(MfxVideoParam const & video);
619 
620         PairU8 Get() const;
621 
622         BiFrameLocation GetBiFrameLocation() const;
623 
624         void Next();
625 
626     private:
627         mfxU32 m_frameOrder;    // in display order
628         mfxU16 m_gopOptFlag;
629         mfxU16 m_gopPicSize;
630         mfxU16 m_gopRefDist;
631         mfxU16 m_refBaseDist;   // key picture distance
632         mfxU16 m_biPyramid;
633         mfxU32 m_idrDist;
634     };
635 
636     /* Intra refresh types */
637     enum {
638         MFX_REFRESH_NO = 0,
639         MFX_REFRESH_VERTICAL = 1,
640         MFX_REFRESH_HORIZONTAL = 2,
641         MFX_REFRESH_SLICE = 3
642     };
643 
644     struct IntraRefreshState
645     {
IntraRefreshStateIntraRefreshState646         IntraRefreshState() : refrType(0), IntraLocation(0), IntraSize(0), IntRefQPDelta(0), firstFrameInCycle(false) {}
647         bool operator==(const IntraRefreshState& rhs) const
648         {
649             return refrType == rhs.refrType &&
650                 IntraLocation == rhs.IntraLocation &&
651                 IntraSize == rhs.IntraSize &&
652                 IntRefQPDelta == rhs.IntRefQPDelta &&
653                 firstFrameInCycle == rhs.firstFrameInCycle;
654         }
655 
656         mfxU16  refrType;
657         mfxU16  IntraLocation;
658         mfxU16  IntraSize;
659         mfxI16  IntRefQPDelta;
660         bool    firstFrameInCycle;
661     };
662 
663     class Surface
664     {
665     public:
Surface()666         Surface()
667             : m_free(true)
668         {
669         }
670 
IsFree()671         bool IsFree() const
672         {
673             return m_free;
674         }
675 
SetFree(bool free)676         void SetFree(bool free)
677         {
678             m_free = free;
679         }
680 
681     private:
682         bool m_free;
683     };
684 
685     class Reconstruct : public Surface
686     {
687     public:
Reconstruct()688         Reconstruct()
689             : Surface()
690             , m_yuv(0)
691             , m_frameOrderIdrInDisplayOrder(0)
692             , m_frameOrderIdr(0)
693             , m_frameOrderI(0)
694             , m_frameOrder(0)
695             , m_baseLayerOrder(0)
696             , m_frameOrderStartTScalStructure(0)
697             , m_frameNum(0)
698             , m_frameNumWrap(0)
699             , m_picNum(0, 0)
700             , m_longTermFrameIdx(NO_INDEX_U8)
701             , m_longTermPicNum(NO_INDEX_U8, NO_INDEX_U8)
702             , m_reference(false, false)
703             , m_picStruct((mfxU16)MFX_PICSTRUCT_PROGRESSIVE)
704             , m_extFrameTag(0)
705             , m_tid(0)
706             , m_tidx(0)
707             , m_panicMode(0)
708         {
709         }
710 
GetPicStructForEncode()711         mfxU16 GetPicStructForEncode() const
712         {
713             return m_picStruct[ENC];
714         }
715 
GetPicStructForDisplay()716         mfxU16 GetPicStructForDisplay() const
717         {
718             return m_picStruct[DISP];
719         }
720 
GetFirstField()721         mfxU8 GetFirstField() const
722         {
723             return (GetPicStructForEncode() & MFX_PICSTRUCT_FIELD_BFF) ? 1 : 0;
724         }
725 
GetPoc(mfxU32 parity)726         mfxI32 GetPoc(mfxU32 parity) const
727         {
728             return 2 * ((m_frameOrder - m_frameOrderIdr) & 0x7fffffff) + (parity != GetFirstField());
729         }
730 
GetPoc()731         PairI32 GetPoc() const
732         {
733             return PairI32(GetPoc(TFIELD), GetPoc(BFIELD));
734         }
735 
GetPictureCount()736         mfxU32 GetPictureCount() const
737         {
738             return (GetPicStructForEncode() & MFX_PICSTRUCT_PROGRESSIVE) ? 1 : 2;
739         }
740 
741         mfxFrameSurface1* m_yuv;
742         mfxU32  m_frameOrderIdrInDisplayOrder; // most recent idr frame in display order
743         mfxU32  m_frameOrderIdr;    // most recent idr frame in encoding order
744         mfxU32  m_frameOrderI;      // most recent i frame in encoding order
745         mfxU32  m_frameOrder;
746         mfxU32  m_baseLayerOrder;
747         mfxU32  m_frameOrderStartTScalStructure; // starting point of temporal scalability structure
748         mfxU16  m_frameNum;
749         mfxI32  m_frameNumWrap;
750         PairI32 m_picNum;
751         mfxU8   m_longTermFrameIdx;
752         PairU8  m_longTermPicNum;
753         PairU8  m_reference;        // is refrence (short or long term) or not
754         PairU16 m_picStruct;
755         mfxU32  m_extFrameTag;
756         mfxU32  m_tid;              // temporal_id
757         mfxU8  m_tidx;             // temporal layer index (in acsending order of temporal_id)
758         mfxU8   m_panicMode;
759     };
760 
761     struct RefListMod
762     {
RefListModRefListMod763         RefListMod() : m_idc(3), m_diff(0) {}
RefListModRefListMod764         RefListMod(mfxU16 idc, mfxU16 diff) : m_idc(idc), m_diff(diff) { assert(idc < 6); }
765         mfxU16 m_idc;
766         mfxU16 m_diff;
767     };
768 
769     struct WeightTab
770     {
771         mfxU8 m_lumaWeightL0Flag:1;
772         mfxU8 m_chromaWeightL0Flag:1;
773         mfxU8 m_lumaWeightL1Flag:1;
774         mfxU8 m_chromaWeightL1Flag:1;
775 
776         mfxI8 m_lumaWeightL0;
777         mfxI8 m_lumaOffsetL0;
778         mfxI8 m_lumaWeightL1;
779         mfxI8 m_lumaOffsetL1;
780         mfxI8 m_chromaWeightL0[2];
781         mfxI8 m_chromaOffsetL0[2];
782         mfxI8 m_chromaWeightL1[2];
783         mfxI8 m_chromaOffsetL1[2];
784     };
785 
786     struct DpbFrame
787     {
DpbFrameDpbFrame788         DpbFrame() { Zero(*this); }
789 
790         PairI32 m_poc;
791         mfxU32  m_frameOrder;
792         mfxU32  m_extFrameTag; // frameOrder assigned by application
793         mfxU32  m_frameNum;
794         mfxI32  m_frameNumWrap;
795         mfxI32  m_picNum[2];
796         mfxU32  m_viewIdx;
797         mfxU32  m_frameIdx;
798         mfxU32  m_tid;
799         PairU8  m_longTermPicNum;
800         PairU8  m_refPicFlag;
801         mfxU8   m_longTermIdxPlus1;
802         mfxU8   m_longterm; // at least one field is a long term reference
803         mfxU8   m_refBase;
804         mfxU8   m_keyRef;   //short term reference stored in DPB as long as possible
805 
806         mfxU8   m_PIFieldFlag; // for P/I field pair
807 
808         mfxMemId        m_midRec;
809         CmSurface2D *   m_cmRaw;
810         CmSurface2D *   m_cmRawLa;
811         CmBufferUP *    m_cmMb;
812 
813         CmBufferUP *  m_cmHist;
814         void *        m_cmHistSys;
815 
816         mfxMemId          m_midRaw; // for RefRaw mode
817         mfxFrameSurface1* m_yuvRaw; // for RefRaw mode
818     };
819 
820     inline bool operator ==(DpbFrame const & l, DpbFrame const & r)
821     {
822         return l.m_frameIdx == r.m_frameIdx && l.m_poc == r.m_poc && l.m_viewIdx == r.m_viewIdx;
823     }
824 
825     typedef FixedArray<mfxU32, 16>     ArrayU32x16;
826     typedef FixedArray<mfxU32, 64>     ArrayU32x64;
827     typedef FixedArray<mfxU16, 16>     ArrayU16x16;
828     typedef FixedArray<mfxU8, 8>       ArrayU8x8;
829     typedef FixedArray<mfxU8, 16>      ArrayU8x16;
830     typedef FixedArray<mfxU8, 32>      ArrayU8x32;
831     typedef FixedArray<mfxU8, 33>      ArrayU8x33;
832     typedef FixedArray<PairU32, 16>    ArrayPairU32x16;
833     typedef FixedArray<RefListMod, 32> ArrayRefListMod;
834 
835     typedef FixedArray<mfxRoiDesc, 256>                               ArrayRoi;
836     typedef FixedArray<mfxRectDesc, MFX_MAX_DIRTY_RECT_COUNT>         ArrayRect;
837     typedef FixedArray<mfxMovingRectDesc, MFX_MAX_MOVE_RECT_COUNT>    ArrayMovingRect;
838 
839     struct ArrayDpbFrame : public FixedArray<DpbFrame, 16>
840     {
ArrayDpbFrameArrayDpbFrame841         ArrayDpbFrame()
842         : FixedArray<DpbFrame, 16>()
843         {
844             m_maxLongTermFrameIdxPlus1.Resize(8, 0);
845         }
846 
847         ArrayU8x8 m_maxLongTermFrameIdxPlus1; // for each temporal layer
848     };
849 
850     struct DecRefPicMarkingInfo
851     {
DecRefPicMarkingInfoDecRefPicMarkingInfo852         DecRefPicMarkingInfo() { Zero(*this); }
853 
854         void PushBack(mfxU8 op, mfxU32 param0, mfxU32 param1 = 0)
855         {
856             mmco.PushBack(op);
857             value.PushBack(param0);
858             value.PushBack(param1);
859         }
860 
ClearDecRefPicMarkingInfo861         void Clear()
862         {
863             mmco.Resize(0);
864             value.Resize(0);
865             value.Resize(0);
866         }
867 
868         mfxU8       no_output_of_prior_pics_flag;
869         mfxU8       long_term_reference_flag;
870         ArrayU8x32  mmco;       // memory management control operation id
871         ArrayU32x64 value;      // operation-dependent data, max 2 per operation
872     };
873 
874     struct DecRefPicMarkingRepeatInfo
875     {
DecRefPicMarkingRepeatInfoDecRefPicMarkingRepeatInfo876         DecRefPicMarkingRepeatInfo()
877             : presentFlag(false)
878             , original_idr_flag(0)
879             , original_frame_num(0)
880             , original_field_pic_flag(0)
881             , original_bottom_field_flag(0)
882             , dec_ref_pic_marking()
883         {
884         }
885 
886         bool                 presentFlag;
887         mfxU8                original_idr_flag;
888         mfxU16               original_frame_num;
889         mfxU8                original_field_pic_flag;
890         mfxU8                original_bottom_field_flag;
891         DecRefPicMarkingInfo dec_ref_pic_marking;
892     };
893     struct SliceStructInfo
894     {
895         mfxU32 startMB;
896         mfxU32 numMB;
897         mfxF32 weight;
898         mfxU32 cost;
899     };
900 
901     struct BRCFrameParams : mfxBRCFrameParam
902     {
903         mfxU16 picStruct;
904         mfxU32 OptimalFrameSizeInBytes;
905         mfxU32 optimalBufferFullness;
906     };
907 
908     class DdiTask : public Reconstruct
909     {
910     public:
DdiTask()911         DdiTask()
912             : Reconstruct()
913             , m_pushed(0)
914             , m_type(0, 0)
915             , m_QPdelta(0)
916             , m_bQPDelta(false)
917             , m_QPmodulation(0)
918             , m_currGopRefDist(0)
919             , m_dpb()
920             , m_internalListCtrlPresent(false)
921             , m_internalListCtrlHasPriority(true)
922             , m_internalListCtrlRefModLTR(false)
923             , m_keyReference(false)
924             , m_initCpbRemoval(0)
925             , m_initCpbRemovalOffset(0)
926             , m_cpbRemoval(0, 0)
927             , m_dpbOutputDelay(0)
928             , m_encOrder(mfxU32(-1))
929             , m_encOrderIdr(0)
930             , m_encOrderI(0)
931 
932             , m_viewIdx(0)
933             , m_idx(NO_INDEX)
934             , m_idxBs(NO_INDEX, NO_INDEX)
935             , m_idxBsOffset(0)
936             , m_idxRecon(NO_INDEX)
937             , m_idxInterLayerRecon(0)
938             , m_idxReconOffset(0)
939             , m_idrPicId(mfxU16(-1))
940             , m_subMbPartitionAllowed(0, 0)
941             , m_cqpValue(0, 0)
942             , m_insertAud(0, 0)
943             , m_insertSps(0, 0)
944             , m_insertPps(0, 0)
945             , m_AUStartsFromSlice(0, 0)
946             , m_nalRefIdc(0, 0)
947             , m_statusReportNumber(0, 0)
948 
949             , m_pid(0)
950             , m_fillerSize(0, 0)
951             , m_addRepackSize(0, 0)
952             , m_maxIFrameSize(0)
953             , m_maxPBFrameSize(0)
954             , m_numMbPerSlice(0)
955             , m_numSlice(0, 0)
956             , m_numRoi(0)
957 #if MFX_VERSION > 1021
958             , m_roiMode(MFX_ROI_MODE_PRIORITY)
959 #endif // #if MFX_VERSION > 1021
960             , m_numDirtyRect(0)
961             , m_numMovingRect(0)
962             , m_did(0)
963             , m_qid(0)
964             , m_storeRefBasePicFlag(0)
965 
966             , m_bs(0)
967             , m_bsDataLength(0, 0)
968             , m_numLeadingFF(0, 0)
969             , m_qpY(0, 0)
970             , m_mad(0, 0)
971             , m_minFrameSize (0)
972             , m_notProtected(false)
973             , m_nextLayerTask(0)
974             , m_repack(0)
975             , m_fractionalQP(0)
976 #ifdef ENABLE_APQ_LQ
977             , m_ALQOffset(0)
978 #endif
979             , m_midRaw(MID_INVALID)
980             , m_midRec(MID_INVALID)
981             , m_midBit(mfxMemId(MID_INVALID))
982 #if defined(MFX_ENABLE_MCTF_IN_AVC)
983             , m_midMCTF(mfxMemId(MID_INVALID))
984             , m_idxMCTF(NO_INDEX)
985             , m_cmMCTF(0)
986 #endif
987             , m_cmRaw(0)
988             , m_cmRawLa(0)
989             , m_cmMb(0)
990             , m_cmMbSys(0)
991             , m_cmRefMb(0)
992             , m_cmCurbe(0)
993             , m_cmRefs(0)
994             , m_cmRefsLa(0)
995             , m_event(0)
996             , m_vmeData(0)
997             , m_fwdRef(0)
998             , m_bwdRef(0)
999             , m_fieldPicFlag(0)
1000             , m_singleFieldMode(false)
1001             , m_fieldCounter(0)
1002             , m_timeStamp(0)
1003             , m_decodeTimeStamp(0)
1004             , m_minQP(0)
1005             , m_maxQP(0)
1006             , m_resetBRC(false)
1007 
1008             , m_idxMBQP(NO_INDEX)
1009             , m_midMBQP(MID_INVALID)
1010             , m_isMBQP(false)
1011             , m_isUseRawRef(false)
1012             , m_isSkipped (false)
1013             , m_toRecode (false)
1014             , m_isMBControl(false)
1015             , m_midMBControl(MID_INVALID)
1016             , m_idxMBControl(NO_INDEX)
1017 
1018             , m_cmRawForHist(0)
1019             , m_cmHist(0)
1020             , m_cmHistSys(0)
1021             , m_isENCPAK(false)
1022             , m_startTime(0)
1023 #ifdef MFX_ENABLE_MFE
1024             , m_beginTime(0)
1025             , m_endTime(0)
1026             , m_flushMfe(0)
1027             , m_mfeTimeToWait(0)
1028             , m_userTimeout(false)
1029 #endif
1030             , m_hwType(MFX_HW_UNKNOWN)
1031             , m_TCBRCTargetFrameSize(0)
1032             , m_SceneChange(0)
1033 #if defined(MFX_ENABLE_MCTF_IN_AVC)
1034             , m_doMCTFIntraFiltering(0)
1035 #endif
1036             , m_LowDelayPyramidLayer(0)
1037             , m_frameLtrOff(1)
1038             , m_frameLtrReassign(0)
1039             , m_LtrOrder(-1)
1040             , m_LtrQp(0)
1041             , m_RefOrder(-1)
1042             , m_RefQp(0)
1043             , m_bFrameReady(false)
1044             , m_idxScd(0)
1045             , m_wsSubSamplingEv(0)
1046             , m_wsSubSamplingTask(0)
1047             , m_wsGpuImage(0)
1048             , m_wsIdxGpuImage(0)
1049             , m_Yscd(0)
1050         {
1051             Zero(m_ctrl);
1052             Zero(m_internalListCtrl);
1053             Zero(m_handleRaw);
1054 #if defined(MFX_ENABLE_MCTF_IN_AVC)
1055             Zero(m_handleMCTF);
1056 #endif
1057             Zero(m_fid);
1058             Zero(m_pwt);
1059             Zero(m_brcFrameParams);
1060             Zero(m_brcFrameCtrl);
1061             m_FrameName[0] = 0;
1062 #ifndef MFX_AVC_ENCODING_UNIT_DISABLE
1063             m_collectUnitsInfo = false;
1064             m_headersCache[0].reserve(10);
1065             m_headersCache[1].reserve(10);
1066 #endif
1067         }
1068 
1069         bool operator == (const DdiTask& task)
1070         {
1071             if(&task == this) return true;
1072             return false;
1073         }
1074 
GetFrameType()1075         mfxU8 GetFrameType() const
1076         {
1077             return m_type[GetFirstField()];
1078         }
1079 
1080         // 0 - no skip, 1 - normal, 2 - pavp
SkipFlag()1081         mfxU8 SkipFlag() const
1082         {
1083             if (    m_ctrl.SkipFrame == 0
1084                 || (m_type.top & MFX_FRAMETYPE_I)
1085                 || (m_type.bot & MFX_FRAMETYPE_I))
1086                 return 0;
1087             return (mfxU8)m_ctrl.SkipFrame;
1088         }
1089 
1090         // Checking timeout for TDR hang detection
CheckForTDRHang(mfxU32 curTime,mfxU32 timeout)1091         bool CheckForTDRHang(mfxU32 curTime, mfxU32 timeout) const
1092         {
1093             MFX_TRACE_D(curTime);
1094             MFX_TRACE_D(m_startTime);
1095             MFX_TRACE_D(timeout);
1096 
1097             if (m_startTime && timeout && (curTime - m_startTime) > timeout)
1098             {
1099                 MFX_TRACE_S("Possible TDR hang:");
1100                 MFX_TRACE_D(((curTime - m_startTime) > timeout));
1101                 return true;
1102             }
1103 
1104             return false;
1105         }
isSEIHRDParam(mfxExtCodingOption const & extOpt,mfxExtCodingOption2 const & extOpt2)1106         inline bool isSEIHRDParam(mfxExtCodingOption const & extOpt, mfxExtCodingOption2 const & extOpt2)
1107         {
1108             return (((GetFrameType() & MFX_FRAMETYPE_IDR) ||
1109                 ((GetFrameType() & MFX_FRAMETYPE_I) && (extOpt2.BufferingPeriodSEI == MFX_BPSEI_IFRAME))) &&
1110                 (IsOn(extOpt.VuiNalHrdParameters) || IsOn(extOpt.VuiVclHrdParameters)));
1111         }
1112 
InitBRCParams()1113         inline void InitBRCParams()
1114         {
1115             Zero(m_brcFrameParams);
1116             Zero(m_brcFrameCtrl);
1117 
1118             m_brcFrameParams.FrameType = m_type[m_fid[0]];
1119             m_brcFrameParams.DisplayOrder = m_frameOrder;
1120             m_brcFrameParams.EncodedOrder = m_encOrder;
1121             m_brcFrameParams.PyramidLayer = (mfxU16)m_loc.level;
1122             m_brcFrameParams.LongTerm = (m_longTermFrameIdx != NO_INDEX_U8) ? 1 : 0;
1123             m_brcFrameParams.SceneChange = (mfxU16)m_SceneChange;
1124             if (!m_brcFrameParams.PyramidLayer && (m_type[m_fid[0]] & MFX_FRAMETYPE_P) && m_LowDelayPyramidLayer)
1125                 m_brcFrameParams.PyramidLayer = (mfxU16)m_LowDelayPyramidLayer;
1126             m_brcFrameParams.picStruct = GetPicStructForEncode();
1127         }
1128 
1129         mfxEncodeCtrl   m_ctrl;
1130         DdiTask *       m_pushed;         // task which was pushed to queue when this task was chosen for encoding
1131         Pair<mfxU8>     m_type;           // encoding type (one for each field)
1132         mfxI16          m_QPdelta;
1133         bool            m_bQPDelta;
1134         mfxU16          m_QPmodulation;
1135         mfxU32          m_currGopRefDist;
1136 
1137         // all info about references
1138         // everything is in pair because task is a per-frame object
1139         Pair<ArrayDpbFrame>   m_dpb;
1140         ArrayDpbFrame         m_dpbPostEncoding; // dpb after encoding a frame (or 2 fields)
1141         Pair<ArrayU8x33>      m_list0;
1142         Pair<ArrayU8x33>      m_list1;
1143         Pair<ArrayRefListMod> m_refPicList0Mod;
1144         Pair<ArrayRefListMod> m_refPicList1Mod;
1145         Pair<mfxU32>          m_initSizeList0;
1146         Pair<mfxU32>          m_initSizeList1;
1147 
1148         // currently used for dpb control when svc temporal layers enabled
1149         mfxExtAVCRefListCtrl  m_internalListCtrl;
1150         bool                  m_internalListCtrlPresent;
1151         bool                  m_internalListCtrlHasPriority;
1152         bool                  m_internalListCtrlRefModLTR;
1153         bool                  m_keyReference; // frame should be stored in DPB as long as possible
1154 
1155         mfxU32  m_initCpbRemoval;       // initial_cpb_removal_delay
1156         mfxU32  m_initCpbRemovalOffset; // initial_cpb_removal_delay_offset
1157         PairU32 m_cpbRemoval;           // one for each field
1158         mfxU32  m_dpbOutputDelay;       // one for entire frame
1159         mfxU32  m_encOrder;
1160         mfxU32  m_encOrderIdr;
1161         mfxU32  m_encOrderI;
1162 
1163         Pair<DecRefPicMarkingRepeatInfo> m_decRefPicMrkRep; // for sei_message() which repeat dec_ref_pic_marking() of previous frame
1164         Pair<DecRefPicMarkingInfo>       m_decRefPicMrk;    // dec_ref_pic_marking() for current frame
1165 
1166         mfxU32  m_viewIdx;
1167         mfxU32  m_idx;                  // index in chain of raw surfaces (set only when sysmem at input)
1168         PairU32 m_idxBs;                // index of bitstream surfaces, 2 - for interlaced frame (snb only)
1169         mfxU32  m_idxBsOffset;          // offset for multi-view coding
1170         mfxU32  m_idxRecon;             // index of reconstructed surface
1171         mfxU32  m_idxInterLayerRecon;   // index of reconstructed surface for inter-layer prediction
1172         mfxU32  m_idxReconOffset;       // offset for multi-view coding
1173         mfxU16  m_idrPicId;
1174         PairU8  m_subMbPartitionAllowed;
1175         PairU8  m_cqpValue;
1176         PairU8  m_insertAud;
1177         PairU8  m_insertSps;
1178         PairU8  m_insertPps;
1179         PairU8  m_AUStartsFromSlice;
1180         PairU8  m_nalRefIdc;
1181         PairU32 m_statusReportNumber;
1182         mfxU32  m_pid;                  // priority_id
1183         PairU32 m_fillerSize;
1184 // MVC BD {
1185         PairU32 m_addRepackSize; // for SNB/IVB: size of padding to compensate re-pack of AVC headers to MVC headers
1186 // MVC BD }
1187         mfxU32  m_maxIFrameSize;
1188         mfxU32  m_maxPBFrameSize;
1189 
1190         mfxU16  m_numMbPerSlice;
1191         PairU16 m_numSlice;
1192 
1193         ArrayRoi        m_roi;
1194         mfxU16          m_numRoi;
1195 #if MFX_VERSION > 1021
1196         mfxU16          m_roiMode;
1197 #endif // MFX_VERSION > 1021
1198         ArrayRect       m_dirtyRect;
1199         mfxU16          m_numDirtyRect;
1200         ArrayMovingRect m_movingRect;
1201         mfxU16          m_numMovingRect;
1202 
1203         mfxU32  m_did;                  // dependency_id
1204         mfxU32  m_qid;                  // quality_id
1205         mfxU32  m_storeRefBasePicFlag;  // for svc key picture
1206 
1207         mfxBitstream *    m_bs;           // output bitstream
1208         PairU32           m_bsDataLength; // bitstream size reported by driver (0 - progr/top, 1 - bottom)
1209         PairU32           m_numLeadingFF; // driver may insert 0xff in the beginning of coded frame
1210         PairU8            m_qpY;          // QpY reported by driver
1211         PairU32           m_mad;          // MAD
1212         BiFrameLocation   m_loc;
1213         IntraRefreshState m_IRState;
1214         mfxU32            m_minFrameSize;
1215 
1216         char   m_FrameName[32];
1217 
1218         bool m_notProtected;             // Driver returns not protected data
1219         DdiTask const * m_nextLayerTask; // set to 0 if no nextLayerResolutionChange
1220         mfxU32  m_repack;
1221         mfxI32  m_fractionalQP; //if m_fractionalQP > 0 set it value in QM matrices
1222 #ifdef ENABLE_APQ_LQ
1223         mfxI32  m_ALQOffset;     // MBQP Offset for Lambda QP adjustment
1224 #endif
1225 
1226         mfxMemId        m_midRaw;       // self-allocated input surface (when app gives input frames in system memory)
1227         mfxMemId        m_midRec;       // reconstruction
1228         Pair<mfxMemId>  m_midBit;       // output bitstream
1229         mfxHDLPair      m_handleRaw;    // native handle to raw surface (self-allocated or given by app)
1230 #if defined(MFX_ENABLE_MCTF_IN_AVC)
1231         mfxMemId        m_midMCTF;
1232         mfxHDLPair      m_handleMCTF;   // Handle to MCTF denoised surface
1233         mfxU32          m_idxMCTF;
1234         CmSurface2D *   m_cmMCTF;
1235 #endif
1236         CmSurface2D *   m_cmRaw;        // CM surface made of m_handleRaw
1237         CmSurface2D *   m_cmRawLa;      // down-sized input surface for Lookahead
1238         CmBufferUP *    m_cmMb;         // macroblock data, VME kernel output
1239         void *          m_cmMbSys;      // pointer to associated system memory buffer
1240         CmBufferUP *    m_cmRefMb;      // macroblock data, VME kernel output for backward ref
1241         CmBuffer *      m_cmCurbe;      // control structure for ME & HME kernels
1242         SurfaceIndex *  m_cmRefs;       // VmeSurfaceG75 for ME kernel
1243         SurfaceIndex *  m_cmRefsLa;     // VmeSurfaceG75 for 2X kernel
1244         CmEvent *       m_event;
1245         VmeData *       m_vmeData;
1246         DdiTask const * m_fwdRef;
1247         DdiTask const * m_bwdRef;
1248 
1249         mfxU8   m_fieldPicFlag;    // true for frames with interlaced content
1250         bool    m_singleFieldMode; // true for FEI single-field processing mode
1251 
1252         // m_fid is a remapper of field parity to field order and vise versa.
1253         // i.e. parity = m_fid[fieldId] and fieldId = m_fid[parity] (fieldId == m_fid[m_fid[fieldId]]).
1254         // It is useful to switch between these two representation, because DdiTask stores all information
1255         // according to parity, but all of the per-field extension buffers are attached according to field order
1256         // (the only exception is mfxExtAVCRefLists).
1257         mfxU8   m_fid[2];               // progressive fid=[0,0]; tff fid=[0,1]; bff fid=[1,0]
1258         mfxU8   m_fieldCounter;
1259         mfxU64  m_timeStamp;
1260         mfxI64  m_decodeTimeStamp;
1261 
1262         mfxU8   m_minQP;
1263         mfxU8   m_maxQP;
1264         std::vector<mfxU8>   m_disableDeblockingIdc[2];
1265         std::vector<mfxI8>   m_sliceAlphaC0OffsetDiv2[2];
1266         std::vector<mfxI8>   m_sliceBetaOffsetDiv2[2];
1267 
1268         bool m_resetBRC;
1269 
1270         mfxU32   m_idxMBQP;
1271         mfxMemId m_midMBQP;
1272         bool     m_isMBQP;
1273         bool     m_isUseRawRef;
1274         bool     m_isSkipped;
1275         bool     m_toRecode;
1276 
1277         bool     m_isMBControl;
1278         mfxMemId m_midMBControl;
1279         mfxU32   m_idxMBControl;
1280 
1281 
1282         CmSurface2D *         m_cmRawForHist;
1283         CmBufferUP *          m_cmHist;     // Histogram data, kernel output
1284         void *                m_cmHistSys;
1285         mfxExtPredWeightTable m_pwt[2];     // obtained from fade detection
1286 
1287         bool     m_isENCPAK;
1288 
1289         std::vector<void*> m_userData;
1290         std::vector<SliceStructInfo> m_SliceInfo;
1291 
1292         mfxU32 m_startTime;
1293 #ifdef MFX_ENABLE_MFE
1294         vm_tick m_beginTime;//where we start counting
1295         vm_tick m_endTime;//where we get bitstream
1296         mfxU16  m_flushMfe;//flush MFE frame buffer
1297         mfxU32  m_mfeTimeToWait;//set by user or used equal to frame rate latency by default
1298         bool m_userTimeout;
1299 #endif
1300         eMFXHWType m_hwType;  // keep HW type information
1301 
1302 
1303 #ifndef MFX_AVC_ENCODING_UNIT_DISABLE
1304         bool m_collectUnitsInfo;
1305         mutable std::vector<mfxEncodedUnitInfo> m_headersCache[2]; //Headers for every field
1306 #endif
1307         mfxU32 m_TCBRCTargetFrameSize;
1308         mfxU32 m_SceneChange;
1309 #if defined(MFX_ENABLE_MCTF_IN_AVC)
1310         mfxU32 m_doMCTFIntraFiltering;
1311 #endif
1312         mfxU32 m_LowDelayPyramidLayer;
1313         mfxU32 m_frameLtrOff;
1314         mfxU32 m_frameLtrReassign;
1315         mfxI32 m_LtrOrder;
1316         mfxI32 m_LtrQp;
1317         mfxI32 m_RefOrder;
1318         mfxI32 m_RefQp;
1319 
1320         bool           m_bFrameReady;
1321         mfxU32         m_idxScd;
1322         CmEvent       *m_wsSubSamplingEv;
1323         CmTask        *m_wsSubSamplingTask;
1324         CmSurface2DUP *m_wsGpuImage;
1325         SurfaceIndex  *m_wsIdxGpuImage;
1326         mfxU8         *m_Yscd;
1327 
1328         BRCFrameParams  m_brcFrameParams;
1329         mfxBRCFrameCtrl m_brcFrameCtrl;
1330     };
1331 
1332     typedef std::list<DdiTask>::iterator DdiTaskIter;
1333     typedef std::list<DdiTask>::const_iterator DdiTaskCiter;
1334 
1335     class TaskManager
1336     {
1337     public:
1338         TaskManager();
1339 
1340         ~TaskManager();
1341 
1342         void Init(
1343             VideoCORE *           core,
1344             MfxVideoParam const & video,
1345             mfxU32                viewIdx);
1346 
1347         void Reset(
1348             MfxVideoParam const & video); // w/o re-allocation
1349 
1350         void Close();
1351 
1352         mfxStatus AssignTask(
1353             mfxEncodeCtrl *    ctrl,
1354             mfxFrameSurface1 * surface,
1355             mfxBitstream *     bs,
1356             DdiTask *&         newTask,
1357             mfxU16             requiredFrameType = MFX_FRAMETYPE_UNKNOWN); //use provided frame type istead of frame type generator
1358 
1359         void ConfirmTask(
1360             DdiTask & task);
1361 
1362         void CompleteTask(
1363             DdiTask & task);
1364 
GetEncodeStat()1365         mfxEncodeStat const & GetEncodeStat() const { return m_stat; }
1366 
1367         mfxU32 CountRunningTasks();
1368 
1369     protected:
1370         void BuildRefPicLists(
1371             DdiTask & task,
1372             mfxU32    field); // 0 - top/progressive, 1 - bottom
1373 
1374         void ModifyRefPicLists(
1375             DdiTask & task,
1376             mfxU32    fieldId) const;
1377 
1378         void UpdateDpb(
1379             DdiTask       & task,
1380             mfxU32          fieldId,
1381             ArrayDpbFrame & dpbPostEncoding);
1382 
1383         void UpdateRefFrames(
1384             ArrayDpbFrame const & dpb,
1385             DdiTask const &       task,
1386             mfxU32                field);
1387 
1388         void SwitchLastB2P();
1389 
1390         DdiTask* PushNewTask(
1391             mfxFrameSurface1 * surface,
1392             mfxEncodeCtrl *    ctrl,
1393             PairU8             type,
1394             mfxU32             frameOrder);
1395 
1396         mfxU32 CountL1Refs(
1397             Reconstruct const & bframe) const;
1398 
1399         mfxU32 FindFrameWithMinFrameNumWrap() const;
1400 
1401         void ProcessFields(
1402             mfxU32                field,
1403             ArrayDpbFrame const & dpb,
1404             ArrayU8x33 const &    picListFrm,
1405             ArrayU8x33 &          picListFld) const;
1406 
1407         bool IsSubmitted(
1408             DdiTask const & task) const;
1409 
1410         DdiTask * SelectNextBFrameFromTail();
1411         DdiTask * FindFrameToEncode();
1412 
1413     private:
1414         TaskManager(TaskManager const &);
1415         TaskManager & operator =(TaskManager const &);
1416 
1417         VideoCORE *   m_core;
1418         UMC::Mutex    m_mutex;
1419         MfxVideoParam m_video;
1420 
1421         std::vector<DdiTask>     m_tasks;
1422         std::vector<Surface>     m_raws;
1423         std::vector<Surface>     m_bitstreams;
1424         std::vector<Reconstruct> m_recons;
1425 
1426         mfxEncodeStat              m_stat;
1427         FrameTypeGenerator         m_frameTypeGen;
1428         ArrayDpbFrame              m_dpb;
1429         DecRefPicMarkingRepeatInfo m_decRefPicMrkRep;
1430 
1431         mfxU16    m_frameNum;
1432         mfxU16    m_frameNumMax;
1433         mfxU32    m_frameOrder;
1434         mfxU32    m_frameOrderIdr;              // most recent idr frame in encoding order
1435         mfxU32    m_frameOrderI;                // most recent i frame in encoding order
1436         mfxU16    m_idrPicId;
1437         mfxU32    m_viewIdx;
1438         mfxU32    m_cpbRemoval;                 // similar to frame_num but increments every frame (reference or not)
1439         mfxU32    m_cpbRemovalBufferingPeriod;  // cpbRemoval of picture with previous buffering period
1440         mfxU32    m_numReorderFrames;
1441         DdiTask * m_pushed;
1442     };
1443 
1444     template <size_t N>
1445     class Regression
1446     {
1447     public:
1448         static const mfxU32 MAX_WINDOW = N;
1449 
Regression()1450         Regression() {
1451             Zero(x);
1452             Zero(y);
1453         }
Reset(mfxU32 size,mfxF64 initX,mfxF64 initY)1454         void Reset(mfxU32 size, mfxF64 initX, mfxF64 initY) {
1455             windowSize = size;
1456             normX = initX;
1457             std::fill_n(x, windowSize, initX);
1458             std::fill_n(y, windowSize, initY);
1459             sumxx = initX * initX * windowSize;
1460             sumxy = initX * initY * windowSize;
1461         }
Add(mfxF64 newx,mfxF64 newy)1462         void Add(mfxF64 newx, mfxF64 newy) {
1463             newy = newy / newx * normX;
1464             newx = normX;
1465             sumxy += newx * newy - x[0] * y[0];
1466             sumxx += newx * newx - x[0] * x[0];
1467             std::copy(x + 1, x + windowSize, x);
1468             std::copy(y + 1, y + windowSize, y);
1469             x[windowSize - 1] = newx;
1470             y[windowSize - 1] = newy;
1471         }
GetCoeff()1472         mfxF64 GetCoeff() const {
1473             return sumxy / sumxx;
1474         }
1475 
1476     //protected:
1477     public: // temporary for debugging and dumping
1478         mfxF64 x[N];
1479         mfxF64 y[N];
1480         mfxU32 windowSize;
1481         mfxF64 normX;
1482         mfxF64 sumxy;
1483         mfxF64 sumxx;
1484     };
1485 
1486     class BrcIface
1487     {
1488     public:
~BrcIface()1489         virtual ~BrcIface() {};
1490         virtual mfxStatus Init(MfxVideoParam  & video) = 0;
1491         virtual mfxStatus Reset(MfxVideoParam  & video) = 0;
1492         virtual void Close() = 0;
1493         virtual void PreEnc(const BRCFrameParams& par, std::vector<VmeData *> const & vmeData) = 0;
1494         virtual void GetQp(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl) = 0;
1495         virtual void GetQpForRecode(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl) = 0;
1496         virtual mfxF32 GetFractionalQp(const BRCFrameParams& par) = 0;
1497         virtual void SetQp(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl) = 0;
1498         virtual mfxU32 Report(const BRCFrameParams& par, mfxU32 userDataLength, mfxU32 maxFrameSize, mfxBRCFrameCtrl &frameCtrl) = 0;
1499         virtual mfxU32 GetMinFrameSize() = 0;
1500 
SetFrameVMEData(const mfxExtLAFrameStatistics *,mfxU32,mfxU32)1501         virtual mfxStatus SetFrameVMEData(const mfxExtLAFrameStatistics*, mfxU32 , mfxU32 ) {return MFX_ERR_NONE;}
1502     };
1503 
1504     BrcIface * CreateBrc(MfxVideoParam const & video, MFX_ENCODE_CAPS const & hwCaps);
1505 
1506     class Brc : public BrcIface
1507     {
1508     public:
1509         Brc(BrcIface * impl = 0)
1510         {
1511             m_impl.reset(impl);
1512         }
SetImpl(BrcIface * impl)1513         void SetImpl(BrcIface * impl)
1514         {
1515             m_impl.reset(impl);
1516         }
~Brc()1517         ~Brc()
1518         {
1519         }
Init(MfxVideoParam & video)1520         mfxStatus Init(MfxVideoParam  & video)
1521         {
1522             return m_impl->Init(video);
1523         }
Reset(MfxVideoParam & video)1524         mfxStatus Reset(MfxVideoParam  & video)
1525         {
1526             return m_impl->Reset(video);
1527         }
Close()1528         void Close()
1529         {
1530             m_impl->Close();
1531         }
PreEnc(const BRCFrameParams & par,std::vector<VmeData * > const & vmeData)1532         void PreEnc(const BRCFrameParams& par, std::vector<VmeData *> const & vmeData)
1533         {
1534             m_impl->PreEnc(par, vmeData);
1535         }
GetQp(const BRCFrameParams & par,mfxBRCFrameCtrl & frameCtrl)1536         void GetQp(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl)
1537         {
1538             m_impl->GetQp(par, frameCtrl);
1539         }
GetQpForRecode(const BRCFrameParams & par,mfxBRCFrameCtrl & frameCtrl)1540         void GetQpForRecode(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl)
1541         {
1542             m_impl->GetQpForRecode(par, frameCtrl);
1543         }
GetFractionalQp(const BRCFrameParams & par)1544         mfxF32 GetFractionalQp(const BRCFrameParams& par)
1545         {
1546             return m_impl->GetFractionalQp(par);
1547         }
SetQp(const BRCFrameParams & par,mfxBRCFrameCtrl & frameCtrl)1548         void SetQp(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl)
1549         {
1550             m_impl->SetQp(par, frameCtrl);
1551         }
Report(const BRCFrameParams & par,mfxU32 userDataLength,mfxU32 maxFrameSize,mfxBRCFrameCtrl & frameCtrl)1552         mfxU32 Report(const BRCFrameParams& par, mfxU32 userDataLength, mfxU32 maxFrameSize, mfxBRCFrameCtrl &frameCtrl)
1553         {
1554             return m_impl->Report(par, userDataLength, maxFrameSize, frameCtrl);
1555         }
GetMinFrameSize()1556         mfxU32 GetMinFrameSize()
1557         {
1558             return m_impl->GetMinFrameSize();
1559         }
SetFrameVMEData(const mfxExtLAFrameStatistics * pLAOutput,mfxU32 width,mfxU32 height)1560         mfxStatus SetFrameVMEData(const mfxExtLAFrameStatistics * pLAOutput, mfxU32 width, mfxU32 height)
1561         {
1562             return m_impl->SetFrameVMEData(pLAOutput,width,height);
1563         }
1564     private:
1565         std::unique_ptr<BrcIface> m_impl;
1566     };
1567 
1568     class UmcBrc : public BrcIface
1569     {
1570     public:
~UmcBrc()1571         ~UmcBrc() { Close(); }
1572 
1573         mfxStatus Init(MfxVideoParam  & video);
Reset(MfxVideoParam &)1574         mfxStatus Reset(MfxVideoParam  & ) { return MFX_ERR_NONE; };
1575         void Close();
1576 
1577         void GetQp(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl);
1578         void GetQpForRecode(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl);
1579 
1580         mfxF32 GetFractionalQp(const BRCFrameParams& par);
1581 
1582         void SetQp(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl);
1583 
1584         void PreEnc(const BRCFrameParams& par, std::vector<VmeData *> const & vmeData);
1585 
1586         mfxU32 Report(const BRCFrameParams& par, mfxU32 userDataLength, mfxU32 maxFrameSize, mfxBRCFrameCtrl &frameCtrl);
1587 
1588         mfxU32 GetMinFrameSize();
1589 
1590     private:
1591         UMC::H264BRC m_impl;
1592         mfxU32 m_lookAhead;
1593     };
1594 
1595     class Hrd
1596     {
1597     public:
1598         Hrd();
1599 
1600         void Setup(MfxVideoParam const & par);
1601 
1602         void Reset(MfxVideoParam const & par);
1603 
1604         void RemoveAccessUnit(
1605             mfxU32 size,
1606             mfxU32 interlace,
1607             mfxU32 bufferingPeriod);
1608 
1609         mfxU32 GetInitCpbRemovalDelay() const;
1610 
1611         mfxU32 GetInitCpbRemovalDelayOffset() const;
1612         mfxU32 GetMaxFrameSize(mfxU32 bufferingPeriod) const;
1613 
1614     private:
1615         mfxU32 m_bitrate;
1616         mfxU32 m_rcMethod;
1617         mfxU32 m_hrdIn90k;  // size of hrd buffer in 90kHz units
1618 
1619         double m_tick;      // clock tick
1620         double m_trn_cur;   // nominal removal time
1621         double m_taf_prv;   // final arrival time of prev unit
1622 
1623         bool m_bIsHrdRequired;
1624     };
1625 
1626     struct sLAThresholds
1627     {
1628         mfxU32 minFramesForClassicLA; // number of frames is needed for classic LA, if lookAhead < minFramesForClassicLA -> short LA
1629         mfxU32 minFramesForStat;      // number of frames at the start of stream which must be analyzed with fixed rate
1630         mfxU32 minCostCalcPeriod;     // minimum number of frames to calulate  cost. costCalcPeriod >= lookAhead,  costCalcPeriod < rateCalcPeriod
1631         mfxF64 maxRateRatioLocal;     // maximum allowed ratio = realRate/initialRate, real rate is calculated per costCalcPeriod
1632         mfxF64 minRateRatioLocal;     // minimum allowed ratio = realRate/initialRate, real rate is calculated per costCalcPeriod
1633         mfxF64 maxAvgRateRatio;       // maximum allowed ratio = avgRate/initialRate, avg rate is calculated per rateCalcPeriod
1634         mfxF64 minAvgRateRatio;       // minimum allowed ratio = avgRate/initialRate, avg rate is calculated per rateCalcPeriod
1635     };
1636 
1637     class LookAheadBrc2 : public BrcIface
1638     {
1639     public:
~LookAheadBrc2()1640         ~LookAheadBrc2() { Close(); }
1641 
1642         mfxStatus Init (MfxVideoParam  & video);
Reset(MfxVideoParam &)1643         mfxStatus Reset(MfxVideoParam  & ) { return MFX_ERR_NONE; };
1644 
1645         void Close();
1646 
1647         void GetQp(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl);
1648         void GetQpForRecode(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl);
GetFractionalQp(const BRCFrameParams &)1649         mfxF32 GetFractionalQp(const BRCFrameParams& ) { assert(0); return 26.0f; }
1650 
1651 
1652         void PreEnc(const BRCFrameParams& par, std::vector<VmeData *> const & vmeData);
1653 
1654         mfxU32 Report(const BRCFrameParams& par, mfxU32 userDataLength, mfxU32 maxFrameSize, mfxBRCFrameCtrl &frameCtrl);
1655 
GetMinFrameSize()1656         mfxU32 GetMinFrameSize() { return 0; }
1657         void  SetQp(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl);
1658 
1659     public:
1660         struct LaFrameData
1661         {
1662             mfxU32  encOrder;
1663             mfxI32  poc;
1664             mfxI32  deltaQp;
1665             mfxF64  estRate[52];
1666             mfxF64  estRateTotal[52];
1667             mfxU32  interCost;
1668             mfxU32  intraCost;
1669             mfxU32  propCost;
1670             mfxU32  bframe;
1671         };
1672 
1673     protected:
1674         sLAThresholds m_thresholds;
1675         mfxU32  m_lookAhead;
1676         mfxU32  m_lookAheadDep;
1677         mfxU16  m_LaScaleFactor;
1678         mfxU32  m_strength;
1679         mfxU32  m_totNumMb;
1680         mfxF64  m_initTargetRate;
1681         mfxF64  m_currRate;
1682         mfxU32  m_framesBehind;
1683         mfxF64  m_bitsBehind;
1684         mfxI32  m_curBaseQp;
1685         mfxI32  m_curQp;
1686         mfxU16  m_qpUpdateRange;
1687         //mfxF32  m_coef;
1688         mfxF64  m_fr;
1689         mfxU16  m_AsyncDepth;
1690         mfxU16  m_first;
1691         mfxU16  m_skipped;
1692         mfxU8  m_QPMin[3]; // for I, P and B
1693         mfxU8  m_QPMax[3]; // for I, P and B
1694         mfxU32 m_MaxframeSize[3];
1695         mfxU32 m_maxFrameSizeForRec;
1696         mfxU32 m_rateCalcPeriod;
1697         mfxU32 m_costCalcPeriod;
1698 
1699         AVGBitrate* m_AvgBitrate; //sliding window
1700         std::unique_ptr<Hrd>  m_hrd;
1701 
1702         std::vector<LaFrameData>    m_laData;
1703         std::vector<LaFrameData>    m_laDataStat;
1704         Regression<20>              m_rateCoeffHistory[52];
1705 
1706         void ClearStat(mfxU32 frameOrder);
1707         void SaveStat(mfxU32 frameOrder);
1708     };
1709 
1710     class VMEBrc : public BrcIface
1711     {
1712     public:
~VMEBrc()1713         ~VMEBrc() { Close(); }
1714 
1715         mfxStatus Init(MfxVideoParam  & video);
Reset(MfxVideoParam &)1716         mfxStatus Reset(MfxVideoParam  & ) { return MFX_ERR_NONE; }
1717         void Close();
1718 
1719         void GetQp(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl);
1720         void GetQpForRecode(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl);
1721 
GetFractionalQp(const BRCFrameParams &)1722         mfxF32 GetFractionalQp(const BRCFrameParams& ) { assert(0); return 26.0f; }
1723 
SetQp(const BRCFrameParams &,mfxBRCFrameCtrl &)1724         void SetQp(const BRCFrameParams& , mfxBRCFrameCtrl & ) { assert(0); }
1725 
1726         void PreEnc(const BRCFrameParams& par, std::vector<VmeData *> const & vmeData);
1727 
1728         mfxU32 Report(const BRCFrameParams& par, mfxU32 userDataLength, mfxU32 maxFrameSize, mfxBRCFrameCtrl &frameCtrl);
1729 
GetMinFrameSize()1730         mfxU32 GetMinFrameSize() { return 0; }
1731 
1732         mfxStatus SetFrameVMEData(const mfxExtLAFrameStatistics *, mfxU32 widthMB, mfxU32 heightMB );
1733 
1734 
1735     public:
1736         struct LaFrameData
1737         {
1738             mfxU32  encOrder;
1739             mfxU32  dispOrder;
1740             mfxI32  poc;
1741             mfxI32  deltaQp;
1742             mfxF64  estRate[52];
1743             mfxF64  estRateTotal[52];
1744             mfxU32  interCost;
1745             mfxU32  intraCost;
1746             mfxU32  propCost;
1747             mfxU32  bframe;
1748             bool    bNotUsed;
1749         };
1750 
1751     protected:
1752         mfxU32  m_lookAhead;
1753         mfxU16  m_LaScaleFactor;
1754         mfxU32  m_strength;
1755         mfxU32  m_totNumMb;
1756         mfxF64  m_initTargetRate;
1757         mfxF64  m_targetRateMin;
1758         mfxF64  m_targetRateMax;
1759         mfxU32  m_framesBehind;
1760         mfxF64  m_bitsBehind;
1761         mfxI32  m_curBaseQp;
1762         mfxI32  m_curQp;
1763         mfxU16  m_qpUpdateRange;
1764         mfxF64  m_fr;
1765         mfxU16  m_skipped;
1766         mfxU8   m_QPMin[3]; // for I, P and B
1767         mfxU8   m_QPMax[3]; // for I, P and B
1768         mfxU32  m_maxFrameSize;
1769 
1770 
1771         AVGBitrate* m_AvgBitrate;
1772 
1773         std::list <LaFrameData>     m_laData;
1774         Regression<20>              m_rateCoeffHistory[52];
1775     };
1776 
1777     class LookAheadCrfBrc : public BrcIface
1778     {
1779     public:
~LookAheadCrfBrc()1780         ~LookAheadCrfBrc() { Close(); }
1781 
1782         mfxStatus Init(MfxVideoParam  & video);
Reset(MfxVideoParam &)1783         mfxStatus Reset(MfxVideoParam  & ) {return MFX_ERR_NONE;};
1784 
Close()1785         void Close() {}
1786 
1787         void GetQp(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl);
1788         void GetQpForRecode(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl);
GetFractionalQp(const BRCFrameParams &)1789         mfxF32 GetFractionalQp(const BRCFrameParams& /*par*/) { assert(0); return 26.0f; }
1790 
SetQp(const BRCFrameParams &,mfxBRCFrameCtrl &)1791         void SetQp(const BRCFrameParams& /*par*/, mfxBRCFrameCtrl & /*frameCtrl*/) { assert(0); }
1792 
1793         void PreEnc(const BRCFrameParams& par, std::vector<VmeData *> const & vmeData);
1794 
1795         mfxU32 Report(const BRCFrameParams& par, mfxU32 userDataLength, mfxU32 maxFrameSize, mfxBRCFrameCtrl &frameCtrl);
1796 
GetMinFrameSize()1797         mfxU32 GetMinFrameSize() { return 0; }
1798 
1799     protected:
1800         mfxU32  m_lookAhead;
1801         mfxI32  m_crfQuality;
1802         mfxI32  m_curQp;
1803         mfxU32  m_totNumMb;
1804         mfxU32  m_intraCost;
1805         mfxU32  m_interCost;
1806         mfxU32  m_propCost;
1807         mfxU8   m_QPMin[3]; // for I, P and B
1808         mfxU8   m_QPMax[3]; // for I, P and B
1809     };
1810     class H264SWBRC : public BrcIface
1811     {
1812     public:
H264SWBRC()1813         H264SWBRC():
1814             m_minSize(0),
1815             m_pBRC(0)
1816         {
1817             memset(&m_BRCLocal,0, sizeof(m_BRCLocal));
1818         }
~H264SWBRC()1819         virtual ~H264SWBRC()
1820         {
1821             Close();
1822         }
1823 
1824 
Init(MfxVideoParam & video)1825         mfxStatus   Init(MfxVideoParam &video)
1826         {
1827             mfxStatus sts = MFX_ERR_NONE;
1828             mfxExtBRC * extBRC = GetExtBuffer(video);
1829 
1830 
1831             if (extBRC->pthis)
1832             {
1833                 m_pBRC = extBRC;
1834             }
1835             else
1836             {
1837                 sts = HEVCExtBRC::Create(m_BRCLocal);
1838                 m_pBRC = &m_BRCLocal;
1839             }
1840             sts = m_pBRC->Init(m_pBRC->pthis, &video);
1841             return sts;
1842         }
Close()1843         void  Close()
1844         {
1845             m_pBRC->Close(m_pBRC->pthis);
1846             HEVCExtBRC::Destroy(m_BRCLocal);
1847         }
Reset(MfxVideoParam & video)1848         mfxStatus  Reset(MfxVideoParam &video )
1849         {
1850             return m_pBRC->Reset(m_pBRC->pthis,&video);
1851         }
Report(const BRCFrameParams & par,mfxU32,mfxU32,mfxBRCFrameCtrl & frameCtrl)1852         mfxU32 Report(const BRCFrameParams& par, mfxU32 /*userDataLength*/, mfxU32 /*maxFrameSize*/, mfxBRCFrameCtrl &frameCtrl)
1853         {
1854             mfxBRCFrameStatus frame_sts = {};
1855             mfxBRCFrameParam frame_par = *((mfxBRCFrameParam*)&par);
1856 
1857             mfxStatus sts = m_pBRC->Update(m_pBRC->pthis,&frame_par, &frameCtrl, &frame_sts);
1858             MFX_CHECK(sts == MFX_ERR_NONE, (mfxU32)UMC::BRC_ERROR); // BRC_ERROR
1859 
1860             m_minSize = frame_sts.MinFrameSize;
1861 
1862             switch (frame_sts.BRCStatus)
1863             {
1864             case ::MFX_BRC_OK:
1865                 return  UMC::BRC_OK;
1866             case ::MFX_BRC_BIG_FRAME:
1867                 return UMC::BRC_ERR_BIG_FRAME;
1868             case ::MFX_BRC_SMALL_FRAME:
1869                 return UMC::BRC_ERR_SMALL_FRAME;
1870             case ::MFX_BRC_PANIC_BIG_FRAME:
1871                 return UMC::BRC_ERR_BIG_FRAME |  UMC::BRC_NOT_ENOUGH_BUFFER;
1872             case ::MFX_BRC_PANIC_SMALL_FRAME:
1873                 return UMC::BRC_ERR_SMALL_FRAME| UMC::BRC_NOT_ENOUGH_BUFFER;
1874             }
1875             return MFX_BRC_OK;
1876         }
GetQp(const BRCFrameParams & par,mfxBRCFrameCtrl & frameCtrl)1877         void GetQp(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl)
1878         {
1879             mfxBRCFrameParam frame_par = *((mfxBRCFrameParam*)&par);
1880             m_pBRC->GetFrameCtrl(m_pBRC->pthis,&frame_par, &frameCtrl);
1881             frameCtrl.QpY = (mfxU8)mfx::clamp(frameCtrl.QpY, 1, 51);
1882         }
GetQpForRecode(const BRCFrameParams & par,mfxBRCFrameCtrl & frameCtrl)1883         void GetQpForRecode(const BRCFrameParams& par, mfxBRCFrameCtrl &frameCtrl)
1884         {
1885             GetQp(par, frameCtrl);
1886         }
1887 
SetQp(const BRCFrameParams &,mfxBRCFrameCtrl &)1888         void   SetQp(const BRCFrameParams& /*par*/, mfxBRCFrameCtrl &/*frameCtrl*/)
1889         {
1890         }
GetMinFrameSize()1891         mfxU32 GetMinFrameSize()
1892         {
1893             return m_minSize;
1894 
1895         }
GetFractionalQp(const BRCFrameParams &)1896         mfxF32 GetFractionalQp(const BRCFrameParams& /*par*/) { assert(0); return 26.0f; }
1897 
PreEnc(const BRCFrameParams &,std::vector<VmeData * > const &)1898         virtual void        PreEnc(const BRCFrameParams& /*par*/, std::vector<VmeData *> const & /* vmeData */) {}
SetFrameVMEData(const mfxExtLAFrameStatistics *,mfxU32,mfxU32)1899         virtual mfxStatus SetFrameVMEData(const mfxExtLAFrameStatistics*, mfxU32 , mfxU32 )
1900         {
1901             return MFX_ERR_UNDEFINED_BEHAVIOR;
1902         }
IsVMEBRC()1903         virtual bool IsVMEBRC()  {return false;}
1904 
1905     private:
1906         mfxU32      m_minSize;
1907         mfxExtBRC * m_pBRC;
1908         mfxExtBRC   m_BRCLocal;
1909 
1910 };
1911 
1912 
1913 #if defined(MFX_ENABLE_ENCTOOLS)
1914 
IsNotDefined(mfxU16 param)1915 inline bool IsNotDefined(mfxU16 param)
1916 {
1917     return (param == MFX_CODINGOPTION_UNKNOWN);
1918 
1919 }
IsEncToolsOptOn(mfxExtEncToolsConfig & config)1920 inline bool IsEncToolsOptOn(mfxExtEncToolsConfig &config)
1921 {
1922     return
1923         (IsOn(config.AdaptiveI) ||
1924             IsOn(config.AdaptiveB) ||
1925             IsOn(config.AdaptiveRefP) ||
1926             IsOn(config.AdaptiveRefB) ||
1927             IsOn(config.SceneChange) ||
1928             IsOn(config.AdaptiveLTR) ||
1929             IsOn(config.AdaptivePyramidQuantP) ||
1930             IsOn(config.AdaptivePyramidQuantB) ||
1931             IsOn(config.AdaptiveQuantMatrices) ||
1932             IsOn(config.BRCBufferHints) ||
1933             IsOn(config.BRC));
1934 
1935 }
ResetEncToolsPar(mfxExtEncToolsConfig & config,mfxU16 value)1936 inline void ResetEncToolsPar(mfxExtEncToolsConfig &config, mfxU16 value)
1937 {
1938     config.AdaptiveI =
1939         config.AdaptiveB =
1940         config.AdaptiveRefP =
1941         config.AdaptiveRefB =
1942         config.SceneChange =
1943         config.AdaptiveLTR =
1944         config.AdaptivePyramidQuantP =
1945         config.AdaptivePyramidQuantB =
1946         config.AdaptiveQuantMatrices =
1947         config.BRCBufferHints =
1948         config.BRC = value;
1949 
1950 }
InitCtrl(mfxVideoParam const & par,mfxEncToolsCtrl * ctrl)1951 static mfxStatus InitCtrl(mfxVideoParam const & par, mfxEncToolsCtrl *ctrl)
1952 {
1953     MFX_CHECK_NULL_PTR1(ctrl);
1954 
1955     mfxExtCodingOption *CO = (mfxExtCodingOption *)GetExtBuffer(par.ExtParam, par.NumExtParam, MFX_EXTBUFF_CODING_OPTION);
1956     mfxExtCodingOption2 *CO2 = (mfxExtCodingOption2 *)GetExtBuffer(par.ExtParam, par.NumExtParam, MFX_EXTBUFF_CODING_OPTION2);
1957     mfxExtCodingOption3 *CO3 = (mfxExtCodingOption3 *)GetExtBuffer(par.ExtParam, par.NumExtParam, MFX_EXTBUFF_CODING_OPTION3);
1958     MFX_CHECK_NULL_PTR3(CO, CO2, CO3);
1959 
1960 
1961     ctrl->CodecId = par.mfx.CodecId;
1962     ctrl->CodecProfile = par.mfx.CodecProfile;
1963     ctrl->CodecLevel = par.mfx.CodecLevel;
1964 
1965     ctrl->FrameInfo = par.mfx.FrameInfo;
1966     ctrl->IOPattern = par.IOPattern;
1967     ctrl->MaxDelayInFrames = CO2->LookAheadDepth;
1968 
1969     ctrl->MaxGopSize = par.mfx.GopPicSize;
1970     ctrl->MaxGopRefDist = par.mfx.GopRefDist;
1971     ctrl->MaxIDRDist = par.mfx.GopPicSize * (par.mfx.IdrInterval + 1);
1972     ctrl->BRefType = CO2->BRefType;
1973 
1974     ctrl->ScenarioInfo = CO3->ScenarioInfo;
1975 
1976     // Rate control info
1977     mfxU32 mult = par.mfx.BRCParamMultiplier ? par.mfx.BRCParamMultiplier : 1;
1978     bool   BRC = (par.mfx.RateControlMethod == MFX_RATECONTROL_CBR ||
1979         par.mfx.RateControlMethod == MFX_RATECONTROL_VBR);
1980 
1981     ctrl->RateControlMethod = par.mfx.RateControlMethod;  //CBR, VBR, CRF,CQP
1982 
1983 
1984     if (!BRC)
1985     {
1986         ctrl->QPLevel[0] = par.mfx.QPI;
1987         ctrl->QPLevel[1] = par.mfx.QPP;
1988         ctrl->QPLevel[2] = par.mfx.QPB;
1989     }
1990 
1991     else
1992     {
1993         ctrl->TargetKbps = par.mfx.TargetKbps*mult;
1994         ctrl->MaxKbps = par.mfx.MaxKbps*mult;
1995 
1996         ctrl->HRDConformance = MFX_BRC_NO_HRD;
1997         if (!IsOff(CO->NalHrdConformance) && !IsOff(CO->VuiNalHrdParameters))
1998             ctrl->HRDConformance = MFX_BRC_HRD_STRONG;
1999         else if (IsOn(CO->NalHrdConformance) && IsOff(CO->VuiNalHrdParameters))
2000             ctrl->HRDConformance = MFX_BRC_HRD_WEAK;
2001 
2002 
2003         if (ctrl->HRDConformance)
2004         {
2005             ctrl->BufferSizeInKB = par.mfx.BufferSizeInKB*mult;      //if HRDConformance is ON
2006             ctrl->InitialDelayInKB = par.mfx.InitialDelayInKB*mult;    //if HRDConformance is ON
2007         }
2008         else
2009         {
2010             ctrl->ConvergencePeriod = 0;     //if HRDConformance is OFF, 0 - the period is whole stream,
2011             ctrl->Accuracy = 10;              //if HRDConformance is OFF
2012         }
2013         ctrl->WinBRCMaxAvgKbps = CO3->WinBRCMaxAvgKbps*mult;
2014         ctrl->WinBRCSize = CO3->WinBRCSize;
2015         ctrl->MaxFrameSizeInBytes[0] = CO3->MaxFrameSizeI ? CO3->MaxFrameSizeI : CO2->MaxFrameSize;     // MaxFrameSize limitation
2016         ctrl->MaxFrameSizeInBytes[1] = CO3->MaxFrameSizeP ? CO3->MaxFrameSizeP : CO2->MaxFrameSize;
2017         ctrl->MaxFrameSizeInBytes[2] = CO2->MaxFrameSize;
2018 
2019         ctrl->MinQPLevel[0] = CO2->MinQPI;       //QP range  limitations
2020         ctrl->MinQPLevel[1] = CO2->MinQPP;
2021         ctrl->MinQPLevel[2] = CO2->MinQPB;
2022 
2023         ctrl->MaxQPLevel[0] = CO2->MaxQPI;       //QP range limitations
2024         ctrl->MaxQPLevel[1] = CO2->MaxQPP;
2025         ctrl->MaxQPLevel[2] = CO2->MaxQPB;
2026 
2027         ctrl->PanicMode = CO3->BRCPanicMode;
2028 
2029     }
2030     if (ctrl->NumExtParam > 1)
2031     {
2032         ctrl->ExtParam[0] = GetExtBuffer(par.ExtParam, par.NumExtParam, MFX_EXTBUFF_ENCTOOLS_DEVICE);
2033         ctrl->ExtParam[1] = GetExtBuffer(par.ExtParam, par.NumExtParam, MFX_EXTBUFF_ENCTOOLS_ALLOCATOR);
2034     }
2035 
2036     return MFX_ERR_NONE;
2037 
2038 }
2039 class H264EncTools
2040 {
2041 public:
2042 
~H264EncTools()2043     virtual ~H264EncTools()
2044     {
2045        Close();
2046     }
2047 
2048 
isEncToolNeeded(MfxVideoParam & video)2049     static bool isEncToolNeeded(MfxVideoParam &video)
2050     {
2051         if (!(video.mfx.RateControlMethod == MFX_RATECONTROL_CBR || video.mfx.RateControlMethod == MFX_RATECONTROL_VBR || video.mfx.RateControlMethod == MFX_RATECONTROL_CQP))
2052             return false;
2053 
2054         mfxEncTools *encTools = GetExtBuffer(video);
2055         mfxExtEncToolsConfig *config = GetExtBuffer(video);
2056 
2057         if (!(encTools && encTools->Context) && (!config))
2058             return false;
2059 
2060         mfxExtEncToolsConfig tmpConfig = {};
2061         if (config)
2062             tmpConfig = *config;
2063 
2064         GetRequiredFunc(video, tmpConfig);
2065 
2066         return IsEncToolsOptOn(tmpConfig);
2067     }
IsPreEncNeeded()2068     bool IsPreEncNeeded()
2069     {
2070         if (m_pEncTools && m_EncToolCtrl.ScenarioInfo != MFX_SCENARIO_GAME_STREAMING)
2071         {
2072             return
2073                 (IsOn(m_EncToolConfig.AdaptiveI) ||
2074                     IsOn(m_EncToolConfig.AdaptiveB) ||
2075                     IsOn(m_EncToolConfig.AdaptiveRefP) ||
2076                     IsOn(m_EncToolConfig.AdaptiveRefB) ||
2077                     IsOn(m_EncToolConfig.SceneChange) ||
2078                     IsOn(m_EncToolConfig.AdaptiveLTR) ||
2079                     IsOn(m_EncToolConfig.AdaptivePyramidQuantP) ||
2080                     IsOn(m_EncToolConfig.AdaptivePyramidQuantB));
2081         }
2082         return false;
2083     }
IsLookAhead()2084     inline bool IsLookAhead()
2085     {
2086         if (m_pEncTools && m_EncToolCtrl.ScenarioInfo == MFX_SCENARIO_GAME_STREAMING)
2087         {
2088             return
2089                 (IsOn(m_EncToolConfig.AdaptiveI) ||
2090                     IsOn(m_EncToolConfig.AdaptiveB) ||
2091                     IsOn(m_EncToolConfig.SceneChange) ||
2092                     IsOn(m_EncToolConfig.AdaptivePyramidQuantP) ||
2093                     IsOn(m_EncToolConfig.BRCBufferHints) ||
2094                     IsOn(m_EncToolConfig.AdaptiveQuantMatrices));
2095         }
2096         return false;
2097     }
IsAdaptiveGOP()2098     inline bool IsAdaptiveGOP()
2099     {
2100         return (m_pEncTools != 0 &&
2101             (IsOn(m_EncToolConfig.AdaptiveI) ||
2102             IsOn(m_EncToolConfig.AdaptiveB)));
2103     }
IsAdaptiveQP()2104     inline bool IsAdaptiveQP()
2105     {
2106         return (m_pEncTools != 0 &&
2107             (IsOn(m_EncToolConfig.AdaptivePyramidQuantP) ||
2108             IsOn(m_EncToolConfig.AdaptivePyramidQuantB)));
2109     }
IsAdaptiveRef()2110     inline bool IsAdaptiveRef()
2111     {
2112         return (m_pEncTools != 0 &&
2113             (IsOn(m_EncToolConfig.AdaptiveRefP) ||
2114             IsOn(m_EncToolConfig.AdaptiveRefB)));
2115     }
IsAdaptiveLTR()2116     inline bool IsAdaptiveLTR()
2117     {
2118         return (m_pEncTools != 0 &&
2119             IsOn(m_EncToolConfig.AdaptiveLTR));
2120     }
IsBRC()2121     inline bool IsBRC()
2122     {
2123         return (m_pEncTools != 0 &&
2124             IsOn(m_EncToolConfig.BRC));
2125     }
2126 
GetPreEncDelay(const MfxVideoParam & par)2127     static mfxU32 GetPreEncDelay(const MfxVideoParam &par)
2128     {
2129         MfxVideoParam video = par;
2130         if (!isEncToolNeeded(video))
2131             return 0;
2132 
2133         bool bCreated = false;
2134 
2135         mfxEncTools *encTools = 0;
2136         mfxExtEncToolsConfig supportedConfig = {};
2137         mfxExtEncToolsConfig requiredConfig = {};
2138         mfxEncToolsCtrl ctrl = {};
2139 
2140         MFX_CHECK_STS(CreateEncTools(video, encTools, bCreated));
2141         MFX_CHECK_STS(InitCtrl(video, &ctrl));
2142 
2143         encTools->GetSupportedConfig(encTools->Context, &supportedConfig,&ctrl);
2144 
2145         CorrectVideoParams(video, supportedConfig);
2146         GetRequiredFunc(video, requiredConfig);
2147 
2148         mfxU32 numFramesForDelay = 0;
2149 
2150         encTools->GetDelayInFrames(encTools->Context, &requiredConfig, &ctrl,&numFramesForDelay);
2151 
2152         if (bCreated)
2153             MFXVideoENCODE_DestroyEncTools(encTools);
2154 
2155         return numFramesForDelay;
2156     }
2157 
Query(MfxVideoParam & video)2158     static mfxStatus Query(MfxVideoParam &video)
2159     {
2160         mfxStatus sts = MFX_ERR_NONE;
2161 
2162         mfxExtEncToolsConfig supportedConfig = {};
2163         mfxEncToolsCtrl ctrl = {};
2164 
2165         mfxEncTools *encTools = 0;
2166         bool bCreated = false;
2167 
2168         MFX_CHECK_STS(CreateEncTools(video, encTools, bCreated));
2169         MFX_CHECK_STS(InitCtrl(video, &ctrl));
2170 
2171         encTools->GetSupportedConfig(encTools->Context, &supportedConfig,&ctrl);
2172 
2173         if (CorrectVideoParams(video, supportedConfig))
2174             sts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
2175 
2176         if (bCreated)
2177             MFXVideoENCODE_DestroyEncTools(encTools);
2178 
2179         return sts;
2180     }
2181 
Init(MfxVideoParam & video)2182     mfxStatus  Init(MfxVideoParam &video)
2183     {
2184         mfxExtEncToolsConfig requiredConf = {};
2185         mfxExtEncToolsConfig supportedConf = {};
2186 
2187         memset(&m_EncToolCtrl, 0, sizeof(mfxEncToolsCtrl));
2188         m_EncToolCtrl.ExtParam = m_ExtParam;
2189         m_EncToolCtrl.NumExtParam = 2;
2190 
2191         mfxStatus sts = InitCtrl(video, &m_EncToolCtrl);
2192         MFX_CHECK_STS(sts);
2193 
2194         sts = CreateEncTools(video, m_pEncTools, m_bEncToolsCreated);
2195         MFX_CHECK_STS(sts);
2196 
2197         m_pEncTools->GetSupportedConfig(m_pEncTools->Context, &supportedConf, &m_EncToolCtrl);
2198 
2199         if (CorrectVideoParams(video, supportedConf))
2200             return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
2201 
2202         GetRequiredFunc(video, requiredConf);
2203 
2204         sts = m_pEncTools->Init(m_pEncTools->Context, &requiredConf, &m_EncToolCtrl);
2205         MFX_CHECK_STS(sts);
2206 
2207         sts = m_pEncTools->GetActiveConfig(m_pEncTools->Context, &m_EncToolConfig);
2208         MFX_CHECK_STS(sts);
2209 
2210         mfxExtEncToolsConfig *pConfig = (mfxExtEncToolsConfig *)GetExtBuffer(video.ExtParam, video.NumExtParam, MFX_EXTBUFF_ENCTOOLS_CONFIG);
2211         if (pConfig)
2212         {
2213             mfxExtBuffer header = pConfig->Header;
2214             *pConfig = m_EncToolConfig;
2215             pConfig->Header = header;
2216         }
2217 
2218 
2219         return MFX_ERR_NONE;
2220     }
2221 
Close()2222     void  Close()
2223     {
2224         if (m_pEncTools)
2225         {
2226             m_pEncTools->Close(m_pEncTools->Context);
2227         }
2228         if (m_bEncToolsCreated)
2229             MFXVideoENCODE_DestroyEncTools(m_pEncTools);
2230 
2231         m_bEncToolsCreated = false;
2232     }
Reset(MfxVideoParam & video)2233     mfxStatus  Reset(MfxVideoParam &video)
2234     {
2235         MFX_CHECK(m_pEncTools != 0, MFX_ERR_NOT_INITIALIZED);
2236 
2237         mfxEncToolsCtrl newCtrl = {};
2238         MFX_CHECK_STS(InitCtrl(video, &newCtrl));
2239 
2240         MFX_CHECK_STS(m_pEncTools->Reset(m_pEncTools->Context, &m_EncToolConfig, &newCtrl));
2241         m_EncToolCtrl = newCtrl;
2242 
2243         return MFX_ERR_NONE;
2244     }
2245 
SubmitForPreEnc(mfxU32 displayOrder,mfxFrameSurface1 * pSurface)2246     mfxStatus SubmitForPreEnc(mfxU32 displayOrder, mfxFrameSurface1 *pSurface)
2247     {
2248         MFX_CHECK(m_pEncTools != 0, MFX_ERR_NOT_INITIALIZED);
2249         MFX_CHECK(IsOn(m_EncToolConfig.AdaptiveI) ||
2250             IsOn(m_EncToolConfig.AdaptiveB) ||
2251             IsOn(m_EncToolConfig.AdaptivePyramidQuantP) ||
2252             IsOn(m_EncToolConfig.AdaptivePyramidQuantB) ||
2253             IsOn(m_EncToolConfig.AdaptiveLTR) ||
2254             IsOn(m_EncToolConfig.AdaptiveRefB) ||
2255             IsOn(m_EncToolConfig.AdaptiveRefP) ||
2256             IsOn(m_EncToolConfig.SceneChange) ||
2257             IsOn(m_EncToolConfig.AdaptivePyramidQuantP) ||
2258             IsOn(m_EncToolConfig.BRCBufferHints) ||
2259             IsOn(m_EncToolConfig.AdaptiveQuantMatrices)
2260             , MFX_ERR_NOT_INITIALIZED);
2261 
2262         mfxEncToolsTaskParam par = {};
2263         par.DisplayOrder = displayOrder;
2264         std::vector<mfxExtBuffer*> extParams;
2265 
2266         mfxEncToolsFrameToAnalyze extFrameData = {};
2267         if (pSurface)
2268         {
2269             extFrameData.Header.BufferId = MFX_EXTBUFF_ENCTOOLS_FRAME_TO_ANALYZE;
2270             extFrameData.Header.BufferSz = sizeof(extFrameData);
2271             extFrameData.Surface = pSurface;
2272             extParams.push_back((mfxExtBuffer *)&extFrameData);
2273         }
2274 
2275         par.ExtParam = &extParams[0];
2276         par.NumExtParam = (mfxU16)extParams.size();
2277 
2278         return m_pEncTools->Submit(m_pEncTools->Context, &par);
2279     }
2280 
QueryPreEncRes(mfxU32 displayOrder,mfxEncToolsHintPreEncodeGOP & preEncodeGOP)2281     mfxStatus QueryPreEncRes(mfxU32 displayOrder, mfxEncToolsHintPreEncodeGOP &preEncodeGOP)
2282     {
2283         MFX_CHECK(m_pEncTools != 0, MFX_ERR_NOT_INITIALIZED);
2284         MFX_CHECK(IsOn(m_EncToolConfig.AdaptiveI) ||
2285             IsOn(m_EncToolConfig.AdaptiveB) ||
2286             IsOn(m_EncToolConfig.AdaptivePyramidQuantP) ||
2287             IsOn(m_EncToolConfig.AdaptivePyramidQuantB)
2288             , MFX_ERR_NOT_INITIALIZED);
2289 
2290         mfxEncToolsTaskParam par = {};
2291         par.DisplayOrder = displayOrder;
2292         std::vector<mfxExtBuffer*> extParams;
2293         memset(&preEncodeGOP, 0, sizeof(preEncodeGOP));
2294         preEncodeGOP.Header.BufferId = MFX_EXTBUFF_ENCTOOLS_HINT_GOP;
2295         preEncodeGOP.Header.BufferSz = sizeof(preEncodeGOP);
2296 
2297         extParams.push_back((mfxExtBuffer *)&preEncodeGOP);
2298 
2299         par.ExtParam = &extParams[0];
2300         par.NumExtParam = (mfxU16)extParams.size();
2301 
2302 
2303         mfxStatus sts = MFX_ERR_NONE;
2304         sts = m_pEncTools->Query(m_pEncTools->Context, &par, 5000);
2305         return sts;
2306     }
2307 
QueryPreEncARef(mfxU32 displayOrder,mfxEncToolsHintPreEncodeARefFrames & preEncodeARef)2308     mfxStatus QueryPreEncARef(mfxU32 displayOrder, mfxEncToolsHintPreEncodeARefFrames &preEncodeARef)
2309     {
2310         MFX_CHECK(m_pEncTools != 0, MFX_ERR_NOT_INITIALIZED);
2311         MFX_CHECK(IsOn(m_EncToolConfig.AdaptiveLTR)||
2312             IsOn(m_EncToolConfig.AdaptiveRefB)||
2313             IsOn(m_EncToolConfig.AdaptiveRefP), MFX_ERR_NOT_INITIALIZED);
2314 
2315         mfxEncToolsTaskParam par = {};
2316         par.DisplayOrder = displayOrder;
2317         std::vector<mfxExtBuffer*> extParams;
2318         preEncodeARef = {};
2319         preEncodeARef.Header.BufferId = MFX_EXTBUFF_ENCTOOLS_HINT_AREF;
2320         preEncodeARef.Header.BufferSz = sizeof(preEncodeARef);
2321 
2322         extParams.push_back((mfxExtBuffer *)&preEncodeARef);
2323 
2324         par.ExtParam = extParams.data();
2325         par.NumExtParam = (mfxU16)extParams.size();
2326 
2327         mfxStatus sts = MFX_ERR_NONE;
2328         sts = m_pEncTools->Query(m_pEncTools->Context, &par, 5000);
2329         return sts;
2330     }
2331 
SubmitFrameForEncoding(DdiTask & task)2332     mfxStatus SubmitFrameForEncoding(DdiTask &task)
2333     {
2334         MFX_CHECK(m_pEncTools != 0, MFX_ERR_NOT_INITIALIZED);
2335         mfxEncToolsTaskParam par = {};
2336         BRCFrameParams *frame_par = &task.m_brcFrameParams;
2337         par.DisplayOrder = frame_par->DisplayOrder;
2338         std::vector<mfxExtBuffer*> extParams;
2339         mfxEncToolsBRCFrameParams extFrameStruct = {};
2340         extFrameStruct.Header.BufferId = MFX_EXTBUFF_ENCTOOLS_BRC_FRAME_PARAM ;
2341         extFrameStruct.Header.BufferSz = sizeof(extFrameStruct);
2342         extFrameStruct.EncodeOrder = frame_par->EncodedOrder;
2343         extFrameStruct.FrameType = frame_par->FrameType;
2344         extFrameStruct.PyramidLayer = frame_par->PyramidLayer;
2345         extParams.push_back((mfxExtBuffer *)&extFrameStruct);
2346 
2347         if (frame_par->OptimalFrameSizeInBytes | frame_par->optimalBufferFullness)
2348         {
2349             mfxEncToolsBRCBufferHint extBRCHints = {};
2350             extBRCHints.Header.BufferId = MFX_EXTBUFF_ENCTOOLS_BRC_BUFFER_HINT;
2351             extBRCHints.Header.BufferSz = sizeof(extBRCHints);
2352             extBRCHints.OptimalFrameSizeInBytes = frame_par->OptimalFrameSizeInBytes;
2353             //extBRCHints.OptimalBufferFullness = frame_par->optimalBufferFullness;
2354             extParams.push_back((mfxExtBuffer *)&extBRCHints);
2355         }
2356 
2357         if ((task.m_bQPDelta && task.m_QPdelta) || (task.m_QPmodulation != MFX_QP_MODULATION_NOT_DEFINED))
2358         {
2359             mfxEncToolsHintPreEncodeGOP gopHints = {};
2360             gopHints.Header.BufferId = MFX_EXTBUFF_ENCTOOLS_HINT_GOP;
2361             gopHints.Header.BufferSz = sizeof(gopHints);
2362             if (task.m_bQPDelta && task.m_QPdelta)
2363                 gopHints.QPDelta = task.m_QPdelta;
2364             if (task.m_QPmodulation != MFX_QP_MODULATION_NOT_DEFINED)
2365                 gopHints.QPModulation = task.m_QPmodulation;
2366             extParams.push_back((mfxExtBuffer *)&gopHints);
2367         }
2368 
2369         par.ExtParam = &extParams[0];
2370         par.NumExtParam = (mfxU16)extParams.size();
2371 
2372         mfxStatus sts = MFX_ERR_NONE;
2373         sts = m_pEncTools->Submit(m_pEncTools->Context, &par);
2374         return sts;
2375     }
2376 
GetFrameCtrl(mfxBRCFrameCtrl * frame_ctrl,mfxU32 dispOrder)2377     mfxStatus GetFrameCtrl(mfxBRCFrameCtrl *frame_ctrl, mfxU32 dispOrder)
2378     {
2379         MFX_CHECK(m_pEncTools != 0, MFX_ERR_NOT_INITIALIZED);
2380         mfxEncToolsTaskParam par = {};
2381         par.DisplayOrder = dispOrder;
2382         std::vector<mfxExtBuffer*> extParams;
2383 
2384         mfxEncToolsBRCQuantControl extFrameQP = {} ;
2385         extFrameQP.Header.BufferId = MFX_EXTBUFF_ENCTOOLS_BRC_QUANT_CONTROL;
2386         extFrameQP.Header.BufferSz = sizeof(extFrameQP);
2387 
2388         extParams.push_back((mfxExtBuffer *)&extFrameQP);
2389 
2390         mfxEncToolsBRCHRDPos extHRDPos = {};
2391         extHRDPos.Header.BufferId = MFX_EXTBUFF_ENCTOOLS_BRC_HRD_POS;
2392         extHRDPos.Header.BufferSz = sizeof(extHRDPos);
2393         extParams.push_back((mfxExtBuffer *)&extHRDPos);
2394 
2395         par.ExtParam = &extParams[0];
2396         par.NumExtParam = (mfxU16)extParams.size();
2397 
2398         mfxStatus sts;
2399         sts = m_pEncTools->Query(m_pEncTools->Context, &par, 5000);
2400         MFX_CHECK_STS(sts);
2401 
2402         frame_ctrl->QpY = extFrameQP.QpY;
2403         frame_ctrl->MaxFrameSize = extFrameQP.MaxFrameSize;
2404         std::copy(extFrameQP.DeltaQP, extFrameQP.DeltaQP + 8, frame_ctrl->DeltaQP);
2405         frame_ctrl->MaxNumRepak = extFrameQP.NumDeltaQP;
2406 
2407         frame_ctrl->InitialCpbRemovalDelay = extHRDPos.InitialCpbRemovalDelay;
2408         frame_ctrl->InitialCpbRemovalOffset = extHRDPos.InitialCpbRemovalDelayOffset;
2409 
2410         return sts;
2411     }
2412 
SubmitEncodeResult(mfxBRCFrameParam * frame_par,mfxU32 qpY)2413     mfxStatus SubmitEncodeResult(mfxBRCFrameParam *frame_par, mfxU32 qpY)
2414     {
2415         MFX_CHECK(m_pEncTools != 0, MFX_ERR_NOT_INITIALIZED);
2416         mfxEncToolsTaskParam par;
2417         par.DisplayOrder = frame_par->DisplayOrder;
2418 
2419         std::vector<mfxExtBuffer*> extParams;
2420         mfxEncToolsBRCEncodeResult extEncRes;
2421         extEncRes.Header.BufferId = MFX_EXTBUFF_ENCTOOLS_BRC_ENCODE_RESULT;
2422         extEncRes.Header.BufferSz = sizeof(extEncRes);
2423         extEncRes.CodedFrameSize = frame_par->CodedFrameSize;
2424         extEncRes.QpY = (mfxU16)qpY;
2425         extEncRes.NumRecodesDone = frame_par->NumRecode;
2426 
2427         extParams.push_back((mfxExtBuffer *)&extEncRes);
2428 
2429         par.ExtParam = &extParams[0];
2430         par.NumExtParam = (mfxU16)extParams.size();
2431 
2432         mfxStatus sts;
2433         sts = m_pEncTools->Submit(m_pEncTools->Context, &par);
2434         MFX_CHECK_STS(sts);
2435         return sts;
2436     }
2437 
GetEncodeStatus(mfxBRCFrameStatus * frame_status,mfxU32 dispOrder)2438     mfxStatus GetEncodeStatus(mfxBRCFrameStatus *frame_status, mfxU32 dispOrder)
2439     {
2440         MFX_CHECK(m_pEncTools != 0, MFX_ERR_NOT_INITIALIZED);
2441 
2442         mfxEncToolsTaskParam par;
2443         par.DisplayOrder = dispOrder;
2444 
2445         std::vector<mfxExtBuffer*> extParams;
2446         mfxEncToolsBRCStatus extSts;
2447         extSts.Header.BufferId = MFX_EXTBUFF_ENCTOOLS_BRC_STATUS;
2448         extSts.Header.BufferSz = sizeof(extSts);
2449         extParams.push_back((mfxExtBuffer *)&extSts);
2450         par.ExtParam = &extParams[0];
2451         par.NumExtParam = (mfxU16)extParams.size();
2452 
2453         mfxStatus sts;
2454         sts = m_pEncTools->Query(m_pEncTools->Context, &par, 5000);
2455 
2456         *frame_status = extSts.FrameStatus;
2457         return sts;
2458     }
2459 
2460 protected:
CheckSCConditions(MfxVideoParam & video)2461     static bool CheckSCConditions(MfxVideoParam &video)
2462     {
2463         return ((video.mfx.GopRefDist == 0 ||
2464             video.mfx.GopRefDist == 1 ||
2465             video.mfx.GopRefDist == 2 ||
2466             video.mfx.GopRefDist == 4 ||
2467             video.mfx.GopRefDist == 8) &&
2468             (video.mfx.FrameInfo.PicStruct == 0 ||
2469                 video.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_PROGRESSIVE) &&
2470             video.calcParam.numTemporalLayer == 0);
2471 
2472     }
2473 
GetRequiredFunc(MfxVideoParam & video,mfxExtEncToolsConfig & config)2474    static void GetRequiredFunc(MfxVideoParam &video, mfxExtEncToolsConfig &config)
2475     {
2476         /*mfxExtCodingOption2  &extOpt2 = GetExtBufferRef(video);*/
2477         mfxExtCodingOption3  &extOpt3 = GetExtBufferRef(video);
2478         mfxExtEncToolsConfig *pConfig = (mfxExtEncToolsConfig *)GetExtBuffer(video.ExtParam, video.NumExtParam, MFX_EXTBUFF_ENCTOOLS_CONFIG);
2479         if (pConfig)
2480             config = *pConfig;
2481 
2482         /* currently, adaptive pyramid quantization and EncTools' own BRC are enabled, other features are disabled */
2483 
2484         if (extOpt3.ScenarioInfo != MFX_SCENARIO_GAME_STREAMING)
2485         {
2486             if (CheckSCConditions(video))
2487             {
2488 /*
2489                 bool bGopStrict = (video.mfx.GopOptFlag & MFX_GOP_STRICT);
2490                 config.AdaptiveI = IsNotDefined(config.AdaptiveI) ?
2491                     (IsNotDefined(extOpt2.AdaptiveI) ? (mfxU16)(bGopStrict ? MFX_CODINGOPTION_OFF: MFX_CODINGOPTION_ON) : extOpt2.AdaptiveI) : config.AdaptiveI;
2492                 config.AdaptiveB = IsNotDefined(config.AdaptiveB) ?
2493                     (IsNotDefined(extOpt2.AdaptiveB) ? config.AdaptiveI : extOpt2.AdaptiveB) :
2494                     config.AdaptiveB;
2495 
2496                 config.AdaptivePyramidQuantP = IsNotDefined(config.AdaptivePyramidQuantP) ?
2497                     config.AdaptiveI : config.AdaptivePyramidQuantP;
2498                 config.AdaptivePyramidQuantB = IsNotDefined(config.AdaptivePyramidQuantB) ?
2499                     config.AdaptiveI : config.AdaptivePyramidQuantB;
2500 
2501                 mfxU16 bAdaptRef = config.AdaptiveI;
2502                 mfxExtCodingOptionDDI const * extDdi = GetExtBuffer(video);
2503                 if (extDdi->NumActiveRefP == 1)
2504                     bAdaptRef = (mfxU16)MFX_CODINGOPTION_OFF;
2505 
2506                 config.AdaptiveRefB = IsNotDefined(config.AdaptiveRefB) ?
2507                     bAdaptRef : config.AdaptiveRefB;
2508 
2509                 config.AdaptiveRefP = IsNotDefined(config.AdaptiveRefP) ?
2510                     bAdaptRef : config.AdaptiveRefP;
2511 
2512                 config.AdaptiveLTR = IsNotDefined(config.AdaptiveLTR) ?
2513                     bAdaptRef : config.AdaptiveLTR;
2514 */
2515 
2516                 config.AdaptivePyramidQuantP = config.AdaptivePyramidQuantB = MFX_CODINGOPTION_ON;
2517 
2518             }
2519 /*
2520             config.BRC = IsNotDefined(config.BRC) ?
2521                 ((video.mfx.RateControlMethod == MFX_RATECONTROL_CBR ||
2522                     video.mfx.RateControlMethod == MFX_RATECONTROL_VBR) ?
2523                     (mfxU16)MFX_CODINGOPTION_ON : (mfxU16)MFX_CODINGOPTION_OFF) : config.BRC;
2524 */
2525 
2526             config.BRC = (video.mfx.RateControlMethod == MFX_RATECONTROL_CBR || video.mfx.RateControlMethod == MFX_RATECONTROL_VBR) ?
2527                     (mfxU16)MFX_CODINGOPTION_ON : (mfxU16)MFX_CODINGOPTION_OFF;
2528         }
2529 
2530    }
CheckFlag(mfxU16 & tested,mfxU16 ref,mfxU32 & errCount)2531    static void CheckFlag(mfxU16 &tested, mfxU16 ref, mfxU32 &errCount)
2532    {
2533        if (IsOn(tested) && IsOff(ref))
2534        {
2535            tested = MFX_CODINGOPTION_OFF;
2536            errCount++;
2537        }
2538    }
CheckFlag(mfxU16 & tested,bool bAllowed,mfxU32 & errCount)2539    static void CheckFlag(mfxU16 &tested, bool bAllowed, mfxU32 &errCount)
2540    {
2541        if (IsOn(tested) && (!bAllowed))
2542        {
2543            tested = MFX_CODINGOPTION_OFF;
2544            errCount++;
2545        }
2546    }
2547 
CorrectVideoParams(MfxVideoParam & video,mfxExtEncToolsConfig & supportedConfig)2548    static mfxU32 CorrectVideoParams(MfxVideoParam &video, mfxExtEncToolsConfig& supportedConfig)
2549    {
2550        mfxExtCodingOption2  &extOpt2 = GetExtBufferRef(video);
2551        mfxExtCodingOptionDDI *    extDdi = GetExtBuffer(video);
2552 
2553        mfxExtBRC*  extBRC = GetExtBuffer(video);
2554        mfxU32 numChanges = 0;
2555        mfxExtEncToolsConfig *pConfig = (mfxExtEncToolsConfig *)GetExtBuffer(video.ExtParam, video.NumExtParam, MFX_EXTBUFF_ENCTOOLS_CONFIG);
2556 
2557        if (pConfig)
2558        {
2559            bool bEncToolsCnd = ((video.mfx.FrameInfo.PicStruct == 0 ||
2560                video.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_PROGRESSIVE) &&
2561                video.calcParam.numTemporalLayer == 0);
2562            bool bGopStrict = ((video.mfx.GopOptFlag & MFX_GOP_STRICT) != 0);
2563            bool bMultiRef = (extDdi->NumActiveRefP != 1);
2564 
2565            CheckFlag(pConfig->AdaptiveI, bEncToolsCnd && (!bGopStrict), numChanges);
2566 
2567            bool bAddLim = !IsOff(pConfig->AdaptiveI);  // additional limititation in current implementation
2568            CheckFlag(pConfig->AdaptiveB, bEncToolsCnd && (!bGopStrict) && bAddLim, numChanges);
2569            CheckFlag(pConfig->AdaptivePyramidQuantB, bEncToolsCnd, numChanges);
2570            CheckFlag(pConfig->AdaptivePyramidQuantP, bEncToolsCnd, numChanges);
2571 
2572            CheckFlag(pConfig->AdaptiveRefP, bEncToolsCnd && bMultiRef && bAddLim, numChanges);
2573            CheckFlag(pConfig->AdaptiveRefB, bEncToolsCnd && bMultiRef && bAddLim, numChanges);
2574            CheckFlag(pConfig->AdaptiveLTR,  bEncToolsCnd && bMultiRef && bAddLim, numChanges);
2575            CheckFlag(pConfig->SceneChange, bEncToolsCnd, numChanges);
2576            CheckFlag(pConfig->BRCBufferHints, bEncToolsCnd, numChanges);
2577            CheckFlag(pConfig->AdaptiveQuantMatrices, bEncToolsCnd, numChanges);
2578            CheckFlag(pConfig->BRC, bEncToolsCnd, numChanges);
2579 
2580            CheckFlag(pConfig->AdaptiveI, supportedConfig.AdaptiveI, numChanges);
2581            CheckFlag(pConfig->AdaptiveB, supportedConfig.AdaptiveB, numChanges);
2582            CheckFlag(pConfig->AdaptivePyramidQuantB, supportedConfig.AdaptivePyramidQuantB, numChanges);
2583            CheckFlag(pConfig->AdaptivePyramidQuantP, supportedConfig.AdaptivePyramidQuantP, numChanges);
2584            CheckFlag(pConfig->AdaptiveRefP, supportedConfig.AdaptiveRefP, numChanges);
2585            CheckFlag(pConfig->AdaptiveRefB, supportedConfig.AdaptiveRefB, numChanges);
2586            CheckFlag(pConfig->AdaptiveLTR, supportedConfig.AdaptiveLTR, numChanges);
2587            CheckFlag(pConfig->SceneChange, supportedConfig.SceneChange, numChanges);
2588            CheckFlag(pConfig->BRCBufferHints, supportedConfig.BRCBufferHints, numChanges);
2589            CheckFlag(pConfig->AdaptiveQuantMatrices, supportedConfig.AdaptiveQuantMatrices, numChanges);
2590            CheckFlag(pConfig->BRC, supportedConfig.BRC, numChanges);
2591        }
2592        CheckFlag(extOpt2.AdaptiveI, supportedConfig.AdaptiveI, numChanges);
2593        CheckFlag(extOpt2.AdaptiveB, supportedConfig.AdaptiveB, numChanges);
2594        //ExtBRC isn't compatible with EncTools
2595 
2596        if (extBRC && (extBRC->pthis || extBRC->Init || extBRC->Close  || extBRC->Update || extBRC->Reset))
2597        {
2598            extBRC->pthis = 0;
2599            extBRC->Init = 0;
2600            extBRC->Close = 0;
2601            extBRC->Update = 0;
2602            extBRC->Reset = 0;
2603            numChanges++;
2604        }
2605        if (IsOn(extOpt2.ExtBRC))
2606        {
2607            extOpt2.ExtBRC = MFX_CODINGOPTION_UNKNOWN;
2608            numChanges++;
2609        }
2610 
2611        return numChanges;
2612    }
CreateEncTools(MfxVideoParam & video,mfxEncTools * & encTools,bool & bCreated)2613    static mfxStatus CreateEncTools(MfxVideoParam &video, mfxEncTools * &encTools, bool &bCreated)
2614    {
2615        encTools = GetExtBuffer(video);
2616        bCreated = false;
2617        if (!encTools->Context)
2618        {
2619            encTools = MFXVideoENCODE_CreateEncTools();
2620            MFX_CHECK(encTools != 0, MFX_ERR_INVALID_VIDEO_PARAM);
2621            bCreated = true;
2622        }
2623        return MFX_ERR_NONE;
2624    }
2625 
2626 private:
2627 
2628     mfxEncTools*            m_pEncTools = nullptr;
2629     bool                    m_bEncToolsCreated = false;
2630     mfxEncToolsCtrl         m_EncToolCtrl = {};
2631     mfxExtEncToolsConfig    m_EncToolConfig = {};
2632     mfxExtBuffer*           m_ExtParam[2] = {};
2633 
2634 };
2635 #endif
2636 
2637 
2638 
2639     class DdiTask2ndField
2640     {
2641     public:
2642         DdiTask * m_1stFieldTask;
2643         DdiTask   m_2ndFieldTask;
2644     };
2645 
2646     // should be called from one thread
2647     // yields tasks in cyclic manner
2648     class CyclicTaskPool
2649     {
2650     public:
2651         void Init(mfxU32 size);
2652 
2653         DdiTask2ndField * GetFreeTask();
2654 
2655     private:
2656         std::vector<DdiTask2ndField>           m_pool;
2657         std::vector<DdiTask2ndField>::iterator m_next;
2658     };
2659 
2660     struct MbData
2661     {
2662         mfxU32      intraCost;
2663         mfxU32      interCost;
2664         mfxU32      propCost;
2665         mfxU8       w0;
2666         mfxU8       w1;
2667         mfxU16      dist;
2668         mfxU16      rate;
2669         mfxU16      lumaCoeffSum[4];
2670         mfxU8       lumaCoeffCnt[4];
2671         mfxI16Pair  costCenter0;
2672         mfxI16Pair  costCenter1;
2673         struct
2674         {
2675             mfxU32  intraMbFlag     : 1;
2676             mfxU32  skipMbFlag      : 1;
2677             mfxU32  mbType          : 5;
2678             mfxU32  reserved0       : 1;
2679             mfxU32  subMbShape      : 8;
2680             mfxU32  subMbPredMode   : 8;
2681             mfxU32  reserved1       : 8;
2682         };
2683         mfxI16Pair  mv[2]; // in sig-sag scan
2684     };
2685 
2686     class CmContext;
2687 
2688     struct VmeData
2689     {
VmeDataVmeData2690         VmeData()
2691             : used(false)
2692             , poc(mfxU32(-1))
2693             , pocL0(mfxU32(-1))
2694             , pocL1(mfxU32(-1))
2695             , encOrder(0)
2696             , intraCost(0)
2697             , interCost(0)
2698             , propCost(0) { }
2699 
2700         bool                used;
2701         mfxU32              poc;
2702         mfxU32              pocL0;
2703         mfxU32              pocL1;
2704         mfxU32              encOrder;
2705         mfxU32              intraCost;
2706         mfxU32              interCost;
2707         mfxU32              propCost;
2708         std::vector<MbData> mb;
2709     };
2710 
2711 
2712     class AsyncRoutineEmulator
2713     {
2714     public:
2715         enum {
2716             STG_ACCEPT_FRAME,
2717             STG_START_SCD,
2718             STG_WAIT_SCD,
2719             STG_START_MCTF,
2720             STG_WAIT_MCTF,
2721             STG_START_LA,
2722             STG_WAIT_LA,
2723             STG_START_HIST,
2724             STG_WAIT_HIST,
2725             STG_START_ENCODE,
2726             STG_WAIT_ENCODE,
2727             STG_COUNT
2728         };
2729 
2730         enum {
2731             STG_BIT_CALL_EMULATOR = 0,
2732             STG_BIT_ACCEPT_FRAME  = 1 << STG_ACCEPT_FRAME,
2733             STG_BIT_START_SCD     = 1 << STG_START_SCD,
2734             STG_BIT_WAIT_SCD      = 1 << STG_WAIT_SCD,
2735             STG_BIT_START_MCTF    = 1 << STG_START_MCTF,
2736             STG_BIT_WAIT_MCTF     = 1 << STG_WAIT_MCTF,
2737             STG_BIT_START_LA      = 1 << STG_START_LA,
2738             STG_BIT_WAIT_LA       = 1 << STG_WAIT_LA,
2739             STG_BIT_START_HIST    = 1 << STG_START_HIST,
2740             STG_BIT_WAIT_HIST     = 1 << STG_WAIT_HIST,
2741             STG_BIT_START_ENCODE  = 1 << STG_START_ENCODE,
2742             STG_BIT_WAIT_ENCODE   = 1 << STG_WAIT_ENCODE,
2743             STG_BIT_RESTART       = 1 << STG_COUNT
2744         };
2745 
2746         AsyncRoutineEmulator();
2747 
2748         AsyncRoutineEmulator(MfxVideoParam const & video,  mfxU32  adaptGopDelay);
2749 
2750         void Init(MfxVideoParam const & video, mfxU32  adaptGopDelay);
2751 
2752         mfxU32 GetTotalGreediness() const;
2753 
2754         mfxU32 GetStageGreediness(mfxU32 i) const;
2755 
2756         mfxU32 Go(bool hasInput);
2757 
2758     protected:
2759         mfxU32 CheckStageOutput(mfxU32 stage);
2760 
2761     private:
2762         mfxU32 m_stageGreediness[STG_COUNT];
2763         mfxU32 m_queueFullness[STG_COUNT + 1];
2764         mfxU32 m_queueFlush[STG_COUNT + 1];
2765     };
2766 
2767     struct LAOutObject;
2768 
2769     using ns_asc::ASC;
2770 
2771     class ImplementationAvc : public VideoENCODE
2772     {
2773     public:
2774         struct FrameTypeAdapt
2775         {
FrameTypeAdaptFrameTypeAdapt2776             FrameTypeAdapt(CmDevice* cmDevice, int width, int height)
2777                 : m_frameNum(0)
2778                 , m_isAdapted(0)
2779                 , m_surface(0)
2780                 , m_cmDevice(cmDevice)
2781 
2782                 , intraCost(0)
2783                 , interCost(0)
2784                 , intraDist(0)
2785                 , interDist(0)
2786                 , totalDist(0)
2787                 , numIntraMb(0)
2788             {
2789                 int numMB = width*height/256;
2790                 mb.resize(numMB);
2791 
2792                 m_surface4X.Reset(m_cmDevice, width/4, height/4, CM_SURFACE_FORMAT_NV12);
2793             }
2794 
2795             mfxU32              m_frameNum;
2796             mfxU32              m_isAdapted;
2797             mfxU16              m_frameType;
2798             mfxEncodeCtrl*      m_ctrl;
2799             mfxFrameSurface1*   m_surface;
2800             CmSurface           m_surface4X;
2801             CmDevice*           m_cmDevice;
2802 
2803             mfxU32              intraCost;
2804             mfxU32              interCost;
2805             mfxU32              intraDist;
2806             mfxU32              interDist;
2807             mfxU32              totalDist;
2808             mfxU32              numIntraMb;
2809             std::vector<MbData> mb;
2810             //std::vector<LAOutObject> m_mb;
2811         };
2812 
2813     public:
2814         static mfxStatus Query(
2815             VideoCORE *     core,
2816             mfxVideoParam * in,
2817             mfxVideoParam * out,
2818             void          * state = 0);
2819 
2820         static mfxStatus QueryIOSurf(
2821             VideoCORE *            core,
2822             mfxVideoParam *        par,
2823             mfxFrameAllocRequest * request);
2824 
2825         ImplementationAvc(VideoCORE * core);
2826 
2827         virtual ~ImplementationAvc();
2828 
2829         virtual mfxStatus Init(mfxVideoParam * par);
2830 
Close()2831         virtual mfxStatus Close() { return MFX_ERR_NONE; }
2832 
2833         virtual mfxStatus Reset(mfxVideoParam * par);
2834 
2835         virtual mfxStatus GetVideoParam(mfxVideoParam * par);
2836 
2837         virtual mfxStatus GetFrameParam(mfxFrameParam * par);
2838 
2839         virtual mfxStatus GetEncodeStat(mfxEncodeStat * stat);
2840 
EncodeFrameCheck(mfxEncodeCtrl *,mfxFrameSurface1 *,mfxBitstream *,mfxFrameSurface1 **,mfxEncodeInternalParams *)2841         virtual mfxStatus EncodeFrameCheck(
2842             mfxEncodeCtrl *,
2843             mfxFrameSurface1 *,
2844             mfxBitstream *,
2845             mfxFrameSurface1 **,
2846             mfxEncodeInternalParams *)
2847         {
2848             return MFX_ERR_UNSUPPORTED;
2849         }
2850 
2851         virtual mfxStatus EncodeFrameCheck(
2852             mfxEncodeCtrl *           ctrl,
2853             mfxFrameSurface1 *        surface,
2854             mfxBitstream *            bs,
2855             mfxFrameSurface1 **       reordered_surface,
2856             mfxEncodeInternalParams * internalParams,
2857             MFX_ENTRY_POINT *         entryPoints,
2858             mfxU32 &                  numEntryPoints);
2859 
2860         virtual mfxStatus EncodeFrameCheckNormalWay(
2861             mfxEncodeCtrl *           ctrl,
2862             mfxFrameSurface1 *        surface,
2863             mfxBitstream *            bs,
2864             mfxFrameSurface1 **       reordered_surface,
2865             mfxEncodeInternalParams * internalParams,
2866             MFX_ENTRY_POINT *         entryPoints,
2867             mfxU32 &                  numEntryPoints);
2868 
EncodeFrame(mfxEncodeCtrl *,mfxEncodeInternalParams *,mfxFrameSurface1 *,mfxBitstream *)2869         virtual mfxStatus EncodeFrame(
2870             mfxEncodeCtrl *,
2871             mfxEncodeInternalParams *,
2872             mfxFrameSurface1 *,
2873             mfxBitstream *)
2874         {
2875             return MFX_ERR_UNSUPPORTED;
2876         }
2877 
CancelFrame(mfxEncodeCtrl *,mfxEncodeInternalParams *,mfxFrameSurface1 *,mfxBitstream *)2878         virtual mfxStatus CancelFrame(
2879             mfxEncodeCtrl *,
2880             mfxEncodeInternalParams *,
2881             mfxFrameSurface1 *,
2882             mfxBitstream *)
2883         {
2884             return MFX_ERR_UNSUPPORTED;
2885         }
2886 
2887     protected:
2888 #if defined(MFX_ENABLE_MCTF_IN_AVC)
2889         std::shared_ptr<CMC>
2890             amtMctf;
2891 
2892         mfxStatus SubmitToMctf(
2893             DdiTask * pTask
2894         );
2895         mfxStatus QueryFromMctf(
2896             void *pParam
2897         );
2898 #endif
2899         ASC       amtScd;
2900         mfxStatus SCD_Put_Frame(
2901             DdiTask & newTask);
2902         mfxStatus SCD_Get_FrameType(
2903             DdiTask & newTask);
2904         mfxStatus CalculateFrameCmplx(
2905             DdiTask const &task,
2906             mfxU32 &raca128);
2907         mfxStatus Prd_LTR_Operation(
2908             DdiTask & task);
2909         void      AssignFrameTypes(
2910             DdiTask & newTask);
2911         mfxStatus BuildPPyr(
2912             DdiTask & task,
2913             mfxU32 pyrWidth,
2914             bool bLastFrameUsing,
2915             bool bResetPyr);
2916         void setFrameInfo(DdiTask & task,
2917             mfxU32    fid);
2918         void      AssignDecodeTimeStamp(
2919             DdiTask & task);
2920         void PreserveTimeStamp(
2921             mfxU64 timeStamp);
2922         mfxStatus UpdateBitstream(
2923             DdiTask & task,
2924             mfxU32    fid); // 0 - top/progressive, 1 - bottom
2925 
2926 #ifndef MFX_AVC_ENCODING_UNIT_DISABLE
2927         void FillEncodingUnitsInfo(
2928             DdiTask &task,
2929             mfxU8 *sbegin,
2930             mfxU8 *send,
2931             mfxExtEncodedUnitsInfo *encUnitsInfo,
2932             mfxU32 fid);
2933 #endif
2934 
2935         mfxStatus AsyncRoutine(
2936             mfxBitstream * bs);
2937 
2938         mfxStatus CheckSliceSize(DdiTask &task, bool &bToRecode);
2939         mfxStatus CheckBufferSize(DdiTask &task, bool &bToRecode, mfxU32 bsDataLength, mfxBitstream * bs);
2940         mfxStatus CheckBRCStatus(DdiTask &task, bool &bToRecode, mfxU32 bsDataLength);
2941         mfxStatus FillPreEncParams(DdiTask &task);
2942         void OnNewFrame();
2943         void SubmitScd();
2944         void OnScdQueried();
2945         void OnScdFinished();
2946 
2947         void SubmitAdaptiveGOP();
2948         bool OnAdaptiveGOPSubmitted();
2949 
2950         void SubmitMCTF();
2951         void OnMctfQueried();
2952         void OnMctfFinished();
2953 
2954         void OnLookaheadSubmitted(DdiTaskIter task);
2955 
2956         void OnLookaheadQueried();
2957 
2958         void OnHistogramSubmitted();
2959 
2960         void OnHistogramQueried();
2961 
2962         void OnEncodingSubmitted(DdiTaskIter task);
2963 
2964         void OnEncodingQueried(DdiTaskIter task);
2965 
2966         void BrcPreEnc(DdiTask const & task);
2967 
2968         static mfxStatus AsyncRoutineHelper(
2969             void * state,
2970             void * param,
2971             mfxU32 threadNumber,
2972             mfxU32 callNumber);
2973 
2974         void RunPreMe(
2975             MfxVideoParam const & video,
2976             DdiTask const &       task);
2977 
2978         void SubmitLookahead(
2979             DdiTask & task);
2980 
2981         mfxStatus QueryLookahead(
2982             DdiTask & task);
2983 
2984         mfxStatus QueryStatus(
2985             DdiTask & task,
2986             mfxU32    ffid);
2987 
2988 
2989         mfxStatus MiniGopSize(
2990             mfxEncodeCtrl**           ctrl,
2991             mfxFrameSurface1**        surface,
2992             mfxU16* requiredFrameType);
2993 
2994         mfxStatus MiniGopSize1(
2995             mfxEncodeCtrl**           ctrl,
2996             mfxFrameSurface1**        surface,
2997             mfxU16* requiredFrameType);
2998 
2999         mfxStatus ProcessAndCheckNewParameters(
3000             MfxVideoParam & newPar,
3001             bool & isBRCReset,
3002             bool & isIdrRequired,
3003             mfxVideoParam const * newParIn = 0);
3004 
3005         void DestroyDanglingCmResources();
3006 
3007         VideoCORE *         m_core;
3008         CmDevicePtr         m_cmDevice;
3009         MfxVideoParam       m_video;
3010         MfxVideoParam       m_videoInit;  // m_video may change by Reset, m_videoInit doesn't change
3011         mfxEncodeStat       m_stat;
3012 
3013         std::list<std::pair<mfxBitstream *, mfxU32> > m_listOfPairsForFieldOutputMode;
3014 
3015         AsyncRoutineEmulator m_emulatorForSyncPart;
3016         AsyncRoutineEmulator m_emulatorForAsyncPart;
3017 
3018         SliceDivider        m_sliceDivider;
3019 
3020         std::list<DdiTask>  m_free;
3021         std::list<DdiTask>  m_incoming;
3022         std::list<DdiTask>  m_ScDetectionStarted;
3023         std::list<DdiTask>  m_ScDetectionFinished;
3024         std::list<DdiTask>  m_MctfStarted;
3025         std::list<DdiTask>  m_MctfFinished;
3026         std::list<DdiTask>  m_reordering;
3027         std::list<DdiTask>  m_lookaheadStarted;
3028         std::list<DdiTask>  m_lookaheadFinished;
3029         std::list<DdiTask>  m_histRun;
3030         std::list<DdiTask>  m_histWait;
3031         std::list<DdiTask>  m_encoding;
3032         std::list<mfxU64>   m_timeStamps;
3033         UMC::Mutex          m_listMutex;
3034         DdiTask             m_lastTask;
3035         mfxU32              m_stagesToGo;
3036         mfxU32              m_bDeferredFrame;
3037 
3038         mfxU32      m_fieldCounter;
3039         mfxStatus   m_1stFieldStatus;
3040         mfxU32      m_frameOrder;
3041         mfxU32      m_baseLayerOrder;
3042         mfxU32      m_frameOrderIdrInDisplayOrder;    // frame order of last IDR frame (in display order)
3043         mfxU32      m_frameOrderIntraInDisplayOrder;  // frame order of last I frame (in display order)
3044         mfxU32      m_frameOrderIPInDisplayOrder;  // frame order of last I or P frame (in display order)
3045         mfxU32      m_frameOrderPyrStart;          // frame order of the first frame of pyramid
3046         mfxU32      m_miniGopCount;
3047         mfxU32      m_frameOrderStartTScalStructure; // starting point of temporal scalability structure
3048 
3049         // parameters for Intra refresh
3050         mfxI64      m_baseLayerOrderStartIntraRefresh; // starting point of Intra refresh cycles (could be negative)
3051         mfxU16      m_intraStripeWidthInMBs; // width of Intra MB stripe (column or row depending on refresh type)
3052 
3053         mfxU32      m_enabledSwBrc;
3054         Brc         m_brc;
3055         Hrd         m_hrd;
3056 #if defined(MFX_ENABLE_ENCTOOLS)
3057         H264EncTools m_encTools;
3058         bool         m_enabledEncTools;
3059 #endif
3060         mfxU32      m_maxBsSize;
3061 
3062         std::unique_ptr<DriverEncoder>    m_ddi;
3063 
3064         std::vector<mfxU32>     m_recFrameOrder;
3065 
3066         mfxU32 m_recNonRef[2];
3067 
3068 #if defined(MFX_ENABLE_MCTF_IN_AVC)
3069         MfxFrameAllocResponse   m_mctf;
3070 #endif
3071         MfxFrameAllocResponse   m_scd;
3072         MfxFrameAllocResponse   m_raw;
3073         MfxFrameAllocResponse   m_rawSkip;
3074         MfxFrameAllocResponse   m_rawLa;
3075         MfxFrameAllocResponse   m_mb;
3076         MfxFrameAllocResponse   m_curbe;
3077         MfxFrameAllocResponse   m_rawSys;
3078         MfxFrameAllocResponse   m_rec;
3079         MfxFrameAllocResponse   m_bit;
3080         MfxFrameAllocResponse   m_opaqResponse;     // Response for opaq
3081         MfxFrameAllocResponse   m_histogram;
3082 
3083         MFX_ENCODE_CAPS         m_caps;
3084         mfxStatus               m_failedStatus;
3085         mfxU32                  m_inputFrameType;
3086         mfxU32                  m_NumSlices;
3087 
3088         MfxFrameAllocResponse   m_mbqp;
3089         bool                    m_useMBQPSurf;
3090 
3091         MfxFrameAllocResponse   m_mbControl;
3092         bool                    m_useMbControlSurfs;
3093 
3094         std::vector<mfxU8>  m_tmpBsBuf;
3095         PreAllocatedVector  m_sei;
3096 
3097         eMFXHWType  m_currentPlatform;
3098         eMFXVAType  m_currentVaType;
3099         bool        m_useWAForHighBitrates;
3100         bool        m_isENCPAK;
3101         bool        m_resetBRC;
3102 
3103         // bitrate reset for SNB
3104 
3105         std::unique_ptr<CmContext>    m_cmCtx;
3106         std::vector<VmeData>        m_vmeDataStorage;
3107         std::vector<VmeData *>      m_tmpVmeData;
3108 
3109 
3110         std::list<DdiTask>  m_adaptiveGOPBuffered;
3111         std::list<DdiTask>  m_adaptiveGOPSubmitted;
3112         std::list<DdiTask>  m_adaptiveGOPFinished;
3113         std::list<DdiTask>  m_adaptiveGOPReady;
3114         mfxU32      m_LowDelayPyramidLayer;
3115         mfxI32      m_LtrQp;
3116         mfxI32      m_LtrOrder;
3117         mfxI32      m_RefQp;
3118         mfxI32      m_RefOrder;
3119 
3120     };
3121 
3122 
3123     struct NalUnit
3124     {
NalUnitNalUnit3125         NalUnit() : begin(0), end(0), type(0), numZero(0)
3126         {}
3127 
NalUnitNalUnit3128         NalUnit(mfxU8 * b, mfxU8 * e, mfxU8 t, mfxU8 z) : begin(b), end(e), type(t), numZero(z)
3129         {}
3130 
3131         mfxU8 * begin;
3132         mfxU8 * end;
3133         mfxU8   type;
3134         mfxU32  numZero;
3135     };
3136 
3137     NalUnit GetNalUnit(mfxU8 * begin, mfxU8 * end);
3138 
3139     class NaluIterator
3140     {
3141     public:
NaluIterator()3142         NaluIterator()
3143             : m_begin(0)
3144             , m_end(0)
3145         {}
3146 
NaluIterator(mfxU8 * begin,mfxU8 * end)3147         NaluIterator(mfxU8 * begin, mfxU8 * end)
3148             : m_nalu(GetNalUnit(begin, end))
3149             , m_begin(m_nalu.end)
3150             , m_end(end)
3151         {
3152         }
3153 
NaluIterator(NalUnit const & nalu,mfxU8 * end)3154         NaluIterator(NalUnit const & nalu, mfxU8 * end)
3155             : m_nalu(nalu)
3156             , m_begin(nalu.end)
3157             , m_end(end)
3158         {
3159         }
3160 
3161         NalUnit & operator *()
3162         {
3163             return m_nalu;
3164         }
3165 
3166         NalUnit * operator ->()
3167         {
3168             return &m_nalu;
3169         }
3170 
3171         NaluIterator & operator++()
3172         {
3173             m_nalu = GetNalUnit(m_begin, m_end);
3174             m_begin = m_nalu.end;
3175             return *this;
3176         }
3177 
3178         NaluIterator operator++(int)
3179         {
3180             NaluIterator tmp;
3181             ++*this;
3182             return tmp;
3183         }
3184 
3185         bool operator ==(NaluIterator const & right) const
3186         {
3187             return m_nalu.begin == right.m_nalu.begin && m_nalu.end == right.m_nalu.end;
3188         }
3189 
3190         bool operator !=(NaluIterator const & right) const
3191         {
3192             return !(*this == right);
3193         }
3194 
3195     private:
3196         NalUnit m_nalu;
3197         mfxU8 * m_begin;
3198         mfxU8 * m_end;
3199     };
3200 
3201     struct BitstreamDesc
3202     {
BitstreamDescBitstreamDesc3203         BitstreamDesc() : begin(0), end(0)
3204         {}
3205 
3206         mfxU8 * begin;
3207         mfxU8 * end;
3208         NalUnit aud;   // byte range within [begin, end)
3209         NalUnit sps;   // byte range within [begin, end)
3210         NalUnit pps;   // byte range within [begin, end)
3211         NalUnit sei;   // first sei if multi sei nal units present
3212         NalUnit slice; // first slice if multi-sliced
3213     };
3214 
3215 
3216     class InputBitstream
3217     {
3218     public:
3219         InputBitstream(
3220             mfxU8 const * buf,
3221             size_t        size,
3222             bool          hasStartCode = true,
3223             bool          doEmulationControl = true);
3224 
3225         InputBitstream(
3226             mfxU8 const * buf,
3227             mfxU8 const * bufEnd,
3228             bool          hasStartCode = true,
3229             bool          doEmulationControl = true);
3230 
3231         mfxU32 NumBitsRead() const;
3232         mfxU32 NumBitsLeft() const;
3233 
3234         mfxU32 GetBit();
3235         mfxU32 GetBits(mfxU32 nbits);
3236         mfxU32 GetUe();
3237         mfxI32 GetSe();
3238 
3239     private:
3240         mfxU8 const * m_buf;
3241         mfxU8 const * m_ptr;
3242         mfxU8 const * m_bufEnd;
3243         mfxU32        m_bitOff;
3244         bool          m_doEmulationControl;
3245     };
3246 
3247     class OutputBitstream
3248     {
3249     public:
3250         OutputBitstream(mfxU8 * buf, size_t size, bool emulationControl = true);
3251         OutputBitstream(mfxU8 * buf, mfxU8 * bufEnd, bool emulationControl = true);
3252 
3253         mfxU32 GetNumBits() const;
3254 
3255         void PutBit(mfxU32 bit);
3256         void PutBits(mfxU32 val, mfxU32 nbits);
3257         void PutUe(mfxU32 val);
3258         void PutSe(mfxI32 val);
3259         void PutRawBytes(mfxU8 const * begin, mfxU8 const * end); // startcode emulation is not controlled
3260         void PutFillerBytes(mfxU8 filler, mfxU32 nbytes);         // startcode emulation is not controlled
3261         void PutTrailingBits();
3262 
3263     private:
3264         mfxU8 * m_buf;
3265         mfxU8 * m_ptr;
3266         mfxU8 * m_bufEnd;
3267         mfxU32  m_bitOff;
3268         bool    m_emulationControl;
3269     };
3270 
3271     class CabacPackerSimple : public OutputBitstream
3272     {
3273     public:
3274         CabacPackerSimple(mfxU8 * buf, mfxU8 * bufEnd, bool emulationControl = true);
3275         void EncodeBin(mfxU8  * ctx, mfxU8 bin);
3276         void TerminateEncode();
3277     private:
3278         void PutBitC(mfxU32 B);
3279         void RenormE();
3280 
3281         mfxU32 m_codILow;
3282         mfxU32 m_codIRange;
3283         mfxU32 m_bitsOutstanding;
3284         mfxU32 m_BinCountsInNALunits;
3285         bool   m_firstBitFlag;
3286     };
3287 
3288     void PutSeiHeader(
3289         OutputBitstream & bs,
3290         mfxU32            payloadType,
3291         mfxU32            payloadSize);
3292 
3293     void PutSeiMessage(
3294         OutputBitstream &                   bs,
3295         mfxExtAvcSeiBufferingPeriod const & msg);
3296 
3297     void PutSeiMessage(
3298         OutputBitstream &              bs,
3299         mfxExtPictureTimingSEI const & extPt,
3300         mfxExtAvcSeiPicTiming const &  msg);
3301 
3302     void PutSeiMessage(
3303         OutputBitstream &                   bs,
3304         mfxExtAvcSeiDecRefPicMrkRep const & msg);
3305 
3306     void PutSeiMessage(
3307         OutputBitstream &    bs,
3308         mfxExtAvcSeiRecPoint const & msg);
3309 
3310     mfxU32 PutScalableInfoSeiMessage(
3311         OutputBitstream &     obs,
3312         MfxVideoParam const & par);
3313 
3314 // MVC BD {
3315     // Put MVC scalable nested SEI
3316     void PutSeiMessage(
3317         OutputBitstream &                   bs,
3318         mfxU32 needBufferingPeriod,
3319         mfxU32 needPicTimingSei,
3320         mfxU32 fillerSize,
3321         MfxVideoParam const & video,
3322         mfxExtAvcSeiBufferingPeriod const & msg_bp,
3323         mfxExtPictureTimingSEI const & extPt,
3324         mfxExtAvcSeiPicTiming const &  msg_pt);
3325 // MVC BD }
3326 
3327 
3328 
3329     mfxU8 const * SkipStartCode(mfxU8 const * begin, mfxU8 const * end);
3330     mfxU8 *       SkipStartCode(mfxU8 *       begin, mfxU8 *       end);
3331 
3332     ArrayRefListMod CreateRefListMod(
3333         ArrayDpbFrame const &            dpb,
3334         std::vector<Reconstruct> const & recons,
3335         ArrayU8x33                       initList,
3336         ArrayU8x33 const &               modList,
3337         mfxU32                           curViewIdx,
3338         mfxI32                           curPicNum,
3339         bool                             optimize = true);
3340 
3341     mfxU8 * CheckedMFX_INTERNAL_CPY(
3342         mfxU8 *       dbegin,
3343         mfxU8 *       dend,
3344         mfxU8 const * sbegin,
3345         mfxU8 const * send);
3346 
3347     mfxU8 * CheckedMemset(
3348         mfxU8 * dbegin,
3349         mfxU8 * dend,
3350         mfxU8   value,
3351         mfxU32  size);
3352 
3353     void ReadRefPicListModification(InputBitstream & reader);
3354 
3355     void ReadDecRefPicMarking(
3356         InputBitstream & reader,
3357         bool             idrPicFlag);
3358 
3359     void WriteRefPicListModification(
3360         OutputBitstream &       writer,
3361         ArrayRefListMod const & refListMod);
3362 
3363     void WriteDecRefPicMarking(
3364         OutputBitstream &            writer,
3365         DecRefPicMarkingInfo const & marking,
3366         bool                         idrPicFlag);
3367 
3368     mfxU8 * RePackSlice(
3369         mfxU8 *               dbegin,
3370         mfxU8 *               dend,
3371         mfxU8 *               sbegin,
3372         mfxU8 *               send,
3373         MfxVideoParam const & par,
3374         DdiTask const &       task,
3375         mfxU32                fieldId);
3376 
3377     enum
3378     {
3379         RPLM_ST_PICNUM_SUB  = 0,
3380         RPLM_ST_PICNUM_ADD  = 1,
3381         RPLM_LT_PICNUM      = 2,
3382         RPLM_END            = 3,
3383         RPLM_INTERVIEW_SUB  = 4,
3384         RPLM_INTERVIEW_ADD  = 5,
3385     };
3386 
3387     enum
3388     {
3389         MMCO_END            = 0,
3390         MMCO_ST_TO_UNUSED   = 1,
3391         MMCO_LT_TO_UNUSED   = 2,
3392         MMCO_ST_TO_LT       = 3,
3393         MMCO_SET_MAX_LT_IDX = 4,
3394         MMCO_ALL_TO_UNUSED  = 5,
3395         MMCO_CURR_TO_LT     = 6,
3396     };
3397 
3398 
3399     void PrepareSeiMessageBuffer(
3400         MfxVideoParam const & video,
3401         DdiTask const &       task,
3402         mfxU32                fieldId, // 0 - top/progressive, 1 - bottom
3403         PreAllocatedVector &  sei);
3404 
3405     void PrepareSeiMessageBufferDepView(
3406         MfxVideoParam const & video,
3407         DdiTask const &       task,
3408         mfxU32                fieldId, // 0 - top/progressive, 1 - bottom
3409         PreAllocatedVector &  sei);
3410 
3411 
3412     bool IsInplacePatchNeeded(
3413         MfxVideoParam const & par,
3414         DdiTask const &       task,
3415         mfxU32                fieldId);
3416 
3417     bool IsSlicePatchNeeded(
3418         DdiTask const & task,
3419         mfxU32          fieldId);
3420 
3421     mfxStatus  CopyBitstream(
3422                 VideoCORE           & core,
3423                 MfxVideoParam const & video,
3424                 DdiTask const       & task,
3425                 mfxU32              fieldId,
3426                 mfxU8 *             bsData,
3427                 mfxU32              bsSizeAvail);
3428 
3429     mfxU32 GetMaxSliceSize(
3430         mfxU8 *               sbegin, // contents of source buffer may be modified
3431         mfxU8 *               send,
3432         mfxU32                &num);
3433 
3434 
3435     mfxStatus UpdateSliceInfo(
3436         mfxU8 *               sbegin, // contents of source buffer may be modified
3437         mfxU8 *               send,
3438         mfxU32                maxSliceSize,
3439         DdiTask&              task,
3440         bool&                 bRecoding);
3441 
3442     mfxU8 * PatchBitstream(
3443         MfxVideoParam const & video,
3444         DdiTask const &       task,
3445         mfxU32                fieldId,
3446         mfxU8 *               sbegin, // contents of source buffer may be modified
3447         mfxU8 *               send,
3448         mfxU8 *               dbegin,
3449         mfxU8 *               dend);
3450     mfxU8 * InsertSVCNAL(
3451         DdiTask const &       task,
3452         mfxU32                fieldId,
3453         mfxU8 *               sbegin, // contents of source buffer may be modified
3454         mfxU8 *               send,
3455         mfxU8 *               dbegin,
3456         mfxU8 *               dend);
3457 
3458     mfxU8 * AddEmulationPreventionAndCopy(
3459         mfxU8 *               sbegin,
3460         mfxU8 *               send,
3461         mfxU8 *               dbegin,
3462         mfxU8 *               dend);
3463 
3464     mfxStatus FillSliceInfo(
3465         DdiTask &           task,
3466         mfxU32              MaxSliceSize,
3467         mfxU32              FrameSize,
3468         mfxU32              widthLa,
3469         mfxU32              heightLa);
3470 
3471     mfxStatus CorrectSliceInfo(
3472         DdiTask &           task,
3473         mfxU32              sliceWeight,
3474         mfxU32              widthLa,
3475         mfxU32              heightLa);
3476 
3477     mfxStatus CorrectSliceInfoForsed(
3478         DdiTask &           task,
3479         mfxU32              widthLa,
3480         mfxU32              heightLa);
3481 
3482 
3483 
3484     mfxU32 CalcBiWeight(
3485         DdiTask const & task,
3486         mfxU32 indexL0,
3487         mfxU32 indexL1);
3488 
3489 
3490     mfxI32 GetPicNum(
3491         ArrayDpbFrame const & dpb,
3492         mfxU8                 ref);
3493 
3494     mfxI32 GetPicNumF(
3495         ArrayDpbFrame const & dpb,
3496         mfxU8                 ref);
3497 
3498     mfxU8 GetLongTermPicNum(
3499         ArrayDpbFrame const & dpb,
3500         mfxU8                 ref);
3501 
3502     mfxU32 GetLongTermPicNumF(
3503         ArrayDpbFrame const & dpb,
3504         mfxU8                 ref);
3505 
3506     mfxI32 GetPoc(
3507         ArrayDpbFrame const & dpb,
3508         mfxU8                 ref);
3509 
3510     DdiTaskIter ReorderFrame(
3511         ArrayDpbFrame const & dpb,
3512         DdiTaskIter           begin,
3513         DdiTaskIter           end);
3514 
3515     DdiTaskIter ReorderFrame(
3516         ArrayDpbFrame const & dpb,
3517         DdiTaskIter           begin,
3518         DdiTaskIter           end,
3519         bool                  gopStrict,
3520         bool                  flush,
3521         bool                  closeGopForSceneChange);
3522 
3523     DdiTaskIter FindFrameToStartEncode(
3524         MfxVideoParam const & video,
3525         DdiTaskIter           begin,
3526         DdiTaskIter           end);
3527 
3528     DdiTaskIter FindFrameToWaitEncode(
3529         DdiTaskIter begin,
3530         DdiTaskIter end);
3531     DdiTaskIter FindFrameToWaitEncodeNext(
3532         DdiTaskIter begin,
3533         DdiTaskIter end,
3534         DdiTaskIter cur);
3535 
3536     PairU8 GetFrameType(
3537         MfxVideoParam const & video,
3538         mfxU32                frameOrder);
3539 
3540     IntraRefreshState GetIntraRefreshState(
3541         MfxVideoParam const & video,
3542         mfxU32                frameOrderInGop,
3543         mfxEncodeCtrl const * ctrl,
3544         mfxU16                intraStripeWidthInMBs,
3545         SliceDivider &        divider,
3546         MFX_ENCODE_CAPS       caps);
3547 
3548     mfxStatus UpdateIntraRefreshWithoutIDR(
3549         MfxVideoParam const & oldPar,
3550         MfxVideoParam const & newPar,
3551         mfxU32                frameOrder,
3552         mfxI64                oldStartFrame,
3553         mfxI64 &              updatedStartFrame,
3554         mfxU16 &              updatedStripeWidthInMBs,
3555         SliceDivider &        divider,
3556         MFX_ENCODE_CAPS       caps);
3557 
3558     BiFrameLocation GetBiFrameLocation(
3559         MfxVideoParam const & video,
3560         mfxU32                frameOrder,
3561         mfxU32                currGopRefDist,
3562         mfxU32                miniGOPCount);
3563 
3564     void UpdateDpbFrames(
3565         DdiTask & task,
3566         mfxU32    field,
3567         mfxU32    frameNumMax);
3568 
3569     void InitRefPicList(
3570         DdiTask & task,
3571         mfxU32    field);
3572 
3573     void ModifyRefPicLists(
3574         MfxVideoParam const & video,
3575         DdiTask &             task,
3576         mfxU32                fieldId);
3577 
3578     void MarkDecodedRefPictures(
3579         MfxVideoParam const & video,
3580         DdiTask &             task,
3581         mfxU32                fid);
3582 
3583     ArrayRefListMod CreateRefListMod(
3584         ArrayDpbFrame const & dpb,
3585         ArrayU8x33            initList,
3586         ArrayU8x33 const &    modList,
3587         mfxU32                curViewIdx,
3588         mfxI32                curPicNum,
3589         bool                  optimize);
3590 
3591     void ConfigureTask(
3592         DdiTask &                 task,
3593         DdiTask const &           prevTask,
3594         MfxVideoParam const &     video,
3595         MFX_ENCODE_CAPS const &   caps);
3596 
3597     mfxStatus GetNativeHandleToRawSurface(
3598         VideoCORE &           core,
3599         MfxVideoParam const & video,
3600         DdiTask const &       task,
3601         mfxHDLPair &          handle);
3602 
3603     bool IsFrameToSkip(DdiTask&  task, MfxFrameAllocResponse & poolRec, std::vector<mfxU32> fo, bool bSWBRC);
3604     mfxStatus CodeAsSkipFrame(  VideoCORE&            core,
3605                                 MfxVideoParam const & video,
3606                                 DdiTask&       task,
3607                                 MfxFrameAllocResponse & pool,
3608                                 MfxFrameAllocResponse & poolRec);
3609     mfxStatus CopyRawSurfaceToVideoMemory(
3610         VideoCORE &           core,
3611         MfxVideoParam const & video,
3612         DdiTask const &       task);
3613 
3614     mfxHDL ConvertMidToNativeHandle(
3615         VideoCORE & core,
3616         mfxMemId    mid,
3617         bool        external = false);
3618 
3619     void AnalyzeVmeData(
3620         DdiTaskIter begin,
3621         DdiTaskIter end,
3622         mfxU32      width,
3623         mfxU32      height);
3624 
3625     void CalcPredWeightTable(
3626         DdiTask & task,
3627         mfxU32 MaxNum_WeightedPredL0,
3628         mfxU32 MaxNum_WeightedPredL1);
3629 
3630 
3631     struct FindByFrameOrder
3632     {
FindByFrameOrderFindByFrameOrder3633         FindByFrameOrder(mfxU32 frameOrder) : m_frameOrder(frameOrder) {}
3634 
operatorFindByFrameOrder3635         template <class T> bool operator ()(T const & task) const
3636         {
3637             return task.m_frameOrder == m_frameOrder;
3638         }
3639 
3640         mfxU32 m_frameOrder;
3641     };
3642 
3643     bool OrderByFrameNumWrap(DpbFrame const & lhs, DpbFrame const & rhs);
3644     bool OrderByFrameNumWrapKeyRef(DpbFrame const & lhs, DpbFrame const & rhs);
3645 
find_if_ptr(T & container,P pred)3646     template <class T, class P> typename T::pointer find_if_ptr(T & container, P pred)
3647     {
3648         typename T::iterator i = std::find_if(container.begin(), container.end(), pred);
3649         return (i == container.end()) ? 0 : &*i;
3650     }
3651 
find_if_ptr2(T & container1,T & container2,P pred)3652     template <class T, class P> typename T::pointer find_if_ptr2(T & container1, T & container2, P pred)
3653     {
3654         typename T::pointer p = find_if_ptr(container1, pred);
3655         if (p == 0)
3656             p = find_if_ptr(container2, pred);
3657         return p;
3658     }
find_if_ptr3(T & container1,T & container2,T & container3,P pred)3659     template <class T, class P> typename T::pointer find_if_ptr3(T & container1, T & container2, T & container3, P pred)
3660     {
3661         typename T::pointer p = find_if_ptr(container1, pred);
3662         if (p == 0)
3663             p = find_if_ptr(container2, pred);
3664         if (p == 0)
3665             p = find_if_ptr(container3, pred);
3666 
3667         return p;
3668     }
find_if_ptr4(T & container1,T & container2,T & container3,T & container4,P pred)3669     template <class T, class P> typename T::pointer find_if_ptr4(T & container1, T & container2, T & container3, T & container4, P pred)
3670     {
3671         typename T::pointer p = find_if_ptr(container1, pred);
3672         if (p == 0)
3673             p = find_if_ptr(container2, pred);
3674         if (p == 0)
3675             p = find_if_ptr(container3, pred);
3676         if (p == 0)
3677             p = find_if_ptr(container4, pred);
3678 
3679         return p;
3680     }
3681 }; // namespace MfxHwH264Encode
3682 
3683 #endif // _MFX_H264_ENCODE_HW_UTILS_H_
3684 #endif // MFX_ENABLE_H264_VIDEO_ENCODE_HW
3685