• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = (WORD32)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_PREFIX_SEI:
455         case NAL_SUFFIX_SEI:
456             if(IVD_DECODE_HEADER == ps_codec->i4_header_mode)
457             {
458                 return IHEVCD_SLICE_IN_HEADER_MODE;
459             }
460 
461             ret = ihevcd_parse_sei(ps_codec, &s_nal);
462             break;
463 
464         case NAL_EOS        :
465             ps_codec->i4_cra_as_first_pic = 1;
466             break;
467 
468         default:
469             DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
470             break;
471     }
472 
473     return ret;
474 }
475 
476