1 /******************************************************************************
2 *
3 * Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
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 /**
19 *******************************************************************************
20 * @file
21 * ihevcd_nal.c
22 *
23 * @brief
24 * Contains functions for NAL level such as search start code etc
25 *
26 * @author
27 * Harish
28 *
29 * @par List of Functions:
30 *
31 * @remarks
32 * None
33 *
34 *******************************************************************************
35 */
36 /*****************************************************************************/
37 /* File Includes */
38 /*****************************************************************************/
39 #include <stdio.h>
40 #include <stddef.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <assert.h>
44
45 #include "ihevc_typedefs.h"
46 #include "iv.h"
47 #include "ivd.h"
48 #include "ihevcd_cxa.h"
49
50 #include "ihevc_defs.h"
51 #include "ihevc_debug.h"
52 #include "ihevc_structs.h"
53 #include "ihevc_macros.h"
54 #include "ihevc_platform_macros.h"
55 #include "ihevc_cabac_tables.h"
56
57
58 #include "ihevcd_defs.h"
59 #include "ihevcd_function_selector.h"
60 #include "ihevcd_structs.h"
61 #include "ihevcd_error.h"
62 #include "ihevcd_nal.h"
63 #include "ihevcd_bitstream.h"
64 #include "ihevcd_parse_headers.h"
65 #include "ihevcd_parse_slice.h"
66 #include "ihevcd_debug.h"
67 /*****************************************************************************/
68 /* Function Prototypes */
69 /*****************************************************************************/
70
71 /**
72 *******************************************************************************
73 *
74 * @brief
75 * Search start code from the given buffer pointer
76 *
77 * @par Description:
78 * Search for start code Return the offset of start code if start code is
79 * found If no start code is found till end of given bitstream then treat
80 * it as invalid NAL and return end of buffer as offset
81 *
82 * @param[in] pu1_buf
83 * Pointer to bitstream
84 *
85 * @param[in] bytes_remaining
86 * Number of bytes remaining in the buffer
87 *
88 * @returns Offset to the first byte in NAL after start code
89 *
90 * @remarks
91 * Incomplete start code at the end of input bitstream is not handled. This
92 * has to be taken care outside this func
93 *
94 *******************************************************************************
95 */
ihevcd_nal_search_start_code(UWORD8 * pu1_buf,WORD32 bytes_remaining)96 WORD32 ihevcd_nal_search_start_code(UWORD8 *pu1_buf, WORD32 bytes_remaining)
97 {
98 WORD32 ofst;
99
100 WORD32 zero_byte_cnt;
101 WORD32 start_code_found;
102
103 ofst = -1;
104
105 zero_byte_cnt = 0;
106 start_code_found = 0;
107 while(ofst < (bytes_remaining - 1))
108 {
109 ofst++;
110 if(pu1_buf[ofst] != 0)
111 {
112 zero_byte_cnt = 0;
113 continue;
114 }
115
116 zero_byte_cnt++;
117 if((ofst < (bytes_remaining - 1)) &&
118 (pu1_buf[ofst + 1] == START_CODE_PREFIX_BYTE) &&
119 (zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE))
120 {
121 /* Found the start code */
122 ofst++;
123 start_code_found = 1;
124 break;
125 }
126 }
127 if((0 == start_code_found) && (ofst < bytes_remaining))
128 {
129 if((START_CODE_PREFIX_BYTE == pu1_buf[ofst]) &&
130 (zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE))
131 {
132 /* Found a start code at the end*/
133 ofst++;
134 }
135 }
136 /* Since ofst started at -1, increment it by 1 */
137 ofst++;
138
139 return ofst;
140 }
141
142 /**
143 *******************************************************************************
144 *
145 * @brief
146 * Remove emulation prevention byte present in the bitstream till next start
147 * code is found. Emulation prevention byte removed data is stored in a
148 * different buffer
149 *
150 * @par Description:
151 * Assumption is first start code is already found and pu1_buf is pointing
152 * to a byte after the start code Search for Next NAL's start code Return
153 * if start code is found Remove any emulation prevention byte present Copy
154 * data to new buffer If no start code is found, then treat complete buffer
155 * as one nal.
156 *
157 * @param[in] pu1_src
158 * Pointer to bitstream (excludes the initial the start code)
159 *
160 * @param[in] pu1_dst
161 * Pointer to destination buffer
162 *
163 * @param[in] bytes_remaining
164 * Number of bytes remaining
165 *
166 * @param[out] pi4_nal_len
167 * NAL length (length of bitstream parsed)
168 *
169 * @param[out] pi4_dst_len
170 * Destination bitstream size (length of bitstream parsed with emulation bytes
171 * removed)
172 *
173 * @returns Error code from IHEVCD_ERROR_T
174 *
175 * @remarks
176 * Incomplete start code at the end of input bitstream is not handled. This
177 * has to be taken care outside this func
178 *
179 *******************************************************************************
180 */
ihevcd_nal_remv_emuln_bytes(UWORD8 * pu1_src,UWORD8 * pu1_dst,WORD32 bytes_remaining,WORD32 * pi4_nal_len,WORD32 * pi4_dst_len)181 IHEVCD_ERROR_T ihevcd_nal_remv_emuln_bytes(UWORD8 *pu1_src,
182 UWORD8 *pu1_dst,
183 WORD32 bytes_remaining,
184 WORD32 *pi4_nal_len,
185 WORD32 *pi4_dst_len)
186 {
187 WORD32 src_cnt;
188 WORD32 dst_cnt;
189 WORD32 zero_byte_cnt;
190 WORD32 start_code_found;
191 UWORD8 u1_src;
192 IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
193
194 src_cnt = 0;
195 dst_cnt = 0;
196 zero_byte_cnt = 0;
197 start_code_found = 0;
198 while(src_cnt < (bytes_remaining - 1))
199 {
200 u1_src = pu1_src[src_cnt++];
201
202 pu1_dst[dst_cnt++] = u1_src;
203 if(u1_src != 0)
204 {
205 zero_byte_cnt = 0;
206 continue;
207 }
208
209 zero_byte_cnt++;
210 if(zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE)
211 {
212 u1_src = pu1_src[src_cnt];
213 if(START_CODE_PREFIX_BYTE == u1_src)
214 {
215 /* Found the start code */
216 src_cnt -= zero_byte_cnt;
217 dst_cnt -= zero_byte_cnt;
218 start_code_found = 1;
219 break;
220 }
221 else if(EMULATION_PREVENT_BYTE == u1_src)
222 {
223 /* Found the emulation prevention byte */
224 src_cnt++;
225 zero_byte_cnt = 0;
226
227 /* Decrement dst_cnt so that the next byte overwrites
228 * the emulation prevention byte already copied to dst above
229 */
230 }
231 }
232
233 }
234
235 if((0 == start_code_found) && (src_cnt < bytes_remaining))
236 {
237 u1_src = pu1_src[src_cnt++];
238 if(zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE)
239 {
240
241 if(START_CODE_PREFIX_BYTE == u1_src)
242 {
243 /* Found a start code at the end*/
244 src_cnt -= zero_byte_cnt;
245 }
246 else if(EMULATION_PREVENT_BYTE == u1_src)
247 {
248 /* Found the emulation prevention byte at the end*/
249 src_cnt++;
250 /* Decrement dst_cnt so that the next byte overwrites
251 * the emulation prevention byte already copied to dst above
252 */
253 dst_cnt--;
254 }
255 }
256 else
257 {
258 pu1_dst[dst_cnt++] = u1_src;
259 }
260
261
262 }
263 *pi4_nal_len = src_cnt;
264 *pi4_dst_len = dst_cnt;
265 return ret;
266 }
267 /**
268 *******************************************************************************
269 *
270 * @brief
271 * Decode given NAL unit's header
272 *
273 * @par Description:
274 * Call NAL unit's header decode Section: 7.3.1.2
275 *
276 * @param[in] ps_bitstrm
277 * Pointer to bitstream context
278 *
279 * @param[out] ps_nal
280 * Pointer to NAL header
281 *
282 * @returns Error code from IHEVCD_ERROR_T
283 *
284 * @remarks
285 *
286 *
287 *******************************************************************************
288 */
ihevcd_nal_unit_header(bitstrm_t * ps_bitstrm,nal_header_t * ps_nal)289 IHEVCD_ERROR_T ihevcd_nal_unit_header(bitstrm_t *ps_bitstrm, nal_header_t *ps_nal)
290 {
291 WORD32 unused;
292 IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
293 UNUSED(unused);
294 /* Syntax : forbidden_zero_bit */
295 unused = ihevcd_bits_get(ps_bitstrm, 1);
296
297 /* Syntax : nal_unit_type */
298 ps_nal->i1_nal_unit_type = ihevcd_bits_get(ps_bitstrm, 6);
299
300 /* Syntax : nuh_reserved_zero_6bits */
301 unused = ihevcd_bits_get(ps_bitstrm, 6);
302
303 /* Syntax : nuh_temporal_id_plus1 */
304 ps_nal->i1_nuh_temporal_id = ihevcd_bits_get(ps_bitstrm, 3) - 1;
305
306 return ret;
307
308 }
309
310 /**
311 *******************************************************************************
312 *
313 * @brief
314 * Decode given NAL
315 *
316 * @par Description:
317 * Based on the NAL type call appropriate decode function Section: 7.3.1.1
318 *
319 *
320 * @param[in,out] ps_codec
321 * Pointer to codec context (Functions called within will modify contents of
322 * ps_codec)
323 *
324 * @returns Error code from IHEVCD_ERROR_T
325 *
326 * @remarks
327 *
328 *
329 *******************************************************************************
330 */
ihevcd_nal_unit(codec_t * ps_codec)331 IHEVCD_ERROR_T ihevcd_nal_unit(codec_t *ps_codec)
332 {
333 IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
334
335 /* NAL Header */
336 nal_header_t s_nal;
337
338 ret = ihevcd_nal_unit_header(&ps_codec->s_parse.s_bitstrm, &s_nal);
339 RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
340
341 if(ps_codec->i4_slice_error)
342 s_nal.i1_nal_unit_type = ps_codec->s_parse.ps_slice_hdr->i1_nal_unit_type;
343
344 /* Setting RASL Output flag */
345 switch(s_nal.i1_nal_unit_type)
346 {
347 case NAL_BLA_W_LP :
348 case NAL_BLA_W_DLP :
349 case NAL_BLA_N_LP :
350 ps_codec->i4_rasl_output_flag = 0;
351 break;
352
353 //TODO: After IDR, there is no case of open GOP
354 //To be fixed appropriately by ignoring RASL only if the
355 // required references are not found
356 case NAL_IDR_W_LP :
357 case NAL_IDR_N_LP :
358 ps_codec->i4_rasl_output_flag = 1;
359 break;
360
361 case NAL_CRA :
362 ps_codec->i4_rasl_output_flag = (0 != ps_codec->i4_cra_as_first_pic) ? 0 : 1;
363 break;
364
365 default:
366 break;
367 }
368
369 switch(s_nal.i1_nal_unit_type)
370 {
371 case NAL_BLA_W_LP :
372 case NAL_BLA_W_DLP :
373 case NAL_BLA_N_LP :
374 case NAL_IDR_W_LP :
375 case NAL_IDR_N_LP :
376 case NAL_CRA :
377 case NAL_TRAIL_N :
378 case NAL_TRAIL_R :
379 case NAL_TSA_N :
380 case NAL_TSA_R :
381 case NAL_STSA_N :
382 case NAL_STSA_R :
383 case NAL_RADL_N :
384 case NAL_RADL_R :
385 case NAL_RASL_N :
386 case NAL_RASL_R :
387 if(ps_codec->i4_header_mode)
388 return IHEVCD_SLICE_IN_HEADER_MODE;
389
390 if((0 == ps_codec->i4_sps_done) ||
391 (0 == ps_codec->i4_pps_done))
392 {
393 return IHEVCD_INVALID_HEADER;
394 }
395
396 ps_codec->i4_header_in_slice_mode = 0;
397 ps_codec->i4_cra_as_first_pic = 0;
398
399 ret = ihevcd_parse_slice_header(ps_codec, &s_nal);
400 DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
401 if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
402 {
403 if((s_nal.i1_nal_unit_type != NAL_RASL_N && s_nal.i1_nal_unit_type != NAL_RASL_R) ||
404 ps_codec->i4_rasl_output_flag ||
405 ps_codec->i4_slice_error)
406 ret = ihevcd_parse_slice_data(ps_codec);
407 }
408 break;
409
410 case NAL_VPS :
411 // ret = ihevcd_parse_vps(ps_codec);
412 DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
413 break;
414
415 case NAL_SPS :
416 if(0 == ps_codec->i4_header_mode)
417 {
418 ps_codec->i4_header_in_slice_mode = 1;
419 if(ps_codec->i4_sps_done &&
420 ps_codec->i4_pic_present)
421 break;
422 }
423
424 ret = ihevcd_parse_sps(ps_codec);
425 if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
426 {
427 sps_t *ps_sps = ps_codec->ps_sps_base + MAX_SPS_CNT - 1;
428 ihevcd_copy_sps(ps_codec, ps_sps->i1_sps_id, MAX_SPS_CNT - 1);
429 }
430 ps_codec->i4_error_code = ret;
431
432 DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
433 break;
434
435 case NAL_PPS :
436 if(0 == ps_codec->i4_header_mode)
437 {
438 ps_codec->i4_header_in_slice_mode = 1;
439 if(ps_codec->i4_pps_done &&
440 ps_codec->i4_pic_present)
441 break;
442 }
443
444 ret = ihevcd_parse_pps(ps_codec);
445 if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
446 {
447 pps_t *ps_pps = ps_codec->ps_pps_base + MAX_PPS_CNT - 1;
448 ihevcd_copy_pps(ps_codec, ps_pps->i1_pps_id, MAX_PPS_CNT - 1);
449 }
450 ps_codec->i4_error_code = ret;
451 DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
452 break;
453
454 case NAL_EOS :
455 ps_codec->i4_cra_as_first_pic = 1;
456 break;
457
458 default:
459 DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
460 break;
461 }
462
463 return ret;
464 }
465
466