demux: mp4: avoid audio cuts on seek
[vlc.git] / modules / codec / scte18.c
blob2a2181fd3bf93e2eb703534cf596352c726cf21e
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 struct decoder_sys_t
51 atsc_a65_handle_t *p_handle;
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 scte18_cea_t *p_cea = scte18_cea_Decode( p_dec->p_sys->p_handle, p_block );
182 if( p_cea )
184 p_spu = decoder_NewSubpictureText( p_dec );
185 if( p_spu )
187 subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
189 p_spu->i_start = p_block->i_pts;
190 if( p_cea->alert_message_time_remaining )
191 p_spu->i_stop = p_spu->i_start + CLOCK_FREQ * p_cea->alert_message_time_remaining;
192 else
193 p_spu->i_stop = VLC_TS_INVALID;
195 p_spu->b_ephemer = true;
196 p_spu->b_absolute = false;
198 p_spu_sys->region.inner_align = SUBPICTURE_ALIGN_TOP;
199 p_spu_sys->p_default_style->i_style_flags = STYLE_BOLD | STYLE_BACKGROUND;
200 p_spu_sys->p_default_style->i_features |= STYLE_HAS_FLAGS;
201 p_spu_sys->p_default_style->i_background_color = 0x000000;
202 p_spu_sys->p_default_style->i_background_alpha = STYLE_ALPHA_OPAQUE;
203 p_spu_sys->p_default_style->i_features |= STYLE_HAS_BACKGROUND_COLOR | STYLE_HAS_BACKGROUND_ALPHA;
204 p_spu_sys->p_default_style->i_font_color = 0xFF0000;
205 p_spu_sys->p_default_style->i_features |= STYLE_HAS_FONT_COLOR;
207 p_spu_sys->region.p_segments = text_segment_New( p_cea->psz_alert_text );
208 decoder_QueueSub( p_dec, p_spu );
210 msg_Info( p_dec, "Received %s", p_cea->psz_alert_text );
211 scte18_cea_Free( p_cea );
214 exit:
215 block_Release( p_block );
216 return VLCDEC_SUCCESS;
219 static int Open( vlc_object_t *object )
221 decoder_t *dec = (decoder_t *)object;
223 if ( dec->fmt_in.i_codec != VLC_CODEC_SCTE_18 )
224 return VLC_EGENERIC;
226 decoder_sys_t *p_sys = malloc( sizeof(decoder_sys_t) );
227 if( unlikely(!p_sys) )
228 return VLC_ENOMEM;
230 p_sys->p_handle = atsc_a65_handle_New( NULL );
231 if( !p_sys->p_handle )
233 free( p_sys );
234 return VLC_EGENERIC;
237 dec->p_sys = p_sys;
238 dec->pf_decode = Decode;
239 dec->fmt_out.i_codec = 0;
241 return VLC_SUCCESS;
244 static void Close( vlc_object_t *p_object )
246 decoder_t *p_dec = (decoder_t *)p_object;
247 decoder_sys_t *p_sys = (decoder_sys_t *) p_dec->p_sys;
248 atsc_a65_handle_Release( p_sys->p_handle );
249 free( p_sys );