• 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((pu1_buf[ofst + 1] == START_CODE_PREFIX_BYTE) &&
118            (zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE))
119         {
120             /* Found the start code */
121             ofst++;
122             start_code_found = 1;
123             break;
124         }
125     }
126     if(0 == start_code_found)
127     {
128         if((START_CODE_PREFIX_BYTE == pu1_buf[ofst]) &&
129            (zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE))
130         {
131             /* Found a start code at the end*/
132             ofst++;
133         }
134     }
135     /* Since ofst started at -1, increment it by 1 */
136     ofst++;
137 
138     return ofst;
139 }
140 
141 /**
142 *******************************************************************************
143 *
144 * @brief
145 *  Remove emulation prevention byte present in the bitstream till next start
146 * code is found. Emulation prevention byte  removed data is stored in a
147 * different buffer
148 *
149 * @par Description:
150 *  Assumption is first start code is already found and  pu1_buf is pointing
151 * to a byte after the start code  Search for Next NAL's start code  Return
152 * if start code is found  Remove any emulation prevention byte present  Copy
153 * data to new buffer  If no start code is found, then treat complete buffer
154 * as  one nal.
155 *
156 * @param[in] pu1_src
157 *  Pointer to bitstream (excludes the initial the start code)
158 *
159 * @param[in] pu1_dst
160 *  Pointer to destination buffer
161 *
162 * @param[in] bytes_remaining
163 *  Number of bytes remaining
164 *
165 * @param[out] pi4_nal_len
166 *  NAL length (length of bitstream parsed)
167 *
168 * @param[out] pi4_dst_len
169 *  Destination bitstream size (length of bitstream parsed with emulation bytes
170 * removed)
171 *
172 * @returns Error code from IHEVCD_ERROR_T
173 *
174 * @remarks
175 *  Incomplete start code at the end of input bitstream is  not handled. This
176 * has to be taken care outside this func
177 *
178 *******************************************************************************
179 */
ihevcd_nal_remv_emuln_bytes(UWORD8 * pu1_src,UWORD8 * pu1_dst,WORD32 bytes_remaining,WORD32 * pi4_nal_len,WORD32 * pi4_dst_len)180 IHEVCD_ERROR_T ihevcd_nal_remv_emuln_bytes(UWORD8 *pu1_src,
181                                            UWORD8 *pu1_dst,
182                                            WORD32 bytes_remaining,
183                                            WORD32 *pi4_nal_len,
184                                            WORD32 *pi4_dst_len)
185 {
186     WORD32 src_cnt;
187     WORD32 dst_cnt;
188     WORD32 zero_byte_cnt;
189     WORD32 start_code_found;
190     UWORD8 u1_src;
191     IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
192 
193     src_cnt = 0;
194     dst_cnt = 0;
195     zero_byte_cnt = 0;
196     start_code_found = 0;
197     while(src_cnt < (bytes_remaining - 1))
198     {
199         u1_src = pu1_src[src_cnt++];
200 
201         pu1_dst[dst_cnt++] = u1_src;
202         if(u1_src != 0)
203         {
204             zero_byte_cnt = 0;
205             continue;
206         }
207 
208         zero_byte_cnt++;
209         if(zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE)
210         {
211             u1_src = pu1_src[src_cnt];
212             if(START_CODE_PREFIX_BYTE == u1_src)
213             {
214                 /* Found the start code */
215                 src_cnt -= zero_byte_cnt;
216                 dst_cnt -= zero_byte_cnt;
217                 start_code_found = 1;
218                 break;
219             }
220             else if(EMULATION_PREVENT_BYTE == u1_src)
221             {
222                 /* Found the emulation prevention byte */
223                 src_cnt++;
224                 zero_byte_cnt = 0;
225 
226                 /* Decrement dst_cnt so that the next byte overwrites
227                  * the emulation prevention byte already copied to dst above
228                  */
229             }
230         }
231 
232     }
233 
234     if(0 == start_code_found)
235     {
236         u1_src = pu1_src[src_cnt++];
237         if(zero_byte_cnt >= NUM_ZEROS_BEFORE_START_CODE)
238         {
239 
240             if(START_CODE_PREFIX_BYTE == u1_src)
241             {
242                 /* Found a start code at the end*/
243                 src_cnt -= zero_byte_cnt;
244             }
245             else if(EMULATION_PREVENT_BYTE == u1_src)
246             {
247                 /* Found the emulation prevention byte at the end*/
248                 src_cnt++;
249                 /* Decrement dst_cnt so that the next byte overwrites
250                  * the emulation prevention byte already copied to dst above
251                  */
252                 dst_cnt--;
253             }
254         }
255         else
256         {
257             pu1_dst[dst_cnt++] = u1_src;
258         }
259 
260 
261     }
262     *pi4_nal_len = src_cnt;
263     *pi4_dst_len = dst_cnt;
264     return ret;
265 }
266 /**
267 *******************************************************************************
268 *
269 * @brief
270 *  Decode given NAL unit's header
271 *
272 * @par Description:
273 *  Call NAL unit's header decode  Section: 7.3.1.2
274 *
275 * @param[in] ps_bitstrm
276 *  Pointer to bitstream context
277 *
278 * @param[out] ps_nal
279 *  Pointer to NAL header
280 *
281 * @returns Error code from IHEVCD_ERROR_T
282 *
283 * @remarks
284 *
285 *
286 *******************************************************************************
287 */
ihevcd_nal_unit_header(bitstrm_t * ps_bitstrm,nal_header_t * ps_nal)288 IHEVCD_ERROR_T ihevcd_nal_unit_header(bitstrm_t *ps_bitstrm, nal_header_t *ps_nal)
289 {
290     WORD32 unused;
291     IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
292     UNUSED(unused);
293     /* Syntax : forbidden_zero_bit */
294     unused = ihevcd_bits_get(ps_bitstrm, 1);
295 
296     /* Syntax : nal_unit_type */
297     ps_nal->i1_nal_unit_type = ihevcd_bits_get(ps_bitstrm, 6);
298 
299     /* Syntax : nuh_reserved_zero_6bits */
300     unused = ihevcd_bits_get(ps_bitstrm, 6);
301 
302     /* Syntax : nuh_temporal_id_plus1 */
303     ps_nal->i1_nuh_temporal_id = ihevcd_bits_get(ps_bitstrm, 3) - 1;
304 
305     return ret;
306 
307 }
308 
309 /**
310 *******************************************************************************
311 *
312 * @brief
313 *  Decode given NAL
314 *
315 * @par Description:
316 *  Based on the NAL type call appropriate decode function  Section: 7.3.1.1
317 *
318 *
319 * @param[in,out] ps_codec
320 *  Pointer to codec context (Functions called within will modify contents of
321 * ps_codec)
322 *
323 * @returns Error code from IHEVCD_ERROR_T
324 *
325 * @remarks
326 *
327 *
328 *******************************************************************************
329 */
ihevcd_nal_unit(codec_t * ps_codec)330 IHEVCD_ERROR_T ihevcd_nal_unit(codec_t *ps_codec)
331 {
332     IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
333 
334     /* NAL Header */
335     nal_header_t s_nal;
336 
337     ret = ihevcd_nal_unit_header(&ps_codec->s_parse.s_bitstrm, &s_nal);
338     RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
339 
340     if(ps_codec->i4_slice_error)
341         s_nal.i1_nal_unit_type = ps_codec->s_parse.ps_slice_hdr->i1_nal_unit_type;
342 
343     /* Setting RASL Output flag */
344     switch(s_nal.i1_nal_unit_type)
345     {
346         case NAL_BLA_W_LP    :
347         case NAL_BLA_W_DLP   :
348         case NAL_BLA_N_LP    :
349             ps_codec->i4_rasl_output_flag = 0;
350             break;
351 
352         //TODO: After IDR, there is no case of open GOP
353         //To be fixed appropriately by ignoring RASL only if the
354         // required references are not found
355         case NAL_IDR_W_LP    :
356         case NAL_IDR_N_LP    :
357             ps_codec->i4_rasl_output_flag = 1;
358             break;
359 
360         case NAL_CRA         :
361             ps_codec->i4_rasl_output_flag = (0 != ps_codec->i4_cra_as_first_pic) ? 0 : 1;
362             break;
363 
364         default:
365             break;
366     }
367 
368     switch(s_nal.i1_nal_unit_type)
369     {
370         case NAL_BLA_W_LP    :
371         case NAL_BLA_W_DLP   :
372         case NAL_BLA_N_LP    :
373         case NAL_IDR_W_LP    :
374         case NAL_IDR_N_LP    :
375         case NAL_CRA         :
376         case NAL_TRAIL_N     :
377         case NAL_TRAIL_R     :
378         case NAL_TSA_N       :
379         case NAL_TSA_R       :
380         case NAL_STSA_N      :
381         case NAL_STSA_R      :
382         case NAL_RADL_N      :
383         case NAL_RADL_R      :
384         case NAL_RASL_N      :
385         case NAL_RASL_R      :
386             if(ps_codec->i4_header_mode)
387                 return IHEVCD_SLICE_IN_HEADER_MODE;
388 
389             if((0 == ps_codec->i4_sps_done) ||
390                             (0 == ps_codec->i4_pps_done))
391             {
392                 return IHEVCD_INVALID_HEADER;
393             }
394 
395             ps_codec->i4_header_in_slice_mode = 0;
396             ps_codec->i4_cra_as_first_pic = 0;
397 
398             ret = ihevcd_parse_slice_header(ps_codec, &s_nal);
399             DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
400             if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
401             {
402                 if((s_nal.i1_nal_unit_type != NAL_RASL_N && s_nal.i1_nal_unit_type != NAL_RASL_R) ||
403                                 ps_codec->i4_rasl_output_flag ||
404                                 ps_codec->i4_slice_error)
405                     ret = ihevcd_parse_slice_data(ps_codec);
406             }
407             break;
408 
409         case NAL_VPS        :
410             // ret = ihevcd_parse_vps(ps_codec);
411             DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
412             break;
413 
414         case NAL_SPS        :
415             if(0 == ps_codec->i4_header_mode)
416             {
417                 ps_codec->i4_header_in_slice_mode = 1;
418                 if(ps_codec->i4_sps_done &&
419                                 ps_codec->i4_pic_present)
420                     break;
421             }
422 
423             ret = ihevcd_parse_sps(ps_codec);
424             if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
425             {
426                 sps_t *ps_sps = ps_codec->ps_sps_base + MAX_SPS_CNT - 1;
427                 ihevcd_copy_sps(ps_codec, ps_sps->i1_sps_id, MAX_SPS_CNT - 1);
428             }
429             ps_codec->i4_error_code = ret;
430 
431             DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
432             break;
433 
434         case NAL_PPS        :
435             if(0 == ps_codec->i4_header_mode)
436             {
437                 ps_codec->i4_header_in_slice_mode = 1;
438                 if(ps_codec->i4_pps_done &&
439                                 ps_codec->i4_pic_present)
440                     break;
441             }
442 
443             ret = ihevcd_parse_pps(ps_codec);
444             if(ret == (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
445             {
446                 pps_t *ps_pps = ps_codec->ps_pps_base + MAX_PPS_CNT - 1;
447                 ihevcd_copy_pps(ps_codec, ps_pps->i1_pps_id, MAX_PPS_CNT - 1);
448             }
449             ps_codec->i4_error_code = ret;
450             DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
451             break;
452 
453         case NAL_EOS        :
454             ps_codec->i4_cra_as_first_pic = 1;
455             break;
456 
457         default:
458             DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
459             break;
460     }
461 
462     return ret;
463 }
464 
465