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 
displayingOrder2EncodingOrder(unsigned long long displaying_order,int bframes,int intracnt,int idrcnt)37 static 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 
getSlotIndex(int bframes,int intracnt,int idrcnt,int displaying_order,int encoding_count,FRAME_ORDER_INFO * last_info)58 static 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 
getFrameDpyOrder(unsigned long long encoding_count,int bframes,int intracnt,int idrcnt,FRAME_ORDER_INFO * p_last_info,unsigned long long * displaying_order)95 int 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
140 int 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