1 // Copyright (c) 2017-2018 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 #include "umc_defs.h"
22 #if defined (MFX_ENABLE_H264_VIDEO_DECODE)
23 
24 #include "umc_h264_frame_list.h"
25 #include "umc_h264_dec_debug.h"
26 #include "umc_h264_task_supplier.h"
27 
28 namespace UMC
29 {
30 
H264DecoderFrameList(void)31 H264DecoderFrameList::H264DecoderFrameList(void)
32 {
33     m_pHead = NULL;
34     m_pTail = NULL;
35 } // H264DecoderFrameList::H264DecoderFrameList(void)
36 
~H264DecoderFrameList(void)37 H264DecoderFrameList::~H264DecoderFrameList(void)
38 {
39     Release();
40 
41 } // H264DecoderFrameList::~H264DecoderFrameList(void)
42 
Release(void)43 void H264DecoderFrameList::Release(void)
44 {
45     // destroy frame list
46     while (m_pHead)
47     {
48         H264DecoderFrame *pNext = m_pHead->future();
49         delete m_pHead;
50         m_pHead = pNext;
51     }
52 
53     m_pHead = NULL;
54     m_pTail = NULL;
55 
56 } // void H264DecoderFrameList::Release(void)
57 
58 
59 //////////////////////////////////////////////////////////////////////////////
60 // append
61 //   Appends a new decoded frame buffer to the "end" of the linked list
62 //////////////////////////////////////////////////////////////////////////////
append(H264DecoderFrame * pFrame)63 void H264DecoderFrameList::append(H264DecoderFrame *pFrame)
64 {
65     // Error check
66     if (!pFrame)
67     {
68         // Sent in a NULL frame
69         return;
70     }
71 
72     // Has a list been constructed - is their a head?
73     if (!m_pHead)
74     {
75         // Must be the first frame appended
76         // Set the head to the current
77         m_pHead = pFrame;
78         m_pHead->setPrevious(0);
79     }
80 
81     if (m_pTail)
82     {
83         // Set the old tail as the previous for the current
84         pFrame->setPrevious(m_pTail);
85 
86         // Set the old tail's future to the current
87         m_pTail->setFuture(pFrame);
88     }
89     else
90     {
91         // Must be the first frame appended
92         // Set the tail to the current
93         m_pTail = pFrame;
94     }
95 
96     // The current is now the new tail
97     m_pTail = pFrame;
98     m_pTail->setFuture(0);
99     //
100 }
101 
swapFrames(H264DecoderFrame * pFrame1,H264DecoderFrame * pFrame2)102 void H264DecoderFrameList::swapFrames(H264DecoderFrame *pFrame1, H264DecoderFrame *pFrame2)
103 {
104     H264DecoderFrame * temp1 = pFrame1->previous();
105     H264DecoderFrame * temp2 = pFrame2->previous();
106 
107     if (temp1)
108     {
109         temp1->setFuture(pFrame2);
110     }
111 
112     if (temp2)
113     {
114         temp2->setFuture(pFrame1);
115     }
116 
117     pFrame1->setPrevious(temp2);
118     pFrame2->setPrevious(temp1);
119 
120     temp1 = pFrame1->future();
121     temp2 = pFrame2->future();
122 
123     if (temp1)
124     {
125         temp1->setPrevious(pFrame2);
126     }
127 
128     if (temp2)
129     {
130         temp2->setPrevious(pFrame1);
131     }
132 
133     pFrame1->setFuture(temp2);
134     pFrame2->setFuture(temp1);
135 
136 
137     if (m_pHead == pFrame1)
138     {
139         m_pHead = pFrame2;
140     }
141     else
142     {
143         if (m_pHead == pFrame2)
144         {
145             m_pHead = pFrame1;
146         }
147     }
148 
149     if (m_pTail == pFrame1)
150     {
151         m_pTail = pFrame2;
152     }
153     else
154     {
155         if (m_pTail == pFrame2)
156         {
157             m_pTail = pFrame1;
158         }
159     }
160 }
161 
H264DBPList()162 H264DBPList::H264DBPList()
163     : m_dpbSize(0)
164     , m_recovery_frame_cnt(-1)
165     , m_wasRecoveryPointFound(false)
166 {
167 }
168 
GetDisposable(void)169 H264DecoderFrame * H264DBPList::GetDisposable(void)
170 {
171     H264DecoderFrame *pOldest = NULL;
172 
173     for (H264DecoderFrame * pTmp = m_pHead; pTmp; pTmp = pTmp->future())
174     {
175         if (pTmp->isDisposable())
176         {
177             pOldest = pTmp;
178         }
179     }
180     return pOldest;
181 }
182 
IsDisposableExist()183 bool H264DBPList::IsDisposableExist()
184 {
185     for (H264DecoderFrame * pTmp = m_pHead; pTmp; pTmp = pTmp->future())
186     {
187         if (pTmp->isDisposable())
188         {
189             return true;
190         }
191     }
192 
193     return false;
194 }
195 
IsAlmostDisposableExist()196 bool H264DBPList::IsAlmostDisposableExist()
197 {
198     int32_t count = 0;
199     for (H264DecoderFrame * pTmp = m_pHead; pTmp; pTmp = pTmp->future())
200     {
201         count++;
202         if (isAlmostDisposable(pTmp))
203         {
204             return true;
205         }
206     }
207 
208     return count < m_dpbSize;
209 }
210 
findDisplayableByDPBDelay(void)211 H264DecoderFrame * H264DBPList::findDisplayableByDPBDelay(void)
212 {
213     H264DecoderFrame *pCurr = m_pHead;
214     H264DecoderFrame *pOldest = NULL;
215     int32_t  SmallestPicOrderCnt = 0x7fffffff;    // very large positive
216     uint32_t  LargestRefPicListResetCount = 0;
217 
218     int32_t count = 0;
219     while (pCurr)
220     {
221         if (pCurr->IsFullFrame() && !pCurr->wasOutputted() && !pCurr->m_dpb_output_delay)
222         {
223             // corresponding frame
224             if (pCurr->RefPicListResetCount(0) > LargestRefPicListResetCount)
225             {
226                 pOldest = pCurr;
227                 SmallestPicOrderCnt = pCurr->PicOrderCnt(0,3);
228                 LargestRefPicListResetCount = pCurr->RefPicListResetCount(0);
229             }
230             else if (pCurr->RefPicListResetCount(0) == LargestRefPicListResetCount &&
231                 pCurr->PicOrderCnt(0,3) <= SmallestPicOrderCnt)
232             {
233                 VM_ASSERT(pCurr->m_UID != -1);
234                 pOldest = pCurr;
235                 SmallestPicOrderCnt = pCurr->PicOrderCnt(0,3);
236             }
237 
238             if (pOldest && !pOldest->IsFrameExist() && pCurr->IsFrameExist())
239             {
240                 if (pCurr->PicOrderCnt(0,3) == SmallestPicOrderCnt &&
241                     pCurr->RefPicListResetCount(0) == LargestRefPicListResetCount)
242                     pOldest = pCurr;
243             }
244 
245             count++;
246         }
247 
248         pCurr = pCurr->future();
249     }
250 
251     // may be OK if NULL
252     return pOldest;
253 }
254 
255 ///////////////////////////////////////////////////////////////////////////////
256 // findOldestDisplayable
257 // Search through the list for the oldest displayable frame. It must be
258 // not disposable, not outputted, and have smallest PicOrderCnt.
259 ///////////////////////////////////////////////////////////////////////////////
findOldestDisplayable(int32_t)260 H264DecoderFrame * H264DBPList::findOldestDisplayable(int32_t /*dbpSize*/ )
261 {
262     H264DecoderFrame *pCurr = m_pHead;
263     H264DecoderFrame *pOldest = NULL;
264     int32_t  SmallestPicOrderCnt = 0x7fffffff;    // very large positive
265     uint32_t  LargestRefPicListResetCount = 0;
266 
267     int32_t count = 0;
268     while (pCurr)
269     {
270         if (pCurr->IsFullFrame() && !pCurr->wasOutputted())
271         {
272             // corresponding frame
273             if (pCurr->RefPicListResetCount(0) > LargestRefPicListResetCount)
274             {
275                 pOldest = pCurr;
276                 SmallestPicOrderCnt = pCurr->PicOrderCnt(0,3);
277                 LargestRefPicListResetCount = pCurr->RefPicListResetCount(0);
278             }
279             else if ((pCurr->PicOrderCnt(0,3) <= SmallestPicOrderCnt) &&
280                      (pCurr->RefPicListResetCount(0) == LargestRefPicListResetCount))
281             {
282                 VM_ASSERT(pCurr->m_UID != -1);
283                 pOldest = pCurr;
284                 SmallestPicOrderCnt = pCurr->PicOrderCnt(0,3);
285             }
286 
287             if (pOldest && !pOldest->IsFrameExist() && pCurr->IsFrameExist())
288             {
289                 if (pCurr->PicOrderCnt(0,3) == SmallestPicOrderCnt &&
290                     pCurr->RefPicListResetCount(0) == LargestRefPicListResetCount)
291                     pOldest = pCurr;
292             }
293 
294             count++;
295         }
296 
297         pCurr = pCurr->future();
298     }
299 
300     // may be OK if NULL
301     return pOldest;
302 
303 }    // findOldestDisplayable
304 
countAllFrames()305 uint32_t H264DBPList::countAllFrames()
306 {
307     H264DecoderFrame *pCurr = head();
308     uint32_t count = 0;
309 
310     while (pCurr)
311     {
312         count++;
313         pCurr = pCurr->future();
314     }
315 
316     return count;
317 }
318 
countNumDisplayable()319 uint32_t H264DBPList::countNumDisplayable()
320 {
321     H264DecoderFrame *pCurr = head();
322     uint32_t NumDisplayable = 0;
323 
324     while (pCurr)
325     {
326         if (pCurr->IsFullFrame() && (pCurr->isShortTermRef() || pCurr->isLongTermRef() || !pCurr->wasOutputted()))
327             NumDisplayable++;
328         pCurr = pCurr->future();
329     }
330 
331     return NumDisplayable;
332 }
333 
334 ///////////////////////////////////////////////////////////////////////////////
335 // countActiveRefs
336 //  Return number of active int16_t and long term reference frames.
337 ///////////////////////////////////////////////////////////////////////////////
countActiveRefs(uint32_t & NumShortTerm,uint32_t & NumLongTerm)338 void H264DBPList::countActiveRefs(uint32_t &NumShortTerm, uint32_t &NumLongTerm)
339 {
340     H264DecoderFrame *pCurr = m_pHead;
341     NumShortTerm = 0;
342     NumLongTerm = 0;
343 
344     while (pCurr)
345     {
346         if (pCurr->isShortTermRef())
347             NumShortTerm++;
348         else if (pCurr->isLongTermRef())
349             NumLongTerm++;
350         pCurr = pCurr->future();
351     }
352 
353 }    // countActiveRefs
354 
IncreaseRefPicListResetCount(H264DecoderFrame * ExcludeFrame)355 void H264DBPList::IncreaseRefPicListResetCount(H264DecoderFrame *ExcludeFrame)
356 {
357     H264DecoderFrame *pCurr = m_pHead;
358 
359     while (pCurr)
360     {
361         if (pCurr!=ExcludeFrame)
362         {
363             pCurr->IncreaseRefPicListResetCount(0);
364             pCurr->IncreaseRefPicListResetCount(1);
365         }
366         pCurr = pCurr->future();
367     }
368 
369 }    // IncreaseRefPicListResetCount
370 
findOldestShortTermRef()371 H264DecoderFrame * H264DBPList::findOldestShortTermRef()
372 {
373     H264DecoderFrame *pCurr = m_pHead;
374     H264DecoderFrame *pOldest = 0;
375     int32_t  SmallestFrameNumWrap = 0x0fffffff;    // very large positive
376 
377     while (pCurr)
378     {
379         if (pCurr->isShortTermRef() && (pCurr->FrameNumWrap() < SmallestFrameNumWrap))
380         {
381             pOldest = pCurr;
382             SmallestFrameNumWrap = pCurr->FrameNumWrap();
383         }
384         pCurr = pCurr->future();
385     }
386 
387     return pOldest;
388 }    // findOldestShortTermRef
389 
findOldestLongTermRef()390 H264DecoderFrame * H264DBPList::findOldestLongTermRef()
391 {
392     H264DecoderFrame *pCurr = m_pHead;
393     H264DecoderFrame *pOldest = 0;
394     int32_t  SmallestFrameNumWrap = 0x0fffffff;    // very large positive
395 
396     while (pCurr)
397     {
398         if (pCurr->isLongTermRef() && (pCurr->FrameNumWrap() < SmallestFrameNumWrap))
399         {
400             pOldest = pCurr;
401             SmallestFrameNumWrap = pCurr->FrameNumWrap();
402         }
403         pCurr = pCurr->future();
404     }
405 
406     return pOldest;
407 }    // findOldestLongTermRef
408 
findLongTermRefIdx(int32_t LongTermFrameIdx)409 H264DecoderFrame * H264DBPList::findLongTermRefIdx(int32_t LongTermFrameIdx)
410 {
411     H264DecoderFrame *pCurr = m_pHead;
412 
413     while (pCurr)
414     {
415         if (pCurr->m_PictureStructureForRef >= FRM_STRUCTURE)
416         {
417             if (pCurr->isLongTermRef() && (pCurr->LongTermFrameIdx() == LongTermFrameIdx ))
418             {
419                 return pCurr;
420             }
421         }
422         else
423         {
424             if (pCurr->isLongTermRef(0) && (pCurr->LongTermFrameIdx() == LongTermFrameIdx ))
425             {
426                 return pCurr;
427             }
428 
429             if (pCurr->isLongTermRef(1) && (pCurr->LongTermFrameIdx() == LongTermFrameIdx ))
430             {
431                 return pCurr;
432             }
433         }
434 
435         pCurr = pCurr->future();
436     }
437 
438     //VM_ASSERT(false);
439     return 0;
440 }
441 
findOldLongTermRef(int32_t MaxLongTermFrameIdx)442 H264DecoderFrame * H264DBPList::findOldLongTermRef(int32_t MaxLongTermFrameIdx)
443 {
444     H264DecoderFrame *pCurr = m_pHead;
445 
446     while (pCurr)
447     {
448         if (pCurr->isLongTermRef(0) && (pCurr->LongTermFrameIdx() > MaxLongTermFrameIdx))
449         {
450             return pCurr;
451         }
452 
453         pCurr = pCurr->future();
454     }
455 
456     return 0;
457     // OK to not find any to free
458 
459 }
460 
findShortTermPic(int32_t picNum,int32_t * field)461 H264DecoderFrame *H264DBPList::findShortTermPic(int32_t  picNum, int32_t * field)
462 {
463     H264DecoderFrame *pCurr = m_pHead;
464 
465     while (pCurr)
466     {
467         if (pCurr->m_PictureStructureForRef >= FRM_STRUCTURE)
468         {
469             if ((pCurr->isShortTermRef() == 3) && (pCurr->PicNum(0) == picNum))
470             {
471                 if (field)
472                     *field = 0;
473                 return pCurr;
474             }
475         }
476         else
477         {
478             if (pCurr->isShortTermRef(0) && (pCurr->PicNum(0) == picNum))
479             {
480                 if (field)
481                     *field = 0;
482                 return pCurr;
483             }
484 
485             if (pCurr->isShortTermRef(1) && (pCurr->PicNum(1) == picNum))
486             {
487                 if (field)
488                     *field = 1;
489                 return pCurr;
490             }
491         }
492 
493         pCurr = pCurr->future();
494     }
495 
496     //VM_ASSERT(false);    // No match found, should not happen.
497     return 0;
498 }    // findShortTermPic
499 
findLongTermPic(int32_t picNum,int32_t * field)500 H264DecoderFrame *H264DBPList::findLongTermPic(int32_t  picNum, int32_t * field)
501 {
502     H264DecoderFrame *pCurr = m_pHead;
503 
504     while (pCurr)
505     {
506         if (pCurr->m_PictureStructureForRef >= FRM_STRUCTURE)
507         {
508             if ((pCurr->isLongTermRef() == 3) && (pCurr->LongTermPicNum(0) == picNum))
509             {
510                 if (field)
511                     *field = 0;
512                 return pCurr;
513             }
514         }
515         else
516         {
517             if (pCurr->isLongTermRef(0) && (pCurr->LongTermPicNum(0) == picNum))
518             {
519                 if (field)
520                     *field = 0;
521                 return pCurr;
522             }
523 
524             if (pCurr->isLongTermRef(1) && (pCurr->LongTermPicNum(1) == picNum))
525             {
526                 if (field)
527                     *field = 1;
528                 return pCurr;
529             }
530         }
531 
532         pCurr = pCurr->future();
533     }
534 
535     //VM_ASSERT(false);    // No match found, should not happen.
536     return 0;
537 }    // findLongTermPic
538 
findInterViewRef(int32_t auIndex,uint32_t bottomFieldFlag)539 H264DecoderFrame *H264DBPList::findInterViewRef(int32_t auIndex, uint32_t bottomFieldFlag)
540 {
541     H264DecoderFrame *pCurr = m_pHead;
542     while (pCurr)
543     {
544         if (pCurr->m_auIndex == auIndex)
545         {
546             uint32_t fieldIdx = pCurr->GetNumberByParity(bottomFieldFlag);
547             return pCurr->isInterViewRef(fieldIdx) ? pCurr : 0;
548         }
549 
550         // get the next frame
551         pCurr = pCurr->future();
552     }
553 
554     return 0;
555 
556 }
557 
FindClosest(H264DecoderFrame * pFrame)558 H264DecoderFrame * H264DBPList::FindClosest(H264DecoderFrame * pFrame)
559 {
560     int32_t originalPOC = pFrame->PicOrderCnt(0, 3);
561     uint32_t originalResetCount = pFrame->RefPicListResetCount(0);
562 
563     H264DecoderFrame * pOldest = 0;
564 
565     int32_t  SmallestPicOrderCnt = 0;    // very large positive
566     uint32_t  SmallestRefPicListResetCount = 0x7fffffff;
567 
568     for (H264DecoderFrame * pTmp = m_pHead; pTmp; pTmp = pTmp->future())
569     {
570         if (pTmp->IsSkipped() || pTmp == pFrame || !pTmp->IsDecodingCompleted())
571             continue;
572 
573         if (pTmp->m_chroma_format != pFrame->m_chroma_format ||
574             pTmp->lumaSize().width != pFrame->lumaSize().width ||
575             pTmp->lumaSize().height != pFrame->lumaSize().height)
576             continue;
577 
578         if (pTmp->RefPicListResetCount(0) < SmallestRefPicListResetCount)
579         {
580             pOldest = pTmp;
581             SmallestPicOrderCnt = pTmp->PicOrderCnt(0,3);
582             SmallestRefPicListResetCount = pTmp->RefPicListResetCount(0);
583         }
584         else if (pTmp->RefPicListResetCount(0) == SmallestRefPicListResetCount)
585         {
586             if (pTmp->RefPicListResetCount(0) == originalResetCount)
587             {
588                 if (SmallestRefPicListResetCount != originalResetCount)
589                 {
590                     SmallestPicOrderCnt = 0x7fff;
591                 }
592 
593                 if (abs(pTmp->PicOrderCnt(0,3) - originalPOC) < SmallestPicOrderCnt)
594                 {
595                     pOldest = pTmp;
596                     SmallestPicOrderCnt = pTmp->PicOrderCnt(0,3);
597                     SmallestRefPicListResetCount = pTmp->RefPicListResetCount(0);
598                 }
599             }
600             else
601             {
602                 if (pTmp->PicOrderCnt(0,3) > SmallestPicOrderCnt)
603                 {
604                     pOldest = pTmp;
605                     SmallestPicOrderCnt = pTmp->PicOrderCnt(0,3);
606                     SmallestRefPicListResetCount = pTmp->RefPicListResetCount(0);
607                 }
608             }
609         }
610     }
611 
612     return pOldest;
613 }
614 
FindByIndex(int32_t index)615 H264DecoderFrame * H264DBPList::FindByIndex(int32_t index)
616 {
617     for (H264DecoderFrame * pTmp = m_pHead; pTmp; pTmp = pTmp->future())
618     {
619         if (pTmp->m_index == index)
620             return pTmp;
621     }
622 
623     return 0;
624 }
625 
GetRecoveryFrameCnt() const626 int32_t H264DBPList::GetRecoveryFrameCnt() const
627 {
628     return m_recovery_frame_cnt;
629 }
630 
SetRecoveryFrameCnt(int32_t recovery_frame_cnt)631 void H264DBPList::SetRecoveryFrameCnt(int32_t recovery_frame_cnt)
632 {
633     if (m_wasRecoveryPointFound && recovery_frame_cnt != -1)
634     {
635         return;
636     }
637 
638     m_recovery_frame_cnt = recovery_frame_cnt;
639     m_wasRecoveryPointFound = true;
640 }
641 
Reset(void)642 void H264DBPList::Reset(void)
643 {
644     H264DecoderFrame *pFrame ;
645 
646     for (pFrame = head(); pFrame; pFrame = pFrame->future())
647     {
648         pFrame->FreeResources();
649     }
650 
651     for (pFrame = head(); pFrame; pFrame = pFrame->future())
652     {
653         pFrame->Reset();
654     }
655 
656     m_wasRecoveryPointFound = false;
657     m_recovery_frame_cnt = -1;
658 
659 } // void H264DBPList::Reset(void)
660 
InitPSliceRefPicList(H264Slice * slice,H264DecoderFrame ** pRefPicList)661 void H264DBPList::InitPSliceRefPicList(H264Slice *slice, H264DecoderFrame **pRefPicList)
662 {
663     int32_t j, k;
664     int32_t NumFramesInList;
665     H264DecoderFrame *pHead = head();
666     H264DecoderFrame *pFrm;
667     int32_t picNum;
668     bool bError = false;
669     bool bIsFieldSlice = (slice->GetSliceHeader()->field_pic_flag != 0);
670 
671     VM_ASSERT(pRefPicList);
672 
673     NumFramesInList = 0;
674 
675     if (!bIsFieldSlice)
676     {
677         // Frame. Ref pic list ordering: Short term largest pic num to
678         // smallest, followed by long term, largest long term pic num to
679         // smallest. Note that ref pic list has one extra slot to assist
680         // with re-ordering.
681         for (pFrm = pHead; pFrm; pFrm = pFrm->future())
682         {
683             if (pFrm->isShortTermRef()==3)
684             {
685                 // add to ordered list
686                 picNum = pFrm->PicNum(0);
687 
688                 // find insertion point
689                 j=0;
690                 while (j<NumFramesInList &&
691                         pRefPicList[j]->isShortTermRef() &&
692                         pRefPicList[j]->PicNum(0) > picNum)
693                     j++;
694 
695                 // make room if needed
696                 if (pRefPicList[j])
697                 {
698                     for (k=NumFramesInList; k>j; k--)
699                     {
700                         // Avoid writing beyond end of list
701                         if (k > (int32_t)(MAX_NUM_REF_FRAMES-1))
702                         {
703                             VM_ASSERT(0);
704                             bError = true;
705                             break;
706                         }
707                         pRefPicList[k] = pRefPicList[k-1];
708                     }
709                 }
710 
711                 // add the short-term reference
712                 pRefPicList[j] = pFrm;
713                 NumFramesInList++;
714             }
715             else if (pFrm->isLongTermRef()==3)
716             {
717                 // add to ordered list
718                 picNum = pFrm->LongTermPicNum(0,3);
719 
720                 // find insertion point
721                 j=0;
722                 // Skip past short-term refs and long term refs with smaller
723                 // long term pic num
724                 while (j<NumFramesInList &&
725                         (pRefPicList[j]->isShortTermRef() ||
726                         (pRefPicList[j]->isLongTermRef() &&
727                         pRefPicList[j]->LongTermPicNum(0,2) < picNum)))
728                     j++;
729 
730                 // make room if needed
731                 if (pRefPicList[j])
732                 {
733                     for (k=NumFramesInList; k>j; k--)
734                     {
735                         // Avoid writing beyond end of list
736                         if (k > (int32_t)(MAX_NUM_REF_FRAMES-1))
737                         {
738                             VM_ASSERT(0);
739                             bError = true;
740                             break;
741                         }
742                         pRefPicList[k] = pRefPicList[k-1];
743                     }
744                 }
745 
746                 // add the long-term reference
747                 pRefPicList[j] = pFrm;
748                 NumFramesInList++;
749             }
750             if (bError) break;
751         }
752     }
753     else
754     {
755         // TBD: field
756         for (pFrm = pHead; pFrm; pFrm = pFrm->future())
757         {
758             if (pFrm->isShortTermRef())
759             {
760                 // add to ordered list
761                 picNum = pFrm->FrameNumWrap();
762 
763                 // find insertion point
764                 j=0;
765                 while (j<NumFramesInList &&
766                     pRefPicList[j]->isShortTermRef() &&
767                     pRefPicList[j]->FrameNumWrap() > picNum)
768                     j++;
769 
770                 // make room if needed
771                 if (pRefPicList[j])
772                 {
773                     for (k=NumFramesInList; k>j; k--)
774                     {
775                         // Avoid writing beyond end of list
776                         if (k > (int32_t)(MAX_NUM_REF_FRAMES-1))
777                         {
778                             VM_ASSERT(0);
779                             bError = true;
780                             break;
781                         }
782                         pRefPicList[k] = pRefPicList[k-1];
783                     }
784                 }
785 
786                 // add the short-term reference
787                 pRefPicList[j] = pFrm;
788                 NumFramesInList++;
789             }
790             else if (pFrm->isLongTermRef())
791             {
792                 // long term reference
793                 picNum = pFrm->LongTermPicNum(0,2);
794 
795                 // find insertion point
796                 j=0;
797                 // Skip past short-term refs and long term refs with smaller
798                 // long term pic num
799                 while (j<NumFramesInList &&
800                     (pRefPicList[j]->isShortTermRef() ||
801                     (pRefPicList[j]->isLongTermRef() &&
802                     pRefPicList[j]->LongTermPicNum(0,2) < picNum)))
803                     j++;
804 
805                 // make room if needed
806                 if (pRefPicList[j])
807                 {
808                     for (k=NumFramesInList; k>j; k--)
809                     {
810                         // Avoid writing beyond end of list
811                         if (k > (int32_t)(MAX_NUM_REF_FRAMES-1))
812                         {
813                             VM_ASSERT(0);
814                             bError = true;
815                             break;
816                         }
817                         pRefPicList[k] = pRefPicList[k-1];
818                     }
819                 }
820 
821                 // add the long-term reference
822                 pRefPicList[j] = pFrm;
823                 NumFramesInList++;
824             }
825             if (bError) break;
826         }
827     }
828 }
829 
InitBSliceRefPicLists(H264Slice * slice,H264DecoderFrame ** pRefPicList0,H264DecoderFrame ** pRefPicList1,H264RefListInfo & rli)830 void H264DBPList::InitBSliceRefPicLists(H264Slice *slice, H264DecoderFrame **pRefPicList0, H264DecoderFrame **pRefPicList1,
831                                       H264RefListInfo &rli)
832 {
833     bool bIsFieldSlice = (slice->GetSliceHeader()->field_pic_flag != 0);
834     int32_t i, j, k;
835     int32_t NumFramesInL0List;
836     int32_t NumFramesInL1List;
837     int32_t NumFramesInLTList;
838     H264DecoderFrame *pHead = head();
839     H264DecoderFrame *pFrm;
840     int32_t FrmPicOrderCnt;
841     H264DecoderFrame *LTRefPicList[MAX_NUM_REF_FRAMES];    // temp storage for long-term ordered list
842     int32_t LongTermPicNum;
843     bool bError = false;
844 
845     for (i=0; i<(int32_t)MAX_NUM_REF_FRAMES; i++)
846     {
847         LTRefPicList[i] = 0;
848     }
849 
850     NumFramesInL0List = 0;
851     NumFramesInL1List = 0;
852     NumFramesInLTList = 0;
853 
854     if (!bIsFieldSlice)
855     {
856         int32_t CurrPicOrderCnt = slice->GetCurrentFrame()->PicOrderCnt(0);
857         // Short term references:
858         // Need L0 and L1 lists. Both contain 2 sets of reference frames ordered
859         // by PicOrderCnt. The "previous" set contains the reference frames with
860         // a PicOrderCnt < current frame. The "future" set contains the reference
861         // frames with a PicOrderCnt > current frame. In both cases the ordering
862         // is from closest to current frame to farthest. L0 has the previous set
863         // followed by the future set; L1 has the future set followed by the previous set.
864         // Accomplish this by one pass through the decoded frames list creating
865         // the ordered previous list in the L0 array and the ordered future list
866         // in the L1 array. Then copy from both to the other for the second set.
867 
868         // Long term references:
869         // The ordered list is the same for L0 and L1, is ordered by ascending
870         // LongTermPicNum. The ordered list is created using local temp then
871         // appended to the L0 and L1 lists after the short-term references.
872 
873         for (pFrm = pHead; pFrm; pFrm = pFrm->future())
874         {
875             if (pFrm->isShortTermRef()==3)
876             {
877                 // add to ordered list
878                 FrmPicOrderCnt = pFrm->PicOrderCnt(0,3);
879 
880                 if (FrmPicOrderCnt < CurrPicOrderCnt)
881                 {
882                     // Previous reference to L0, order large to small
883                     j=0;
884                     while (j < NumFramesInL0List &&
885                         (pRefPicList0[j]->PicOrderCnt(0,3) > FrmPicOrderCnt))
886                         j++;
887 
888                     // make room if needed
889                     if (pRefPicList0[j])
890                     {
891                         for (k = NumFramesInL0List; k > j; k--)
892                         {
893                             // Avoid writing beyond end of list
894                             if (k > (int32_t)(MAX_NUM_REF_FRAMES-1))
895                             {
896                                 VM_ASSERT(0);
897                                 bError = true;
898                                 break;
899                             }
900                             pRefPicList0[k] = pRefPicList0[k-1];
901                         }
902                     }
903 
904                     // add the short-term reference
905                     pRefPicList0[j] = pFrm;
906                     NumFramesInL0List++;
907                 }
908                 else
909                 {
910                     // Future reference to L1, order small to large
911                     j=0;
912                     while (j<NumFramesInL1List &&
913                             pRefPicList1[j]->PicOrderCnt(0,3) < FrmPicOrderCnt)
914                         j++;
915 
916                     // make room if needed
917                     if (pRefPicList1[j])
918                     {
919                         for (k=NumFramesInL1List; k>j; k--)
920                         {
921                             // Avoid writing beyond end of list
922                             if (k > (int32_t)(MAX_NUM_REF_FRAMES-1))
923                             {
924                                 VM_ASSERT(0);
925                                 bError = true;
926                                 break;
927                             }
928                             pRefPicList1[k] = pRefPicList1[k-1];
929                         }
930                     }
931 
932                     // add the short-term reference
933                     pRefPicList1[j] = pFrm;
934                     NumFramesInL1List++;
935                 }
936             }    // short-term B
937             else if (pFrm->isLongTermRef()==3)
938             {
939                 // long term reference
940                 LongTermPicNum = pFrm->LongTermPicNum(0,3);
941 
942                 // order smallest to largest
943                 j=0;
944                 while (j<NumFramesInLTList &&
945                         LTRefPicList[j]->LongTermPicNum(0) < LongTermPicNum)
946                     j++;
947 
948                 // make room if needed
949                 if (LTRefPicList[j])
950                 {
951                     for (k=NumFramesInLTList; k>j; k--)
952                     {
953                         // Avoid writing beyond end of list
954                         if (k > (int32_t)(MAX_NUM_REF_FRAMES-1))
955                         {
956                             VM_ASSERT(0);
957                             bError = true;
958                             break;
959                         }
960                         LTRefPicList[k] = LTRefPicList[k-1];
961                     }
962                 }
963 
964                 // add the long-term reference
965                 LTRefPicList[j] = pFrm;
966                 NumFramesInLTList++;
967 
968             }    // long term reference
969 
970             if (bError) break;
971 
972         }    // for pFrm
973 
974         if ((NumFramesInL0List + NumFramesInL1List + NumFramesInLTList) < MAX_NUM_REF_FRAMES)
975         {
976             // Complete L0 and L1 lists
977             // Add future short-term references to L0 list, after previous
978             for (i=0; i<NumFramesInL1List; i++)
979                 pRefPicList0[NumFramesInL0List+i] = pRefPicList1[i];
980 
981             // Add previous short-term references to L1 list, after future
982             for (i=0; i<NumFramesInL0List; i++)
983                 pRefPicList1[NumFramesInL1List+i] = pRefPicList0[i];
984 
985             // Add long term list to both L0 and L1
986             for (i=0; i<NumFramesInLTList; i++)
987             {
988                 pRefPicList0[NumFramesInL0List+NumFramesInL1List+i] = LTRefPicList[i];
989                 pRefPicList1[NumFramesInL0List+NumFramesInL1List+i] = LTRefPicList[i];
990             }
991 
992             // Special rule: When L1 has more than one entry and L0 == L1, all entries,
993             // swap the first two entries of L1.
994             // They can be equal only if there are no future or no previous short-term
995             // references.
996             if ((NumFramesInL0List == 0 || NumFramesInL1List == 0) &&
997                 ((NumFramesInL0List+NumFramesInL1List+NumFramesInLTList) > 1))
998             {
999                 pRefPicList1[0] = pRefPicList0[1];
1000                 pRefPicList1[1] = pRefPicList0[0];
1001             }
1002         }
1003         else
1004         {
1005             // too many reference frames
1006             VM_ASSERT(0);
1007         }
1008 
1009     }    // not field slice
1010     else
1011     {
1012         int32_t CurrPicOrderCnt = slice->GetCurrentFrame()->PicOrderCnt(slice->GetCurrentFrame()->GetNumberByParity(slice->GetSliceHeader()->bottom_field_flag));
1013         // Short term references:
1014         // Need L0 and L1 lists. Both contain 2 sets of reference frames ordered
1015         // by PicOrderCnt. The "previous" set contains the reference frames with
1016         // a PicOrderCnt < current frame. The "future" set contains the reference
1017         // frames with a PicOrderCnt > current frame. In both cases the ordering
1018         // is from closest to current frame to farthest. L0 has the previous set
1019         // followed by the future set; L1 has the future set followed by the previous set.
1020         // Accomplish this by one pass through the decoded frames list creating
1021         // the ordered previous list in the L0 array and the ordered future list
1022         // in the L1 array. Then copy from both to the other for the second set.
1023 
1024         // Long term references:
1025         // The ordered list is the same for L0 and L1, is ordered by ascending
1026         // LongTermPicNum. The ordered list is created using local temp then
1027         // appended to the L0 and L1 lists after the short-term references.
1028 
1029         for (pFrm = pHead; pFrm; pFrm = pFrm->future())
1030         {
1031             if (pFrm->isShortTermRef())
1032             {
1033                 // add to ordered list
1034                 FrmPicOrderCnt = pFrm->PicOrderCnt(0,2);//returns POC of reference field (or min if both are reference)
1035 
1036                 if (FrmPicOrderCnt <= CurrPicOrderCnt)
1037                 {
1038                     // Previous reference to L0, order large to small
1039                     j=0;
1040                     while (j < NumFramesInL0List &&
1041                         (pRefPicList0[j]->PicOrderCnt(0,2) > FrmPicOrderCnt))
1042                         j++;
1043 
1044                     // make room if needed
1045                     if (pRefPicList0[j])
1046                     {
1047                         for (k = NumFramesInL0List; k > j; k--)
1048                         {
1049                             // Avoid writing beyond end of list
1050                             if (k > (int32_t)(MAX_NUM_REF_FRAMES-1))
1051                             {
1052                                 VM_ASSERT(0);
1053                                 bError = true;
1054                                 break;
1055                             }
1056                             pRefPicList0[k] = pRefPicList0[k-1];
1057                         }
1058                     }
1059                     // add the short-term reference
1060                     pRefPicList0[j] = pFrm;
1061                     NumFramesInL0List++;
1062                 }
1063                 else
1064                 {
1065                     // Future reference to L1, order small to large
1066                     j=0;
1067                     while (j<NumFramesInL1List &&
1068                         pRefPicList1[j]->PicOrderCnt(0,2) < FrmPicOrderCnt)
1069                         j++;
1070 
1071                     // make room if needed
1072                     if (pRefPicList1[j])
1073                     {
1074                         for (k=NumFramesInL1List; k>j; k--)
1075                         {
1076                             // Avoid writing beyond end of list
1077                             if (k > (int32_t)(MAX_NUM_REF_FRAMES-1))
1078                             {
1079                                 VM_ASSERT(0);
1080                                 bError = true;
1081                                 break;
1082                             }
1083                             pRefPicList1[k] = pRefPicList1[k-1];
1084                         }
1085                     }
1086 
1087                     // add the short-term reference
1088                     pRefPicList1[j] = pFrm;
1089                     NumFramesInL1List++;
1090                 }
1091             }    // short-term B
1092             else if (pFrm->isLongTermRef())
1093             {
1094                 // long term reference
1095                 LongTermPicNum = pFrm->LongTermPicNum(0,2);
1096 
1097                 // order smallest to largest
1098                 j=0;
1099                 while (j < NumFramesInLTList &&
1100                     LTRefPicList[j]->LongTermPicNum(0,2) < LongTermPicNum)
1101                     j++;
1102 
1103                 // make room if needed
1104                 if (LTRefPicList[j])
1105                 {
1106                     for (k=NumFramesInLTList; k>j; k--)
1107                     {
1108                         // Avoid writing beyond end of list
1109                         if (k > (int32_t)(MAX_NUM_REF_FRAMES-1))
1110                         {
1111                             VM_ASSERT(0);
1112                             bError = true;
1113                             break;
1114                         }
1115                         LTRefPicList[k] = LTRefPicList[k-1];
1116                     }
1117                 }
1118 
1119                 // add the long-term reference
1120                 LTRefPicList[j] = pFrm;
1121                 NumFramesInLTList++;
1122 
1123             }    // long term reference
1124 
1125             if (bError) break;
1126         }    // for pFrm
1127 
1128         if ((NumFramesInL0List+NumFramesInL1List+NumFramesInLTList) < MAX_NUM_REF_FRAMES)
1129         {
1130             // Complete L0 and L1 lists
1131             // Add future short-term references to L0 list, after previous
1132             for (i=0; i<NumFramesInL1List; i++)
1133                 pRefPicList0[NumFramesInL0List+i] = pRefPicList1[i];
1134 
1135 
1136             // Add previous short-term references to L1 list, after future
1137             for (i=0; i<NumFramesInL0List; i++)
1138                 pRefPicList1[NumFramesInL1List+i] = pRefPicList0[i];
1139 
1140 
1141             // Add long term list to both L0 and L1
1142             for (i=0; i<NumFramesInLTList; i++)
1143             {
1144                 pRefPicList0[NumFramesInL0List+NumFramesInL1List+i] = LTRefPicList[i];
1145                 pRefPicList1[NumFramesInL0List+NumFramesInL1List+i] = LTRefPicList[i];
1146             }
1147 
1148             // Special rule: When L1 has more than one entry and L0 == L1, all entries,
1149             // swap the first two entries of L1.
1150             // They can be equal only if there are no future or no previous short-term
1151             // references. For fields will be done later.
1152             /*
1153             if ((NumFramesInL0List == 0 || NumFramesInL1List == 0) &&
1154                 ((NumFramesInL0List+NumFramesInL1List+NumFramesInLTList) > 1))
1155             {
1156                 pRefPicList1[0] = pRefPicList0[1];
1157                 pRefPicList1[1] = pRefPicList0[0];
1158             }*/
1159         }
1160         else
1161         {
1162             // too many reference frames
1163             VM_ASSERT(0);
1164         }
1165     }
1166 
1167     rli.m_iNumFramesInL0List = NumFramesInL0List;
1168     rli.m_iNumFramesInL1List = NumFramesInL1List;
1169     rli.m_iNumFramesInLTList = NumFramesInLTList;
1170 }
1171 
AddInterViewRefs(H264Slice * slice,H264DecoderFrame ** pRefPicList,ReferenceFlags * pFields,uint32_t listNum,ViewList & views)1172 void H264DBPList::AddInterViewRefs(H264Slice *slice, H264DecoderFrame **pRefPicList,
1173                                       ReferenceFlags *pFields, uint32_t listNum, ViewList &views)
1174 {
1175     uint32_t curRefIdx = 0;
1176     uint32_t num_refs_lx;
1177     const uint16_t *refs_lx;
1178 
1179     // get the number of entries in the list
1180     while ((MAX_NUM_REF_FIELDS > curRefIdx) &&
1181            (pRefPicList[curRefIdx]))
1182     {
1183         curRefIdx += 1;
1184     }
1185 
1186     // get the number of inter-view references and
1187     // corresponding view Id array
1188     {
1189         uint32_t VOIdx = GetVOIdx(slice->GetSeqMVCParam(), slice->GetSliceHeader()->nal_ext.mvc.view_id);
1190         const UMC_H264_DECODER::H264ViewRefInfo &refInfo = slice->GetSeqMVCParam()->viewInfo[VOIdx];
1191 
1192         if (slice->GetSliceHeader()->nal_ext.mvc.anchor_pic_flag)
1193         {
1194             num_refs_lx = refInfo.num_anchor_refs_lx[listNum];
1195             refs_lx = refInfo.anchor_refs_lx[listNum];
1196         }
1197         else
1198         {
1199             num_refs_lx = refInfo.num_non_anchor_refs_lx[listNum];
1200             refs_lx = refInfo.non_anchor_refs_lx[listNum];
1201         }
1202     }
1203 
1204     // append inter-view references to ref list
1205     for (uint32_t j = 0; j < num_refs_lx; j += 1)
1206     {
1207         // get reference view Id
1208         uint32_t refViewIdx = refs_lx[j];
1209         // get the corresponding view
1210         H264DBPList *pDPB = GetDPB(views, refViewIdx);
1211         if (pDPB)
1212         {
1213             // get the reference from the same access unit
1214             H264DecoderFrame *pRef = pDPB->findInterViewRef(slice->GetCurrentFrame()->m_auIndex, slice->GetSliceHeader()->bottom_field_flag);
1215             if (pRef)
1216             {
1217                 pRefPicList[curRefIdx] = pRef;
1218                 pFields[curRefIdx].field = slice->GetSliceHeader()->bottom_field_flag;
1219                 pFields[curRefIdx].isShortReference = 1;
1220                 curRefIdx += 1;
1221             }
1222         }
1223     }
1224 
1225 } // void AddInterViewRefs(H264DecoderFrame **pRefPicList,
1226 
DebugPrint()1227 void H264DBPList::DebugPrint()
1228 {
1229 #ifdef ENABLE_TRACE
1230     Trace(VM_STRING("-==========================================\n"));
1231     H264DecoderFrame * pTmp = m_pHead;
1232     for (int i = 0; pTmp; pTmp = pTmp->future(), i++)
1233     {
1234         Trace(VM_STRING("\n\n#%02d: UID - %d POC - %d %d  - resetcount - %d\n"), i, pTmp->m_UID, pTmp->m_PicOrderCnt[0], pTmp->m_PicOrderCnt[1], pTmp->RefPicListResetCount(0));
1235         Trace(VM_STRING("ViewId - %d, m_isInterViewRef - %d \n"), pTmp->m_viewId, pTmp->m_isInterViewRef[0]);
1236         Trace(VM_STRING("Short - %d %d \n"), pTmp->isShortTermRef(0), pTmp->isShortTermRef(1));
1237         Trace(VM_STRING("Long - %d %d \n"), pTmp->isLongTermRef(0), pTmp->isLongTermRef(1));
1238         Trace(VM_STRING("Busy - %d \n"), pTmp->GetRefCounter());
1239         Trace(VM_STRING("Skipping - %d, FrameExist - %d \n"), pTmp->IsSkipped(), pTmp->IsFrameExist());
1240         Trace(VM_STRING("FrameNum - %d \n"), pTmp->m_FrameNum);
1241         Trace(VM_STRING("PicNum - (%d, %d) \n"), pTmp->m_PicNum[0], pTmp->m_PicNum[1]);
1242         Trace(VM_STRING("LongPicNum - (%d, %d) \n"), pTmp->m_LongTermPicNum[0], pTmp->m_LongTermPicNum[1]);
1243         Trace(VM_STRING("Disp - %d , wasOutput - %d wasDisplayed - %d\n"), pTmp->IsDecoded(), pTmp->wasOutputted(), pTmp->wasDisplayed());
1244         Trace(VM_STRING("frame ID - %d, this - %d, decoded - %d, %d \n"), pTmp->GetFrameData()->GetFrameMID(), pTmp, pTmp->m_isDecoded, pTmp->m_isDecodingCompleted);
1245     }
1246 
1247     Trace(VM_STRING("-==========================================\n"));
1248     fflush(stdout);
1249 #endif
1250 }
1251 
1252 
1253 } // end namespace UMC
1254 #endif // MFX_ENABLE_H264_VIDEO_DECODE
1255