1/* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18#include "avclib_common.h"
19
20/** see subclause 8.2.4 Decoding process for reference picture lists construction. */
21OSCL_EXPORT_REF void RefListInit(AVCCommonObj *video)
22{
23    AVCSliceHeader *sliceHdr = video->sliceHdr;
24    AVCDecPicBuffer *dpb = video->decPicBuf;
25    int slice_type = video->slice_type;
26    int i, list0idx;
27
28    AVCPictureData *tmp_s;
29
30    list0idx = 0;
31
32    if (slice_type == AVC_I_SLICE)
33    {
34        video->refList0Size = 0;
35        video->refList1Size = 0;
36
37        /* we still have to calculate FrameNumWrap to make sure that all I-slice clip
38        can perform sliding_window_operation properly. */
39
40        for (i = 0; i < dpb->num_fs; i++)
41        {
42            if ((dpb->fs[i]->IsReference == 3) && (!dpb->fs[i]->IsLongTerm))
43            {
44                /* subclause 8.2.4.1 Decoding process for picture numbers. */
45                if (dpb->fs[i]->FrameNum > (int)sliceHdr->frame_num)
46                {
47                    dpb->fs[i]->FrameNumWrap = dpb->fs[i]->FrameNum - video->MaxFrameNum;
48                }
49                else
50                {
51                    dpb->fs[i]->FrameNumWrap = dpb->fs[i]->FrameNum;
52                }
53                dpb->fs[i]->frame.PicNum = dpb->fs[i]->FrameNumWrap;
54            }
55        }
56
57
58        return ;
59    }
60    if (slice_type == AVC_P_SLICE)
61    {
62        /* Calculate FrameNumWrap and PicNum */
63
64        for (i = 0; i < dpb->num_fs; i++)
65        {
66            if ((dpb->fs[i]->IsReference == 3) && (!dpb->fs[i]->IsLongTerm))
67            {
68                /* subclause 8.2.4.1 Decoding process for picture numbers. */
69                if (dpb->fs[i]->FrameNum > (int)sliceHdr->frame_num)
70                {
71                    dpb->fs[i]->FrameNumWrap = dpb->fs[i]->FrameNum - video->MaxFrameNum;
72                }
73                else
74                {
75                    dpb->fs[i]->FrameNumWrap = dpb->fs[i]->FrameNum;
76                }
77                dpb->fs[i]->frame.PicNum = dpb->fs[i]->FrameNumWrap;
78                video->RefPicList0[list0idx++] = &(dpb->fs[i]->frame);
79            }
80        }
81
82        if (list0idx == 0)
83        {
84            dpb->fs[0]->IsReference = 3;
85            video->RefPicList0[0] = &(dpb->fs[0]->frame);
86            list0idx = 1;
87        }
88        /* order list 0 by PicNum from max to min, see subclause 8.2.4.2.1 */
89        SortPicByPicNum(video->RefPicList0, list0idx);
90        video->refList0Size = list0idx;
91
92        /* long term handling */
93        for (i = 0; i < dpb->num_fs; i++)
94        {
95            if (dpb->fs[i]->IsLongTerm == 3)
96            {
97                /* subclause 8.2.4.1 Decoding process for picture numbers. */
98                dpb->fs[i]->frame.LongTermPicNum = dpb->fs[i]->LongTermFrameIdx;
99                video->RefPicList0[list0idx++] = &(dpb->fs[i]->frame);
100            }
101        }
102
103        /* order PicNum from min to max, see subclause 8.2.4.2.1  */
104        SortPicByPicNumLongTerm(&(video->RefPicList0[video->refList0Size]), list0idx - video->refList0Size);
105        video->refList0Size = list0idx;
106
107
108        video->refList1Size = 0;
109    }
110
111
112    if ((video->refList0Size == video->refList1Size) && (video->refList0Size > 1))
113    {
114        /* check if lists are identical, if yes swap first two elements of listX[1] */
115        /* last paragraph of subclause 8.2.4.2.4 */
116
117        for (i = 0; i < video->refList0Size; i++)
118        {
119            if (video->RefPicList0[i] != video->RefPicList1[i])
120            {
121                break;
122            }
123        }
124        if (i == video->refList0Size)
125        {
126            tmp_s = video->RefPicList1[0];
127            video->RefPicList1[0] = video->RefPicList1[1];
128            video->RefPicList1[1] = tmp_s;
129        }
130    }
131
132    /* set max size */
133    video->refList0Size = AVC_MIN(video->refList0Size, (int)video->sliceHdr->num_ref_idx_l0_active_minus1 + 1);
134    video->refList1Size = AVC_MIN(video->refList1Size, (int)video->sliceHdr->num_ref_idx_l1_active_minus1 + 1);
135
136    return ;
137}
138/* see subclause 8.2.4.3 */
139OSCL_EXPORT_REF AVCStatus ReOrderList(AVCCommonObj *video)
140{
141    AVCSliceHeader *sliceHdr = video->sliceHdr;
142    AVCStatus status = AVC_SUCCESS;
143    int slice_type = video->slice_type;
144
145    if (slice_type != AVC_I_SLICE)
146    {
147        if (sliceHdr->ref_pic_list_reordering_flag_l0)
148        {
149            status = ReorderRefPicList(video, 0);
150            if (status != AVC_SUCCESS)
151                return status;
152        }
153        if (video->refList0Size == 0)
154        {
155            return AVC_FAIL;
156        }
157    }
158    return status;
159}
160
161AVCStatus ReorderRefPicList(AVCCommonObj *video, int isL1)
162{
163    AVCSliceHeader *sliceHdr = video->sliceHdr;
164    AVCStatus status;
165
166    int *list_size;
167    int num_ref_idx_lX_active_minus1;
168    uint *remapping_of_pic_nums_idc;
169    int *abs_diff_pic_num_minus1;
170    int *long_term_pic_idx;
171    int i;
172    int maxPicNum, currPicNum, picNumLXNoWrap, picNumLXPred, picNumLX;
173    int refIdxLX = 0;
174    void* tmp;
175
176    if (!isL1) /* list 0 */
177    {
178        list_size = &(video->refList0Size);
179        num_ref_idx_lX_active_minus1 = sliceHdr->num_ref_idx_l0_active_minus1;
180        remapping_of_pic_nums_idc = sliceHdr->reordering_of_pic_nums_idc_l0;
181        tmp = (void*)sliceHdr->abs_diff_pic_num_minus1_l0;
182        abs_diff_pic_num_minus1 = (int*) tmp;
183        tmp = (void*)sliceHdr->long_term_pic_num_l0;
184        long_term_pic_idx = (int*) tmp;
185    }
186    else
187    {
188        list_size = &(video->refList1Size);
189        num_ref_idx_lX_active_minus1 = sliceHdr->num_ref_idx_l1_active_minus1;
190        remapping_of_pic_nums_idc = sliceHdr->reordering_of_pic_nums_idc_l1;
191        tmp = (void*) sliceHdr->abs_diff_pic_num_minus1_l1;
192        abs_diff_pic_num_minus1 = (int*) tmp;
193        tmp = (void*) sliceHdr->long_term_pic_num_l1;
194        long_term_pic_idx = (int*)tmp;
195    }
196
197    maxPicNum = video->MaxPicNum;
198    currPicNum = video->CurrPicNum;
199
200    picNumLXPred = currPicNum; /* initial value */
201
202    for (i = 0; remapping_of_pic_nums_idc[i] != 3; i++)
203    {
204        if ((remapping_of_pic_nums_idc[i] > 3) || (i >= MAX_REF_PIC_LIST_REORDERING))
205        {
206            return AVC_FAIL; /* out of range */
207        }
208        /* see subclause 8.2.4.3.1 */
209        if (remapping_of_pic_nums_idc[i] < 2)
210        {
211            if (remapping_of_pic_nums_idc[i] == 0)
212            {
213                if (picNumLXPred - (abs_diff_pic_num_minus1[i] + 1) < 0)
214                    picNumLXNoWrap = picNumLXPred - (abs_diff_pic_num_minus1[i] + 1) + maxPicNum;
215                else
216                    picNumLXNoWrap = picNumLXPred - (abs_diff_pic_num_minus1[i] + 1);
217            }
218            else /* (remapping_of_pic_nums_idc[i] == 1) */
219            {
220                if (picNumLXPred + (abs_diff_pic_num_minus1[i] + 1)  >=  maxPicNum)
221                    picNumLXNoWrap = picNumLXPred + (abs_diff_pic_num_minus1[i] + 1) - maxPicNum;
222                else
223                    picNumLXNoWrap = picNumLXPred + (abs_diff_pic_num_minus1[i] + 1);
224            }
225            picNumLXPred = picNumLXNoWrap; /* prediction for the next one */
226
227            if (picNumLXNoWrap > currPicNum)
228                picNumLX = picNumLXNoWrap - maxPicNum;
229            else
230                picNumLX = picNumLXNoWrap;
231
232            status = ReorderShortTerm(video, picNumLX, &refIdxLX, isL1);
233            if (status != AVC_SUCCESS)
234            {
235                return status;
236            }
237        }
238        else /* (remapping_of_pic_nums_idc[i] == 2), subclause 8.2.4.3.2 */
239        {
240            status = ReorderLongTerm(video, long_term_pic_idx[i], &refIdxLX, isL1);
241            if (status != AVC_SUCCESS)
242            {
243                return status;
244            }
245        }
246    }
247    /* that's a definition */
248    *list_size = num_ref_idx_lX_active_minus1 + 1;
249
250    return AVC_SUCCESS;
251}
252
253/* see subclause 8.2.4.3.1 */
254AVCStatus ReorderShortTerm(AVCCommonObj *video, int picNumLX, int *refIdxLX, int isL1)
255{
256    int cIdx, nIdx;
257    int num_ref_idx_lX_active_minus1;
258    AVCPictureData *picLX, **RefPicListX;
259
260    if (!isL1) /* list 0 */
261    {
262        RefPicListX = video->RefPicList0;
263        num_ref_idx_lX_active_minus1 = video->sliceHdr->num_ref_idx_l0_active_minus1;
264    }
265    else
266    {
267        RefPicListX = video->RefPicList1;
268        num_ref_idx_lX_active_minus1 = video->sliceHdr->num_ref_idx_l1_active_minus1;
269    }
270
271    picLX = GetShortTermPic(video, picNumLX);
272
273    if (picLX == NULL)
274    {
275        return AVC_FAIL;
276    }
277    /* Note RefPicListX has to access element number num_ref_idx_lX_active */
278    /* There could be access violation here. */
279    if (num_ref_idx_lX_active_minus1 + 1 >= MAX_REF_PIC_LIST)
280    {
281        return AVC_FAIL;
282    }
283
284    for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX; cIdx--)
285    {
286        RefPicListX[ cIdx ] = RefPicListX[ cIdx - 1];
287    }
288
289    RefPicListX[(*refIdxLX)++ ] = picLX;
290
291    nIdx = *refIdxLX;
292
293    for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1; cIdx++)
294    {
295        if (RefPicListX[ cIdx ])
296        {
297            if ((RefPicListX[ cIdx ]->isLongTerm) || ((int)RefPicListX[ cIdx ]->PicNum != picNumLX))
298            {
299                RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ];
300            }
301        }
302    }
303    return AVC_SUCCESS;
304}
305
306/* see subclause 8.2.4.3.2 */
307AVCStatus ReorderLongTerm(AVCCommonObj *video, int LongTermPicNum, int *refIdxLX, int isL1)
308{
309    AVCPictureData **RefPicListX;
310    int num_ref_idx_lX_active_minus1;
311    int cIdx, nIdx;
312    AVCPictureData *picLX;
313
314    if (!isL1) /* list 0 */
315    {
316        RefPicListX = video->RefPicList0;
317        num_ref_idx_lX_active_minus1 = video->sliceHdr->num_ref_idx_l0_active_minus1;
318    }
319    else
320    {
321        RefPicListX = video->RefPicList1;
322        num_ref_idx_lX_active_minus1 = video->sliceHdr->num_ref_idx_l1_active_minus1;
323    }
324
325    picLX = GetLongTermPic(video, LongTermPicNum);
326    if (picLX == NULL)
327    {
328        return AVC_FAIL;
329    }
330    /* Note RefPicListX has to access element number num_ref_idx_lX_active */
331    /* There could be access violation here. */
332    if (num_ref_idx_lX_active_minus1 + 1 >= MAX_REF_PIC_LIST)
333    {
334        return AVC_FAIL;
335    }
336    for (cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > *refIdxLX; cIdx--)
337        RefPicListX[ cIdx ] = RefPicListX[ cIdx - 1];
338
339    RefPicListX[(*refIdxLX)++ ] = picLX;
340
341    nIdx = *refIdxLX;
342
343    for (cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1; cIdx++)
344    {
345        if ((!RefPicListX[ cIdx ]->isLongTerm) || ((int)RefPicListX[ cIdx ]->LongTermPicNum != LongTermPicNum))
346        {
347            RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ];
348        }
349    }
350    return AVC_SUCCESS;
351}
352
353
354AVCPictureData*  GetShortTermPic(AVCCommonObj *video, int picNum)
355{
356    int i;
357    AVCDecPicBuffer *dpb = video->decPicBuf;
358
359    for (i = 0; i < dpb->num_fs; i++)
360    {
361
362        if (dpb->fs[i]->IsReference == 3)
363        {
364            if ((dpb->fs[i]->frame.isLongTerm == FALSE) && (dpb->fs[i]->frame.PicNum == picNum))
365            {
366                return &(dpb->fs[i]->frame);
367            }
368        }
369
370    }
371
372    return NULL;
373}
374
375AVCPictureData*  GetLongTermPic(AVCCommonObj *video, int LongtermPicNum)
376{
377    AVCDecPicBuffer *dpb = video->decPicBuf;
378    int i;
379
380    for (i = 0; i < dpb->num_fs; i++)
381    {
382
383        if (dpb->fs[i]->IsReference == 3)
384        {
385            if ((dpb->fs[i]->frame.isLongTerm == TRUE) && (dpb->fs[i]->frame.LongTermPicNum == LongtermPicNum))
386            {
387                return &(dpb->fs[i]->frame);
388            }
389        }
390
391    }
392    return NULL;
393}
394
395int is_short_ref(AVCPictureData *s)
396{
397    return ((s->isReference) && !(s->isLongTerm));
398}
399
400int is_long_ref(AVCPictureData *s)
401{
402    return ((s->isReference) && (s->isLongTerm));
403}
404
405
406/* sort by PicNum, descending order */
407void SortPicByPicNum(AVCPictureData *data[], int num)
408{
409    int i, j;
410    AVCPictureData *temp;
411
412    for (i = 0; i < num - 1; i++)
413    {
414        for (j = i + 1; j < num; j++)
415        {
416            if (data[j]->PicNum > data[i]->PicNum)
417            {
418                temp = data[j];
419                data[j] = data[i];
420                data[i] = temp;
421            }
422        }
423    }
424
425    return ;
426}
427
428/* sort by PicNum, ascending order */
429void SortPicByPicNumLongTerm(AVCPictureData *data[], int num)
430{
431    int i, j;
432    AVCPictureData *temp;
433
434    for (i = 0; i < num - 1; i++)
435    {
436        for (j = i + 1; j < num; j++)
437        {
438            if (data[j]->LongTermPicNum < data[i]->LongTermPicNum)
439            {
440                temp = data[j];
441                data[j] = data[i];
442                data[i] = temp;
443            }
444        }
445    }
446
447    return ;
448}
449
450
451/* sort by FrameNumWrap, descending order */
452void SortFrameByFrameNumWrap(AVCFrameStore *data[], int num)
453{
454    int i, j;
455    AVCFrameStore *temp;
456
457    for (i = 0; i < num - 1; i++)
458    {
459        for (j = i + 1; j < num; j++)
460        {
461            if (data[j]->FrameNumWrap > data[i]->FrameNumWrap)
462            {
463                temp = data[j];
464                data[j] = data[i];
465                data[i] = temp;
466            }
467        }
468    }
469
470    return ;
471}
472
473/* sort frames by LongTermFrameIdx, ascending order */
474void SortFrameByLTFrameIdx(AVCFrameStore *data[], int num)
475{
476    int i, j;
477    AVCFrameStore *temp;
478
479    for (i = 0; i < num - 1; i++)
480    {
481        for (j = i + 1; j < num; j++)
482        {
483            if (data[j]->LongTermFrameIdx < data[i]->LongTermFrameIdx)
484            {
485                temp = data[j];
486                data[j] = data[i];
487                data[i] = temp;
488            }
489        }
490    }
491
492    return ;
493}
494
495/* sort PictureData by POC in descending order */
496void SortPicByPOC(AVCPictureData *data[], int num, int descending)
497{
498    int i, j;
499    AVCPictureData *temp;
500
501    if (descending)
502    {
503        for (i = 0; i < num - 1; i++)
504        {
505            for (j = i + 1; j < num; j++)
506            {
507                if (data[j]->PicOrderCnt > data[i]->PicOrderCnt)
508                {
509                    temp = data[j];
510                    data[j] = data[i];
511                    data[i] = temp;
512                }
513            }
514        }
515    }
516    else
517    {
518        for (i = 0; i < num - 1; i++)
519        {
520            for (j = i + 1; j < num; j++)
521            {
522                if (data[j]->PicOrderCnt < data[i]->PicOrderCnt)
523                {
524                    temp = data[j];
525                    data[j] = data[i];
526                    data[i] = temp;
527                }
528            }
529        }
530    }
531    return ;
532}
533
534/* sort PictureData by LongTermPicNum in ascending order */
535void SortPicByLTPicNum(AVCPictureData *data[], int num)
536{
537    int i, j;
538    AVCPictureData *temp;
539
540    for (i = 0; i < num - 1; i++)
541    {
542        for (j = i + 1; j < num; j++)
543        {
544            if (data[j]->LongTermPicNum < data[i]->LongTermPicNum)
545            {
546                temp = data[j];
547                data[j] = data[i];
548                data[i] = temp;
549            }
550        }
551    }
552
553    return ;
554}
555
556/* sort by PicOrderCnt, descending order */
557void SortFrameByPOC(AVCFrameStore *data[], int num, int descending)
558{
559    int i, j;
560    AVCFrameStore *temp;
561
562    if (descending)
563    {
564        for (i = 0; i < num - 1; i++)
565        {
566            for (j = i + 1; j < num; j++)
567            {
568                if (data[j]->PicOrderCnt > data[i]->PicOrderCnt)
569                {
570                    temp = data[j];
571                    data[j] = data[i];
572                    data[i] = temp;
573                }
574            }
575        }
576    }
577    else
578    {
579        for (i = 0; i < num - 1; i++)
580        {
581            for (j = i + 1; j < num; j++)
582            {
583                if (data[j]->PicOrderCnt < data[i]->PicOrderCnt)
584                {
585                    temp = data[j];
586                    data[j] = data[i];
587                    data[i] = temp;
588                }
589            }
590        }
591    }
592
593    return ;
594}
595
596
597