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 /* DEBUG: this file is requred to changing name
25 to umc_h264_dec_slice_decode_pic */
26
27 #include "umc_h264_slice_decoding.h"
28 #include "umc_h264_dec.h"
29 #include "vm_debug.h"
30 #include "umc_h264_frame_list.h"
31
32 #include "umc_h264_task_supplier.h"
33
34 //#define ENABLE_LIST_TRACE
35 #define LIST_TRACE_FILE_NAME "d:/ipp.ref"
36
37 namespace UMC
38 {
39
FindLastValidReference(H264DecoderFrame ** pList,int32_t iLength)40 static H264DecoderFrame *FindLastValidReference(H264DecoderFrame **pList, int32_t iLength)
41 {
42 int32_t i;
43 H264DecoderFrame *pLast = NULL;
44
45 for (i = 0; i < iLength; i += 1)
46 {
47 if (pList[i])
48 pLast = pList[i];
49 }
50
51 return pLast;
52
53 } // H264DecoderFrame *FindLastValidReference(H264DecoderFrame **pList,
54
55
UpdateReferenceList(ViewList & views,int32_t dIdIndex)56 Status H264Slice::UpdateReferenceList(ViewList &views,
57 int32_t dIdIndex)
58 {
59 UMC_H264_DECODER::RefPicListReorderInfo *pReorderInfo_L0 = &ReorderInfoL0;
60 UMC_H264_DECODER::RefPicListReorderInfo *pReorderInfo_L1 = &ReorderInfoL1;
61 const UMC_H264_DECODER::H264SeqParamSet *sps = GetSeqParam();
62 uint32_t uMaxFrameNum;
63 uint32_t uMaxPicNum;
64 H264DecoderFrame *pFrm;
65 H264DBPList *pDecoderFrameList = GetDPB(views, m_SliceHeader.nal_ext.mvc.view_id, dIdIndex);
66 H264DecoderFrame *pHead = pDecoderFrameList->head();
67 //uint32_t i;
68 H264DecoderFrame **pRefPicList0;
69 H264DecoderFrame **pRefPicList1;
70 ReferenceFlags *pFields0;
71 ReferenceFlags *pFields1;
72 uint32_t NumShortTermRefs, NumLongTermRefs;
73 H264RefListInfo rli;
74 H264DecoderFrame *pLastInList[2] = {NULL, NULL};
75
76 if (m_pCurrentFrame == nullptr)
77 return UMC_ERR_NULL_PTR;
78
79 const H264DecoderRefPicList* pH264DecRefPicList0 = m_pCurrentFrame->GetRefPicList(m_iNumber, 0);
80 const H264DecoderRefPicList* pH264DecRefPicList1 = m_pCurrentFrame->GetRefPicList(m_iNumber, 1);
81 if (pH264DecRefPicList0 == nullptr || pH264DecRefPicList1 == nullptr)
82 return UMC_ERR_NULL_PTR;
83
84 pRefPicList0 = pH264DecRefPicList0->m_RefPicList;
85 pRefPicList1 = pH264DecRefPicList1->m_RefPicList;
86 pFields0 = pH264DecRefPicList0->m_Flags;
87 pFields1 = pH264DecRefPicList1->m_Flags;
88
89 // Spec reference: 8.2.4, "Decoding process for reference picture lists
90 // construction"
91
92 // get pointers to the picture and sequence parameter sets currently in use
93 uMaxFrameNum = (1<<sps->log2_max_frame_num);
94 uMaxPicNum = (m_SliceHeader.field_pic_flag == 0) ? uMaxFrameNum : uMaxFrameNum<<1;
95
96 for (pFrm = pHead; pFrm; pFrm = pFrm->future())
97 {
98 // update FrameNumWrap and picNum if frame number wrap occurred,
99 // for short-term frames
100 // TBD: modify for fields
101 pFrm->UpdateFrameNumWrap((int32_t)m_SliceHeader.frame_num,
102 uMaxFrameNum,
103 m_pCurrentFrame->m_PictureStructureForDec +
104 m_SliceHeader.bottom_field_flag);
105
106 // For long-term references, update LongTermPicNum. Note this
107 // could be done when LongTermFrameIdx is set, but this would
108 // only work for frames, not fields.
109 // TBD: modify for fields
110 pFrm->UpdateLongTermPicNum(m_pCurrentFrame->m_PictureStructureForDec +
111 m_SliceHeader.bottom_field_flag);
112 }
113
114 for (uint32_t number = 0; number <= MAX_NUM_REF_FRAMES + 1; number++)
115 {
116 pRefPicList0[number] = 0;
117 pRefPicList1[number] = 0;
118 pFields0[number].field = 0;
119 pFields0[number].isShortReference = 0;
120 pFields1[number].field = 0;
121 pFields1[number].isShortReference = 0;
122 }
123
124 if ((m_SliceHeader.slice_type != INTRASLICE) && (m_SliceHeader.slice_type != S_INTRASLICE))
125 {
126 uint32_t NumInterViewRefs = 0;
127
128 // Detect and report no available reference frames
129 pDecoderFrameList->countActiveRefs(NumShortTermRefs, NumLongTermRefs);
130 // calculate number of inter-view references
131 if (m_SliceHeader.nal_ext.mvc.view_id != views.front().viewId)
132 {
133 NumInterViewRefs = GetInterViewFrameRefs(views, m_SliceHeader.nal_ext.mvc.view_id, m_pCurrentFrame->m_auIndex, m_SliceHeader.bottom_field_flag);
134 }
135
136 if ((NumShortTermRefs + NumLongTermRefs + NumInterViewRefs) == 0)
137 {
138 return UMC_ERR_INVALID_STREAM;
139 }
140
141
142 // Initialize the reference picture lists
143 // Note the slice header get function always fills num_ref_idx_lx_active
144 // fields with a valid value; either the override from the slice
145 // header in the bitstream or the values from the pic param set when
146 // there is no override.
147
148 if (!m_SliceHeader.IdrPicFlag)
149 {
150 if ((m_SliceHeader.slice_type == PREDSLICE) ||
151 (m_SliceHeader.slice_type == S_PREDSLICE))
152 {
153 pDecoderFrameList->InitPSliceRefPicList(this, pRefPicList0);
154 pLastInList[0] = FindLastValidReference(pRefPicList0,
155 m_SliceHeader.num_ref_idx_l0_active);
156 }
157 else
158 {
159 pDecoderFrameList->InitBSliceRefPicLists(this, pRefPicList0, pRefPicList1, rli);
160 pLastInList[0] = FindLastValidReference(pRefPicList0,
161 m_SliceHeader.num_ref_idx_l0_active);
162 pLastInList[1] = FindLastValidReference(pRefPicList1,
163 m_SliceHeader.num_ref_idx_l1_active);
164 }
165
166 // Reorder the reference picture lists
167 if (m_pCurrentFrame->m_PictureStructureForDec < FRM_STRUCTURE)
168 {
169 rli.m_iNumFramesInL0List = AdjustRefPicListForFields(pRefPicList0, pFields0, rli);
170 }
171
172 if (BPREDSLICE == m_SliceHeader.slice_type)
173 {
174 if (m_pCurrentFrame->m_PictureStructureForDec < FRM_STRUCTURE)
175 {
176 rli.m_iNumFramesInL1List = AdjustRefPicListForFields(pRefPicList1, pFields1, rli);
177 }
178
179 if ((rli.m_iNumFramesInL0List == rli.m_iNumFramesInL1List) &&
180 (rli.m_iNumFramesInL0List > 1))
181 {
182 bool isNeedSwap = true;
183 for (int32_t i = 0; i < rli.m_iNumFramesInL0List; i++)
184 {
185 if (pRefPicList1[i] != pRefPicList0[i] ||
186 pFields1[i].field != pFields0[i].field)
187 {
188 isNeedSwap = false;
189 break;
190 }
191 }
192
193 if (isNeedSwap)
194 {
195 std::swap(pRefPicList1[0], pRefPicList1[1]);
196 std::swap(pFields1[0], pFields1[1]);
197 }
198 }
199 }
200 }
201
202 // MVC extension. Add inter-view references
203 if ((H264VideoDecoderParams::H264_PROFILE_MULTIVIEW_HIGH == m_pSeqParamSet->profile_idc) ||
204 (H264VideoDecoderParams::H264_PROFILE_STEREO_HIGH == m_pSeqParamSet->profile_idc))
205 {
206 pDecoderFrameList->AddInterViewRefs(this, pRefPicList0, pFields0, LIST_0, views);
207 if (m_SliceHeader.IdrPicFlag)
208 {
209 pLastInList[0] = FindLastValidReference(pRefPicList0, m_SliceHeader.num_ref_idx_l0_active);
210 }
211
212 if (BPREDSLICE == m_SliceHeader.slice_type)
213 {
214 pDecoderFrameList->AddInterViewRefs(this, pRefPicList1, pFields1, LIST_1, views);
215 if (m_SliceHeader.IdrPicFlag)
216 pLastInList[1] = FindLastValidReference(pRefPicList1, m_SliceHeader.num_ref_idx_l1_active);
217 }
218 }
219
220
221 if (pReorderInfo_L0->num_entries > 0)
222 ReOrderRefPicList(pRefPicList0, pFields0, pReorderInfo_L0, uMaxPicNum, views, dIdIndex, 0);
223
224 pRefPicList0[m_SliceHeader.num_ref_idx_l0_active] = 0;
225
226 if (BPREDSLICE == m_SliceHeader.slice_type)
227 {
228 if (pReorderInfo_L1->num_entries > 0)
229 ReOrderRefPicList(pRefPicList1, pFields1, pReorderInfo_L1, uMaxPicNum, views, dIdIndex, 1);
230
231 pRefPicList1[m_SliceHeader.num_ref_idx_l1_active] = 0;
232 }
233
234
235
236 // set absent references
237 {
238 int32_t i;
239 int32_t iCurField = 1;
240
241 if (!pLastInList[0])
242 {
243 for (;;)
244 {
245 for (H264DecoderFrame *pFrame = pDecoderFrameList->head(); pFrame; pFrame = pFrame->future())
246 {
247 if (pFrame->isShortTermRef()==3)
248 pLastInList[0] = pFrame;
249 }
250
251 if (pLastInList[0])
252 break;
253
254 for (H264DecoderFrame *pFrame = pDecoderFrameList->head(); pFrame; pFrame = pFrame->future())
255 {
256 if (pFrame->isLongTermRef()==3)
257 pLastInList[0] = pFrame;
258 }
259 break;
260 }
261 }
262
263 if (BPREDSLICE == m_SliceHeader.slice_type && !pLastInList[1])
264 {
265 pLastInList[1] = pLastInList[0];
266 }
267
268 for (i = 0; i < m_SliceHeader.num_ref_idx_l0_active; i += 1)
269 {
270 if (NULL == pRefPicList0[i])
271 {
272 pRefPicList0[i] = pLastInList[0];
273 m_pCurrentFrame->AddReference(pLastInList[0]);
274 pFields0[i].field = (int8_t) (iCurField ^= 1);
275 if (pRefPicList0[i])
276 pFields0[i].isShortReference = (pRefPicList0[i]->m_viewId == m_pCurrentFrame->m_viewId) ? 1 : 0;
277 else
278 pFields0[i].isShortReference = 1;
279 pFields0[i].isLongReference = 0;
280 m_pCurrentFrame->SetErrorFlagged(ERROR_FRAME_MAJOR);
281 }
282 else
283 {
284 m_pCurrentFrame->AddReference(pRefPicList0[i]);
285 m_pCurrentFrame->SetErrorFlagged(pRefPicList0[i]->IsFrameExist() ? 0 : ERROR_FRAME_MAJOR);
286 pFields0[i].isShortReference =
287 pRefPicList0[i]->isShortTermRef(pRefPicList0[i]->GetNumberByParity(pFields0[i].field));
288 pFields0[i].isLongReference =
289 pRefPicList0[i]->isLongTermRef(pRefPicList0[i]->GetNumberByParity(pFields0[i].field));
290
291 if (pRefPicList0[i]->m_viewId != m_pCurrentFrame->m_viewId)
292 pFields0[i].isShortReference = pFields0[i].isLongReference = 0;
293 }
294 }
295
296 if (BPREDSLICE == m_SliceHeader.slice_type)
297 {
298 iCurField = 1;
299
300 for (i = 0; i < m_SliceHeader.num_ref_idx_l1_active; i += 1)
301 {
302 if (NULL == pRefPicList1[i])
303 {
304 pRefPicList1[i] = pLastInList[1];
305 m_pCurrentFrame->AddReference(pLastInList[1]);
306 pFields1[i].field = (int8_t) (iCurField ^= 1);
307 pFields1[i].isShortReference = 1;
308 if (pRefPicList1[i])
309 pFields1[i].isShortReference = (pRefPicList1[i]->m_viewId == m_pCurrentFrame->m_viewId) ? 1 : 0;
310 else
311 pFields1[i].isShortReference = 1;
312 pFields1[i].isLongReference = 0;
313 m_pCurrentFrame->SetErrorFlagged(ERROR_FRAME_MAJOR);
314 }
315 else
316 {
317 m_pCurrentFrame->AddReference(pRefPicList1[i]);
318 m_pCurrentFrame->SetErrorFlagged(pRefPicList1[i]->IsFrameExist() ? 0 : ERROR_FRAME_MAJOR);
319 pFields1[i].isShortReference =
320 pRefPicList1[i]->isShortTermRef(pRefPicList1[i]->GetNumberByParity(pFields1[i].field));
321 pFields1[i].isLongReference =
322 pRefPicList1[i]->isLongTermRef(pRefPicList1[i]->GetNumberByParity(pFields1[i].field));
323
324 if (pRefPicList1[i]->m_viewId != m_pCurrentFrame->m_viewId)
325 pFields1[i].isShortReference = pFields1[i].isLongReference = 0;
326 }
327 }
328 }
329 }
330 }
331
332 return UMC_OK;
333
334 } // Status H264Slice::UpdateRefPicList(H264DecoderFrameList *pDecoderFrameList)
335
AdjustRefPicListForFields(H264DecoderFrame ** pRefPicList,ReferenceFlags * pFields,H264RefListInfo & rli)336 int32_t H264Slice::AdjustRefPicListForFields(H264DecoderFrame **pRefPicList,
337 ReferenceFlags *pFields,
338 H264RefListInfo &rli)
339 {
340 H264DecoderFrame *TempList[MAX_NUM_REF_FRAMES+1];
341 uint8_t TempFields[MAX_NUM_REF_FRAMES+1];
342 //walk through list and set correct indices
343 int32_t i=0,j=0,numSTR=0,numLTR=0;
344 int32_t num_same_parity = 0, num_opposite_parity = 0;
345 int8_t current_parity = m_SliceHeader.bottom_field_flag;
346 //first scan the list to determine number of shortterm and longterm reference frames
347 while ((numSTR < 16) && pRefPicList[numSTR] && pRefPicList[numSTR]->isShortTermRef()) numSTR++;
348 while ((numSTR + numLTR < 16) && pRefPicList[numSTR+numLTR] && pRefPicList[numSTR+numLTR]->isLongTermRef()) numLTR++;
349
350 while (num_same_parity < numSTR || num_opposite_parity < numSTR)
351 {
352 //try to fill shorttermref fields with the same parity first
353 if (num_same_parity < numSTR)
354 {
355 while (num_same_parity < numSTR)
356 {
357 int32_t ref_field = pRefPicList[num_same_parity]->GetNumberByParity(current_parity);
358 if (pRefPicList[num_same_parity]->isShortTermRef(ref_field))
359 break;
360
361 num_same_parity++;
362
363 }
364
365 if (num_same_parity<numSTR)
366 {
367 TempList[i] = pRefPicList[num_same_parity];
368 TempFields[i] = current_parity;
369 i++;
370 num_same_parity++;
371 }
372 }
373 //now process opposite parity
374 if (num_opposite_parity < numSTR)
375 {
376 while (num_opposite_parity < numSTR)
377 {
378 int32_t ref_field = pRefPicList[num_opposite_parity]->GetNumberByParity(!current_parity);
379 if (pRefPicList[num_opposite_parity]->isShortTermRef(ref_field))
380 break;
381 num_opposite_parity++;
382 }
383
384 if (num_opposite_parity<numSTR) //selected field is reference
385 {
386 TempList[i] = pRefPicList[num_opposite_parity];
387 TempFields[i] = !current_parity;
388 i++;
389 num_opposite_parity++;
390 }
391 }
392 }
393
394 rli.m_iNumShortEntriesInList = (uint8_t) i;
395 num_same_parity = num_opposite_parity = 0;
396 //now processing LongTermRef
397 while(num_same_parity<numLTR || num_opposite_parity<numLTR)
398 {
399 //try to fill longtermref fields with the same parity first
400 if (num_same_parity < numLTR)
401 {
402 while (num_same_parity < numLTR)
403 {
404 int32_t ref_field = pRefPicList[num_same_parity+numSTR]->GetNumberByParity(current_parity);
405 if (pRefPicList[num_same_parity+numSTR]->isLongTermRef(ref_field))
406 break;
407 num_same_parity++;
408 }
409 if (num_same_parity<numLTR)
410 {
411 TempList[i] = pRefPicList[num_same_parity+numSTR];
412 TempFields[i] = current_parity;
413 i++;
414 num_same_parity++;
415 }
416 }
417 //now process opposite parity
418 if (num_opposite_parity<numLTR)
419 {
420 while (num_opposite_parity < numLTR)
421 {
422 int32_t ref_field = pRefPicList[num_opposite_parity+numSTR]->GetNumberByParity(!current_parity);
423
424 if (pRefPicList[num_opposite_parity+numSTR]->isLongTermRef(ref_field))
425 break;
426 num_opposite_parity++;
427 }
428
429 if (num_opposite_parity<numLTR) //selected field is reference
430 {
431 TempList[i] = pRefPicList[num_opposite_parity+numSTR];
432 TempFields[i] = !current_parity;
433 i++;
434 num_opposite_parity++;
435 }
436 }
437 }
438
439 rli.m_iNumLongEntriesInList = (uint8_t) (i - rli.m_iNumShortEntriesInList);
440 j = 0;
441 while(j < i)//copy data back to list
442 {
443 pRefPicList[j] = TempList[j];
444 pFields[j].field = TempFields[j];
445 pFields[j].isShortReference = (unsigned char) (pRefPicList[j]->isShortTermRef(pRefPicList[j]->GetNumberByParity(TempFields[j])) ? 1 : 0);
446 j++;
447 }
448
449 while(j < (int32_t)MAX_NUM_REF_FRAMES)//fill remaining entries
450 {
451 pRefPicList[j] = NULL;
452 pFields[j].field = 0;
453 pFields[j].isShortReference = 0;
454 j++;
455 }
456
457 return i;
458 } // int32_t H264Slice::AdjustRefPicListForFields(H264DecoderFrame **pRefPicList, int8_t *pFields)
459
ReOrderRefPicList(H264DecoderFrame ** pRefPicList,ReferenceFlags * pFields,UMC_H264_DECODER::RefPicListReorderInfo * pReorderInfo,int32_t MaxPicNum,ViewList & views,int32_t dIdIndex,uint32_t listNum)460 void H264Slice::ReOrderRefPicList(H264DecoderFrame **pRefPicList,
461 ReferenceFlags *pFields,
462 UMC_H264_DECODER::RefPicListReorderInfo *pReorderInfo,
463 int32_t MaxPicNum,
464 ViewList &views,
465 int32_t dIdIndex,
466 uint32_t listNum)
467 {
468 bool bIsFieldSlice = (m_SliceHeader.field_pic_flag != 0);
469 uint32_t NumRefActive = (0 == listNum) ?
470 m_SliceHeader.num_ref_idx_l0_active :
471 m_SliceHeader.num_ref_idx_l1_active;
472 uint32_t i;
473 int32_t picNumNoWrap;
474 int32_t picNum;
475 int32_t picNumPred;
476 int32_t picNumCurr;
477 int32_t picViewIdxLXPred = -1;
478 H264DBPList *pDecoderFrameList = GetDPB(views, m_SliceHeader.nal_ext.mvc.view_id, dIdIndex);
479
480 int32_t pocForce = bIsFieldSlice ? 0 : 3;
481
482 // Reference: Reordering process for reference picture lists, 8.2.4.3
483 picNumCurr = m_pCurrentFrame->PicNum(m_pCurrentFrame->GetNumberByParity(m_SliceHeader.bottom_field_flag), pocForce);
484 picNumPred = picNumCurr;
485
486 for (i=0; i<pReorderInfo->num_entries; i++)
487 {
488 if (pReorderInfo->reordering_of_pic_nums_idc[i] < 2)
489 {
490 // short-term reorder
491 if (pReorderInfo->reordering_of_pic_nums_idc[i] == 0)
492 {
493 picNumNoWrap = picNumPred - pReorderInfo->reorder_value[i];
494 if (picNumNoWrap < 0)
495 picNumNoWrap += MaxPicNum;
496 }
497 else
498 {
499 picNumNoWrap = picNumPred + pReorderInfo->reorder_value[i];
500 if (picNumNoWrap >= MaxPicNum)
501 picNumNoWrap -= MaxPicNum;
502 }
503 picNumPred = picNumNoWrap;
504
505 picNum = picNumNoWrap;
506 if (picNum > picNumCurr)
507 picNum -= MaxPicNum;
508
509 int32_t frameField;
510 H264DecoderFrame* pFrame = pDecoderFrameList->findShortTermPic(picNum, &frameField);
511
512 for (uint32_t k = NumRefActive; k > i; k--)
513 {
514 pRefPicList[k] = pRefPicList[k - 1];
515 pFields[k] = pFields[k - 1];
516 }
517
518 // Place picture with picNum on list, shifting pictures
519 // down by one while removing any duplication of picture with picNum.
520 pRefPicList[i] = pFrame;
521 pFields[i].field = (char) ((pFrame && bIsFieldSlice) ? pFrame->m_bottom_field_flag[frameField] : 0);
522 pFields[i].isShortReference = 1;
523 int32_t refIdxLX = i + 1;
524
525 for(uint32_t kk = i + 1; kk <= NumRefActive; kk++)
526 {
527 if (pRefPicList[kk])
528 {
529 if (!(pRefPicList[kk]->isShortTermRef(pRefPicList[kk]->GetNumberByParity(pFields[kk].field)) &&
530 pRefPicList[kk]->PicNum(pRefPicList[kk]->GetNumberByParity(pFields[kk].field), 1) == picNum))
531 {
532 pRefPicList[refIdxLX] = pRefPicList[kk];
533 pFields[refIdxLX] = pFields[kk];
534 refIdxLX++;
535 }
536 }
537 }
538 } // short-term reorder
539 else if (2 == pReorderInfo->reordering_of_pic_nums_idc[i])
540 {
541 // long term reorder
542 picNum = pReorderInfo->reorder_value[i];
543
544 int32_t frameField;
545 H264DecoderFrame* pFrame = pDecoderFrameList->findLongTermPic(picNum, &frameField);
546
547 for (uint32_t k = NumRefActive; k > i; k--)
548 {
549 pRefPicList[k] = pRefPicList[k - 1];
550 pFields[k] = pFields[k - 1];
551 }
552
553 // Place picture with picNum on list, shifting pictures
554 // down by one while removing any duplication of picture with picNum.
555 pRefPicList[i] = pFrame;
556 pFields[i].field = (char) ((pFrame && bIsFieldSlice) ? pFrame->m_bottom_field_flag[frameField] : 0);
557 pFields[i].isShortReference = 0;
558 int32_t refIdxLX = i + 1;
559
560 for(uint32_t kk = i + 1; kk <= NumRefActive; kk++)
561 {
562 if (pRefPicList[kk])
563 {
564 if (!(pRefPicList[kk]->isLongTermRef(pRefPicList[kk]->GetNumberByParity(pFields[kk].field)) &&
565 pRefPicList[kk]->LongTermPicNum(pRefPicList[kk]->GetNumberByParity(pFields[kk].field), 1) == picNum))
566 {
567 pRefPicList[refIdxLX] = pRefPicList[kk];
568 pFields[refIdxLX] = pFields[kk];
569 refIdxLX++;
570 }
571 }
572 }
573 } // long term reorder
574 // MVC reordering
575 else if ((4 == pReorderInfo->reordering_of_pic_nums_idc[i]) ||
576 (5 == pReorderInfo->reordering_of_pic_nums_idc[i]))
577 {
578 int32_t abs_diff_view_idx = pReorderInfo->reorder_value[i];
579 int32_t maxViewIdx;
580 int32_t targetViewID;
581
582 if (!m_pSeqParamSetMvcEx)
583 {
584 m_pCurrentFrame->SetErrorFlagged(ERROR_FRAME_MAJOR);
585 continue;
586 }
587
588 uint32_t picViewIdxLX;
589 H264DecoderFrame* pFrame = NULL;
590 int32_t curPOC = m_pCurrentFrame->PicOrderCnt(m_pCurrentFrame->GetNumberByParity(m_SliceHeader.bottom_field_flag), pocForce);
591
592 // set current VO index
593 const auto currView = std::find_if(m_pSeqParamSetMvcEx->viewInfo.begin(), m_pSeqParamSetMvcEx->viewInfo.end(),
594 [this](const UMC_H264_DECODER::H264ViewRefInfo &item){ return item.view_id == m_SliceHeader.nal_ext.mvc.view_id; });
595 if (currView == m_pSeqParamSetMvcEx->viewInfo.end())
596 {
597 throw h264_exception(UMC_ERR_INVALID_STREAM);
598 }
599
600 // get the maximum number of reference
601 if (m_SliceHeader.nal_ext.mvc.anchor_pic_flag)
602 {
603 maxViewIdx = currView->num_anchor_refs_lx[listNum];
604 }
605 else
606 {
607 maxViewIdx = currView->num_non_anchor_refs_lx[listNum];
608 }
609
610 // get the index of view reference
611 if (4 == pReorderInfo->reordering_of_pic_nums_idc[i])
612 {
613 if (picViewIdxLXPred - abs_diff_view_idx < 0)
614 {
615 picViewIdxLX = picViewIdxLXPred - abs_diff_view_idx + maxViewIdx;
616 }
617 else
618 {
619 picViewIdxLX = picViewIdxLXPred - abs_diff_view_idx;
620 }
621 }
622 else
623 {
624 if (picViewIdxLXPred + abs_diff_view_idx >= maxViewIdx)
625 {
626 picViewIdxLX = picViewIdxLXPred + abs_diff_view_idx - maxViewIdx;
627 }
628 else
629 {
630 picViewIdxLX = picViewIdxLXPred + abs_diff_view_idx;
631 }
632 }
633 picViewIdxLXPred = picViewIdxLX;
634 if (picViewIdxLX >= UMC::H264_MAX_NUM_VIEW_REF)
635 {
636 m_pCurrentFrame->SetErrorFlagged(ERROR_FRAME_MAJOR);
637 continue;
638 }
639 // get the target view
640 if (m_SliceHeader.nal_ext.mvc.anchor_pic_flag)
641 {
642 targetViewID = currView->anchor_refs_lx[listNum][picViewIdxLX];
643 }
644 else
645 {
646 targetViewID = currView->non_anchor_refs_lx[listNum][picViewIdxLX];
647 }
648 ViewList::iterator iter = views.begin();
649 ViewList::iterator iter_end = views.end();
650 for (; iter != iter_end; ++iter)
651 {
652 if (targetViewID == iter->viewId)
653 {
654 pFrame = iter->GetDPBList(dIdIndex)->findInterViewRef(m_pCurrentFrame->m_auIndex, m_SliceHeader.bottom_field_flag);
655 break;
656 }
657 }
658 // corresponding frame is found
659 if (!pFrame)
660 continue;
661
662 // make some space to insert the reference
663 for (uint32_t k = NumRefActive; k > i; k--)
664 {
665 pRefPicList[k] = pRefPicList[k - 1];
666 pFields[k] = pFields[k - 1];
667 }
668
669 // Place picture with picNum on list, shifting pictures
670 // down by one while removing any duplication of picture with cuuPOC.
671 pRefPicList[i] = pFrame;
672 pFields[i].field = m_SliceHeader.bottom_field_flag;
673 pFields[i].isShortReference = 1;
674 uint32_t refIdxLX = i + 1;
675
676 for (uint32_t kk = i + 1; kk <= NumRefActive; kk++)
677 {
678 if (pRefPicList[kk])
679 {
680 uint32_t refFieldIdx = pRefPicList[kk]->GetNumberByParity(m_SliceHeader.bottom_field_flag);
681
682 if ((pRefPicList[kk]->m_viewId != targetViewID) ||
683 (pRefPicList[kk]->PicOrderCnt(refFieldIdx, pocForce) != curPOC))
684 {
685 pRefPicList[refIdxLX] = pRefPicList[kk];
686 pFields[refIdxLX] = pFields[kk];
687 refIdxLX++;
688 }
689 }
690 }
691 }
692 } // for i
693 } // void H264Slice::ReOrderRefPicList(H264DecoderFrame **pRefPicList,
694
695 } // namespace UMC
696
697 #endif // MFX_ENABLE_H264_VIDEO_DECODE
698