demux: libmp4: fix ReadBoxUsing function return check
[vlc.git] / modules / codec / scte18.c
blob73ee7cda210e62b58fe9b91d13f3f98772c74d65
1 /*****************************************************************************
2 * scte18.c : SCTE-18 EAS decoder
3 *****************************************************************************
4 * Copyright (C) 2016 - VideoLAN Authors
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *****************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
24 #include <vlc_common.h>
25 #include <vlc_plugin.h>
26 #include <vlc_codec.h>
28 #include "atsc_a65.h"
29 #include "scte18.h"
30 #include "substext.h"
32 #include <time.h>
34 /*****************************************************************************
35 * Module descriptor.
36 *****************************************************************************/
37 static int Open (vlc_object_t *);
38 static void Close(vlc_object_t *);
40 vlc_module_begin ()
41 set_description(N_("SCTE-18 decoder"))
42 set_shortname(N_("SCTE-18"))
43 set_capability( "spu decoder", 51)
44 set_category(CAT_INPUT)
45 set_subcategory(SUBCAT_INPUT_SCODEC)
46 set_callbacks(Open, Close)
47 vlc_module_end ()
49 typedef struct
51 atsc_a65_handle_t *p_handle;
52 } decoder_sys_t;
54 //#define GPS_UTC_EPOCH_OFFSET 315964800
55 //#define GPS_CUR_UTC_LEAP_OFFSET 16 /* 1 Jul 2015 */
57 typedef struct scte18_cea_t
59 uint16_t i_eas_event_id;
60 char rgc_eas_originator_code[3];
61 char * psz_eas_event_code;
62 char * psz_nature_of_activation;
63 uint8_t alert_message_time_remaining;
64 uint32_t event_start_time;
65 uint16_t event_duration;
66 uint8_t alert_priority;
68 char * psz_alert_text;
70 } scte18_cea_t;
72 /****************************************************************************
73 * Local prototypes
74 ****************************************************************************/
75 #define BUF_ADVANCE(n) p_buffer += n; i_buffer -= n;
77 static inline scte18_cea_t * scte18_cea_New()
79 return calloc( 1, sizeof(scte18_cea_t) );
82 static void scte18_cea_Free( scte18_cea_t *p_cea )
84 free( p_cea->psz_alert_text );
85 free( p_cea->psz_nature_of_activation );
86 free( p_cea->psz_eas_event_code );
87 free( p_cea );
90 static scte18_cea_t * scte18_cea_Decode( atsc_a65_handle_t *p_handle, const block_t *p_block )
92 size_t len;
93 scte18_cea_t *p_cea = scte18_cea_New();
94 if( !p_cea )
95 return NULL;
97 const uint8_t *p_buffer = p_block->p_buffer;
98 size_t i_buffer = p_block->i_buffer;
100 if( i_buffer < 34 || p_buffer[0] != 0 )
101 goto error;
103 BUF_ADVANCE(1);
105 p_cea->i_eas_event_id = GetWBE( p_buffer );
106 BUF_ADVANCE(2);
108 memcpy( p_cea->rgc_eas_originator_code, p_buffer, 3 );
109 BUF_ADVANCE(3);
111 len = p_buffer[0];
112 if( i_buffer < 23 + len )
113 goto error;
114 p_cea->psz_eas_event_code = malloc( len + 1 );
115 memcpy( p_cea->psz_eas_event_code, &p_buffer[1], len );
116 p_cea->psz_eas_event_code[len] = 0;
117 BUF_ADVANCE( len + 1 );
119 len = p_buffer[0];
120 if( i_buffer < len + 22 )
121 goto error;
122 p_cea->psz_nature_of_activation = atsc_a65_Decode_multiple_string( p_handle, &p_buffer[1], len );
123 BUF_ADVANCE(1 + len);
125 if( i_buffer < 21 )
126 goto error;
127 p_cea->alert_message_time_remaining = p_buffer[0];
128 BUF_ADVANCE(1);
130 p_cea->event_start_time = GetDWBE( p_buffer );
131 BUF_ADVANCE(4);
133 p_cea->event_duration = GetWBE( p_buffer );
134 if( p_cea->event_duration != 0 && ( p_cea->event_duration < 15 || p_cea->event_duration > 6000 ) )
135 goto error;
136 BUF_ADVANCE(2);
138 p_cea->alert_priority = p_buffer[1] & 0x0f;
139 switch( p_cea->alert_priority )
141 case EAS_PRIORITY_TEST:
142 case EAS_PRIORITY_LOW:
143 case EAS_PRIORITY_MEDIUM:
144 case EAS_PRIORITY_HIGH:
145 case EAS_PRIORITY_MAX:
146 break;
147 default:
148 goto error;
151 BUF_ADVANCE(2);
153 BUF_ADVANCE(2); //OOB_ID
155 BUF_ADVANCE(2); //
156 BUF_ADVANCE(2); //
158 BUF_ADVANCE(2); //audio_OOB_ID
160 len = GetWBE( p_buffer );
161 if( i_buffer < len + 2 )
162 goto error;
163 p_cea->psz_alert_text = atsc_a65_Decode_multiple_string( p_handle, &p_buffer[2], len );
165 return p_cea;
167 error:
168 scte18_cea_Free( p_cea );
169 return NULL;
172 static int Decode( decoder_t *p_dec, block_t *p_block )
174 if ( p_block == NULL ) /* No Drain */
175 return VLCDEC_SUCCESS;
176 subpicture_t *p_spu = NULL;
178 if (p_block->i_flags & (BLOCK_FLAG_CORRUPTED))
179 goto exit;
181 decoder_sys_t *p_sys = p_dec->p_sys;
183 scte18_cea_t *p_cea = scte18_cea_Decode( p_sys->p_handle, p_block );
184 if( p_cea )
186 p_spu = decoder_NewSubpictureText( p_dec );
187 if( p_spu )
189 subtext_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
191 p_spu->i_start = p_block->i_pts;
192 if( p_cea->alert_message_time_remaining )
193 p_spu->i_stop = p_spu->i_start + vlc_tick_from_sec( p_cea->alert_message_time_remaining );
194 else
195 p_spu->i_stop = VLC_TICK_INVALID;
197 p_spu->b_ephemer = true;
198 p_spu->b_absolute = false;
200 p_spu_sys->region.inner_align = SUBPICTURE_ALIGN_TOP;
201 p_spu_sys->p_default_style->i_style_flags = STYLE_BOLD | STYLE_BACKGROUND;
202 p_spu_sys->p_default_style->i_features |= STYLE_HAS_FLAGS;
203 p_spu_sys->p_default_style->i_background_color = 0x000000;
204 p_spu_sys->p_default_style->i_background_alpha = STYLE_ALPHA_OPAQUE;
205 p_spu_sys->p_default_style->i_features |= STYLE_HAS_BACKGROUND_COLOR | STYLE_HAS_BACKGROUND_ALPHA;
206 p_spu_sys->p_default_style->i_font_color = 0xFF0000;
207 p_spu_sys->p_default_style->i_features |= STYLE_HAS_FONT_COLOR;
209 p_spu_sys->region.p_segments = text_segment_New( p_cea->psz_alert_text );
210 decoder_QueueSub( p_dec, p_spu );
212 msg_Info( p_dec, "Received %s", p_cea->psz_alert_text );
213 scte18_cea_Free( p_cea );
216 exit:
217 block_Release( p_block );
218 return VLCDEC_SUCCESS;
221 static int Open( vlc_object_t *object )
223 decoder_t *dec = (decoder_t *)object;
225 if ( dec->fmt_in.i_codec != VLC_CODEC_SCTE_18 )
226 return VLC_EGENERIC;
228 decoder_sys_t *p_sys = malloc( sizeof(decoder_sys_t) );
229 if( unlikely(!p_sys) )
230 return VLC_ENOMEM;
232 p_sys->p_handle = atsc_a65_handle_New( NULL );
233 if( !p_sys->p_handle )
235 free( p_sys );
236 return VLC_EGENERIC;
239 dec->p_sys = p_sys;
240 dec->pf_decode = Decode;
241 dec->fmt_out.i_codec = 0;
243 return VLC_SUCCESS;
246 static void Close( vlc_object_t *p_object )
248 decoder_t *p_dec = (decoder_t *)p_object;
249 decoder_sys_t *p_sys = (decoder_sys_t *) p_dec->p_sys;
250 atsc_a65_handle_Release( p_sys->p_handle );
251 free( p_sys );