1/******************************************************************************
2 *
3 * Copyright (C) 2015 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/*                                                                           */
23/*  File Name         : ih264d_sei.c                                                */
24/*                                                                           */
25/*  Description       : This file contains routines to parse SEI NAL's       */
26/*                                                                           */
27/*  List of Functions : <List the functions defined in this file>            */
28/*                                                                           */
29/*  Issues / Problems : None                                                 */
30/*                                                                           */
31/*  Revision History  :                                                      */
32/*                                                                           */
33/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
34/*         25 05 2005   NS              Draft                                */
35/*                                                                           */
36/*****************************************************************************/
37
38#include "ih264_typedefs.h"
39#include "ih264_macros.h"
40#include "ih264_platform_macros.h"
41#include "ih264d_sei.h"
42#include "ih264d_bitstrm.h"
43#include "ih264d_structs.h"
44#include "ih264d_error_handler.h"
45#include "ih264d_vui.h"
46#include "ih264d_parse_cavlc.h"
47#include "ih264d_defs.h"
48
49/*****************************************************************************/
50/*                                                                           */
51/*  Function Name : ih264d_parse_buffering_period                                   */
52/*                                                                           */
53/*  Description   : This function parses SEI message buffering_period        */
54/*  Inputs        : ps_buf_prd pointer to struct buf_period_t                  */
55/*                  ps_bitstrm    Bitstream                                */
56/*  Globals       : None                                                     */
57/*  Processing    : Parses SEI payload buffering period.                     */
58/*  Outputs       : None                                                     */
59/*  Returns       : None                                                     */
60/*                                                                           */
61/*  Issues        : Not implemented fully                                    */
62/*                                                                           */
63/*  Revision History:                                                        */
64/*                                                                           */
65/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
66/*         06 05 2002   NS              Draft                                */
67/*                                                                           */
68/*****************************************************************************/
69
70WORD32 ih264d_parse_buffering_period(buf_period_t *ps_buf_prd,
71                                     dec_bit_stream_t *ps_bitstrm,
72                                     dec_struct_t *ps_dec)
73{
74    UWORD8 u1_seq_parameter_set_id;
75    dec_seq_params_t *ps_seq;
76    UWORD8 u1_nal_hrd_present, u1_vcl_hrd_present;
77    UWORD32 i;
78    UWORD32 *pu4_bitstrm_ofst = &ps_bitstrm->u4_ofst;
79    UWORD32 *pu4_bitstrm_buf = ps_bitstrm->pu4_buffer;
80    UNUSED(ps_buf_prd);
81    u1_seq_parameter_set_id = ih264d_uev(pu4_bitstrm_ofst,
82                                         pu4_bitstrm_buf);
83    if(u1_seq_parameter_set_id > MAX_NUM_SEQ_PARAMS)
84        return ERROR_INVALID_SEQ_PARAM;
85    ps_seq = &ps_dec->ps_sps[u1_seq_parameter_set_id];
86    if(TRUE != ps_seq->u1_is_valid)
87        return (-1);
88
89    ps_dec->ps_sei->u1_seq_param_set_id = u1_seq_parameter_set_id;
90    ps_dec->ps_cur_sps = ps_seq;
91    if(FALSE == ps_seq->u1_is_valid)
92        return ERROR_INVALID_SEQ_PARAM;
93    if(1 == ps_seq->u1_vui_parameters_present_flag)
94    {
95        u1_nal_hrd_present = ps_seq->s_vui.u1_nal_hrd_params_present;
96        if(u1_nal_hrd_present)
97        {
98            for(i = 0; i < ps_seq->s_vui.s_nal_hrd.u4_cpb_cnt; i++)
99            {
100                ih264d_get_bits_h264(
101                                ps_bitstrm,
102                                ps_seq->s_vui.s_nal_hrd.u1_initial_cpb_removal_delay);
103                ih264d_get_bits_h264(
104                                ps_bitstrm,
105                                ps_seq->s_vui.s_nal_hrd.u1_initial_cpb_removal_delay);
106            }
107        }
108
109        u1_vcl_hrd_present = ps_seq->s_vui.u1_vcl_hrd_params_present;
110        if(u1_vcl_hrd_present)
111        {
112            for(i = 0; i < ps_seq->s_vui.s_vcl_hrd.u4_cpb_cnt; i++)
113            {
114                ih264d_get_bits_h264(
115                                ps_bitstrm,
116                                ps_seq->s_vui.s_vcl_hrd.u1_initial_cpb_removal_delay);
117                ih264d_get_bits_h264(
118                                ps_bitstrm,
119                                ps_seq->s_vui.s_vcl_hrd.u1_initial_cpb_removal_delay);
120            }
121        }
122    }
123    return OK;
124}
125
126/*****************************************************************************/
127/*                                                                           */
128/*  Function Name : ih264d_parse_pic_timing                                         */
129/*                                                                           */
130/*  Description   : This function parses SEI message pic_timing              */
131/*  Inputs        : ps_bitstrm    Bitstream                                */
132/*                  ps_dec          Poniter decoder context                  */
133/*                  ui4_payload_size pay load i4_size                           */
134/*  Globals       : None                                                     */
135/*  Processing    : Parses SEI payload picture timing                        */
136/*  Outputs       : None                                                     */
137/*  Returns       : None                                                     */
138/*                                                                           */
139/*  Issues        : Not implemented fully                                    */
140/*                                                                           */
141/*  Revision History:                                                        */
142/*                                                                           */
143/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
144/*         06 05 2002   NS              Draft                                */
145/*                                                                           */
146/*****************************************************************************/
147WORD32 ih264d_parse_pic_timing(dec_bit_stream_t *ps_bitstrm,
148                               dec_struct_t *ps_dec,
149                               UWORD32 ui4_payload_size)
150{
151    sei *ps_sei;
152    vui_t *ps_vu4;
153    UWORD8 u1_cpb_dpb_present;
154    UWORD8 u1_pic_struct_present_flag;
155    UWORD32 u4_start_offset, u4_bits_consumed;
156    UWORD8 u1_cpb_removal_delay_length, u1_dpb_output_delay_length;
157
158    ps_sei = (sei *)ps_dec->ps_sei;
159    ps_vu4 = &ps_dec->ps_cur_sps->s_vui;
160
161    u1_cpb_dpb_present = ps_vu4->u1_vcl_hrd_params_present
162                    + ps_vu4->u1_nal_hrd_params_present;
163
164    if(ps_vu4->u1_vcl_hrd_params_present)
165    {
166        u1_cpb_removal_delay_length =
167                        ps_vu4->s_vcl_hrd.u1_cpb_removal_delay_length;
168        u1_dpb_output_delay_length =
169                        ps_vu4->s_vcl_hrd.u1_dpb_output_delay_length;
170    }
171    else if(ps_vu4->u1_nal_hrd_params_present)
172    {
173        u1_cpb_removal_delay_length =
174                        ps_vu4->s_nal_hrd.u1_cpb_removal_delay_length;
175        u1_dpb_output_delay_length =
176                        ps_vu4->s_nal_hrd.u1_dpb_output_delay_length;
177    }
178    else
179    {
180        u1_cpb_removal_delay_length = 24;
181        u1_dpb_output_delay_length = 24;
182
183    }
184
185    u4_start_offset = ps_bitstrm->u4_ofst;
186    if(u1_cpb_dpb_present)
187    {
188        ih264d_get_bits_h264(ps_bitstrm, u1_cpb_removal_delay_length);
189        ih264d_get_bits_h264(ps_bitstrm, u1_dpb_output_delay_length);
190    }
191
192    u1_pic_struct_present_flag = ps_vu4->u1_pic_struct_present_flag;
193    if(u1_pic_struct_present_flag)
194    {
195        ps_sei->u1_pic_struct = ih264d_get_bits_h264(ps_bitstrm, 4);
196        ps_dec->u1_pic_struct_copy = ps_sei->u1_pic_struct;
197        ps_sei->u1_is_valid = 1;
198    }
199    u4_bits_consumed = ps_bitstrm->u4_ofst - u4_start_offset;
200    ih264d_flush_bits_h264(ps_bitstrm,
201                           (ui4_payload_size << 3) - u4_bits_consumed);
202
203    return (0);
204}
205
206/*****************************************************************************/
207/*                                                                           */
208/*  Function Name : ih264d_parse_recovery_point                                     */
209/*                                                                           */
210/*  Description   : This function parses SEI message recovery point          */
211/*  Inputs        : ps_bitstrm    Bitstream                                */
212/*                  ps_dec          Poniter decoder context                  */
213/*                  ui4_payload_size pay load i4_size                           */
214/*  Globals       : None                                                     */
215/*  Processing    : Parses SEI payload picture timing                        */
216/*  Outputs       : None                                                     */
217/*  Returns       : None                                                     */
218/*                                                                           */
219/*  Issues        : Not implemented fully                                    */
220/*                                                                           */
221/*  Revision History:                                                        */
222/*                                                                           */
223/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
224/*         06 05 2002   NS              Draft                                */
225/*                                                                           */
226/*****************************************************************************/
227WORD32 ih264d_parse_recovery_point(dec_bit_stream_t *ps_bitstrm,
228                                   dec_struct_t *ps_dec,
229                                   UWORD32 ui4_payload_size)
230{
231    sei *ps_sei = ps_dec->ps_sei;
232    dec_err_status_t *ps_err = ps_dec->ps_dec_err_status;
233    UWORD32 *pu4_bitstrm_ofst = &ps_bitstrm->u4_ofst;
234    UWORD32 *pu4_bitstrm_buf = ps_bitstrm->pu4_buffer;
235    UNUSED(ui4_payload_size);
236    ps_sei->u2_recovery_frame_cnt = ih264d_uev(pu4_bitstrm_ofst,
237                                               pu4_bitstrm_buf);
238    ps_err->u4_frm_sei_sync = ps_err->u4_cur_frm
239                    + ps_sei->u2_recovery_frame_cnt;
240    ps_sei->u1_exact_match_flag = ih264d_get_bit_h264(ps_bitstrm);
241    ps_sei->u1_broken_link_flag = ih264d_get_bit_h264(ps_bitstrm);
242    ps_sei->u1_changing_slice_grp_idc = ih264d_get_bits_h264(ps_bitstrm, 2);
243
244    return (0);
245}
246
247/*****************************************************************************/
248/*                                                                           */
249/*  Function Name : ih264d_parse_sei_payload                                        */
250/*                                                                           */
251/*  Description   : This function parses SEI pay loads. Currently it's       */
252/*                  implemented partially.                                   */
253/*  Inputs        : ps_bitstrm    Bitstream                                */
254/*                  ui4_payload_type  SEI payload type                       */
255/*                  ui4_payload_size  SEI payload i4_size                       */
256/*  Globals       : None                                                     */
257/*  Processing    : Parses SEI payloads units and stores the info            */
258/*  Outputs       : None                                                     */
259/*  Returns       : None                                                     */
260/*                                                                           */
261/*  Issues        : Not implemented fully                                    */
262/*                                                                           */
263/*  Revision History:                                                        */
264/*                                                                           */
265/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
266/*         06 05 2002   NS              Draft                                */
267/*                                                                           */
268/*****************************************************************************/
269
270WORD32 ih264d_parse_sei_payload(dec_bit_stream_t *ps_bitstrm,
271                                UWORD32 ui4_payload_type,
272                                UWORD32 ui4_payload_size,
273                                dec_struct_t *ps_dec)
274{
275    sei *ps_sei;
276    WORD32 i4_status = 0;
277    ps_sei = (sei *)ps_dec->ps_sei;
278    switch(ui4_payload_type)
279    {
280        case SEI_BUF_PERIOD:
281
282            i4_status = ih264d_parse_buffering_period(&ps_sei->s_buf_period,
283                                                      ps_bitstrm, ps_dec);
284            /*if(i4_status != OK)
285                return i4_status;*/
286            break;
287        case SEI_PIC_TIMING:
288            if(NULL == ps_dec->ps_cur_sps)
289                ih264d_flush_bits_h264(ps_bitstrm, (ui4_payload_size << 3));
290            else
291                ih264d_parse_pic_timing(ps_bitstrm, ps_dec,
292                                        ui4_payload_size);
293            break;
294        case SEI_RECOVERY_PT:
295            ih264d_parse_recovery_point(ps_bitstrm, ps_dec,
296                                        ui4_payload_size);
297            break;
298        default:
299            ih264d_flush_bits_h264(ps_bitstrm, (ui4_payload_size << 3));
300            break;
301    }
302    return (i4_status);
303}
304
305/*****************************************************************************/
306/*                                                                           */
307/*  Function Name : ih264d_parse_sei_message                                        */
308/*                                                                           */
309/*  Description   : This function is parses and decode SEI. Currently it's   */
310/*                  not implemented fully.                                   */
311/*  Inputs        : ps_dec    Decoder parameters                       */
312/*                  ps_bitstrm    Bitstream                                */
313/*  Globals       : None                                                     */
314/*  Processing    : Parses SEI NAL units and stores the info                 */
315/*  Outputs       : None                                                     */
316/*  Returns       : None                                                     */
317/*                                                                           */
318/*  Issues        : Not implemented fully                                    */
319/*                                                                           */
320/*  Revision History:                                                        */
321/*                                                                           */
322/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
323/*         06 05 2002   NS              Draft                                */
324/*                                                                           */
325/*****************************************************************************/
326
327WORD32 ih264d_parse_sei_message(dec_struct_t *ps_dec,
328                                dec_bit_stream_t *ps_bitstrm)
329{
330    UWORD32 ui4_payload_type, ui4_payload_size;
331    UWORD32 u4_bits;
332    WORD32 i4_status = 0;
333
334    do
335    {
336        ui4_payload_type = 0;
337
338        u4_bits = ih264d_get_bits_h264(ps_bitstrm, 8);
339        while(0xff == u4_bits)
340        {
341            u4_bits = ih264d_get_bits_h264(ps_bitstrm, 8);
342            ui4_payload_type += 255;
343        }
344        ui4_payload_type += u4_bits;
345
346        ui4_payload_size = 0;
347        u4_bits = ih264d_get_bits_h264(ps_bitstrm, 8);
348        while(0xff == u4_bits)
349        {
350            u4_bits = ih264d_get_bits_h264(ps_bitstrm, 8);
351            ui4_payload_size += 255;
352        }
353        ui4_payload_size += u4_bits;
354
355        i4_status = ih264d_parse_sei_payload(ps_bitstrm, ui4_payload_type,
356                                             ui4_payload_size, ps_dec);
357        if(i4_status == -1)
358        {
359            i4_status = 0;
360            break;
361        }
362
363        if(i4_status != OK)
364            return i4_status;
365
366        if(ih264d_check_byte_aligned(ps_bitstrm) == 0)
367        {
368            u4_bits = ih264d_get_bit_h264(ps_bitstrm);
369            if(0 == u4_bits)
370            {
371                H264_DEC_DEBUG_PRINT("\nError in parsing SEI message");
372            }
373            while(0 == ih264d_check_byte_aligned(ps_bitstrm))
374            {
375                u4_bits = ih264d_get_bit_h264(ps_bitstrm);
376                if(u4_bits)
377                {
378                    H264_DEC_DEBUG_PRINT("\nError in parsing SEI message");
379                }
380            }
381        }
382    }
383    while(ps_bitstrm->u4_ofst < ps_bitstrm->u4_max_ofst);
384    return (i4_status);
385}
386
387