1/*
2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved.
3 * Copyright (c) Imagination Technologies Limited, UK
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Authors:
26 *    Edward Lin <edward.lin@intel.com>
27 *
28 */
29
30#include <unistd.h>
31#include <stdio.h>
32#include <memory.h>
33#include "psb_drv_video.h"
34#include "tng_hostheader.h"
35#include "tng_slotorder.h"
36
37static unsigned long long displayingOrder2EncodingOrder(
38    unsigned long long displaying_order,
39    int bframes,
40    int intracnt,
41    int idrcnt)
42{
43    int poc;
44    if (idrcnt != 0)
45        poc = displaying_order % (intracnt * idrcnt + 1);
46    else
47        poc = displaying_order;
48
49    if (poc == 0) //IDR
50        return displaying_order;
51    else if ((poc % (bframes + 1)) == 0) //I or P
52        return (displaying_order - bframes);
53    else
54        return (displaying_order + 1); //B
55}
56
57
58static int getSlotIndex(
59    int bframes, int intracnt, int idrcnt,
60    int displaying_order, int encoding_count,
61    FRAME_ORDER_INFO *last_info)
62{
63    int i, slot_idx = 0;
64    if (displaying_order == 0) {
65        for (i = 0; i < (bframes + 2); i++)  {
66            //encoding order
67            if (i == 0)
68                last_info->slot_consume_enc_order[0] = 0;
69            else if (i == 1)
70                last_info->slot_consume_enc_order[bframes + 2 - 1] = 1;
71            else
72                last_info->slot_consume_enc_order[i - 1] = i;
73            last_info->slot_consume_dpy_order[i] = i; //displaying order
74	}
75        last_info->slot_consume_dpy_order[0] = bframes + 2;
76        last_info->slot_consume_enc_order[0] = displayingOrder2EncodingOrder(bframes + 2, bframes, intracnt, idrcnt);
77        last_info->max_dpy_num = bframes + 2;
78    } else {
79        for (i = 0; i < (bframes + 2); i++) {
80            if (last_info->slot_consume_enc_order[i] == encoding_count) {
81               slot_idx = i;
82               break;
83            }
84        }
85        last_info->max_dpy_num++;
86        last_info->slot_consume_dpy_order[slot_idx] = last_info->max_dpy_num;
87        last_info->slot_consume_enc_order[slot_idx] =
88        displayingOrder2EncodingOrder(last_info->max_dpy_num,
89            bframes, intracnt, idrcnt);
90    }
91
92    return slot_idx;
93}
94
95int getFrameDpyOrder(
96    unsigned long long encoding_count, /*Input, the encoding order, start from 0*/
97    int bframes, /*Input, The number of B frames between P and I */
98    int intracnt, /*Input, Intra period*/
99    int idrcnt, /*INput, IDR period. 0: only one IDR; */
100    FRAME_ORDER_INFO *p_last_info, /*Input & Output. Reset to 0 on first call*/
101    unsigned long long *displaying_order) /* Output. The displaying order */
102{
103    IMG_FRAME_TYPE frame_type; /*Output. Frame type. 0: I frame. 1: P frame. 2: B frame*/
104    int slot; /*Output. The corresponding slot index */
105
106    // int i;
107    unsigned long long disp_index;
108    unsigned long long val;
109
110    if ((intracnt % (bframes + 1)) != 0 || bframes == 0)
111        return -1;
112
113    val = ((idrcnt == 0) ? encoding_count : encoding_count % (intracnt * idrcnt + 1));
114    if ((idrcnt == 0 && encoding_count == 0) ||
115        (idrcnt != 0 && (encoding_count % (intracnt * idrcnt + 1) == 0))) {
116        frame_type = IMG_INTRA_IDR;
117        disp_index = encoding_count;
118    } else if (((val - 1) % (bframes + 1)) != 0) {
119        frame_type = IMG_INTER_B;
120        disp_index = encoding_count - 1;
121    } else if (p_last_info->last_frame_type == IMG_INTRA_IDR ||
122        ((val - 1) / (bframes + 1) % (intracnt / (bframes + 1))) != 0) {
123        frame_type = IMG_INTER_P;
124        disp_index = encoding_count + bframes;
125    } else {
126        frame_type = IMG_INTRA_FRAME;
127        disp_index = encoding_count + bframes;
128    }
129
130    *displaying_order = disp_index;
131    slot = getSlotIndex(bframes, intracnt, idrcnt,
132                 disp_index, encoding_count, p_last_info);
133
134    p_last_info->last_frame_type = frame_type;
135    p_last_info->last_slot = slot;
136    return 0;
137}
138
139#if 0
140int main(int argc, char **argv) {
141    int bframes, intracnt, frame_num;
142    int i;
143    int displaying_order, frame_type, slot;
144    int j;
145     char ac_frame_type[] = {'I', 'P', 'B'};
146    FRAME_ORDER_INFO last_info;
147
148    if (argc != 4)
149    {
150	    printf("%s [bframe_number] [intra period] [frame_number]\n", argv[0]);
151	    return 0;
152    }
153    else {
154		bframes = atoi(argv[1]);
155		intracnt = atoi(argv[2]);
156		frame_num = atoi(argv[3]);
157    }
158    if (intracnt % (bframes + 1) != 0) {
159		printf(" intra count must be a muliple of (bframe_number + 1)\n");
160		return 0;
161    }
162
163    memset(&last_info, 0, sizeof(FRAME_ORDER_INFO));
164    last_info.slot_consume_dpy_order = (int *)malloc((bframes + 2)  * sizeof(int));
165    last_info.slot_consume_enc_order = (int *)malloc((bframes + 2)  * sizeof(int));
166
167    printf("encodingorder displaying order	frame_type	slot index\n");
168    for (i = 0; i < frame_num; i++) {
169		getFrameDpyOrder(i, bframes, intracnt, &last_info, &displaying_order, &frame_type, &slot);
170		printf("%5d\t%5d\t%c\t%d\n", i, displaying_order, ac_frame_type[frame_type], slot);
171    }
172    free(last_info.slot_consume_dpy_order);
173    free(last_info.slot_consume_enc_order);
174
175    return 0;
176}
177#endif //test routine
178