1 /******************************************************************************
2 *
3 * Copyright (C) 2022 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 * \file isvcd_nal_parse.c
23 *
24 * \brief
25 * Contains routines that resample for SVC resampling
26 *
27 * Detailed_description
28 *
29 * \date
30 *
31 *
32 * \author : Kishore
33 **************************************************************************
34 */
35
36 /*****************************************************************************/
37 /* File Includes */
38 /*****************************************************************************/
39
40 /* System include files */
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <limits.h>
45 #include <stddef.h>
46 #include <assert.h>
47
48 /* standard interface include files */
49 #include "ih264_typedefs.h"
50 #include "ih264_macros.h"
51 #include "ih264_platform_macros.h"
52 #include "ih264d_tables.h"
53 #include "iv.h"
54 #include "ivd.h"
55 #include "ih264d_defs.h"
56 #include "ih264d_debug.h"
57 #include "ih264_debug.h"
58 #include "ih264d_inter_pred.h"
59 #include "isvcd_structs.h"
60 #include "ih264d_nal.h"
61 #include "ih264d_error_handler.h"
62
63 /*****************************************************************************/
64 /*Extern Variable Declarations */
65 /*****************************************************************************/
66
67 /*****************************************************************************/
68 /* Global Variable Definitions */
69 /*****************************************************************************/
70
71 /*****************************************************************************/
72 /* Static Global Variable Definitions */
73 /*****************************************************************************/
74
75 /*****************************************************************************/
76 /* Static function Definitions */
77 /*****************************************************************************/
78
79 /*****************************************************************************/
80 /* */
81 /* Function Name : isvcd_get_nal_buf */
82 /* */
83 /* Description : This routine returns the NAL buffer structure to use for */
84 /* current NAL unit. This will also perform the initializa -*/
85 /* tion of the structure */
86 /* Inputs : 1. NAL parse structure */
87 /* 2. Place holder for nal buffer structure */
88 /* Globals : None */
89 /* Processing : If current NAL unit prefix NAL unit then */
90 /* - Resets the prefix nal buffer structure */
91 /* - Assigns the buffer pointer */
92 /* Otherwise */
93 /* - Assigns the buffer pointer */
94 /* Outputs : - Updated NAL buffer strcuture */
95 /* - Updates the place holder with correct NAL buffer */
96 /* structure */
97 /* Returns : None */
98 /* */
99 /* Issues : None */
100 /* */
101 /* Revision History: */
102 /* */
103 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
104 /* 06 09 2021 Vijay Draft */
105 /* */
106 /*****************************************************************************/
isvcd_get_nal_buf(nal_parse_ctxt_t * ps_nal_parse_ctxt,nal_buf_t ** pps_nal_buf)107 void isvcd_get_nal_buf(nal_parse_ctxt_t *ps_nal_parse_ctxt, nal_buf_t **pps_nal_buf)
108 {
109 nal_prms_t *ps_nal_prms;
110 nal_buf_t *ps_nal_buf;
111
112 ps_nal_prms = &ps_nal_parse_ctxt->s_nal_prms;
113
114 /* Get the NAL buffer structure */
115 if(PREFIX_UNIT_NAL == ps_nal_prms->i4_nal_unit_type)
116 {
117 ps_nal_buf = &ps_nal_parse_ctxt->s_prefix_nal_buf;
118
119 /* Note: This reset will cause a prefix NAL unit */
120 /* which is followed by another prefix NAL unit */
121 /* to be ignored by the module. This is indeed */
122 /* a desired behaviour */
123 isvcd_nal_buf_reset(ps_nal_buf);
124 }
125 else
126 {
127 ps_nal_buf = &ps_nal_parse_ctxt->s_nal_buf;
128 }
129
130 /* Initialize the buffer structure */
131 ps_nal_buf->i4_valid_flag = SVCD_TRUE;
132 if(VCL_NAL == ps_nal_prms->i4_derived_nal_type)
133 {
134 ps_nal_buf->pu1_buf = ps_nal_parse_ctxt->pu1_vcl_nal_buf;
135 }
136 else if(NON_VCL_NAL == ps_nal_prms->i4_derived_nal_type)
137 {
138 ps_nal_buf->pu1_buf = ps_nal_parse_ctxt->pu1_non_vcl_nal_buf;
139 }
140 else
141 {
142 ps_nal_buf->pu1_buf = NULL;
143 return;
144 }
145
146 *pps_nal_buf = ps_nal_buf;
147 }
148
149 /*****************************************************************************/
150 /* */
151 /* Function Name : isvcd_dqid_ctxt_reset */
152 /* */
153 /* Description : This routine resets the DQID context. This routine shall */
154 /* be invoked once in a picture */
155 /* */
156 /* Inputs : DQID context structure */
157 /* Globals : None */
158 /* Processing : Invalidates all the DQID nodes */
159 /* */
160 /* Outputs : Updated DQID context */
161 /* Returns : status */
162 /* */
163 /* Issues : None */
164 /* */
165 /* Revision History: */
166 /* */
167 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
168 /* 06 09 2021 Vijay Draft */
169 /* */
170 /*****************************************************************************/
isvcd_dqid_ctxt_reset(dqid_ctxt_t * ps_dqid_ctxt)171 WORD32 isvcd_dqid_ctxt_reset(dqid_ctxt_t *ps_dqid_ctxt)
172 {
173 WORD32 i4_lyr_idx;
174 WORD32 i4_max_num_lyrs;
175 dqid_node_t *ps_dqid_node;
176
177 /* sanity checks */
178 if(NULL == ps_dqid_ctxt)
179 {
180 return NOT_OK;
181 }
182
183 i4_max_num_lyrs = ps_dqid_ctxt->i4_max_num_lyrs;
184 ps_dqid_node = ps_dqid_ctxt->ps_dqid_node;
185
186 /* Loop over all the layers */
187 for(i4_lyr_idx = 0; i4_lyr_idx < i4_max_num_lyrs; i4_lyr_idx++)
188 {
189 /* Reset the valid flag */
190 ps_dqid_node->u1_valid_flag = SVCD_FALSE;
191
192 /* Loop updates */
193 ps_dqid_node += 1;
194 } /* loop over all the layers */
195
196 return (OK);
197 }
198
199 /*****************************************************************************/
200 /* */
201 /* Function Name : isvcd_get_dqid_node */
202 /* */
203 /* Description : This routine gets a DQID node corresponding to a DQID */
204 /* */
205 /* Inputs : 1. DQID context */
206 /* 2. DQID */
207 /* 3. Place holder for DQID node (output) */
208 /* Globals : None */
209 /* Processing : It performs the following */
210 /* - Searches for all elements untill it gets element having*/
211 /* DQID equal to input DQID. */
212 /* - If not found it finds a free (un-occupied) node */
213 /* */
214 /* Outputs : 1. Updated DQID node */
215 /* Returns : status */
216 /* */
217 /* Issues : None */
218 /* */
219 /* Revision History: */
220 /* */
221 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
222 /* 06 09 2021 Vijay Draft */
223 /* */
224 /*****************************************************************************/
isvcd_get_dqid_node(dqid_ctxt_t * ps_dqid_ctxt,UWORD8 u1_dqid,dqid_node_t ** pps_dqid_node)225 WORD32 isvcd_get_dqid_node(dqid_ctxt_t *ps_dqid_ctxt, UWORD8 u1_dqid, dqid_node_t **pps_dqid_node)
226 {
227 WORD32 i4_lyr_idx;
228 WORD32 i4_max_num_lyrs;
229 dqid_node_t *ps_dqid_node;
230 dqid_node_t *ps_rqrd_dqid_node;
231
232 /* sanity checks */
233 if((NULL == ps_dqid_ctxt) || (NULL == pps_dqid_node))
234 {
235 return NOT_OK;
236 }
237
238 i4_max_num_lyrs = ps_dqid_ctxt->i4_max_num_lyrs;
239 ps_dqid_node = ps_dqid_ctxt->ps_dqid_node;
240
241 /*Initialization */
242 ps_rqrd_dqid_node = NULL;
243
244 /* Loop over all the buffer nodes */
245 for(i4_lyr_idx = 0; i4_lyr_idx < i4_max_num_lyrs; i4_lyr_idx++)
246 {
247 if((SVCD_TRUE == ps_dqid_node->u1_valid_flag) && (u1_dqid == ps_dqid_node->u1_dqid))
248 {
249 ps_rqrd_dqid_node = ps_dqid_node;
250 break;
251 }
252 /* Loop updates */
253 ps_dqid_node += 1;
254 } /* Loop over all the buffer nodes */
255
256 if(NULL == ps_rqrd_dqid_node)
257 {
258 /* If vcl node is not allocated for the requested DQID then allocate buffer */
259 ps_dqid_node = ps_dqid_ctxt->ps_dqid_node;
260 for(i4_lyr_idx = 0; i4_lyr_idx < i4_max_num_lyrs; i4_lyr_idx++)
261 {
262 if(SVCD_FALSE == ps_dqid_node->u1_valid_flag)
263 {
264 break;
265 }
266 /* Loop updates */
267 ps_dqid_node += 1;
268 } /* Loop over all the nodes */
269 /* Update the node structure */
270 ps_rqrd_dqid_node = ps_dqid_node;
271 }
272
273 /* sanity checks */
274 if(NULL == ps_rqrd_dqid_node)
275 {
276 return NOT_OK;
277 }
278 *pps_dqid_node = ps_rqrd_dqid_node;
279
280 return (OK);
281 }
282
283 /*****************************************************************************/
284 /* */
285 /* Function Name : isvcd_nal_reset_ctxt */
286 /* */
287 /* Description : This routine performs NAL unit level initialization */
288 /* This routine shall be called before parsing a NAL unit */
289 /* */
290 /* Inputs : 1. NAL parse context structure */
291 /* Globals : None */
292 /* Processing : This does initializaiton of NAL unit level tracking */
293 /* varaibles */
294 /* */
295 /* Outputs : Updated context structure */
296 /* Returns : status */
297 /* */
298 /* Issues : None */
299 /* */
300 /* Revision History: */
301 /* */
302 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
303 /* 06 09 2021 Vijay Draft */
304 /* */
305 /*****************************************************************************/
isvcd_nal_reset_ctxt(nal_parse_ctxt_t * ps_nal_parse_ctxt)306 WORD32 isvcd_nal_reset_ctxt(nal_parse_ctxt_t *ps_nal_parse_ctxt)
307 {
308 nal_unit_t *ps_nal_unit;
309
310 if(NULL == ps_nal_parse_ctxt)
311 {
312 return NOT_OK;
313 }
314
315 /* Reset the NAL boundary detetction */
316 ps_nal_parse_ctxt->i4_find_nal_state = NAL_START;
317 ps_nal_parse_ctxt->i4_zero_byte_cnt = 0;
318 ps_nal_unit = ps_nal_parse_ctxt->pv_nal_unit;
319 ps_nal_unit->i4_num_bufs = 0;
320
321 /*Reset emulation prevention */
322 isvcd_reset_emulation_ctxt(&ps_nal_parse_ctxt->s_emulation_ctxt);
323
324 /*Reset the NAL header prms */
325 isvcd_set_default_nal_prms(&ps_nal_parse_ctxt->s_nal_prms);
326
327 /* Reset other NAL level tracking variables */
328 ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_FALSE;
329
330 /*Reset NAL buffer structure*/
331 isvcd_nal_buf_reset(&ps_nal_parse_ctxt->s_nal_buf);
332
333 return (OK);
334 }
335
336 /*****************************************************************************/
337 /* */
338 /* Function Name : isvcd_pic_reset_ctxt */
339 /* */
340 /* Description : This routine performs the picture level initialization. */
341 /* This routine shall be called before parsing a access unit*/
342 /* */
343 /* Inputs : pv_nal_parse_ctxt - Pointer to context structure */
344 /* */
345 /* Globals : None */
346 /* */
347 /* Processing : 1. Resets the varaibles */
348 /* */
349 /* Outputs : Updated context structure */
350 /* */
351 /* Returns : none */
352 /* */
353 /* Issues : None */
354 /* */
355 /* Revision History: */
356 /* DD MM YYYY Author(s) Changes */
357 /* 06 09 2021 Vijay Draft */
358 /* */
359 /*****************************************************************************/
isvcd_pic_reset_ctxt(nal_parse_ctxt_t * ps_nal_parse_ctxt)360 void isvcd_pic_reset_ctxt(nal_parse_ctxt_t *ps_nal_parse_ctxt)
361 {
362 WORD32 i4_status;
363
364 /*-----------------------------------------------------------------------*/
365 /*! Reset NAL boundary detetction logic */
366 /*-----------------------------------------------------------------------*/
367 i4_status = isvcd_nal_reset_ctxt(ps_nal_parse_ctxt);
368
369 UNUSED(i4_status);
370
371 /*-----------------------------------------------------------------------*/
372 /*! Reset picture boundary detctetion logic */
373 /*-----------------------------------------------------------------------*/
374 ps_nal_parse_ctxt->i4_is_frst_vcl_nal_in_au = SVCD_TRUE;
375
376 /*-----------------------------------------------------------------------*/
377 /*! Reset VCL and non VCL NAL buffer tracking variables */
378 /*-----------------------------------------------------------------------*/
379 ps_nal_parse_ctxt->pu1_non_vcl_nal_buf = ps_nal_parse_ctxt->pv_non_vcl_nal_buf;
380 ps_nal_parse_ctxt->pu1_vcl_nal_buf = ps_nal_parse_ctxt->pv_vcl_nal_buf;
381
382 /* reset the bytes left to buffer size */
383 ps_nal_parse_ctxt->u4_bytes_left_vcl = MAX_VCL_NAL_BUFF_SIZE;
384
385 ps_nal_parse_ctxt->u4_bytes_left_non_vcl = MAX_NON_VCL_NAL_BUFF_SIZE;
386
387 /* Offset the buffer to start of vcl data */
388 UPDATE_NAL_BUF_PTR(&ps_nal_parse_ctxt->pu1_non_vcl_nal_buf, NON_VCL_NAL,
389 &ps_nal_parse_ctxt->u4_bytes_left_non_vcl);
390
391 UPDATE_NAL_BUF_PTR(&ps_nal_parse_ctxt->pu1_vcl_nal_buf, VCL_NAL,
392 &ps_nal_parse_ctxt->u4_bytes_left_vcl);
393
394 /* Reset previous field */
395 ps_nal_parse_ctxt->ps_prev_non_vcl_buf = NULL;
396 ps_nal_parse_ctxt->i4_idr_pic_err_flag = 0;
397
398 /*-----------------------------------------------------------------------*/
399 /*! Reset other NAL related tracking variables */
400 /*-----------------------------------------------------------------------*/
401 ps_nal_parse_ctxt->i4_num_non_vcl_nals = 0;
402
403 /* Reset the vcl nal node buffer context */
404 i4_status = isvcd_dqid_ctxt_reset(&ps_nal_parse_ctxt->s_dqid_ctxt);
405
406 /* Reset target layer update flag */
407 ps_nal_parse_ctxt->i4_tgt_lyr_update = SVCD_TRUE;
408 }
409
410 /*****************************************************************************/
411 /* */
412 /* Function Name : isvcd_get_nal_prms */
413 /* */
414 /* Description : This routine will update the nal prms */
415 /* Inputs : 1. Start of bitstream buffer containing NAL header */
416 /* 2. Size of the buffer */
417 /* 3. NAL prms structure */
418 /* 4. Place holder for error code */
419 /* 5. Place holder for nal discard flag */
420 /* 6. NAL parse context structure */
421 /* Globals : None */
422 /* Processing : 1. Parses the NAL header */
423 /* 2. Sets the discard flag */
424 /* 3. If NAL is not discarded and nal is VCL NAL unit then */
425 /* decodes the slice prms (prefix nal units are excluded)*/
426 /* Outputs : Updated NAL prms structure */
427 /* Updated NAL discrd flag */
428 /* Updates the error code if encountered with error */
429 /* Returns : status */
430 /* */
431 /* Issues : None */
432 /* */
433 /* Revision History: */
434 /* */
435 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
436 /* 06 09 2021 Vijay Draft */
437 /* */
438 /*****************************************************************************/
isvcd_get_nal_prms(UWORD8 * pu1_buf,WORD32 i4_buf_size,nal_prms_t * ps_nal_prms,nal_prms_t * ps_prefix_nal_prms,nal_buf_t * ps_prefix_nal_buf,UWORD32 * pu4_err_code,WORD32 * pi4_sps_pps_status,WORD32 * pi4_nal_discard_flag,nal_parse_ctxt_t * ps_nal_parse_ctxt)439 WORD32 isvcd_get_nal_prms(UWORD8 *pu1_buf, WORD32 i4_buf_size, nal_prms_t *ps_nal_prms,
440 nal_prms_t *ps_prefix_nal_prms, nal_buf_t *ps_prefix_nal_buf,
441 UWORD32 *pu4_err_code, WORD32 *pi4_sps_pps_status,
442 WORD32 *pi4_nal_discard_flag, nal_parse_ctxt_t *ps_nal_parse_ctxt)
443 {
444 UWORD8 *pu1_input_buf;
445 WORD32 i4_status;
446 dec_seq_params_t *ps_sps;
447 dec_pic_params_t *ps_pps;
448
449 ps_sps = ps_nal_parse_ctxt->pv_seq_prms;
450 ps_pps = ps_nal_parse_ctxt->pv_pic_prms;
451
452 *pu4_err_code = 0;
453 *pi4_sps_pps_status = NAL_CORRUPT_DATA;
454
455 /* Decode the NAL header */
456 isvcd_dec_nal_hdr(pu1_buf, i4_buf_size, ps_nal_parse_ctxt->pv_nal_header_buf, ps_nal_prms,
457 ps_prefix_nal_buf, ps_prefix_nal_prms, pu4_err_code);
458
459 /* If encountered with error return fail */
460 if(0 != *pu4_err_code)
461 {
462 return (NOT_OK);
463 }
464
465 if(ACCESS_UNIT_DELIMITER_RBSP == ps_nal_prms->i4_nal_unit_type)
466 {
467 *pi4_nal_discard_flag = 1;
468 return OK;
469 }
470
471 /* Set the discard flag */
472 *pi4_nal_discard_flag = isvcd_discard_nal(
473 (void *) ps_nal_prms, (void *) &ps_nal_parse_ctxt->s_app_attr,
474 (void *) &ps_nal_parse_ctxt->s_int_attr, ps_nal_parse_ctxt->i4_tgt_lyr_update);
475
476 /* Parse the slice header if all the following */
477 /* conditions are true */
478 /* 1. NAL is a VCL NAL unit */
479 /* 2. NAL is not a prefix NAL unit */
480 /* 3. NAL is not discarded */
481 if((NON_VCL_NAL == ps_nal_prms->i4_derived_nal_type) ||
482 (PREFIX_UNIT_NAL == ps_nal_prms->i4_nal_unit_type) || (SVCD_TRUE == *pi4_nal_discard_flag))
483 {
484 return (OK);
485 }
486
487 pu1_input_buf = pu1_buf;
488 pu1_input_buf += ps_nal_prms->i4_nal_header_len;
489 i4_buf_size -= ps_nal_prms->i4_nal_header_len;
490
491 i4_status =
492 isvcd_parse_part_slice_hdr(pu1_input_buf, i4_buf_size, ps_nal_parse_ctxt->pv_nal_header_buf,
493 ps_sps, ps_pps, ps_nal_prms, pu4_err_code, pi4_sps_pps_status);
494
495 return (i4_status);
496 }
497
498 /*****************************************************************************/
499 /* */
500 /* Function Name : isvcd_compare_nal_prms */
501 /* */
502 /* Description : Detects the picture boundary for annex B based input */
503 /* bitstream */
504 /* */
505 /* Inputs : 1. Pointer to NAL prms */
506 /* 2. Pass (first pass or second pass (verification) */
507 /* 3. Place holder for picture boundary type */
508 /* 4. Place holder for picture boundary status */
509 /* 4. pointer to bitstream extract context structure */
510 /* Globals : */
511 /* Processing : Detects the picture bounadry as described in G.7.4.1.2.4 */
512 /* */
513 /* Outputs : Detects the picture boundary */
514 /* Updates the first NAL in AU field */
515 /* Updates the picture boundary type if picture boundary is */
516 /* detetcetd otherwise it's value shall be ignored */
517 /* Updates the picture boundary status with either */
518 /* PIC_BOUNDARY_TRUE if picture boundary is detetcted or */
519 /* PIC_BOUNDARY_FALSE otherwise */
520 /* Updates the error code */
521 /* Returns : status */
522 /* */
523 /* Issues : None */
524 /* */
525 /* Revision History: */
526 /* */
527 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
528 /* 06 09 2021 Vijay Draft */
529 /* */
530 /*****************************************************************************/
isvcd_compare_nal_prms(nal_prms_t * ps_nal_prms,WORD32 i4_pass,WORD32 i4_prev_dqid,WORD32 * pi4_pic_bound_type,WORD32 * pi4_pic_bound_status,nal_parse_ctxt_t * ps_nal_parse_ctxt)531 WORD32 isvcd_compare_nal_prms(nal_prms_t *ps_nal_prms, WORD32 i4_pass, WORD32 i4_prev_dqid,
532 WORD32 *pi4_pic_bound_type, WORD32 *pi4_pic_bound_status,
533 nal_parse_ctxt_t *ps_nal_parse_ctxt)
534 {
535 dqid_node_t *ps_dqid_node;
536 vcl_node_t *ps_vcl_node;
537 WORD32 i4_status;
538
539 /* If DQID is lesser than the DQID of the previous */
540 /* NAL then declare the picture boundary */
541 *pi4_pic_bound_type = PIC_BOUND_DQID;
542 if(i4_prev_dqid > ps_nal_prms->i4_dqid)
543 {
544 *pi4_pic_bound_status = PIC_BOUNDARY_TRUE;
545 return (OK);
546 }
547
548 /* Perform the picture boundary detection only for */
549 /* the layers with quality id equal to 0 */
550 if((FIRST_PASS == i4_pass) && (0 != (ps_nal_prms->i4_dqid & 0x0F)))
551 {
552 *pi4_pic_bound_status = PIC_BOUNDARY_FALSE;
553 return (OK);
554 }
555
556 /* Get the DQID node */
557 i4_status =
558 isvcd_get_dqid_node(&ps_nal_parse_ctxt->s_dqid_ctxt, (UWORD8) i4_prev_dqid, &ps_dqid_node);
559 if((OK != i4_status) || (NULL == ps_dqid_node))
560 {
561 return NOT_OK;
562 }
563 /* If the current slice is first slice in the layer */
564 /* then do not compare */
565 if(SVCD_FALSE == ps_dqid_node->u1_valid_flag)
566 {
567 *pi4_pic_bound_status = PIC_BOUNDARY_FALSE;
568 return (OK);
569 }
570
571 *pi4_pic_bound_type = PIC_BOUND_SLICE_PRMS;
572 *pi4_pic_bound_status = PIC_BOUNDARY_TRUE;
573 ps_vcl_node = ps_dqid_node->ps_vcl_node;
574
575 /* Compare NAL ref idc */
576 {
577 WORD32 i4_prev_ref_pic_flag;
578 WORD32 i4_cur_ref_pic_flag;
579
580 i4_prev_ref_pic_flag = (0 != ps_vcl_node->i4_nal_ref_idc);
581 i4_cur_ref_pic_flag = (0 != ps_nal_prms->i4_nal_ref_idc);
582
583 if(i4_prev_ref_pic_flag != i4_cur_ref_pic_flag)
584 {
585 return (OK);
586 }
587 }
588
589 /* Compare IDR picture flag */
590 if(ps_vcl_node->i4_idr_pic_flag != ps_nal_prms->i4_idr_pic_flag)
591 {
592 return (OK);
593 }
594
595 /* Compare PPS id */
596 if(ps_vcl_node->u1_pps_id != ps_nal_prms->u1_pps_id)
597 {
598 return (OK);
599 }
600
601 /* Compare idr pic num */
602 if((SVCD_TRUE == ps_nal_prms->i4_idr_pic_flag) &&
603 (ps_vcl_node->i4_idr_pic_num != ps_nal_prms->i4_idr_pic_num))
604 {
605 return (OK);
606 }
607
608 /* Compare frame number */
609 if(ps_vcl_node->u2_frm_num != ps_nal_prms->u2_frm_num)
610 {
611 return (OK);
612 }
613
614 /* Compare poc lsb */
615 if(ps_dqid_node->i4_poc_lsb != ps_nal_prms->i4_poc_lsb)
616 {
617 return (OK);
618 }
619
620 /* Compare delta poc bottom */
621 if(ps_dqid_node->i4_delta_poc_bot != ps_nal_prms->i4_delta_poc_bot)
622 {
623 return (OK);
624 }
625
626 /* Compare delta poc [0] */
627 if(ps_dqid_node->ai4_delta_poc[0] != ps_nal_prms->ai4_delta_poc[0])
628 {
629 return (OK);
630 }
631
632 /* Compare delta poc [0] */
633 if(ps_dqid_node->ai4_delta_poc[1] != ps_nal_prms->ai4_delta_poc[1])
634 {
635 return (OK);
636 }
637
638 *pi4_pic_bound_status = PIC_BOUNDARY_FALSE;
639 return (OK);
640 }
641
642 /*****************************************************************************/
643 /* */
644 /* Function Name : isvcd_detetct_pic_boundary_annex_b */
645 /* */
646 /* Description : Detects the picture boundary for annex B based input */
647 /* bitstream */
648 /* */
649 /* */
650 /* Inputs : 1. Pointer to NAL prms */
651 /* 2. Input bitstream structure */
652 /* 3. Current position of the bitstream pointer */
653 /* 4. Place holder for picture boundary status */
654 /* 5. pointer to bitstream extract context structure */
655 /* Globals : */
656 /* Processing : It does the following */
657 /* 1. Look for next NAL. */
658 /* If not found then declare picture boundary */
659 /* Otherwsie goto next step */
660 /* 2. Parse the NAL header */
661 /* If encountered with error then declare picture */
662 /* boundary */
663 /* Otherwise goto next step */
664 /* 3. If picture boundary type is */
665 /* DQID change and DQID is not equal previous DQID then */
666 /* declare picture boundary. Otherwise, the comapre the */
667 /* rest of parameters. If during comparison, if there is*/
668 /* 4. If picture boundary type is */
669 /* SLICE PRMS CHANGE and Dependency id is not equal then*/
670 /* declare picture boundary. Otherwise compre rest of */
671 /* parameters and goto step 5 */
672 /* 5. If during comparison, if there is */
673 /* * an error - then declare picture boundary */
674 /* * Otherwsie if picture boundary is not detetcted */
675 /* then discard the second slice and proceed. */
676 /* */
677 /* Outputs : Detects the picture boundary */
678 /* Updates the first NAL in AU field */
679 /* Updates the picture boundary type if picture boundary is */
680 /* detetcetd otherwise it's value shall be ignored */
681 /* Updates the error code */
682 /* Returns : status */
683 /* */
684 /* Issues : None */
685 /* */
686 /* Revision History: */
687 /* */
688 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
689 /* 06 09 2021 Vijay Draft */
690 /* */
691 /*****************************************************************************/
isvcd_detect_pic_boundary_annex_b(nal_prms_t * ps_nal_prms,UWORD8 * pu1_stream_buffer,WORD32 i4_cur_pos,WORD32 * pi4_pic_bound_status,nal_parse_ctxt_t * ps_nal_parse_ctxt,UWORD32 * pu4_num_bytes)692 WORD32 isvcd_detect_pic_boundary_annex_b(nal_prms_t *ps_nal_prms, UWORD8 *pu1_stream_buffer,
693 WORD32 i4_cur_pos, WORD32 *pi4_pic_bound_status,
694 nal_parse_ctxt_t *ps_nal_parse_ctxt,
695 UWORD32 *pu4_num_bytes)
696 {
697 UWORD32 u4_err_code;
698 WORD32 i4_zero_cnt;
699 WORD32 i4_status;
700 nal_prms_t s_nal_prms = {0};
701 nal_prms_t s_prefix_nal_prms = {0};
702 nal_buf_t s_prefix_nal_buf = {0};
703 WORD32 i4_pic_bound_type;
704 WORD32 i4_pic_bound_status;
705 UWORD8 *pu1_buf;
706 WORD32 i4_buf_size;
707 WORD32 i4_more_data_flag;
708 WORD32 i4_new_lyr_flag;
709 WORD32 i4_prev_dqid;
710 WORD32 i4_nal_discard_flag;
711
712 /* Initializations */
713 i4_zero_cnt = 0;
714 s_prefix_nal_buf.i4_valid_flag = SVCD_FALSE;
715 *pi4_pic_bound_status = PIC_BOUNDARY_FALSE;
716 i4_new_lyr_flag = SVCD_TRUE;
717
718 /* Get the previous layer's DQID */
719 if(SVCD_TRUE == ps_nal_parse_ctxt->i4_is_frst_vcl_nal_in_au)
720 {
721 ps_nal_parse_ctxt->i4_prev_dq_id = ps_nal_prms->i4_dqid;
722 ps_nal_parse_ctxt->i4_is_frst_vcl_nal_in_au = SVCD_FALSE;
723 }
724 i4_prev_dqid = ps_nal_parse_ctxt->i4_prev_dq_id;
725 ps_nal_parse_ctxt->i4_prev_dq_id = ps_nal_prms->i4_dqid;
726
727 /* Detect the picture boundary */
728 if(ps_nal_prms->i4_dqid <= i4_prev_dqid)
729 {
730 i4_status =
731 isvcd_compare_nal_prms(ps_nal_prms, FIRST_PASS, i4_prev_dqid, &i4_pic_bound_type,
732 &i4_pic_bound_status, ps_nal_parse_ctxt);
733 if(OK != i4_status)
734 {
735 return NOT_OK;
736 }
737 i4_new_lyr_flag = SVCD_FALSE;
738
739 /* Check whether the picture boundary is detected */
740 /* or not */
741 if(PIC_BOUNDARY_FALSE == i4_pic_bound_status)
742 {
743 return (OK);
744 }
745
746 /* Otherwise look for next nal and compare again */
747 *pi4_pic_bound_status = PIC_BOUNDARY_TRUE;
748 }
749
750 do
751 {
752 WORD32 i4_sps_pps_corrupt_status;
753 WORD32 i4_tgt_lyr_bckup;
754 /* If following conditions are true then there */
755 /* is no data left to decode next NAL and hence*/
756 /* no further processing is required */
757 if((NAL_END != ps_nal_parse_ctxt->i4_find_nal_state) ||
758 ((WORD64) i4_cur_pos >= (WORD64) *pu4_num_bytes))
759 {
760 return (OK);
761 }
762
763 /* Otherwise fill the parameters */
764 pu1_buf = pu1_stream_buffer;
765 pu1_buf += i4_cur_pos;
766 i4_buf_size = *pu4_num_bytes - i4_cur_pos;
767
768 /* Get the NAL prms. This involves the following things*/
769 /* 1. Decode the NAL header */
770 /* 2. Set the discard flag */
771 /* 3. Decode the slice header if needed */
772 isvcd_set_default_nal_prms(&s_nal_prms);
773
774 /* take a back up of tgt lyr update flag */
775 i4_tgt_lyr_bckup = ps_nal_parse_ctxt->i4_tgt_lyr_update;
776
777 /* the tgt attributes should not be updaetd while pic boundary det*/
778 ps_nal_parse_ctxt->i4_tgt_lyr_update = SVCD_FALSE;
779
780 i4_status = isvcd_get_nal_prms(pu1_buf, i4_buf_size, &s_nal_prms, &s_prefix_nal_prms,
781 &s_prefix_nal_buf, &u4_err_code, &i4_sps_pps_corrupt_status,
782 &i4_nal_discard_flag, ps_nal_parse_ctxt);
783 /* restore back the tgt lyr update flag */
784 ps_nal_parse_ctxt->i4_tgt_lyr_update = i4_tgt_lyr_bckup;
785 /* If the error code by the nal prms decoder then declare*/
786 /* picture boundary */
787 if(0 != u4_err_code)
788 {
789 return (OK);
790 }
791
792 i4_more_data_flag = SVCD_FALSE;
793
794 /* If prefix NAL unit comes then save the nal prms*/
795 if(PREFIX_UNIT_NAL == s_nal_prms.i4_nal_unit_type)
796 {
797 UWORD32 u4_bytes_consumed;
798 WORD32 i4_status;
799
800 /* If prefix NAL is not discarded then set the varaibles */
801 /* appropriatly */
802 if(SVCD_FALSE == i4_nal_discard_flag)
803 {
804 s_prefix_nal_buf.i4_valid_flag = SVCD_TRUE;
805 memcpy(&s_prefix_nal_prms, &s_nal_prms, sizeof(nal_prms_t));
806 }
807
808 /* Go to next start code */
809 i4_zero_cnt = 0;
810 u4_bytes_consumed = 0;
811 i4_status = isvcd_nal_find_start_code(pu1_stream_buffer, i4_cur_pos, *pu4_num_bytes,
812 &i4_zero_cnt, &u4_bytes_consumed);
813 /* If associated NAL unit is not present then */
814 if(SC_FOUND != i4_status)
815 {
816 return (OK);
817 }
818 i4_cur_pos += u4_bytes_consumed;
819 i4_more_data_flag = SVCD_TRUE;
820 }
821 } while(SVCD_TRUE == i4_more_data_flag);
822
823 /* Do further picture boundary detection only for */
824 /* VCL NAL unit (excliding prefix NAL unit) */
825 if((NON_VCL_NAL == s_nal_prms.i4_derived_nal_type) ||
826 (PREFIX_UNIT_NAL == s_nal_prms.i4_nal_unit_type) || (SVCD_TRUE == i4_nal_discard_flag))
827 {
828 return (OK);
829 }
830
831 if(SVCD_FALSE == i4_new_lyr_flag)
832 {
833 if(PIC_BOUND_DQID == i4_pic_bound_type)
834 {
835 /* If picture boundary was detetcted based on change*/
836 /* in DQID then declare picture boundary if DQID of the third slice is different */
837 if(i4_prev_dqid != s_nal_prms.i4_dqid)
838 {
839 return (OK);
840 }
841 }
842 else
843 {
844 /* If picture boundary was detetcted based on change in DQID */
845 /* then declare picture boundary if dependency id of third slice is different */
846 if(PIC_BOUND_SLICE_PRMS != i4_pic_bound_type)
847 {
848 return NOT_OK;
849 }
850
851 if((i4_prev_dqid & 0xF) != (s_nal_prms.i4_dqid & 0xF))
852 {
853 return (OK);
854 }
855 }
856
857 isvcd_compare_nal_prms(&s_nal_prms, SECOND_PASS, i4_prev_dqid, &i4_pic_bound_type,
858 &i4_pic_bound_status, ps_nal_parse_ctxt);
859 *pi4_pic_bound_status = i4_pic_bound_status;
860
861 if(PIC_BOUNDARY_FALSE == i4_pic_bound_status)
862 {
863 ps_nal_parse_ctxt->i4_prev_dq_id = i4_prev_dqid;
864 }
865 }
866 else
867 {
868 if(SVCD_TRUE != i4_new_lyr_flag)
869 {
870 return NOT_OK;
871 }
872 /* The NAL header is not corrupted only if any of the following conditions are true */
873 /* 1. The DQID of the first slice differs with DQID of the third slice */
874 /* 2. Picture boundary is detected between first slice and third slice */
875 if(i4_prev_dqid == s_nal_prms.i4_dqid)
876 {
877 isvcd_compare_nal_prms(&s_nal_prms, SECOND_PASS, i4_prev_dqid, &i4_pic_bound_type,
878 &i4_pic_bound_status, ps_nal_parse_ctxt);
879 /* NAL header is corrupted and hence correct it */
880 if(PIC_BOUNDARY_FALSE == i4_pic_bound_status)
881 {
882 ps_nal_prms->i4_dqid = s_nal_prms.i4_dqid;
883 ps_nal_prms->i4_dependency_id = s_nal_prms.i4_dependency_id;
884 ps_nal_prms->i4_quality_id = s_nal_prms.i4_quality_id;
885 ps_nal_parse_ctxt->i4_prev_dq_id = ps_nal_prms->i4_dqid;
886 }
887 }
888 *pi4_pic_bound_status = PIC_BOUNDARY_FALSE;
889 }
890 return (OK);
891 }
892
893 /*****************************************************************************/
894 /* */
895 /* Function Name : isvcd_insert_vcl_node */
896 /* */
897 /* Description : This routine inserts a DQID layer into DQID list */
898 /* (this will add a VCL NAL node into VCL NAL structure */
899 /* */
900 /* Inputs : 1. vcl nal structure */
901 /* 2. VCL node to be inserted */
902 /* Globals : None */
903 /* Processing : */
904 /* */
905 /* Outputs : Updated vcl nal structure */
906 /* Returns : status */
907 /* */
908 /* Issues : None */
909 /* */
910 /* Revision History: */
911 /* */
912 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
913 /* 06 09 2021 Vijay Draft */
914 /* */
915 /*****************************************************************************/
isvcd_insert_vcl_node(vcl_nal_t * ps_vcl_nal,vcl_node_t * ps_vcl_node)916 WORD32 isvcd_insert_vcl_node(vcl_nal_t *ps_vcl_nal, vcl_node_t *ps_vcl_node)
917 {
918 vcl_node_t *ps_bot_node;
919 vcl_node_t *ps_top_node;
920 vcl_node_t *ps_node;
921 WORD32 i4_rqrd_dqid;
922
923 /* sanity checks */
924 if((NULL == ps_vcl_nal) || (NULL == ps_vcl_node))
925 {
926 return NOT_OK;
927 }
928
929 i4_rqrd_dqid = (ps_vcl_node->i4_dependency_id << 4);
930 i4_rqrd_dqid += ps_vcl_node->i4_quality_id;
931 ps_node = ps_vcl_nal->ps_bot_node;
932
933 /* Search for node which has a DQID which is */
934 /* lesser than taht of the node to inserted */
935 while(NULL != ps_node)
936 {
937 WORD32 i4_dqid;
938
939 i4_dqid = (ps_node->i4_dependency_id << 4);
940 i4_dqid += ps_node->i4_quality_id;
941
942 /* If we get a DQID which is greater than*/
943 /* the DQID of the node to be inserted */
944 /* then break out of the loop and update */
945 if(i4_dqid > i4_rqrd_dqid)
946 {
947 ps_bot_node = ps_node->ps_bot_node;
948 break;
949 }
950
951 ps_node = ps_node->ps_top_node;
952 }
953
954 /* If none of the nodes in the list have DQId */
955 /* greater than the node to be inserted then */
956 /* bottom node will be top most node */
957 if(NULL == ps_node)
958 {
959 ps_bot_node = ps_vcl_nal->ps_top_node;
960 }
961
962 /* Insert the node into DQID list */
963 if(NULL != ps_bot_node)
964 {
965 ps_top_node = ps_bot_node->ps_top_node;
966 }
967 else
968 {
969 ps_top_node = ps_vcl_nal->ps_bot_node;
970 }
971
972 /* Join previous node and specified node */
973 if(NULL != ps_bot_node)
974 {
975 ps_bot_node->ps_top_node = ps_vcl_node;
976 }
977 else
978 {
979 ps_vcl_nal->ps_bot_node = ps_vcl_node;
980 }
981 ps_vcl_node->ps_bot_node = ps_bot_node;
982
983 /* Join next node and specified node */
984 if(NULL != ps_top_node)
985 {
986 ps_top_node->ps_bot_node = ps_vcl_node;
987 }
988 else
989 {
990 ps_vcl_nal->ps_top_node = ps_vcl_node;
991 }
992 ps_vcl_node->ps_top_node = ps_top_node;
993
994 return (OK);
995 }
996 /*****************************************************************************/
997 /* */
998 /* Function Name : isvcd_update_nal_ctxt */
999 /* */
1000 /* Description : Updates the vcl nal or non vcl structures. */
1001 /* */
1002 /* Inputs : ps_nal_parse_ctxt - Bitstream extract context structure */
1003 /* vcl nal structure pointer */
1004 /* NON vcl nal structure */
1005 /* */
1006 /* Globals : None */
1007 /* */
1008 /* Processing : If VCL NAL then adds a node to DQID list */
1009 /* otherwise adds information to non vcl structure */
1010 /* */
1011 /* Outputs : None */
1012 /* */
1013 /* Returns : None */
1014 /* */
1015 /* Issues : None */
1016 /* */
1017 /* Revision History: */
1018 /* DD MM YYYY Author(s) Changes */
1019 /* 06 09 2021 Vijay Draft */
1020 /* */
1021 /*****************************************************************************/
isvcd_update_nal_ctxt(nal_parse_ctxt_t * ps_nal_parse_ctxt,vcl_nal_t * ps_vcl_nal,non_vcl_nal_t * ps_non_vcl_nal)1022 void isvcd_update_nal_ctxt(nal_parse_ctxt_t *ps_nal_parse_ctxt, vcl_nal_t *ps_vcl_nal,
1023 non_vcl_nal_t *ps_non_vcl_nal)
1024 {
1025 /*! If current NAL is VCL NAL then
1026 - Insert a VCL node into DQID list if neccessery
1027 - update the information part of NAL unit */
1028 /*! Otherwise, populate the buffer parameters into non vcl output
1029 structure */
1030 nal_prms_t *ps_nal_prms;
1031 nal_buf_t *ps_nal_buf, *ps_prefix_nal_buf;
1032
1033 ps_nal_prms = &ps_nal_parse_ctxt->s_nal_prms;
1034 ps_nal_prms = &ps_nal_parse_ctxt->s_nal_prms;
1035 ps_nal_buf = &ps_nal_parse_ctxt->s_nal_buf;
1036 ps_prefix_nal_buf = &ps_nal_parse_ctxt->s_prefix_nal_buf;
1037
1038 /* If prefix NAL unit then */
1039 /* - calculate the SODB length */
1040 if(PREFIX_UNIT_NAL == ps_nal_prms->i4_nal_unit_type)
1041 {
1042 /* Since we consume the zeroes in start code also */
1043 /* size has to reduced */
1044 if(NAL_END == ps_nal_parse_ctxt->i4_find_nal_state)
1045 {
1046 ps_prefix_nal_buf->i4_buf_size -= 2;
1047 }
1048
1049 ps_prefix_nal_buf->u4_max_bits =
1050 isvcd_nal_rbsp_to_sodb(ps_prefix_nal_buf->pu1_buf, ps_prefix_nal_buf->i4_buf_size, 0);
1051 memcpy(&ps_nal_parse_ctxt->s_prefix_nal_prms, &ps_nal_parse_ctxt->s_nal_prms,
1052 sizeof(nal_prms_t));
1053 return;
1054 }
1055
1056 if(ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode)
1057 {
1058 /* Since we consume the zeroes in start code also */
1059 /* size has to reduced */
1060 if(NAL_END == ps_nal_parse_ctxt->i4_find_nal_state)
1061 {
1062 ps_nal_buf->i4_buf_size -= 2;
1063 }
1064 }
1065
1066 if(VCL_NAL == ps_nal_prms->i4_derived_nal_type)
1067 {
1068 dqid_node_t *ps_dqid_node;
1069 vcl_node_t *ps_node;
1070 WORD32 i4_status;
1071 dec_pic_params_t *ps_pps;
1072 dec_seq_params_t *ps_sps;
1073 vcl_buf_hdr_t *ps_vcl_hdr;
1074 vcl_buf_hdr_t *ps_prev_vcl_hdr;
1075 WORD32 i4_slice_offset;
1076
1077 ps_sps = ps_nal_parse_ctxt->pv_seq_prms;
1078 ps_sps += ps_nal_prms->u1_sps_id;
1079 ps_pps = ps_nal_parse_ctxt->pv_pic_prms;
1080 ps_pps += ps_nal_prms->u1_pps_id;
1081
1082 /* Get the VCL NAL node */
1083 i4_status = isvcd_get_dqid_node(&ps_nal_parse_ctxt->s_dqid_ctxt,
1084 (UWORD8) ps_nal_parse_ctxt->i4_prev_dq_id, &ps_dqid_node);
1085
1086 ps_node = ps_dqid_node->ps_vcl_node;
1087
1088 if(NULL == ps_node)
1089 {
1090 /* no active node has been acquired */
1091 return;
1092 }
1093
1094 /*-------------------------------------------------------------------*/
1095 /* The DQID list updation should happen only once in a */
1096 /* layer. Hence a flag used to determine whether the */
1097 /* layer is already initialized or not. */
1098 /*-------------------------------------------------------------------*/
1099 if(SVCD_FALSE == ps_dqid_node->u1_valid_flag)
1100 {
1101 /* Update the DQID node */
1102 ps_dqid_node->u1_valid_flag = SVCD_TRUE;
1103 ps_dqid_node->u1_dqid = (ps_nal_prms->i4_dependency_id << 4);
1104 ps_dqid_node->u1_dqid += ps_nal_prms->i4_quality_id;
1105 ps_dqid_node->i4_poc_lsb = ps_nal_prms->i4_poc_lsb;
1106 ps_dqid_node->i4_delta_poc_bot = ps_nal_prms->i4_delta_poc_bot;
1107 ps_dqid_node->ai4_delta_poc[0] = ps_nal_prms->ai4_delta_poc[0];
1108 ps_dqid_node->ai4_delta_poc[1] = ps_nal_prms->ai4_delta_poc[1];
1109
1110 /* Update the VCL node */
1111 ps_node->i4_quality_id = ps_nal_prms->i4_quality_id;
1112 ps_node->i4_dependency_id = ps_nal_prms->i4_dependency_id;
1113 ps_node->i4_temporal_id = ps_nal_prms->i4_temporal_id;
1114 ps_node->i4_priority_id = ps_nal_prms->i4_priority_id;
1115 ps_node->i4_idr_pic_flag = ps_nal_prms->i4_idr_pic_flag;
1116 ps_node->i4_nal_ref_idc = ps_nal_prms->i4_nal_ref_idc;
1117 ps_node->i4_nal_unit_type = ps_nal_prms->i4_nal_unit_type;
1118 ps_node->i4_use_ref_base = ps_nal_prms->i4_use_ref_base_pic_flag;
1119 ps_node->i4_nal_ref_idc = ps_nal_prms->i4_nal_ref_idc;
1120 ps_node->u1_sps_id = ps_nal_prms->u1_sps_id;
1121 ps_node->u1_pps_id = ps_nal_prms->u1_pps_id;
1122 ps_node->u2_frm_num = ps_nal_prms->u2_frm_num;
1123 ps_node->i4_idr_pic_num = ps_nal_prms->i4_idr_pic_num;
1124 ps_node->i4_num_slices = 0;
1125 ps_node->u1_acc_no_int_pred = 1;
1126 if(0 == ps_sps->u1_pic_order_cnt_type)
1127 {
1128 ps_node->i4_poc_syntax = ps_nal_prms->i4_poc_lsb;
1129 }
1130 else
1131 {
1132 ps_node->i4_poc_syntax = ps_nal_prms->ai4_delta_poc[0];
1133 }
1134
1135 /* Insert the node into DQID list */
1136 i4_status = isvcd_insert_vcl_node(ps_vcl_nal, ps_node);
1137 if(OK != i4_status)
1138 {
1139 return;
1140 }
1141
1142 /* Reset the previous field */
1143 ps_nal_parse_ctxt->ps_prev_vcl_buf = NULL;
1144 ps_node->ps_first_vcl_nal = NULL;
1145 }
1146
1147 /* Update accumulated no inter layer prediction */
1148 ps_node->u1_acc_no_int_pred &= (UWORD8) ps_nal_prms->i4_no_int_lyr_pred;
1149
1150 /****************** Fill VCL BUF header ************/
1151
1152 /* If prefix NAL unit is present then update */
1153 /* the following */
1154 /* - Start of buffer header will be present in*/
1155 /* before the start of prefix NAL unit's SODB*/
1156 /* data. */
1157 /* Note: If memeory left for buffer header */
1158 /* of the prefix NAL unit will have junk */
1159 /* values */
1160
1161 if(NULL == ps_nal_buf->pu1_buf)
1162 {
1163 /* no nal needs to be added into the list hence return */
1164 return;
1165 }
1166 else
1167 {
1168 ps_vcl_hdr = (vcl_buf_hdr_t *) (ps_nal_buf->pu1_buf - GET_NAL_BUF_INC(VCL_NAL));
1169 }
1170
1171 i4_slice_offset = 0;
1172 if(SVCD_TRUE == ps_prefix_nal_buf->i4_valid_flag)
1173 {
1174 ps_vcl_hdr = (vcl_buf_hdr_t *) (ps_prefix_nal_buf->pu1_buf - GET_NAL_BUF_INC(VCL_NAL));
1175 i4_slice_offset = ps_nal_buf->pu1_buf - ps_prefix_nal_buf->pu1_buf;
1176 }
1177
1178 /* Update the next field of the previous nal */
1179 /* unit or if it is the first NAL then update */
1180 /* VCL node information */
1181 ps_prev_vcl_hdr = ps_nal_parse_ctxt->ps_prev_vcl_buf;
1182 if(NULL != ps_prev_vcl_hdr)
1183 {
1184 ps_prev_vcl_hdr->ps_next = ps_vcl_hdr;
1185 }
1186 else
1187 {
1188 ps_node->ps_first_vcl_nal = ps_vcl_hdr;
1189 }
1190
1191 /* Fill the VCL buffer header */
1192 ps_vcl_hdr->ps_next = NULL;
1193 ps_vcl_hdr->i4_no_int_lyr_pred = ps_nal_prms->i4_no_int_lyr_pred;
1194 ps_vcl_hdr->i4_first_mb_addr = ps_nal_prms->u4_first_mb_addr;
1195 ps_vcl_hdr->u4_prefix_nal_bits = ps_prefix_nal_buf->u4_max_bits;
1196 ps_vcl_hdr->i4_slice_offset = 0;
1197 ps_vcl_hdr->i4_buf_offset = GET_NAL_BUF_INC(VCL_NAL);
1198 ps_vcl_hdr->i4_slice_offset = i4_slice_offset;
1199
1200 /* Determine max num bits */
1201 ps_nal_buf->u4_max_bits = isvcd_nal_rbsp_to_sodb(
1202 ps_nal_buf->pu1_buf, ps_nal_buf->i4_buf_size, ps_pps->u1_entropy_coding_mode);
1203 ps_vcl_hdr->u4_max_bits = ps_nal_buf->u4_max_bits;
1204
1205 /* Updates */
1206 ps_nal_parse_ctxt->ps_prev_vcl_buf = ps_vcl_hdr;
1207 ps_node->i4_num_slices += 1;
1208 }
1209 /*-----------------------------------------------------------------------*/
1210 /* If start of NAL and if its a NON VCL NAL then update the */
1211 /* start address of the NON VCL NAL */
1212 /*-----------------------------------------------------------------------*/
1213 else
1214 {
1215 non_vcl_buf_hdr_t *ps_non_vcl_buf_hdr;
1216 non_vcl_buf_hdr_t *ps_prev_non_vcl_buf_hdr;
1217
1218 ps_non_vcl_buf_hdr =
1219 (non_vcl_buf_hdr_t *) (ps_nal_buf->pu1_buf - GET_NAL_BUF_INC(NON_VCL_NAL));
1220
1221 /* Update NON VCL structure */
1222 ps_non_vcl_buf_hdr->i4_nal_unit_type = ps_nal_prms->i4_nal_unit_type;
1223 ps_non_vcl_buf_hdr->ps_next = NULL;
1224 ps_non_vcl_buf_hdr->i4_buf_offset = GET_NAL_BUF_INC(NON_VCL_NAL);
1225 ps_non_vcl_buf_hdr->i4_buf_size = ps_nal_buf->i4_buf_size;
1226
1227 /* Update the next field and first non vcl fields of */
1228 /* non vcl buffer header structure and non vcl */
1229 /* structure respectively */
1230 ps_prev_non_vcl_buf_hdr = ps_nal_parse_ctxt->ps_prev_non_vcl_buf;
1231 if(NULL != ps_prev_non_vcl_buf_hdr)
1232 {
1233 ps_prev_non_vcl_buf_hdr->ps_next = ps_non_vcl_buf_hdr;
1234 }
1235 else
1236 {
1237 ps_non_vcl_nal->ps_first_non_vcl_nal = ps_non_vcl_buf_hdr;
1238 }
1239
1240 /* Updates */
1241 ps_nal_parse_ctxt->i4_num_non_vcl_nals += 1;
1242 ps_non_vcl_nal->i4_num_non_vcl_nals = ps_nal_parse_ctxt->i4_num_non_vcl_nals;
1243 ps_nal_parse_ctxt->ps_prev_non_vcl_buf = ps_non_vcl_buf_hdr;
1244 }
1245 }
1246
1247 /*****************************************************************************/
1248 /* */
1249 /* Function Name : isvcd_idr_err_hdlr */
1250 /* */
1251 /* Description : This routine shall be invoked to handle a case when a */
1252 /* slice is an IDR picture and it is referring to corrupted */
1253 /* SPS or PPS */
1254 /* */
1255 /* Inputs : 1. VCL NAL structure */
1256 /* 2. NAL paramters */
1257 /* 3. NAL parse context structure */
1258 /* Globals : None */
1259 /* Processing : It will set the highest available dependency id below the*/
1260 /* current dependency id as the target layer. Also sets the */
1261 /* update target layer flag to FALSE as target layer need not*/
1262 /* adopt to the application's target layer in the current */
1263 /* picture */
1264 /* */
1265 /* Outputs : Updated vcl nal structure */
1266 /* Updated internal target layer attributes */
1267 /* Updated target layer update flag */
1268 /* Returns : status */
1269 /* */
1270 /* Issues : None */
1271 /* */
1272 /* Revision History: */
1273 /* */
1274 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
1275 /* 06 09 2021 Vijay Draft */
1276 /* */
1277 /*****************************************************************************/
isvcd_idr_err_hdlr(vcl_nal_t * ps_vcl_nal,nal_prms_t * ps_nal_prms,nal_parse_ctxt_t * ps_nal_parse_ctxt)1278 WORD32 isvcd_idr_err_hdlr(vcl_nal_t *ps_vcl_nal, nal_prms_t *ps_nal_prms,
1279 nal_parse_ctxt_t *ps_nal_parse_ctxt)
1280 {
1281 vcl_node_t *ps_vcl_node;
1282 target_lyr_attr_t *ps_int_attr;
1283
1284 /* sanity checks */
1285 if((NULL == ps_vcl_nal) || (NULL == ps_nal_prms) || (NULL == ps_nal_parse_ctxt))
1286 {
1287 return NOT_OK;
1288 }
1289 UNUSED(ps_nal_prms);
1290
1291 /* Initializations */
1292 ps_vcl_node = ps_vcl_nal->ps_top_node;
1293 ps_int_attr = &ps_nal_parse_ctxt->s_int_attr;
1294
1295 /* the highest node present in the depedency list will be */
1296 /* considered as targte layer and appropriate params will be used */
1297
1298 /* If not found then delete all the layers in the AU */
1299 if(NULL == ps_vcl_node)
1300 {
1301 ps_int_attr->i4_dependency_id = -1;
1302 ps_int_attr->i4_quality_id = MAX_QUALITY_ID;
1303 }
1304 else
1305 {
1306 /* Set the target layer */
1307 ps_int_attr->i4_dependency_id = ps_vcl_node->i4_dependency_id;
1308 ps_int_attr->i4_quality_id = ps_vcl_node->i4_quality_id;
1309 }
1310
1311 return (OK);
1312 }
1313 /*****************************************************************************/
1314 /* */
1315 /* Function Name :svcd_refine_dqid_list */
1316 /* */
1317 /* Description : Inserts the dummy nodes for each dependency id which */
1318 /* have not come in the bitstream */
1319 /* */
1320 /* Inputs :VCL NAL structure */
1321 /* NAL parse context structure */
1322 /* Globals : None */
1323 /* Processing : For each dependency id till the target dependency id */
1324 /* - If layer already exists (came in the bitstream) then */
1325 /* do nothing */
1326 /* - Otherwsie insert a dummy node */
1327 /* */
1328 /* Outputs : Updated VCL NAL structure */
1329 /* Returns : None */
1330 /* */
1331 /* Issues : None */
1332 /* */
1333 /* Revision History: */
1334 /* */
1335 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
1336 /* 06 09 2021 Vijay Draft */
1337 /* */
1338 /*****************************************************************************/
isvcd_refine_dqid_list(vcl_nal_t * ps_vcl_nal,nal_parse_ctxt_t * ps_nal_parse_ctxt)1339 WORD32 isvcd_refine_dqid_list(vcl_nal_t *ps_vcl_nal, nal_parse_ctxt_t *ps_nal_parse_ctxt)
1340 {
1341 vcl_node_t *ps_node;
1342 target_lyr_attr_t *ps_int_attr;
1343 dqid_ctxt_t *ps_dqid_ctxt;
1344 UWORD8 u1_dep_id;
1345 WORD32 i4_status;
1346 WORD32 i4_dep_id;
1347
1348 ps_int_attr = &ps_nal_parse_ctxt->s_int_attr;
1349 ps_dqid_ctxt = &ps_nal_parse_ctxt->s_dqid_ctxt;
1350 i4_dep_id = -1;
1351
1352 for(u1_dep_id = 0; u1_dep_id <= ps_int_attr->i4_dependency_id; u1_dep_id++)
1353 {
1354 dqid_node_t *ps_dqid_node;
1355
1356 /* Get a DQID node */
1357 i4_status = isvcd_get_dqid_node(ps_dqid_ctxt, (UWORD8) (u1_dep_id << 4), &ps_dqid_node);
1358 if(OK != i4_status)
1359 {
1360 return NOT_OK;
1361 }
1362
1363 /* If node does not exist already then insert a dummy node */
1364 if(SVCD_FALSE == ps_dqid_node->u1_valid_flag)
1365 {
1366 if(1 == ps_nal_parse_ctxt->i4_idr_pic_err_flag)
1367 {
1368 ps_int_attr->i4_dependency_id = i4_dep_id;
1369 ps_int_attr->i4_quality_id = MAX_QUALITY_ID;
1370
1371 /* remove all the nodes from dependency list */
1372 /* which are at higher dependency than the */
1373 /* value set in init attributes */
1374 while(NULL != ps_vcl_nal->ps_top_node)
1375 {
1376 /* if higher dependency */
1377 if(ps_vcl_nal->ps_top_node->i4_dependency_id > i4_dep_id)
1378 {
1379 ps_vcl_nal->ps_top_node = ps_vcl_nal->ps_top_node->ps_bot_node;
1380 }
1381 else
1382 {
1383 break;
1384 }
1385 }
1386
1387 /* if no node exists in the dependency list */
1388 if(NULL == ps_vcl_nal->ps_top_node)
1389 {
1390 ps_vcl_nal->ps_bot_node = NULL;
1391 }
1392 else if(ps_vcl_nal->ps_top_node == ps_vcl_nal->ps_bot_node)
1393 {
1394 /* if a single node exists */
1395 ps_vcl_nal->ps_top_node->ps_bot_node = NULL;
1396 ps_vcl_nal->ps_bot_node->ps_top_node = NULL;
1397 }
1398
1399 return (NOT_OK);
1400 }
1401 else
1402 {
1403 ps_dqid_node->u1_valid_flag = SVCD_TRUE;
1404 ps_dqid_node->u1_dqid = (u1_dep_id << 4);
1405
1406 /* Fill VCL node information */
1407 ps_node = ps_dqid_node->ps_vcl_node;
1408 ps_node->i4_dependency_id = u1_dep_id;
1409 ps_node->i4_quality_id = 0;
1410 ps_node->ps_first_vcl_nal = NULL;
1411 }
1412
1413 /* Insert node into DQID list */
1414 i4_status = isvcd_insert_vcl_node(ps_vcl_nal, ps_node);
1415 if(OK != i4_status)
1416 {
1417 return (NOT_OK);
1418 }
1419 }
1420
1421 i4_dep_id++;
1422 } /* End of loop over all the dependency id */
1423 return (OK);
1424 }
1425
1426 /*****************************************************************************/
1427 /* */
1428 /* Function Name : isvcd_nal_parse_set_target_attr */
1429 /* */
1430 /* Description : Sets the target layer attributes */
1431 /* */
1432 /* Inputs : i4_target_quality_id - Target layer quality id */
1433 /* i4_target_dependency_id - Target layer dependency id */
1434 /* i4_target_temporal_id - Target layer temporal id */
1435 /* i4_target_priority_id - Target layer priority id */
1436 /* pv_nal_parse_ctxt - Pointer module handle */
1437 /* */
1438 /* Globals : None */
1439 /* */
1440 /* Processing : None */
1441 /* */
1442 /* Outputs : None */
1443 /* */
1444 /* Returns : None */
1445 /* */
1446 /* Issues : None */
1447 /* */
1448 /* Revision History: */
1449 /* DD MM YYYY Author(s) Changes */
1450 /* 06 09 2021 Vijay Draft */
1451 /* */
1452 /*****************************************************************************/
1453
isvcd_nal_parse_set_target_attr(WORD32 i4_target_quality_id,WORD32 i4_target_dependency_id,WORD32 i4_target_temporal_id,WORD32 i4_target_priority_id,void * pv_nal_parse_ctxt)1454 WORD32 isvcd_nal_parse_set_target_attr(WORD32 i4_target_quality_id, WORD32 i4_target_dependency_id,
1455 WORD32 i4_target_temporal_id, WORD32 i4_target_priority_id,
1456 void *pv_nal_parse_ctxt)
1457 {
1458 nal_parse_ctxt_t *ps_nal_parse_ctxt;
1459 target_lyr_attr_t *ps_app_attr;
1460
1461 if((i4_target_quality_id > MAX_QUALITY_ID) || (i4_target_dependency_id > MAX_DEPENDENCY_ID))
1462 {
1463 return IV_FAIL;
1464 }
1465
1466 ps_nal_parse_ctxt = (nal_parse_ctxt_t *) pv_nal_parse_ctxt;
1467 ps_app_attr = &ps_nal_parse_ctxt->s_app_attr;
1468
1469 /*-----------------------------------------------------------------------*/
1470 /*! Register the target information into context structure */
1471 /*-----------------------------------------------------------------------*/
1472 ps_app_attr->i4_quality_id = i4_target_quality_id;
1473 ps_app_attr->i4_dependency_id = i4_target_dependency_id;
1474 ps_app_attr->i4_temporal_id = i4_target_temporal_id;
1475 ps_app_attr->i4_priority_id = i4_target_priority_id;
1476 return IV_SUCCESS;
1477 }
1478
1479 /*****************************************************************************/
1480 /* */
1481 /* Function Name : isvcd_nal_parse_reset_ctxt */
1482 /* */
1483 /* Description : Initializes the bitstream extraction module. Should be */
1484 /* called once in a sequence */
1485 /* */
1486 /* Inputs : i4_input_bitstream_mode - Input bitstream mode RFC or */
1487 /* Annex B */
1488 /* i4_input_mode - Input mode - Full input mode or partial */
1489 /* input mode */
1490 /* pv_nal_parse_ctxt - Module handle */
1491 /* */
1492 /* Globals : None */
1493 /* */
1494 /* Processing : None */
1495 /* */
1496 /* Outputs : None */
1497 /* */
1498 /* Returns : None */
1499 /* */
1500 /* Issues : None */
1501 /* */
1502 /* Revision History: */
1503 /* DD MM YYYY Author(s) Changes */
1504 /* 06 09 2021 Vijay Draft */
1505 /* */
1506 /*****************************************************************************/
1507
isvcd_nal_parse_reset_ctxt(WORD32 i4_input_bitstream_mode,WORD32 i4_input_mode,void * pv_nal_parse_ctxt)1508 void isvcd_nal_parse_reset_ctxt(WORD32 i4_input_bitstream_mode, WORD32 i4_input_mode,
1509 void *pv_nal_parse_ctxt)
1510 {
1511 nal_parse_ctxt_t *ps_nal_parse_ctxt = (nal_parse_ctxt_t *) pv_nal_parse_ctxt;
1512 UNUSED(i4_input_mode);
1513
1514 /*-----------------------------------------------------------------------*/
1515 /*! Set the input bitstream mode of context structure */
1516 /*-----------------------------------------------------------------------*/
1517 switch(i4_input_bitstream_mode)
1518 {
1519 case ANNEX_B:
1520 case NON_ANNEX_B:
1521 break;
1522 default:
1523 break;
1524 }
1525
1526 ps_nal_parse_ctxt->i4_input_bitstream_mode = i4_input_bitstream_mode;
1527
1528 /*-----------------------------------------------------------------------*/
1529 /*! Perform the picture level initialization */
1530 /*-----------------------------------------------------------------------*/
1531 isvcd_pic_reset_ctxt(pv_nal_parse_ctxt);
1532
1533 /* Reset the prefix nal unit buffer structure */
1534 isvcd_nal_buf_reset(&ps_nal_parse_ctxt->s_prefix_nal_buf);
1535
1536 /*-----------------------------------------------------------------------*/
1537 /*! Reset other varaibles */
1538 /*-----------------------------------------------------------------------*/
1539 ps_nal_parse_ctxt->i4_dec_frst_sc_flag = SVCD_TRUE;
1540 ps_nal_parse_ctxt->i4_eos_flag = SVCD_FALSE;
1541 ps_nal_parse_ctxt->u1_pic_boundary_aud_flag = 0;
1542 ps_nal_parse_ctxt->u4_bytes_left = 0;
1543
1544 /* Reset target layer attributes */
1545 {
1546 target_lyr_attr_t *ps_app_attr;
1547 target_lyr_attr_t *ps_int_attr;
1548
1549 ps_app_attr = &ps_nal_parse_ctxt->s_app_attr;
1550 ps_int_attr = &ps_nal_parse_ctxt->s_int_attr;
1551
1552 ps_app_attr->i4_dependency_id = MAX_DEPENDENCY_ID;
1553 ps_app_attr->i4_quality_id = MAX_QUALITY_ID;
1554 ps_app_attr->i4_temporal_id = MAX_TEMPORAL_ID;
1555 ps_app_attr->i4_priority_id = MAX_PRIORITY_ID;
1556
1557 ps_int_attr->i4_dependency_id = -1;
1558 ps_int_attr->i4_quality_id = MAX_QUALITY_ID;
1559 ps_int_attr->i4_temporal_id = 0;
1560 ps_int_attr->i4_priority_id = MAX_PRIORITY_ID;
1561 }
1562 }
1563
1564 /*****************************************************************************/
1565 /* */
1566 /* Function Name : isvcd_nal_parse_partial_signal_eos */
1567 /* */
1568 /* Description : Does processing when end of stream occurs for partial */
1569 /* input mode of operation. */
1570 /* */
1571 /* Inputs : pv_nal_parse_ctxt - bitstream extract context structure */
1572 /* pv_out_vcl_nal - vcl nal structure */
1573 /* pv_out_non_vcl_nal - non vcl nal structure */
1574 /* */
1575 /* Globals : None */
1576 /* */
1577 /* Processing : None */
1578 /* */
1579 /* Outputs : None */
1580 /* */
1581 /* Returns : Picture boundary detetcted or not */
1582 /* */
1583 /* Issues : None */
1584 /* */
1585 /* Revision History: */
1586 /* DD MM YYYY Author(s) Changes */
1587 /* 06 09 2021 Vijay Draft */
1588 /* */
1589 /*****************************************************************************/
1590
isvcd_nal_parse_partial_signal_eos(void * pv_nal_parse_ctxt,void * pv_out_vcl_nal,void * pv_out_non_vcl_nal)1591 WORD32 isvcd_nal_parse_partial_signal_eos(void *pv_nal_parse_ctxt, void *pv_out_vcl_nal,
1592 void *pv_out_non_vcl_nal)
1593 {
1594 nal_parse_ctxt_t *ps_nal_parse_ctxt;
1595 vcl_nal_t *ps_vcl_nal;
1596
1597 ps_nal_parse_ctxt = (nal_parse_ctxt_t *) pv_nal_parse_ctxt;
1598 ps_vcl_nal = (vcl_nal_t *) pv_out_vcl_nal;
1599
1600 /* for RFC mode */
1601 if(NON_ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode)
1602 {
1603 /* Reset the end of stream flag so that in */
1604 ps_nal_parse_ctxt->i4_eos_flag = SVCD_TRUE;
1605 }
1606
1607 if(1 == ps_nal_parse_ctxt->u1_pic_boundary_aud_flag)
1608 {
1609 ps_nal_parse_ctxt->i4_eos_flag = SVCD_TRUE;
1610 }
1611 /* Update VCL node if it is first call in the */
1612 /* flush mode */
1613 if(SVCD_FALSE == ps_nal_parse_ctxt->i4_eos_flag)
1614 {
1615 WORD32 i4_status;
1616
1617 /* Update the unfinished NAL into VCL node if */
1618 /* all the following conditions are true */
1619 /* 1. We have not found the start code and */
1620 /* NAL boundary is not detected yet */
1621 /* 2. NAL is not discarded */
1622 if((FIND_NAL_END == ps_nal_parse_ctxt->i4_find_nal_state) &&
1623 (SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag))
1624 {
1625 isvcd_update_nal_ctxt(ps_nal_parse_ctxt, pv_out_vcl_nal, pv_out_non_vcl_nal);
1626 }
1627
1628 ps_nal_parse_ctxt->i4_idr_pic_err_flag = 0;
1629 /* Refine based on the no inter layer pred flag*/
1630 i4_status = isvcd_refine_dqid_list(ps_vcl_nal, ps_nal_parse_ctxt);
1631
1632 if(!(OK == i4_status))
1633 {
1634 return i4_status;
1635 }
1636 UNUSED(i4_status);
1637
1638 /* Reset the context structure variables */
1639 isvcd_nal_reset_ctxt(ps_nal_parse_ctxt);
1640
1641 /* Reset the end of stream flag so that in */
1642 /* the next flush call the above steps need */
1643 /* not be performed */
1644 ps_nal_parse_ctxt->i4_eos_flag = SVCD_TRUE;
1645
1646 return (PIC_BOUNDARY_TRUE);
1647 }
1648 else
1649 {
1650 return (FLUSH_DECODED_PICTURE);
1651 }
1652 }
1653 /*****************************************************************************/
1654 /* */
1655 /* Function Name : isvcd_nal_parse_pic_bound_proc */
1656 /* */
1657 /* Description : Function does the picture end processign and resets */
1658 /* */
1659 /* */
1660 /* Inputs : ps_nal_parse_ctxt, ps_vcl_nal */
1661 /* Globals : none */
1662 /* Processing : DQid list refiniment and resets */
1663 /* */
1664 /* Outputs : none */
1665 /* Returns : none */
1666 /* */
1667 /* Issues : none */
1668 /* */
1669 /* Revision History: */
1670 /* */
1671 /* DD MM YYYY Author(s) Changes (Describe the changes made) */
1672 /* 06 09 2021 vijayakumar creation */
1673 /* */
1674 /*****************************************************************************/
isvcd_nal_parse_pic_bound_proc(nal_parse_ctxt_t * ps_nal_parse_ctxt,vcl_nal_t * ps_vcl_nal,nal_prms_t * ps_nal_prms)1675 void isvcd_nal_parse_pic_bound_proc(nal_parse_ctxt_t *ps_nal_parse_ctxt, vcl_nal_t *ps_vcl_nal,
1676 nal_prms_t *ps_nal_prms)
1677 {
1678 WORD32 i4_status;
1679
1680 i4_status = isvcd_refine_dqid_list(ps_vcl_nal, ps_nal_parse_ctxt);
1681
1682 /* in case of IDR pictures if the node */
1683 /* which has to be added into dependency */
1684 /* list is not valied then the layer below */
1685 /* that node is set as target layer */
1686
1687 if(NOT_OK == i4_status)
1688 {
1689 ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
1690 ps_vcl_nal->i1_nal_ref_id_next = -1;
1691 }
1692 else
1693 {
1694 /* update the next access unit params */
1695 /* will be used by lower level decoder*/
1696 /* for concealment of frame number */
1697 /* applicable for single layer cases */
1698 ps_vcl_nal->i1_nal_ref_id_next = ps_nal_prms->i4_nal_ref_idc;
1699
1700 ps_vcl_nal->u2_frm_num_next = ps_nal_prms->u2_frm_num;
1701 }
1702
1703 /* -------- reset few variables in context structure ----*/
1704 isvcd_pic_reset_ctxt(ps_nal_parse_ctxt);
1705 }
1706 /*****************************************************************************/
1707 /* */
1708 /* Function Name : isvcd_nal_parse_vcl_nal_partial */
1709 /* */
1710 /* Description : None */
1711 /* */
1712 /* Inputs : pv_nal_parse_ctxt - bitstream extract ctxt */
1713 /* structure */
1714 /* pv_input_bitstream_ctxt - bitstream context */
1715 /* pv_out_non_vcl_nal - non vcl nal structure (output) */
1716 /* pv_out_vcl_nal - vcl nal structure (output) */
1717 /* pu4_bytes_consumed - bytes consumed variable(output) */
1718 /* pi4_num_packets_consumed - packets consumed (output/RFC) */
1719 /* */
1720 /* Globals : None */
1721 /* */
1722 /* Processing : None */
1723 /* */
1724 /* Outputs : Updates bytes consumed variable, packets consumed, */
1725 /* output structures (vcl nal , non vcl nal) */
1726 /* */
1727 /* Returns : If picture bounadry is detetcted then PIC_BOUNDARY_TRUE */
1728 /* otherwise PIC_BOUNDARY_FALSE */
1729 /* */
1730 /* Issues : None */
1731 /* */
1732 /* Revision History: */
1733 /* DD MM YYYY Author(s) Changes */
1734 /* 06 09 2021 Vijay Draft */
1735 /* */
1736 /*****************************************************************************/
1737
isvcd_nal_parse_vcl_nal_partial(void * pv_nal_parse_ctxt,UWORD8 * pu1_stream_buffer,void * pv_out_non_vcl_nal,void * pv_out_vcl_nal,UWORD32 * pu4_bytes_consumed,UWORD32 * pu4_num_bytes)1738 WORD32 isvcd_nal_parse_vcl_nal_partial(void *pv_nal_parse_ctxt, UWORD8 *pu1_stream_buffer,
1739 void *pv_out_non_vcl_nal, void *pv_out_vcl_nal,
1740 UWORD32 *pu4_bytes_consumed, UWORD32 *pu4_num_bytes)
1741 {
1742 /*! - Search for the NAL boundary
1743 - If NAL boundary is not found and bytes consumed is lesser than
1744 minimum buffer size then break out of the loop
1745 - if it is start of NAL then read the NAL header
1746 - If it is a VCL NAL then invoke picture boundary detection logic and
1747 picture boundary is detected then break out of the loop without
1748 updating the bytes consumed variable
1749 - NAL discard logic determines whther the current NAL has to be
1750 discarded or not
1751 - If NAL is not discarded then populate the vcl or non vcl output
1752 structures
1753 */
1754 nal_parse_ctxt_t *ps_nal_parse_ctxt;
1755 vcl_nal_t *ps_vcl_nal;
1756 non_vcl_nal_t *ps_non_vcl_nal;
1757 nal_unit_t *ps_nal_unit;
1758 WORD32 i4_nal_start_flag, i4_cur_pos, i4_status;
1759 WORD32 i4_nal_header_len, i4_more_data_flag;
1760 UWORD32 u4_bytes_consumed_temp = 0;
1761 UWORD8 **ppu1_out_buf;
1762 nal_prms_t *ps_nal_prms;
1763 WORD32 i4_pic_bound_status;
1764
1765 ps_nal_parse_ctxt = (nal_parse_ctxt_t *) pv_nal_parse_ctxt;
1766 ps_vcl_nal = (vcl_nal_t *) pv_out_vcl_nal;
1767 ps_non_vcl_nal = (non_vcl_nal_t *) pv_out_non_vcl_nal;
1768 ps_nal_unit = (nal_unit_t *) ps_nal_parse_ctxt->pv_nal_unit;
1769 ps_nal_prms = &ps_nal_parse_ctxt->s_nal_prms;
1770
1771 /* Initialization */
1772 i4_cur_pos = 0;
1773 *pu4_bytes_consumed = 0;
1774 i4_nal_header_len = 0;
1775 i4_nal_start_flag = SVCD_FALSE;
1776 i4_more_data_flag = SVCD_TRUE;
1777 i4_pic_bound_status = PIC_BOUNDARY_FALSE;
1778
1779 ps_non_vcl_nal->i4_num_non_vcl_nals = ps_nal_parse_ctxt->i4_num_non_vcl_nals;
1780
1781 /* Since we do not perform the picture boundary detection */
1782 /* on the prefix NAL unit, the current picture's prefix */
1783 /* NAL unit will be at the bottom of the buffer. Hence */
1784 /* it should be copied to top of the buffer */
1785 if(SVCD_TRUE == ps_nal_parse_ctxt->i4_is_frst_vcl_nal_in_au)
1786 {
1787 nal_buf_t *ps_prefix_nal_buf;
1788
1789 ps_prefix_nal_buf = &ps_nal_parse_ctxt->s_prefix_nal_buf;
1790 if(SVCD_TRUE == ps_prefix_nal_buf->i4_valid_flag)
1791 {
1792 WORD32 i4_buf_size;
1793 UWORD8 *pu1_vcl_nal;
1794
1795 if(ps_prefix_nal_buf->i4_buf_size > 0)
1796 {
1797 i4_buf_size = ps_prefix_nal_buf->i4_buf_size;
1798 i4_buf_size = UP_ALIGN_8(i4_buf_size + BUFFER_ALIGN_4);
1799 }
1800 else
1801 {
1802 i4_buf_size = 0;
1803 }
1804
1805 pu1_vcl_nal = ps_nal_parse_ctxt->pu1_vcl_nal_buf + i4_buf_size;
1806
1807 memmove(ps_nal_parse_ctxt->pu1_vcl_nal_buf, ps_prefix_nal_buf->pu1_buf, i4_buf_size);
1808 ps_prefix_nal_buf->pu1_buf = ps_nal_parse_ctxt->pu1_vcl_nal_buf;
1809 ps_nal_parse_ctxt->pu1_vcl_nal_buf = pu1_vcl_nal;
1810
1811 /* subtract the buffer size left */
1812 ps_nal_parse_ctxt->u4_bytes_left_vcl -= i4_buf_size;
1813 }
1814 /* Reset the top and bottom node */
1815 ps_vcl_nal->ps_top_node = NULL;
1816 ps_vcl_nal->ps_bot_node = NULL;
1817 ps_vcl_nal->i1_nal_ref_id_next = -1;
1818 ps_vcl_nal->u2_frm_num_next = 0;
1819 }
1820
1821 /* If number of bytes left in the previous process call */
1822 /* is is greater or equal to number of bytes in input */
1823 /* buffer of the current process call then declare that */
1824 /* end of bitstream has occurred and consume the bytes */
1825 /* but do not decode */
1826 if(ps_nal_parse_ctxt->u4_bytes_left >= (UWORD32) *pu4_num_bytes)
1827 {
1828 ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
1829 *pu4_bytes_consumed = *pu4_num_bytes;
1830
1831 i4_status =
1832 isvcd_nal_parse_partial_signal_eos(ps_nal_parse_ctxt, ps_vcl_nal, ps_non_vcl_nal);
1833 /* set the next AU params to default values */
1834 ps_vcl_nal->i1_nal_ref_id_next = -1;
1835 ps_vcl_nal->u2_frm_num_next = 0;
1836
1837 return (i4_status);
1838 }
1839 ps_nal_parse_ctxt->u4_bytes_left = 0;
1840
1841 /*************************************************************************/
1842 /* LOOP OVER NALs */
1843 /*************************************************************************/
1844 do
1845 {
1846 nal_buf_t *ps_nal_buf;
1847 UWORD32 *pu4_bytes_left;
1848
1849 /* Find NAL boundary */
1850 if(ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode)
1851 {
1852 i4_nal_start_flag = isvcd_get_annex_b_nal_unit(
1853 pu1_stream_buffer, i4_cur_pos, *pu4_num_bytes,
1854 &ps_nal_parse_ctxt->i4_find_nal_state, &ps_nal_parse_ctxt->i4_zero_byte_cnt,
1855 &u4_bytes_consumed_temp, ps_nal_parse_ctxt->pv_nal_unit, &i4_more_data_flag);
1856
1857 i4_cur_pos += u4_bytes_consumed_temp;
1858 }
1859
1860 /*********************************************************************/
1861 /* READ NAL HEADER AND NAL DISCARD LOGIC */
1862 /*********************************************************************/
1863
1864 /* If it is the start of NAL header perform the following */
1865 /* 1. Decode NAL header */
1866 /* 2. Determine whether the NAL has to be discarded or not*/
1867 /* 3. Detect the picture boundary */
1868 if(SVCD_TRUE == i4_nal_start_flag)
1869 {
1870 UWORD32 u4_err_code;
1871 WORD32 i4_sps_pps_corrupt_status;
1872 WORD32 i4_internal_dep_id_prev;
1873
1874 /* Get the NAL prms. This involves the following things*/
1875 /* 1. Decode the NAL header */
1876 /* 2. Set the discard flag */
1877 /* 3. Decode the slice header if needed */
1878
1879 /* get the dependency id at which the NAl parse is currently */
1880 /* present */
1881 i4_internal_dep_id_prev = ps_nal_parse_ctxt->s_int_attr.i4_dependency_id;
1882
1883 i4_status = isvcd_get_nal_prms(
1884 ps_nal_unit->pu1_bufs, ps_nal_unit->i4_buf_sizes, ps_nal_prms,
1885 &ps_nal_parse_ctxt->s_prefix_nal_prms, &ps_nal_parse_ctxt->s_prefix_nal_buf,
1886 &u4_err_code, &i4_sps_pps_corrupt_status, &ps_nal_parse_ctxt->i4_discard_nal_flag,
1887 ps_nal_parse_ctxt);
1888
1889 if(NON_ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode)
1890 {
1891 ps_nal_parse_ctxt->i4_prev_dq_id = ps_nal_prms->i4_dqid;
1892 }
1893
1894 /* If the error code returned by the "picture boundary" */
1895 /* detetction is */
1896 /* 1. Insufficient bitstream size: then store the bytes */
1897 /* left and break out of the loop */
1898 /* 2. Corrupted slice: then discard the slice */
1899 if((NAL_INSUFFICIENT_DATA == (WORD32) u4_err_code) &&
1900 (NAL_END != ps_nal_parse_ctxt->i4_find_nal_state))
1901 {
1902 ps_nal_parse_ctxt->u4_bytes_left = *pu4_num_bytes - *pu4_bytes_consumed;
1903
1904 /* Reset the NAL level tracking variables */
1905 isvcd_nal_reset_ctxt(ps_nal_parse_ctxt);
1906 break;
1907 }
1908 else if(0 != u4_err_code)
1909 {
1910 ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
1911
1912 if(SVCD_TRUE == ps_nal_prms->i4_idr_pic_flag)
1913 {
1914 /* IDR Error handler is called */
1915 /* only if for a given layer the NAL */
1916 /* haeder and partial slice decode */
1917 /* routine comes out as no SPS PPS */
1918 /* error. But for Lowest layer in */
1919 /* access unit it is doen always */
1920 if(i4_internal_dep_id_prev != ps_nal_parse_ctxt->s_int_attr.i4_dependency_id)
1921 {
1922 /* if the target depedency id has been */
1923 /* changed while decoding currnet NAL */
1924
1925 if((0 != i4_sps_pps_corrupt_status) ||
1926 (-1 == ps_nal_parse_ctxt->i4_prev_dq_id))
1927 {
1928 i4_status =
1929 isvcd_idr_err_hdlr(ps_vcl_nal, ps_nal_prms, ps_nal_parse_ctxt);
1930 if(OK != i4_status)
1931 {
1932 return i4_status;
1933 }
1934 UNUSED(i4_status);
1935
1936 ps_nal_parse_ctxt->i4_tgt_lyr_update = SVCD_FALSE;
1937 }
1938 else
1939 {
1940 if(0 == ps_nal_prms->i4_quality_id)
1941 {
1942 /* over write the frame number */
1943 ps_nal_parse_ctxt->s_nal_prms.u2_frm_num = 0;
1944
1945 /* Get the previous layer's DQID */
1946 if(ps_nal_parse_ctxt->i4_prev_dq_id < ps_nal_prms->i4_dqid)
1947 {
1948 ps_nal_parse_ctxt->i4_prev_dq_id = ps_nal_prms->i4_dqid;
1949 ps_nal_parse_ctxt->i4_is_frst_vcl_nal_in_au = SVCD_FALSE;
1950 }
1951
1952 /* update the nal context with the nal */
1953 /* header params */
1954 isvcd_update_nal_ctxt(ps_nal_parse_ctxt, ps_vcl_nal,
1955 ps_non_vcl_nal);
1956 }
1957 }
1958 }
1959 }
1960 }
1961
1962 /* Populate the derived nal type into bitstream extract*/
1963 /* context structure */
1964 i4_nal_header_len = ps_nal_prms->i4_nal_header_len;
1965 ps_nal_parse_ctxt->i4_nal_type = ps_nal_prms->i4_derived_nal_type;
1966
1967 /* get the accumulated idr pic error flag */
1968 ps_nal_parse_ctxt->i4_idr_pic_err_flag |=
1969 ((SVCD_TRUE == ps_nal_prms->i4_idr_pic_flag) &&
1970 (SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag) &&
1971 (i4_internal_dep_id_prev != ps_nal_parse_ctxt->s_int_attr.i4_dependency_id));
1972
1973 if(ACCESS_UNIT_DELIMITER_RBSP == ps_nal_prms->i4_nal_unit_type)
1974 {
1975 i4_pic_bound_status = PIC_BOUNDARY_TRUE;
1976 ps_nal_parse_ctxt->u1_pic_boundary_aud_flag = 1;
1977 /* If picture boundary is detected then come out of */
1978 /* the loop */
1979 if(PIC_BOUNDARY_TRUE == i4_pic_bound_status)
1980 {
1981 isvcd_nal_parse_pic_bound_proc(ps_nal_parse_ctxt, ps_vcl_nal, ps_nal_prms);
1982 break;
1983 }
1984 }
1985 /* Perform the picture boundary detetction if all the */
1986 /* following conditions are TRUE */
1987 /* 1. VCL NAL */
1988 /* 2. Not a prefix NAL */
1989 /* 3. Not a discardable NAL */
1990 if((VCL_NAL == ps_nal_prms->i4_derived_nal_type) &&
1991 (PREFIX_UNIT_NAL != ps_nal_prms->i4_nal_unit_type) &&
1992 (SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag))
1993 {
1994 if(ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode)
1995 {
1996 ps_nal_parse_ctxt->u1_pic_boundary_aud_flag = 0;
1997
1998 i4_status = isvcd_detect_pic_boundary_annex_b(ps_nal_prms, pu1_stream_buffer,
1999 i4_cur_pos, &i4_pic_bound_status,
2000 ps_nal_parse_ctxt, pu4_num_bytes);
2001 }
2002
2003 /* If picture boundary is detected then come out of */
2004 /* the loop */
2005 if(PIC_BOUNDARY_TRUE == i4_pic_bound_status)
2006 {
2007 isvcd_nal_parse_pic_bound_proc(ps_nal_parse_ctxt, ps_vcl_nal, ps_nal_prms);
2008 break;
2009 }
2010 }
2011
2012 if(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag)
2013 {
2014 /* Set the active NAL buffer structure and initialize */
2015 /* the nal buffer structure */
2016 isvcd_get_nal_buf(ps_nal_parse_ctxt, &ps_nal_buf);
2017 ps_nal_parse_ctxt->ps_nal_buf = ps_nal_buf;
2018 }
2019 else
2020 {
2021 ps_nal_parse_ctxt->ps_nal_buf = NULL;
2022 }
2023 }
2024
2025 /*-------------------------------------------------------------------*/
2026 /* In RFC based bitstreams, this is a dummy update (in this mode, the*/
2027 /* bytes consumed updation is done by picture boundary dectection */
2028 /* But for Annex B based streams this is valid update */
2029 /*-------------------------------------------------------------------*/
2030 *pu4_bytes_consumed += u4_bytes_consumed_temp;
2031
2032 /*********************************************************************/
2033 /* EMULATION PREVENTION AND BYTE SWAPPING */
2034 /*********************************************************************/
2035
2036 /* Determine output buffer */
2037 ps_nal_buf = ps_nal_parse_ctxt->ps_nal_buf;
2038
2039 if(VCL_NAL == ps_nal_parse_ctxt->i4_nal_type)
2040 {
2041 ppu1_out_buf = &ps_nal_parse_ctxt->pu1_vcl_nal_buf;
2042 pu4_bytes_left = &ps_nal_parse_ctxt->u4_bytes_left_vcl;
2043 if(*pu4_bytes_left < (MAX_VCL_NAL_BUFF_SIZE * 0.05))
2044 {
2045 return (VCL_NAL_FOUND_FALSE);
2046 }
2047 }
2048 else
2049 {
2050 ppu1_out_buf = &ps_nal_parse_ctxt->pu1_non_vcl_nal_buf;
2051 pu4_bytes_left = &ps_nal_parse_ctxt->u4_bytes_left_non_vcl;
2052 if(*pu4_bytes_left < (MAX_NON_VCL_NAL_BUFF_SIZE * 0.05))
2053 {
2054 return (VCL_NAL_FOUND_FALSE);
2055 }
2056 }
2057
2058 /* if 0 bytes left then discard the current NAL */
2059 if(0 >= (WORD32) *pu4_bytes_left)
2060 {
2061 ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
2062 }
2063
2064 /* Perform the emulation prevention and byte swap */
2065 if(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag)
2066 {
2067 UWORD32 u4_output_bytes, u4_buf_inc;
2068
2069 /* Do emulation prevention and byte swapping on all the packets */
2070 /* of RFC or current partial or full Annex B NAL unit */
2071 {
2072 UWORD32 u4_buf_size;
2073
2074 /* clip the size before emulation prevention */
2075 u4_buf_size = (UWORD32) CLIP3(0, (WORD32) *pu4_bytes_left,
2076 (ps_nal_unit->i4_buf_sizes - i4_nal_header_len));
2077
2078 u4_buf_inc = isvcd_nal_byte_swap_emulation(
2079 (UWORD32 *) *ppu1_out_buf, &u4_output_bytes,
2080 ps_nal_unit->pu1_bufs + i4_nal_header_len, u4_buf_size,
2081 NUM_OF_ZERO_BYTES_BEFORE_START_CODE, &ps_nal_parse_ctxt->s_emulation_ctxt);
2082
2083 i4_nal_header_len = 0;
2084 u4_buf_inc = UP_ALIGN_8(u4_buf_inc);
2085 *ppu1_out_buf += u4_buf_inc;
2086 *pu4_bytes_left -= u4_buf_inc;
2087 ps_nal_buf->i4_buf_size += u4_output_bytes;
2088 }
2089 }
2090
2091 /*********************************************************************/
2092 /* UPDATE VARIABLES */
2093 /*********************************************************************/
2094 if(NAL_END == ps_nal_parse_ctxt->i4_find_nal_state)
2095 {
2096 if(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag)
2097 {
2098 /* This fucntions updates output nal ctxt - vcl nal structure*/
2099 /* and non vcl nal structure depending upon the current NAL */
2100 /* type. */
2101 /* This will only update parameters which are available at */
2102 /* end of NAL unit like nal unit's total size */
2103 isvcd_update_nal_ctxt(ps_nal_parse_ctxt, ps_vcl_nal, ps_non_vcl_nal);
2104
2105 UPDATE_NAL_BUF_PTR(ppu1_out_buf, ps_nal_prms->i4_derived_nal_type, pu4_bytes_left);
2106 }
2107
2108 /* If the prefix NAL unit is not immediatly followed by */
2109 /* a AVC NAL unit it shall be discarded and hence reset */
2110 /* is done */
2111 /* Also if prefix NAL unit is discarded then we should */
2112 /* not associate the prefix NAL unit with AVC NAL unit */
2113 /* and hence a reset is required */
2114 if((PREFIX_UNIT_NAL != ps_nal_prms->i4_nal_unit_type) ||
2115 (SVCD_TRUE == ps_nal_parse_ctxt->i4_discard_nal_flag))
2116 {
2117 isvcd_nal_buf_reset(&ps_nal_parse_ctxt->s_prefix_nal_buf);
2118 }
2119
2120 /* Reset the nal level tracking variables */
2121 isvcd_nal_reset_ctxt(ps_nal_parse_ctxt);
2122 }
2123
2124 /*------------- while loop ends here --------------------------------*/
2125 } while(SVCD_TRUE == i4_more_data_flag);
2126
2127 return (i4_pic_bound_status);
2128 }
2129
2130 /*****************************************************************************/
2131 /* */
2132 /* Function Name : isvcd_nal_parse_non_vcl_nal */
2133 /* */
2134 /* Description : None */
2135 /* */
2136 /* Inputs : pv_nal_parse_ctxt - bitstream extract ctxt */
2137 /* structure */
2138 /* pv_input_bitstream_ctxt - bitstream context */
2139 /* pv_out_non_vcl_nal - non vcl nal structure (output) */
2140 /* pu4_bytes_consumed - bytes consumed variable(output) */
2141 /* pi4_num_packets_consumed - packets consumed (output/RFC) */
2142 /* */
2143 /* Globals : None */
2144 /* */
2145 /* Processing : None */
2146 /* */
2147 /* Outputs : Updates bytes consumed variable, packets consumed, */
2148 /* output structures (non vcl nal) */
2149 /* */
2150 /* Returns : If vcl nal is found then VCL_NAL_FOUND_TRUE otherwise */
2151 /* VCL_NAL_FOUND_FALSE */
2152 /* */
2153 /* Issues : None */
2154 /* */
2155 /* Revision History: */
2156 /* DD MM YYYY Author(s) Changes */
2157 /* 06 09 2021 Vijay Draft */
2158 /* */
2159 /*****************************************************************************/
2160
isvcd_nal_parse_non_vcl_nal(void * pv_nal_parse_ctxt,UWORD8 * pu1_stream_buffer,void * pv_out_non_vcl_nal,UWORD32 * pu4_bytes_consumed,UWORD32 * pu4_num_bytes)2161 WORD32 isvcd_nal_parse_non_vcl_nal(void *pv_nal_parse_ctxt, UWORD8 *pu1_stream_buffer,
2162 void *pv_out_non_vcl_nal, UWORD32 *pu4_bytes_consumed,
2163 UWORD32 *pu4_num_bytes)
2164 {
2165 /*! - Search for the NAL boundary
2166 - If NAL boundary is not found and bytes consumed is lesser than
2167 minimum buffer size then break out of the loop
2168 - if it is start of NAL then read the NAL header
2169 - If it is a VCL NAL then return from this fucntion saying that
2170 VCL NAL found
2171 - NAL discard logic determines whther the current NAL has to be
2172 discarded or not
2173 - If NAL is not discarded then populate the vcl or non vcl output
2174 structures
2175 */
2176
2177 nal_parse_ctxt_t *ps_nal_parse_ctxt;
2178 non_vcl_nal_t *ps_non_vcl_nal;
2179 nal_unit_t *ps_nal_unit;
2180 WORD32 i4_nal_start_flag, i4_cur_pos, i4_status;
2181 WORD32 i4_nal_header_len, i4_more_data_flag;
2182 UWORD32 u4_bytes_consumed_temp = 0;
2183 UWORD8 **ppu1_out_buf;
2184 nal_prms_t *ps_nal_prms;
2185
2186 ps_nal_parse_ctxt = (nal_parse_ctxt_t *) pv_nal_parse_ctxt;
2187 ps_non_vcl_nal = (non_vcl_nal_t *) pv_out_non_vcl_nal;
2188 ps_nal_unit = (nal_unit_t *) ps_nal_parse_ctxt->pv_nal_unit;
2189 ps_nal_prms = &ps_nal_parse_ctxt->s_nal_prms;
2190
2191 /* Initialization */
2192 i4_cur_pos = 0;
2193 *pu4_bytes_consumed = 0;
2194 i4_nal_header_len = 0;
2195 i4_nal_start_flag = SVCD_FALSE;
2196 i4_more_data_flag = SVCD_TRUE;
2197 i4_status = PIC_BOUNDARY_FALSE;
2198
2199 /* reset the target layer update flag */
2200 ps_nal_parse_ctxt->i4_tgt_lyr_update = SVCD_FALSE;
2201 /*************************************************************************/
2202 /* SEARCHING FOR THE START OF BITSTREAM */
2203 /*************************************************************************/
2204
2205 /*-----------------------------------------------------------------------*/
2206 /* For Annex B based bitstreams the first start code has to decoded */
2207 /* The first start code can come after multiple process call also. This */
2208 /* has to be carefully handled */
2209 /*-----------------------------------------------------------------------*/
2210
2211 if(ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode &&
2212 SVCD_TRUE == ps_nal_parse_ctxt->i4_dec_frst_sc_flag)
2213 {
2214 WORD32 i4_status;
2215
2216 i4_status =
2217 isvcd_get_first_start_code(pu1_stream_buffer, pu4_bytes_consumed, pu4_num_bytes);
2218
2219 /*-------------------------------------------------------------------*/
2220 /* If start code found then proceed with bitstream extraction */
2221 /*-------------------------------------------------------------------*/
2222
2223 if(i4_status == SC_NOT_FOUND)
2224 {
2225 return (VCL_NAL_FOUND_FALSE);
2226 }
2227
2228 i4_cur_pos = *pu4_bytes_consumed;
2229 ps_nal_parse_ctxt->i4_dec_frst_sc_flag = SVCD_FALSE;
2230 }
2231
2232 /* If number of bytes left in the previous process call */
2233 /* is is greater or equal to number of bytes in input */
2234 /* buffer of the current process call then declare that */
2235 /* end of bitstream has occurred and consume the bytes */
2236 /* but do not decode */
2237 if(ps_nal_parse_ctxt->u4_bytes_left >= (UWORD32) *pu4_num_bytes)
2238 {
2239 ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
2240 *pu4_bytes_consumed = *pu4_num_bytes;
2241
2242 i4_status = isvcd_nal_parse_partial_signal_eos(ps_nal_parse_ctxt, NULL, ps_non_vcl_nal);
2243 return (i4_status);
2244 }
2245
2246 do
2247 {
2248 nal_buf_t *ps_nal_buf;
2249 UWORD32 *pu4_bytes_left;
2250
2251 /*********************************************************************/
2252 /* NAL BOUNDARY DETECTION */
2253 /*********************************************************************/
2254 /*-------------------------------------------------------------------*/
2255 /* Detect NAL boundary */
2256 /* After return, this NAL boundary detetction logic might be in */
2257 /* one of following states: */
2258 /* - NAL_START */
2259 /* - FIND_NAL_END */
2260 /* - NAL_END */
2261 /*-------------------------------------------------------------------*/
2262 if(ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode)
2263 {
2264 i4_nal_start_flag = isvcd_get_annex_b_nal_unit(
2265 pu1_stream_buffer, i4_cur_pos, *pu4_num_bytes,
2266 &ps_nal_parse_ctxt->i4_find_nal_state, &ps_nal_parse_ctxt->i4_zero_byte_cnt,
2267 &u4_bytes_consumed_temp, ps_nal_parse_ctxt->pv_nal_unit, &i4_more_data_flag);
2268
2269 i4_cur_pos += u4_bytes_consumed_temp;
2270 }
2271
2272 /* If current NAL unit is start of new NAL unit then parse the NAL
2273 header. If the current NAL unit type is VCL NAL then return from
2274 this function. otherwise apply NAL discard logic and discard the
2275 NAL if discard NAL flag is true */
2276
2277 if(SVCD_TRUE == i4_nal_start_flag)
2278 {
2279 UWORD32 u4_err_code;
2280 WORD32 i4_sps_pps_corrupt_status;
2281
2282 /* Get the NAL prms. This involves the following things*/
2283 /* 1. Decode the NAL header */
2284 /* 2. Set the discard flag */
2285 /* 3. Decode the slice header if needed */
2286 isvcd_get_nal_prms(ps_nal_unit->pu1_bufs, ps_nal_unit->i4_buf_sizes, ps_nal_prms,
2287 &ps_nal_parse_ctxt->s_prefix_nal_prms,
2288 &ps_nal_parse_ctxt->s_prefix_nal_buf, &u4_err_code,
2289 &i4_sps_pps_corrupt_status, &ps_nal_parse_ctxt->i4_discard_nal_flag,
2290 ps_nal_parse_ctxt);
2291 /* If the error code returned by the "picture boundary" */
2292 /* detetction is */
2293 /* 1. Insufficient bitstream size: then store the bytes */
2294 /* left and break out of the loop */
2295 /* 2. Corrupted slice: then discard the slice */
2296 if((NAL_INSUFFICIENT_DATA == (WORD32) u4_err_code) &&
2297 (NAL_END != ps_nal_parse_ctxt->i4_find_nal_state))
2298 {
2299 ps_nal_parse_ctxt->u4_bytes_left = *pu4_num_bytes - *pu4_bytes_consumed;
2300
2301 /* Reset the NAL level tracking variables */
2302 isvcd_nal_reset_ctxt(ps_nal_parse_ctxt);
2303 break;
2304 }
2305 else if(0 != u4_err_code)
2306 {
2307 ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
2308 }
2309
2310 /* Populate other paramters based on the nal prms */
2311 ps_nal_parse_ctxt->i4_nal_type = ps_nal_prms->i4_derived_nal_type;
2312 i4_nal_header_len = ps_nal_prms->i4_nal_header_len;
2313
2314 /* If derived NAL unit is VCL_NAL then return from this function */
2315 if(VCL_NAL == ps_nal_prms->i4_derived_nal_type &&
2316 PREFIX_UNIT_NAL != ps_nal_prms->i4_nal_unit_type)
2317 {
2318 isvcd_pic_reset_ctxt(ps_nal_parse_ctxt);
2319
2320 return (VCL_NAL_FOUND_TRUE);
2321 }
2322
2323 /* Set the active NAL buffer structure and initialize */
2324 /* the nal buffer structure */
2325 isvcd_get_nal_buf(ps_nal_parse_ctxt, &ps_nal_buf);
2326
2327 ps_nal_parse_ctxt->ps_nal_buf = ps_nal_buf;
2328 }
2329
2330 /* Update the bytes consumed variable */
2331
2332 *pu4_bytes_consumed += u4_bytes_consumed_temp;
2333
2334 ps_nal_buf = ps_nal_parse_ctxt->ps_nal_buf;
2335 if(VCL_NAL == ps_nal_parse_ctxt->i4_nal_type)
2336 {
2337 ppu1_out_buf = &ps_nal_parse_ctxt->pu1_vcl_nal_buf;
2338 pu4_bytes_left = &ps_nal_parse_ctxt->u4_bytes_left_vcl;
2339 if(*pu4_bytes_left < (MAX_VCL_NAL_BUFF_SIZE * 0.05))
2340 {
2341 return (VCL_NAL_FOUND_FALSE);
2342 }
2343 }
2344 else
2345 {
2346 ppu1_out_buf = &ps_nal_parse_ctxt->pu1_non_vcl_nal_buf;
2347 pu4_bytes_left = &ps_nal_parse_ctxt->u4_bytes_left_non_vcl;
2348 if(*pu4_bytes_left < (MAX_NON_VCL_NAL_BUFF_SIZE * 0.05))
2349 {
2350 return (VCL_NAL_FOUND_FALSE);
2351 }
2352 }
2353
2354 /* if 0 bytes left then discard the current NAL */
2355 if(0 >= (WORD32) *pu4_bytes_left)
2356 {
2357 ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
2358 }
2359
2360 /* If NAL is not discarded then :
2361 1) Perform emulation prevention and byte swapping on the RBSP data
2362 2) Update the NAL unit ctxt:
2363 a) If VCL NAL then update DQID list
2364 b) If NON VCL NAL then update the non vcl output structure */
2365
2366 if(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag)
2367 {
2368 UWORD32 u4_output_bytes, u4_buf_inc;
2369
2370 {
2371 UWORD32 u4_buf_size;
2372
2373 /* clip the size before emulation prevention */
2374 u4_buf_size = (UWORD32) CLIP3(0, (WORD32) *pu4_bytes_left,
2375 (ps_nal_unit->i4_buf_sizes - i4_nal_header_len));
2376
2377 u4_buf_inc = isvcd_nal_byte_swap_emulation(
2378 (UWORD32 *) *ppu1_out_buf, &u4_output_bytes,
2379 ps_nal_unit->pu1_bufs + i4_nal_header_len, u4_buf_size,
2380 NUM_OF_ZERO_BYTES_BEFORE_START_CODE, &ps_nal_parse_ctxt->s_emulation_ctxt);
2381 i4_nal_header_len = 0;
2382
2383 u4_buf_inc = UP_ALIGN_8(u4_buf_inc);
2384 *ppu1_out_buf += u4_buf_inc;
2385 *pu4_bytes_left -= u4_buf_inc;
2386 ps_nal_buf->i4_buf_size += u4_output_bytes;
2387 }
2388 }
2389
2390 /*********************************************************************/
2391 /* UPDATE VARIABLES */
2392 /*********************************************************************/
2393
2394 if(NAL_END == ps_nal_parse_ctxt->i4_find_nal_state)
2395 {
2396 /*---------------------------------------------------------------*/
2397 /* - Update the total bits in the NAL. While doing so bits */
2398 /* calculated so far should be converted to SODB length */
2399 /*---------------------------------------------------------------*/
2400 if(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag)
2401 {
2402 isvcd_update_nal_ctxt(ps_nal_parse_ctxt, NULL, ps_non_vcl_nal);
2403
2404 UPDATE_NAL_BUF_PTR(ppu1_out_buf, ps_nal_prms->i4_derived_nal_type, pu4_bytes_left);
2405 }
2406
2407 /* If the prefix NAL unit is not immediatly followed by */
2408 /* a AVC NAL unit it shall be discarded and hence reset */
2409 /* is done */
2410 /* Also if prefix NAL unit is discarded then we should */
2411 /* not associate the prefix NAL unit with AVC NAL unit */
2412 /* and hence a reset is required */
2413 if((PREFIX_UNIT_NAL != ps_nal_prms->i4_nal_unit_type) ||
2414 (SVCD_TRUE == ps_nal_parse_ctxt->i4_discard_nal_flag))
2415 {
2416 isvcd_nal_buf_reset(&ps_nal_parse_ctxt->s_prefix_nal_buf);
2417 }
2418
2419 /* Reset NAL level tracking variables */
2420 isvcd_nal_reset_ctxt(ps_nal_parse_ctxt);
2421 }
2422
2423 i4_nal_header_len = 0;
2424 /*------------- while loop ends here --------------------------------*/
2425 } while(SVCD_TRUE == i4_more_data_flag);
2426
2427 if(i4_more_data_flag == 0)
2428 {
2429 isvcd_pic_reset_ctxt(ps_nal_parse_ctxt);
2430 return (VCL_NAL_FOUND_TRUE);
2431 }
2432
2433 return (VCL_NAL_FOUND_FALSE);
2434 }