1 // Copyright (c) 2017-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 
21 #ifndef _MFX_FRAMES_H_
22 #define _MFX_FRAMES_H_
23 
24 #include <memory.h>
25 #include <mutex>
26 #include "mfxdefs.h"
27 #include "mfx_common_int.h"
28 
29 #define NUM_TASKS 256
30 
31     /*------- Task  between sync/async encoder parts (1 entry point in async part)-------------------------*/
32 
33     struct sExtTask1
34     {
35       mfxEncodeInternalParams   m_inputInternalParams;
36       mfxFrameSurface1          *m_pInput_surface;
37       mfxBitstream              *m_pBs;
38 
sExtTask1sExtTask139       sExtTask1()
40           : m_inputInternalParams()
41       {
42           m_pInput_surface = 0;
43           m_pBs = 0;
44       }
~sExtTask1sExtTask145       virtual ~sExtTask1()
46       {
47       }
48     };
49 
50     /*------- Task  between sync/async encoder parts (2 entry points in async part: submit and query)------------*/
51 
52     struct sExtTask2 : public sExtTask1
53     {
54         mfxU32            m_nInternalTask;
55 
sExtTask2sExtTask256         sExtTask2():
57             sExtTask1(),
58             m_nInternalTask(0)
59         {
60         }
~sExtTask2sExtTask261         virtual ~sExtTask2()
62         {
63         }
64     };
65 
66     /*------- Tasks between sync/async encoder parts (1 entry point in async part)-------------------------*/
67 
68     class clExtTasks1
69     {
70     public:
clExtTasks1()71         clExtTasks1()
72         {
73            m_numTasks          = 0;
74            m_currTask          = 0;
75            m_maxTasks          = NUM_TASKS;
76            m_pTasks            = new sExtTask1[m_maxTasks];
77         }
~clExtTasks1()78         virtual ~clExtTasks1()
79         {
80             if (m_pTasks)
81             {
82                 delete [] m_pTasks;
83             }
84         }
85 
AddTask(mfxEncodeInternalParams * pParams,mfxFrameSurface1 * input_surface,mfxBitstream * bs,sExtTask1 ** pOutTask)86         mfxStatus AddTask ( mfxEncodeInternalParams *pParams,
87                             mfxFrameSurface1 *input_surface,
88                             mfxBitstream *bs,
89                             sExtTask1 **pOutTask)
90         {
91             std::lock_guard<std::mutex> guard(m_mGuard);
92             if (m_numTasks < m_maxTasks)
93             {
94                 sExtTask1 *pTask = &m_pTasks[(m_currTask + m_numTasks)% m_maxTasks];
95                 if (pParams)
96                 {
97                     pTask->m_inputInternalParams = *pParams;
98                 }
99                 pTask->m_pInput_surface = input_surface;
100                 pTask->m_pBs = bs;
101                 *pOutTask = pTask;
102                 m_numTasks ++;
103                 return MFX_ERR_NONE;
104             }
105             return MFX_WRN_IN_EXECUTION;
106         }
CheckTask(sExtTask1 * pInputTask)107         mfxStatus CheckTask (sExtTask1 *pInputTask)
108         {
109             mfxStatus sts = MFX_ERR_MORE_DATA;
110             std::lock_guard<std::mutex> guard(m_mGuard);
111             if (m_numTasks > 0)
112             {
113                 /* task for current frame or task for the same frame */
114                 if (pInputTask == &m_pTasks[m_currTask])
115                 {
116                     sts = MFX_ERR_NONE;
117                 }
118                 else
119                 {
120                     m_currTask = (m_currTask + 1)% m_maxTasks;
121                     m_numTasks = m_numTasks - 1;
122                     if (m_numTasks > 0 && pInputTask == &m_pTasks[m_currTask])
123                     {
124                         sts = MFX_ERR_NONE;
125                     }
126                 }
127             }
128             return sts;
129         }
130 
131     private:
132         sExtTask1* m_pTasks;
133         std::mutex      m_mGuard;
134 
135         mfxU32          m_maxTasks;
136         mfxU32          m_numTasks;
137         mfxU32          m_currTask;
138 
139 
140         // Declare private copy constructor to avoid accidental assignment
141         // and klocwork complaining.
142 
143         clExtTasks1(const clExtTasks1 &);
144         clExtTasks1 & operator = (const clExtTasks1 &);
145     };
146 
147     /*------- Tasks between sync/async encoder parts (2 entry points in async part: submit and query)------------*/
148 
149     class clExtTasks2
150     {
151     public:
clExtTasks2()152         clExtTasks2()
153         {
154            m_numTasks          = 0;
155            m_currTask          = 0;
156            m_maxTasks          = NUM_TASKS;
157            m_pTasks            = new sExtTask2[m_maxTasks];
158            m_numSubmittedTasks = 0;
159         }
~clExtTasks2()160         virtual ~clExtTasks2()
161         {
162             if (m_pTasks)
163             {
164                 delete [] m_pTasks;
165             }
166         }
167 
AddTask(mfxEncodeInternalParams * pParams,mfxFrameSurface1 * input_surface,mfxBitstream * bs,sExtTask2 ** pOutTask)168         mfxStatus AddTask ( mfxEncodeInternalParams *pParams,
169                             mfxFrameSurface1 *input_surface,
170                             mfxBitstream *bs,
171                             sExtTask2 **pOutTask)
172         {
173             std::lock_guard<std::mutex> guard(m_mGuard);
174             if (m_numTasks < m_maxTasks)
175             {
176                 sExtTask2 *pTask = &m_pTasks[(m_currTask + m_numTasks)% m_maxTasks];
177                 if (pParams)
178                 {
179                     pTask->m_inputInternalParams = *pParams;
180                 }
181                 pTask->m_pInput_surface = input_surface;
182                 pTask->m_pBs = bs;
183                 pTask->m_nInternalTask = 0;
184 
185                 *pOutTask = pTask;
186                 m_numTasks ++;
187                 return MFX_ERR_NONE;
188             }
189             return MFX_WRN_IN_EXECUTION;
190         }
191 
CheckTaskForSubmit(sExtTask2 * pInputTask)192         mfxStatus CheckTaskForSubmit(sExtTask2 *pInputTask)
193         {
194             mfxStatus sts = MFX_ERR_MORE_DATA;
195             std::lock_guard<std::mutex> guard(m_mGuard);
196             if (m_numTasks >= m_numSubmittedTasks)
197             {
198                 if (pInputTask == m_pTasks + ((m_currTask + m_numSubmittedTasks - 1)% m_maxTasks))
199                 {
200                     sts = MFX_ERR_NONE;
201                 }
202                 else if (m_numTasks > m_numSubmittedTasks)
203                 {
204                     m_numSubmittedTasks ++;
205                     mfxU32 nTask = (m_currTask + m_numSubmittedTasks - 1)% m_maxTasks;
206                     sts  = ( pInputTask == &m_pTasks[nTask]) ? MFX_ERR_NONE : MFX_ERR_UNDEFINED_BEHAVIOR;
207                 }
208             }
209             return sts;
210         }
GetTaskForQuery()211         sExtTask2* GetTaskForQuery ()
212         {
213             std::lock_guard<std::mutex> guard(m_mGuard);
214             sExtTask2* task =  (m_numTasks > 0 && m_numSubmittedTasks > 0) ? &m_pTasks[m_currTask] : 0;
215             return task;
216         }
NextFrame()217         mfxStatus NextFrame ()
218         {
219             mfxStatus sts = MFX_ERR_UNDEFINED_BEHAVIOR;
220             std::lock_guard<std::mutex> guard(m_mGuard);
221             if (m_numTasks > 0 && m_numSubmittedTasks > 0)
222             {
223                 m_currTask  = (m_currTask + 1)% m_maxTasks;
224                 m_numTasks  = m_numTasks - 1;
225                 m_numSubmittedTasks = m_numSubmittedTasks - 1;
226                 sts = MFX_ERR_NONE;
227             }
228             return sts;
229         }
230 
231 
232     private:
233 
234         sExtTask2* m_pTasks;
235         std::mutex      m_mGuard;
236 
237         mfxU32          m_maxTasks;
238         mfxU32          m_numTasks;
239         mfxU32          m_currTask;
240         mfxU32          m_numSubmittedTasks;
241 
242         // Declare private copy constructor to avoid accidental assignment
243         // and klocwork complaining.
244 
245         clExtTasks2(const clExtTasks2 &);
246         clExtTasks2 & operator = (const clExtTasks2 &);
247     };
248 
249     struct sFrameEx
250     {
251         mfxFrameSurface1*       m_pFrame;
252         mfxU16                  m_FrameType;
253         mfxU32                  m_FrameOrder;
254         mfxEncodeInternalParams m_sEncodeInternalParams;
255         bool                    m_bAddHeader;
256         bool                    m_bAddEOS;
257         bool                    m_bOnlyBwdPrediction;
258         bool                    m_bOnlyFwdPrediction;
259     };
260 
GetFrameTypeMpeg2(mfxI32 FrameOrder,mfxI32 GOPSize,mfxI32 IPDist,bool bClosedGOP,mfxU16 * FrameType)261     inline void GetFrameTypeMpeg2 (mfxI32 FrameOrder, mfxI32 GOPSize, mfxI32 IPDist, bool bClosedGOP, mfxU16* FrameType)
262     {
263         mfxI32 pos = (GOPSize)? (FrameOrder %(GOPSize)):FrameOrder;
264 
265         if (pos == 0 || IPDist == 0 || (*FrameType & MFX_FRAMETYPE_IDR) != 0)
266         {
267             *FrameType = MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF | MFX_FRAMETYPE_IDR;
268         }
269         else
270         {
271             pos = (bClosedGOP && pos == GOPSize-1)? 0 : pos % (IPDist);
272             *FrameType  = ((pos != 0) && ((*FrameType & MFX_FRAMETYPE_REF) == 0)) ?  (mfxU16)MFX_FRAMETYPE_B : (mfxU16)(MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF);
273         }
274     }
ReleasePlane(mfxFrameSurface1 * pFrame)275     inline mfxStatus ReleasePlane(mfxFrameSurface1* pFrame)
276     {
277         if (pFrame)
278         {
279             //pFrame->Data.Locked= 0;
280         }
281 
282         return MFX_ERR_NONE;
283     }
284 
isReferenceFrame(mfxU16 FrameType)285     inline bool isReferenceFrame(mfxU16 FrameType)
286     {
287         return ((FrameType & MFX_FRAMETYPE_I) ||
288                 (FrameType & MFX_FRAMETYPE_P) ||
289                 (FrameType & MFX_FRAMETYPE_REF));
290     }
isIntraFrame(mfxU16 FrameType)291     inline bool isIntraFrame(mfxU16 FrameType)
292     {
293         return (FrameType & MFX_FRAMETYPE_I);
294     }
295 
isReferenceFrame(mfxU16 FrameType,mfxU16 FrameType2)296     inline bool isReferenceFrame(mfxU16 FrameType, mfxU16 FrameType2)
297     {
298         if(!FrameType2)
299         {
300             return ((FrameType & MFX_FRAMETYPE_I) ||
301                     (FrameType & MFX_FRAMETYPE_P) ||
302                     (FrameType & MFX_FRAMETYPE_REF));
303 
304         }
305         else
306         {
307             return (((FrameType & MFX_FRAMETYPE_I) ||
308                     (FrameType & MFX_FRAMETYPE_P) ||
309                     (FrameType & MFX_FRAMETYPE_REF))
310                     &&
311                    ((FrameType2 & MFX_FRAMETYPE_I) ||
312                     (FrameType2 & MFX_FRAMETYPE_P) ||
313                     (FrameType2 & MFX_FRAMETYPE_REF)) );
314         }
315     }
316 
isPredictedFrame(mfxU16 FrameType)317     inline bool isPredictedFrame(mfxU16 FrameType)
318     {
319          return (FrameType & MFX_FRAMETYPE_P) != 0;
320     }
321 
isPredictedFrame(mfxU16 FrameType,mfxU16 FrameType2)322     inline bool isPredictedFrame(mfxU16 FrameType, mfxU16 FrameType2)
323     {
324          return ((FrameType & MFX_FRAMETYPE_P) || (FrameType2 & MFX_FRAMETYPE_P)) != 0;
325     }
326 
isBPredictedFrame(mfxU16 FrameType)327     inline bool isBPredictedFrame(mfxU16 FrameType)
328     {
329          return (FrameType & MFX_FRAMETYPE_B) != 0;
330     }
331 
isBPredictedFrame(mfxU16 FrameType,mfxU16 FrameType2)332     inline bool isBPredictedFrame(mfxU16 FrameType, mfxU16 FrameType2)
333     {
334         return ((FrameType & MFX_FRAMETYPE_B) || (FrameType2 & MFX_FRAMETYPE_B)) != 0;
335     }
336 
337 
338     class MFXGOP
339     {
340     public:
MFXGOP()341         MFXGOP():
342           m_maxB(0),
343           m_pFrames(0),
344           m_numBuffB(0),
345           m_iCurr(0),
346           m_bClosedGOP(0),
347           m_nGOPsInSeq(0),
348           m_bAddEOS(0),
349           m_bEncodedOrder(0),
350           m_nGOPs (0)
351           {};
352 
~MFXGOP()353         virtual ~MFXGOP()
354         {
355             Close();
356         }
357 
GetNumberOfB()358         inline mfxU32 GetNumberOfB()
359         {
360             return m_numBuffB;
361         }
362     protected:
363         mfxI32               m_maxB;
364         sFrameEx           * m_pFrames; /*  0     - forward  reference frame,
365                                             1     - backward reference frame
366                                             other - B frames*/
367 
368         mfxI32               m_numBuffB;
369         mfxI32               m_iCurr;
370 
371         bool                 m_bClosedGOP;
372         mfxI32               m_nGOPsInSeq;
373         bool                 m_bAddEOS;
374         bool                 m_bEncodedOrder;
375 
376         mfxI32               m_nGOPs;
377 
378 
379     protected:
380 
381 
NewGOP()382         inline bool NewGOP ()
383         {
384             mfxStatus       MFXSts = MFX_ERR_NONE;
385 
386             MFXSts = ReleasePlane(m_pFrames[0].m_pFrame);
387             if(MFXSts != MFX_ERR_NONE)
388                 return false;
389 
390             m_pFrames[0]   = m_pFrames[1];
391 
392             memset (&m_pFrames[1], 0, sizeof(sFrameEx));
393 
394             m_iCurr     = 1;
395             m_numBuffB  = 0;
396 
397             return true;
398         }
399 
AddBFrame(sFrameEx * pFrameEx)400         inline virtual bool AddBFrame(sFrameEx* pFrameEx)
401         {
402             if (m_numBuffB < m_maxB && m_pFrames[0].m_pFrame != 0 && ((m_bEncodedOrder && m_pFrames[1].m_pFrame != 0)|| (!m_bEncodedOrder && m_pFrames[1].m_pFrame == 0)))
403             {
404                 m_pFrames[m_numBuffB+2] = *pFrameEx;
405                 m_numBuffB ++;
406                 return true;
407             }
408             return false;
409         }
410 
AddReferenceFrame(sFrameEx * pFrameEx)411         inline virtual bool AddReferenceFrame(sFrameEx* pFrameEx)
412         {
413             if (m_pFrames[0].m_pFrame && m_pFrames[1].m_pFrame ) return false;
414 
415             if (isIntraFrame(pFrameEx->m_FrameType))
416             {
417                 if (!m_nGOPs)
418                 {
419                     pFrameEx->m_bAddHeader = true;
420                 }
421                 m_nGOPs ++;
422                 if (m_nGOPsInSeq!=0 && m_nGOPs >= m_nGOPsInSeq)
423                 {
424                     m_nGOPs = 0;
425                 }
426             }
427             if (m_pFrames[0].m_pFrame == 0)
428             {
429                 m_pFrames[0]= *pFrameEx;
430                 return true;
431             }
432             else if (m_pFrames[1].m_pFrame == 0)
433             {
434                 m_pFrames[1]= *pFrameEx;
435                 return true;
436             }
437             return false;
438         }
439 
440     public:
441 
AddFrame(sFrameEx * pFrameEx)442         inline bool AddFrame(sFrameEx* pFrameEx)
443         {
444             if (isReferenceFrame(pFrameEx->m_FrameType))
445             {
446                if (m_iCurr>= m_numBuffB+2 && m_bEncodedOrder)
447                {
448                     NewGOP();
449                }
450                return AddReferenceFrame(pFrameEx);
451             }
452             else
453             {
454                 return AddBFrame(pFrameEx);
455             }
456         }
457 
Init(mfxU32 maxB,bool bClosedGOP,mfxI32 nGOPsInSeq,bool bAddEOS,bool bEncodedOrder)458         inline virtual mfxStatus Init(mfxU32 maxB, bool bClosedGOP, mfxI32 nGOPsInSeq, bool bAddEOS, bool bEncodedOrder)
459         {
460             Close();
461 
462             m_maxB         = maxB;
463 
464             m_pFrames = new sFrameEx [m_maxB+2];
465 
466             Reset(bClosedGOP,nGOPsInSeq,bAddEOS, bEncodedOrder);
467             return MFX_ERR_NONE;
468         }
GetMaxBFrames()469         inline mfxI32 GetMaxBFrames ()
470         {
471             return m_maxB;
472         }
473 
Reset(bool bClosedGOP,mfxI32 nGOPsInSeq,bool bAddEOS,bool bEncodedOrder)474         inline virtual void Reset(bool bClosedGOP,mfxI32 nGOPsInSeq, bool bAddEOS,  bool bEncodedOrder)
475         {
476             if (m_pFrames)
477             {
478                 memset(m_pFrames,0,sizeof(sFrameEx)*(m_maxB+2));
479             }
480 
481             m_iCurr = 0;
482             m_numBuffB = 0;
483             m_nGOPs    = 0;
484 
485             m_bClosedGOP   = bClosedGOP;
486             m_nGOPsInSeq   = nGOPsInSeq;
487             m_bAddEOS      = bAddEOS;
488             m_bEncodedOrder = bEncodedOrder;
489 
490         };
GetFrameExForDecoding(sFrameEx * pFrame,bool bNextRefIntra,bool bNextB,bool bLast)491         inline bool GetFrameExForDecoding(sFrameEx* pFrame, bool bNextRefIntra, bool bNextB, bool bLast)
492         {
493             if (m_iCurr < m_numBuffB + 2 && m_pFrames[m_iCurr].m_pFrame)
494             {
495                 *pFrame = m_pFrames[m_iCurr];
496                 if ((m_iCurr > 1) && isIntraFrame(m_pFrames[1].m_FrameType) && (m_bClosedGOP))
497                 {
498                     pFrame->m_bOnlyBwdPrediction = true;
499                 }
500                 if (m_bAddEOS && ((bNextRefIntra && m_nGOPs == 0) || bLast) &&
501                     ((m_bEncodedOrder && !bNextB ) || (!m_bEncodedOrder && m_iCurr == 2 + m_numBuffB - 1)))
502                 {
503                     pFrame->m_bAddEOS = true;
504                 }
505 
506                 return true;
507             }
508             if (m_iCurr < m_numBuffB + 2 && !m_pFrames[m_iCurr].m_pFrame && bLast)  // check if all next fwd_only && no refs for this one
509             {
510                 m_iCurr++;
511                 *pFrame = m_pFrames[m_iCurr];
512                 if (m_bAddEOS
513                  && ((m_bEncodedOrder && !bNextB) || (!m_bEncodedOrder && m_iCurr == 2 + m_numBuffB - 1)))
514                 {
515                     pFrame->m_bAddEOS = true;
516                 }
517 
518                 return true;
519             }
520 
521             return false;
522         }
523 
ReleaseCurrentFrame()524         inline  virtual void ReleaseCurrentFrame()
525         {
526             if (!m_pFrames[m_iCurr].m_pFrame)
527                 return;
528 
529             if (m_iCurr>1)
530             {
531                 ReleasePlane(m_pFrames[m_iCurr].m_pFrame);
532                 memset (&m_pFrames[m_iCurr], 0, sizeof(sFrameEx));
533             }
534             m_iCurr++;
535             if (m_iCurr>= m_numBuffB+2 && (!m_bEncodedOrder))
536             {
537                 NewGOP();
538             }
539         }
540 
541         // with strictGop make B w/only forward reference. without - change type to P
CloseGop(bool strictGop)542         inline  virtual void CloseGop(bool strictGop)
543         {
544             if (m_pFrames[1].m_pFrame == 0 && m_numBuffB>0)
545             {
546                 mfxU16       pictureType = 0;
547 
548                 if (!strictGop)
549                 {
550                     sFrameEx *  pFrame = &m_pFrames[2 + m_numBuffB-1];
551                     m_pFrames[1]= *pFrame;
552                     pictureType = (mfxU16)(MFX_FRAMETYPE_P  | MFX_FRAMETYPE_REF);
553 
554                     memset (pFrame, 0, sizeof (sFrameEx));
555 
556                     m_numBuffB --;
557 
558                     m_pFrames[1].m_FrameType = pictureType;
559                     m_pFrames[1].m_sEncodeInternalParams.FrameType = pictureType;
560                     m_pFrames[1].m_bOnlyFwdPrediction = true;
561 
562                     if (m_bAddEOS && (m_numBuffB == 0))
563                     {
564                         m_pFrames[1].m_bAddEOS = true;
565                     }
566                 }
567                 else
568                 {
569                     for (int i = 0; i < m_numBuffB; i++)
570                     {
571                         m_pFrames[2 + i].m_bOnlyFwdPrediction = true;
572                     }
573                 }
574             }
575             if (m_bAddEOS && (!strictGop || (m_numBuffB != 0)))
576             {
577                 m_pFrames[2 + m_numBuffB - 1].m_bAddEOS = true;
578             }
579 
580         }
581         inline bool GetFrameExReference(sFrameEx* pFrame, bool bBackward = false)
582         {
583             mfxU32 n = (bBackward)? 1:0;
584             if (m_pFrames[n].m_pFrame)
585             {
586                 *pFrame = m_pFrames[n];
587                 return true;
588             }
589             return false;
590         }
591 
Close()592         void Close()
593         {
594             if (m_pFrames)
595             {
596                 delete [] m_pFrames;
597                 m_pFrames = 0;
598             }
599             m_iCurr = 0;
600             m_numBuffB = 0;
601             m_maxB = 0;
602             m_nGOPs = 0;
603         }
604 
605     private:
606         // Declare private copy constructor to avoid accidental assignment
607         // and klocwork complaining.
608         MFXGOP(const MFXGOP &);
609         MFXGOP & operator = (const MFXGOP &);
610     };
611 
612 
613     class MFXWaitingList
614     {
615     public:
MFXWaitingList()616         MFXWaitingList():
617             m_maxN(0),
618             m_curIndex(0),
619             m_nFrames(0),
620             m_pFrames(0),
621             m_minN(0),
622             m_delay(0)
623             {};
~MFXWaitingList()624         ~MFXWaitingList()
625         {
626             Close();
627         }
Close()628         void Close()
629         {
630             if (m_pFrames)
631             {
632                 delete [] m_pFrames;
633                 m_pFrames = 0;
634             }
635 
636             m_maxN = 0;
637             m_curIndex = 0;
638             m_nFrames = 0;
639             m_minN=0;
640             m_delay = 0;
641         }
642 
Init(mfxU32 maxN,mfxU32 minN,mfxU32 delay)643         mfxStatus Init(mfxU32 maxN, mfxU32 minN, mfxU32 delay)
644         {
645             Close();
646 
647             m_maxN  = maxN;
648             m_minN  = minN;
649             m_delay = delay;
650 
651             if (m_minN > m_maxN)
652                 return MFX_ERR_UNSUPPORTED;
653 
654             m_pFrames = new sFrameEx [ m_maxN];
655             if (!m_pFrames)
656                 return MFX_ERR_MEMORY_ALLOC;
657 
658             memset (m_pFrames,0, sizeof(sFrameEx)*m_maxN);
659 
660             return MFX_ERR_NONE;
661         }
662 
GetMaxFrames()663         mfxI32 GetMaxFrames ()
664         {
665             return m_maxN;
666         }
GetDelay()667         mfxI32 GetDelay()
668         {
669             return m_delay;
670         }
671 
Reset(mfxI32 minN,mfxU32 delay)672         void Reset(mfxI32 minN, mfxU32 delay)
673         {
674             mfxU32 i = 0;
675 
676             if(m_pFrames)
677             {
678                 for(i = 0; i < m_maxN; i++)
679                 {
680                      ReleasePlane(m_pFrames[i].m_pFrame);
681 
682                 }
683                 memset (m_pFrames,0, sizeof(sFrameEx)* m_maxN);
684             }
685 
686             m_curIndex = 0;
687             m_nFrames = 0;
688             m_minN = minN;
689             m_delay = delay;
690         }
691 
AddFrame(mfxFrameSurface1 * frame,mfxEncodeInternalParams * pInInternalParams)692         bool AddFrame(mfxFrameSurface1* frame, mfxEncodeInternalParams *pInInternalParams)
693         {
694             if (m_nFrames < m_maxN)
695             {
696                 mfxU32 ind = (m_curIndex + m_nFrames)%m_maxN;
697 
698                 m_pFrames[ind].m_pFrame     = frame;
699                 m_pFrames[ind].m_FrameOrder = pInInternalParams->FrameOrder;
700                 m_pFrames[ind].m_FrameType  = pInInternalParams->FrameType;
701 
702                 m_pFrames[ind].m_bAddEOS            = false;
703                 m_pFrames[ind].m_bAddHeader         = false;
704                 m_pFrames[ind].m_bOnlyBwdPrediction = false;
705 
706                 m_pFrames[ind].m_sEncodeInternalParams  = *pInInternalParams;
707                 m_nFrames ++;
708                 return true;
709             }
710             return false;
711         }
712         bool GetFrameEx(sFrameEx* pFrameEx, bool bEOF = false)
713         {
714             if (m_nFrames>0 && (bEOF || (m_nFrames > m_minN && m_nFrames > m_delay)))
715             {
716                 *pFrameEx = m_pFrames[m_curIndex];
717                 m_delay = 0;
718                 return true;
719             }
720             return false;
721         }
722 
MoveOnNextFrame()723         bool MoveOnNextFrame()
724         {
725             if (m_nFrames>0)
726             {
727                 m_curIndex = (1+m_curIndex)%m_maxN;
728                 m_nFrames--;
729                 return true;
730             }
731             return false;
732         }
733 
isNextReferenceIntra()734         bool isNextReferenceIntra()
735         {
736             for (mfxU32 i=0; i < m_nFrames; i++)
737             {
738                 mfxU32 ind = (m_curIndex+i)%m_maxN;
739                 mfxU16 type = m_pFrames[ind].m_FrameType;
740                 if (isReferenceFrame(type))
741                 {
742                     return isIntraFrame(type)? true:false;
743                 }
744             }
745             return false;
746         }
isLastFrame()747         bool isLastFrame()
748         {
749             return (m_nFrames < 1);
750         }
isNextBFrame()751         bool isNextBFrame()
752         {
753             if (m_nFrames != 0)
754             {
755                 mfxU32 ind = (m_curIndex)%m_maxN;
756                 mfxU16 type = m_pFrames[ind].m_FrameType;
757                 return (isReferenceFrame (type))? false:true;
758             }
759             return false;
760         }
761 
762     private:
763         mfxU32              m_maxN;
764         mfxU32              m_curIndex;
765         mfxU32              m_nFrames;
766         sFrameEx*           m_pFrames;
767         mfxU32              m_minN;
768         mfxU32              m_delay;
769 
770         // Declare private copy constructor to avoid accidental assignment
771         // and klocwork complaining.
772         MFXWaitingList(const MFXWaitingList &);
773         MFXWaitingList & operator = (const MFXWaitingList &);
774     };
775 
776 #endif //_MFX_FRAMES_H_
777