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