blob: cc4a27fe297a196bd86ded0e1d13649660e0eca9 [file] [log] [blame]
Harish Mahendrakar0d8951c2014-05-16 10:31:13 -07001/******************************************************************************
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*/
96WORD32 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++;
Naveen Kumar P4b200182017-05-25 15:30:59 +0530117 if((ofst < (bytes_remaining - 1)) &&
118 (pu1_buf[ofst + 1] == START_CODE_PREFIX_BYTE) &&
Harish Mahendrakar0d8951c2014-05-16 10:31:13 -0700119 (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 }
Naveen Kumar P4b200182017-05-25 15:30:59 +0530127 if((0 == start_code_found) && (ofst < bytes_remaining))
Harish Mahendrakar0d8951c2014-05-16 10:31:13 -0700128 {
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*/
181IHEVCD_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
Naveen Kumar P4b200182017-05-25 15:30:59 +0530235 if((0 == start_code_found) && (src_cnt < bytes_remaining))
Harish Mahendrakar0d8951c2014-05-16 10:31:13 -0700236 {
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*/
289IHEVCD_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*/
331IHEVCD_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 :
Naveen Kumar Ponnusamy221aacc2014-10-28 11:23:59 +0530362 ps_codec->i4_rasl_output_flag = (0 != ps_codec->i4_cra_as_first_pic) ? 0 : 1;
Harish Mahendrakar0d8951c2014-05-16 10:31:13 -0700363 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;
Naveen Kumar Ponnusamy221aacc2014-10-28 11:23:59 +0530397 ps_codec->i4_cra_as_first_pic = 0;
Harish Mahendrakar0d8951c2014-05-16 10:31:13 -0700398
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 }
Naveen Kumar Ponnusamy221aacc2014-10-28 11:23:59 +0530430 ps_codec->i4_error_code = ret;
Harish Mahendrakar0d8951c2014-05-16 10:31:13 -0700431
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 }
Naveen Kumar Ponnusamy221aacc2014-10-28 11:23:59 +0530450 ps_codec->i4_error_code = ret;
Harish Mahendrakar0d8951c2014-05-16 10:31:13 -0700451 DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
452 break;
453
Naveen Kumar Ponnusamy221aacc2014-10-28 11:23:59 +0530454 case NAL_EOS :
455 ps_codec->i4_cra_as_first_pic = 1;
456 break;
457
Harish Mahendrakar0d8951c2014-05-16 10:31:13 -0700458 default:
459 DEBUG_PRINT_NAL_INFO(ps_codec, s_nal.i1_nal_unit_type);
460 break;
461 }
462
463 return ret;
464}
465