1 /******************************************************************************
2 *
3 * Copyright (C) 2018 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20
21 /**
22 ******************************************************************************
23 * @file
24 * ihevce_buffer_que.c
25 *
26 * @brief
27 * This file contains all the functions related to Buffer Queue manager
28 *
29 * @author
30 * ittiam
31 *
32 * @par List of Functions:
33 * ihevce_buff_que_get_mem_recs
34 * ihevce_buff_que_get_num_mem_recs
35 * ihevce_buff_que_init
36 * ihevce_buff_que_get_free_buf
37 * ihevce_buff_que_get_next_buf
38 * ihevce_buff_que_get_next_reorder_buf
39 * ihevce_buff_que_set_buf_prod
40 * ihevce_buff_que_rel_buf
41 * ihevce_buff_que_get_active_bufs
42 * ihevce_buff_que_set_reorder_buf
43 *
44 ******************************************************************************
45 */
46
47 /*****************************************************************************/
48 /* File Includes */
49 /*****************************************************************************/
50
51 /* System Include Files */
52 #include <stdio.h>
53 #include <string.h>
54 #include <stdlib.h>
55 #include <stdint.h>
56 #include <assert.h>
57
58 /* User Include Files */
59 #include "ihevc_typedefs.h"
60 #include "itt_video_api.h"
61 #include "ihevce_buffer_que_interface.h"
62 #include "ihevce_buffer_que_private.h"
63
64 /*****************************************************************************/
65 /* Function Definitions */
66 /*****************************************************************************/
67
68 /*!
69 ************************************************************************
70 * \brief
71 * return number of records used by Buffer Que manager.
72 ************************************************************************
73 */
ihevce_buff_que_get_num_mem_recs(void)74 WORD32 ihevce_buff_que_get_num_mem_recs(void)
75 {
76 return (NUM_BUFFER_QUE_MEM_RECS);
77 }
78
79 /*!
80 ************************************************************************
81 * \brief
82 * return each record attributes of Buffer Que manager
83 ************************************************************************
84 */
ihevce_buff_que_get_mem_recs(iv_mem_rec_t * ps_mem_tab,WORD32 max_num_bufs_in_que,WORD32 i4_mem_space)85 WORD32 ihevce_buff_que_get_mem_recs(
86 iv_mem_rec_t *ps_mem_tab, WORD32 max_num_bufs_in_que, WORD32 i4_mem_space)
87 {
88 /* Que manager state structure */
89 ps_mem_tab[BUFFER_QUE_CTXT].i4_mem_size = sizeof(buf_que_t);
90 ps_mem_tab[BUFFER_QUE_CTXT].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space;
91 ps_mem_tab[BUFFER_QUE_CTXT].i4_mem_alignment = 8;
92
93 /* number of users memory */
94 ps_mem_tab[BUFFER_QUE_NUM_USER_MEM].i4_mem_size = (sizeof(WORD32) * max_num_bufs_in_que);
95 ps_mem_tab[BUFFER_QUE_NUM_USER_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space;
96 ps_mem_tab[BUFFER_QUE_NUM_USER_MEM].i4_mem_alignment = 8;
97
98 /* Produced status memory */
99 ps_mem_tab[BUFFER_QUE_PROD_STS_MEM].i4_mem_size = (sizeof(WORD32) * max_num_bufs_in_que);
100 ps_mem_tab[BUFFER_QUE_PROD_STS_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space;
101 ps_mem_tab[BUFFER_QUE_PROD_STS_MEM].i4_mem_alignment = 8;
102
103 /* Encode sequence memory */
104 ps_mem_tab[BUFFER_QUE_ENC_SEQ_MEM].i4_mem_size = (sizeof(UWORD32) * max_num_bufs_in_que);
105 ps_mem_tab[BUFFER_QUE_ENC_SEQ_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space;
106 ps_mem_tab[BUFFER_QUE_ENC_SEQ_MEM].i4_mem_alignment = 8;
107
108 /* Queued sequence memory */
109 ps_mem_tab[BUFFER_QUE_QUED_SEQ_MEM].i4_mem_size = (sizeof(UWORD32) * max_num_bufs_in_que);
110 ps_mem_tab[BUFFER_QUE_QUED_SEQ_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space;
111 ps_mem_tab[BUFFER_QUE_QUED_SEQ_MEM].i4_mem_alignment = 8;
112
113 return (NUM_BUFFER_QUE_MEM_RECS);
114 }
115
116 /*!
117 ************************************************************************
118 * \brief
119 * Intialization for Buffer Que manager state structure
120 ************************************************************************
121 */
ihevce_buff_que_init(iv_mem_rec_t * ps_mem_tab,WORD32 num_bufs_in_que,void ** ppv_buff_ptrs)122 void *ihevce_buff_que_init(iv_mem_rec_t *ps_mem_tab, WORD32 num_bufs_in_que, void **ppv_buff_ptrs)
123 {
124 buf_que_t *ps_buf_que;
125 WORD32 i;
126
127 /* que manager state structure */
128 ps_buf_que = (buf_que_t *)ps_mem_tab[BUFFER_QUE_CTXT].pv_base;
129
130 /* buffer status memory init */
131 ps_buf_que->pi4_num_users = (WORD32 *)ps_mem_tab[BUFFER_QUE_NUM_USER_MEM].pv_base;
132
133 ps_buf_que->pi4_produced_sts = (WORD32 *)ps_mem_tab[BUFFER_QUE_PROD_STS_MEM].pv_base;
134
135 ps_buf_que->pu4_enc_seq = (UWORD32 *)ps_mem_tab[BUFFER_QUE_ENC_SEQ_MEM].pv_base;
136
137 ps_buf_que->pu4_que_seq = (UWORD32 *)ps_mem_tab[BUFFER_QUE_QUED_SEQ_MEM].pv_base;
138
139 /* reset the state structure variables */
140 ps_buf_que->i4_num_bufs = num_bufs_in_que;
141 ps_buf_que->i4_num_active_bufs = 0;
142 ps_buf_que->u4_last_prod = 0;
143 ps_buf_que->u4_last_cons = 0;
144 ps_buf_que->u4_next_disp_seq = 0;
145 ps_buf_que->u4_last_disp_seq = 0;
146 ps_buf_que->ppv_buff_ptrs = ppv_buff_ptrs;
147
148 /* init all the buffer status to default values */
149 for(i = 0; i < ps_buf_que->i4_num_bufs; i++)
150 {
151 ps_buf_que->pi4_num_users[i] = 0;
152 ps_buf_que->pi4_produced_sts[i] = 0;
153 ps_buf_que->pu4_enc_seq[i] = UINT32_MAX;
154 ps_buf_que->pu4_que_seq[i] = UINT32_MAX;
155 }
156
157 return ((void *)ps_buf_que);
158 }
159
160 /*!
161 **************************************************************************
162 * \brief
163 * This function gets the next free buffer. This function is called by the
164 * Producer to get a free buffer
165 **************************************************************************
166 */
ihevce_buff_que_get_free_buf(void * pv_buf_que,WORD32 * pi4_id)167 void *ihevce_buff_que_get_free_buf(void *pv_buf_que, WORD32 *pi4_id)
168 {
169 buf_que_t *ps_buf_que;
170 WORD32 i;
171 WORD32 num_bufs;
172
173 ps_buf_que = (buf_que_t *)pv_buf_que;
174 num_bufs = ps_buf_que->i4_num_bufs;
175
176 /* loop unitl a free buffer is found */
177 for(i = 0; i < num_bufs; i++)
178 {
179 if((ps_buf_que->pi4_num_users[i] == 0) && (ps_buf_que->pi4_produced_sts[i] == 0))
180 {
181 *(pi4_id) = i;
182 ps_buf_que->pi4_num_users[i] = 1;
183 ps_buf_que->pu4_que_seq[i] = ps_buf_que->u4_last_prod;
184 ps_buf_que->u4_last_prod += 1;
185
186 return (ps_buf_que->ppv_buff_ptrs[i]);
187 }
188 }
189 return (NULL);
190 }
191
192 /*!
193 **************************************************************************
194 * \brief
195 * This function gets the next buffer in Que . This function will be called by
196 * consumer to get the next buffer in Queued order.
197 **************************************************************************
198 */
ihevce_buff_que_get_next_buf(void * pv_buf_que,WORD32 * pi4_id)199 void *ihevce_buff_que_get_next_buf(void *pv_buf_que, WORD32 *pi4_id)
200 {
201 buf_que_t *ps_buf_que;
202 WORD32 i;
203 UWORD32 next_qued_seq;
204
205 ps_buf_que = (buf_que_t *)pv_buf_que;
206
207 /* get the next queued buffer to be sent */
208 next_qued_seq = ps_buf_que->u4_last_cons;
209
210 /* check for matching index */
211 for(i = 0; i < ps_buf_que->i4_num_bufs; i++)
212 {
213 if(next_qued_seq == ps_buf_que->pu4_que_seq[i])
214 {
215 if(1 == ps_buf_que->pi4_produced_sts[i])
216 {
217 *(pi4_id) = i;
218 ps_buf_que->u4_last_cons += 1;
219
220 return (ps_buf_que->ppv_buff_ptrs[i]);
221 }
222 else
223 {
224 break;
225 }
226 }
227 }
228
229 /* Buffer not ready for Consumption */
230 return (NULL);
231 }
232
233 /*!
234 **************************************************************************
235 * \brief
236 * This function gives the buffer curresponding to the id passed
237 **************************************************************************
238 */
ihevce_buff_que_get_buf(void * pv_buf_que,WORD32 i4_id)239 void *ihevce_buff_que_get_buf(void *pv_buf_que, WORD32 i4_id)
240 {
241 buf_que_t *ps_buf_que;
242
243 ps_buf_que = (buf_que_t *)pv_buf_que;
244
245 if(i4_id >= ps_buf_que->i4_num_bufs)
246 return (NULL);
247
248 return (ps_buf_que->ppv_buff_ptrs[i4_id]);
249 }
250
251 /*!
252 **************************************************************************
253 * \brief
254 * This function gets the next buffer for in reordered order. This function
255 * will be called by consumer to get the next buffer in reordered order
256 **************************************************************************
257 */
ihevce_buff_que_get_next_reorder_buf(void * pv_buf_que,WORD32 * pi4_id)258 void *ihevce_buff_que_get_next_reorder_buf(void *pv_buf_que, WORD32 *pi4_id)
259 {
260 buf_que_t *ps_buf_que;
261 WORD32 i;
262 UWORD32 next_disp_seq;
263
264 ps_buf_que = (buf_que_t *)pv_buf_que;
265
266 /* get the next reordered buffer to be sent */
267 next_disp_seq = ps_buf_que->u4_last_disp_seq;
268
269 /* check for matching index */
270 for(i = 0; i < ps_buf_que->i4_num_bufs; i++)
271 {
272 if(next_disp_seq == ps_buf_que->pu4_enc_seq[i])
273 {
274 *(pi4_id) = i;
275 ps_buf_que->u4_last_disp_seq += 1;
276
277 return (ps_buf_que->ppv_buff_ptrs[i]);
278 }
279 }
280
281 /* Buffer not ready for Consumption */
282 return (NULL);
283 }
284
285 /*!
286 **************************************************************************
287 * \brief
288 * This function sets the buffer as produced. This function will be called
289 * by Producer to say that buffer is ready for consumption.
290 **************************************************************************
291 */
ihevce_buff_que_set_buf_prod(void * pv_buf_que,WORD32 buf_id,WORD32 num_users)292 WORD32 ihevce_buff_que_set_buf_prod(void *pv_buf_que, WORD32 buf_id, WORD32 num_users)
293 {
294 buf_que_t *ps_buf_que;
295
296 ps_buf_que = (buf_que_t *)pv_buf_que;
297
298 if(buf_id < ps_buf_que->i4_num_bufs)
299 {
300 if(ps_buf_que->pi4_produced_sts[buf_id] == 0)
301 {
302 ps_buf_que->pi4_num_users[buf_id] += num_users;
303 ps_buf_que->i4_num_active_bufs += 1;
304 ps_buf_que->pi4_produced_sts[buf_id] = 1;
305
306 return 0;
307 }
308 else
309 {
310 /* Buffer is already marked as Produced */
311 return (-1);
312 }
313 }
314 else
315 {
316 /* Unable to recognize the Buffer ID */
317 return (-1);
318 }
319
320 return (-1);
321 }
322
323 /*!
324 **************************************************************************
325 * \brief
326 * This function decrements number of users. If Number of users are Zero,
327 * then active Buffers in list gets decremented and this buffer is marked
328 * unused.
329 **************************************************************************
330 */
ihevce_buff_que_rel_buf(void * pv_buf_que,WORD32 buf_id)331 WORD32 ihevce_buff_que_rel_buf(void *pv_buf_que, WORD32 buf_id)
332 {
333 buf_que_t *ps_buf_que;
334 WORD32 i;
335
336 ps_buf_que = (buf_que_t *)pv_buf_que;
337 i = buf_id;
338
339 /* check if the buf id is less than max num buffers */
340 if(i < ps_buf_que->i4_num_bufs)
341 {
342 if(ps_buf_que->pi4_produced_sts[i] > 0)
343 {
344 /* decrease the number of users */
345 ps_buf_que->pi4_num_users[i] -= 1;
346
347 if(ps_buf_que->pi4_num_users[i] == 0)
348 {
349 if(0 == ps_buf_que->i4_num_active_bufs)
350 {
351 return (-1);
352 }
353
354 ps_buf_que->i4_num_active_bufs -= 1;
355 ps_buf_que->pi4_produced_sts[i] = 0;
356 }
357 return 0;
358 }
359 else
360 {
361 /* Illeagal release of Buffer, No one is using it */
362 return (-1);
363 }
364 }
365
366 /* Unable to recognize the Buffer ID */
367 return (-1);
368 }
369
370 /*!
371 **************************************************************************
372 * \brief
373 * This function gets number of active buffers.
374 **************************************************************************
375 */
ihevce_buff_que_get_active_bufs(void * pv_buf_que)376 WORD32 ihevce_buff_que_get_active_bufs(void *pv_buf_que)
377 {
378 buf_que_t *ps_buf_que;
379
380 ps_buf_que = (buf_que_t *)pv_buf_que;
381 return (ps_buf_que->i4_num_active_bufs);
382 }
383
384 /*!
385 **************************************************************************
386 * \brief
387 * This function sets the reorder number for given buffer.
388 * this will set the order for the consumer who is consuming in reorder order
389 **************************************************************************
390 */
ihevce_buff_que_set_reorder_buf(void * pv_buf_que,WORD32 buf_id)391 WORD32 ihevce_buff_que_set_reorder_buf(void *pv_buf_que, WORD32 buf_id)
392 {
393 buf_que_t *ps_buf_que;
394
395 ps_buf_que = (buf_que_t *)pv_buf_que;
396
397 if(buf_id < ps_buf_que->i4_num_bufs)
398 {
399 WORD32 next_disp_seq = ps_buf_que->u4_next_disp_seq;
400
401 /* increment the seq number */
402 ps_buf_que->u4_next_disp_seq++;
403
404 /* set the reorder number to the corresponding id */
405 ps_buf_que->pu4_enc_seq[buf_id] = next_disp_seq;
406
407 return 0;
408 }
409 else
410 {
411 /* invalid buffer id */
412 return (-1);
413 }
414
415 return (-1);
416 }
417