/src/vlc/modules/demux/mpeg/ts_psip.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * ts_psip.c : TS demux ATSC A65 PSIP handling |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2016 - VideoLAN Authors |
5 | | * |
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. |
10 | | * |
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. |
15 | | * |
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 | | *****************************************************************************/ |
19 | | #ifdef HAVE_CONFIG_H |
20 | | # include "config.h" |
21 | | #endif |
22 | | |
23 | | #include <vlc_common.h> |
24 | | #include <vlc_demux.h> |
25 | | #include <vlc_meta.h> |
26 | | #include <vlc_epg.h> |
27 | | |
28 | | #ifndef _DVBPSI_DVBPSI_H_ |
29 | | #include <dvbpsi/dvbpsi.h> |
30 | | #endif |
31 | | #ifndef _DVBPSI_DEMUX_H_ |
32 | | #include <dvbpsi/demux.h> |
33 | | #endif |
34 | | #include <dvbpsi/descriptor.h> |
35 | | #include <dvbpsi/atsc_mgt.h> |
36 | | #include <dvbpsi/atsc_vct.h> |
37 | | #include <dvbpsi/atsc_eit.h> |
38 | | #include <dvbpsi/atsc_ett.h> |
39 | | #include <dvbpsi/atsc_stt.h> |
40 | | #include <dvbpsi/dr_a0.h> |
41 | | #include "../../mux/mpeg/dvbpsi_compat.h" /* dvbpsi_messages */ |
42 | | /* Custom decoders */ |
43 | | #include <dvbpsi/psi.h> |
44 | | #include "ts_decoders.h" |
45 | | #include "ts_psip_dvbpsi_fixes.h" |
46 | | |
47 | | #include "timestamps.h" |
48 | | #include "ts_pid.h" |
49 | | #include "ts.h" |
50 | | #include "ts_streams_private.h" |
51 | | #include "ts_scte.h" |
52 | | |
53 | | #include "ts_psip.h" |
54 | | |
55 | | #include "../../codec/atsc_a65.h" |
56 | | #include "../../codec/scte18.h" |
57 | | |
58 | | #include <assert.h> |
59 | | |
60 | | static inline char *grab_notempty( char **ppsz ) |
61 | 0 | { |
62 | 0 | char *psz_ret = NULL; |
63 | 0 | if( *ppsz && **ppsz ) |
64 | 0 | { |
65 | 0 | psz_ret = *ppsz; |
66 | 0 | *ppsz = NULL; |
67 | 0 | } |
68 | 0 | return psz_ret; |
69 | 0 | } |
70 | | |
71 | | /* |
72 | | * Decoders activation order due to dependencies, |
73 | | * and because callbacks will be fired once per MGT/VCT version |
74 | | * STT(ref by EIT,EAS) -> MGT |
75 | | * MGT -> VCT,EAS,EIT/ETT |
76 | | */ |
77 | | |
78 | | struct ts_psip_context_t |
79 | | { |
80 | | dvbpsi_t *p_handle; |
81 | | int i_version; |
82 | | dvbpsi_atsc_mgt_t *p_mgt; /* Used to match (EITx,ETTx)<->PIDn */ |
83 | | dvbpsi_atsc_stt_t *p_stt; /* Time reference for EIT/EAS */ |
84 | | dvbpsi_atsc_vct_t *p_vct; /* Required for EIT vchannel -> program remapping */ |
85 | | atsc_a65_handle_t *p_a65; /* Shared Handle to avoid iconv reopens */ |
86 | | uint16_t i_tabletype; /* Only used by EIT/ETT pid */ |
87 | | DECL_ARRAY(dvbpsi_atsc_ett_t *) etts; /* For ETT pid, used on new EIT update */ |
88 | | DECL_ARRAY(dvbpsi_atsc_eit_t *) eits; /* For EIT pid, used on new ETT update */ |
89 | | }; |
90 | | |
91 | | static void ATSC_Detach_Dvbpsi_Decoders( dvbpsi_t *p_handle ); |
92 | | |
93 | | void ts_psip_Packet_Push( ts_pid_t *p_pid, const uint8_t *p_pktbuffer ) |
94 | 97 | { |
95 | 97 | ts_psip_context_t *p_ctx = p_pid->u.p_psip->p_ctx; |
96 | 97 | if( p_ctx->p_handle->p_decoder && likely(p_pid->type == TYPE_PSIP) ) |
97 | 97 | dvbpsi_packet_push( p_ctx->p_handle, (uint8_t *) p_pktbuffer ); |
98 | 97 | } |
99 | | |
100 | | ts_psip_context_t * ts_psip_context_New( demux_t *p_demux ) |
101 | 95 | { |
102 | 95 | ts_psip_context_t *p_ctx = malloc(sizeof(*p_ctx)); |
103 | 95 | if(likely(p_ctx)) |
104 | 95 | { |
105 | 95 | p_ctx->p_handle = dvbpsi_new( &dvbpsi_messages, DVBPSI_MSG_DEBUG ); |
106 | 95 | if( !p_ctx->p_handle ) |
107 | 0 | { |
108 | 0 | free( p_ctx ); |
109 | 0 | return NULL; |
110 | 0 | } |
111 | 95 | p_ctx->p_handle->p_sys = (void *) p_demux; |
112 | 95 | p_ctx->i_version = -1; |
113 | 95 | p_ctx->p_mgt = NULL; |
114 | 95 | p_ctx->p_stt = NULL; |
115 | 95 | p_ctx->p_vct = NULL; |
116 | 95 | p_ctx->p_a65 = NULL; |
117 | 95 | p_ctx->i_tabletype = 0; |
118 | 95 | ARRAY_INIT(p_ctx->etts); |
119 | 95 | ARRAY_INIT(p_ctx->eits); |
120 | 95 | } |
121 | 95 | return p_ctx; |
122 | 95 | } |
123 | | |
124 | | void ts_psip_context_Delete( ts_psip_context_t *p_ctx ) |
125 | 95 | { |
126 | 95 | assert( !p_ctx->p_mgt || !p_ctx->etts.i_size ); |
127 | 95 | assert( !p_ctx->p_vct || !p_ctx->eits.i_size ); |
128 | | |
129 | 95 | ATSC_Detach_Dvbpsi_Decoders( p_ctx->p_handle ); |
130 | 95 | dvbpsi_delete( p_ctx->p_handle ); |
131 | | |
132 | 95 | if( p_ctx->p_mgt ) |
133 | 0 | dvbpsi_atsc_DeleteMGT( p_ctx->p_mgt ); |
134 | 95 | if( p_ctx->p_stt ) |
135 | 0 | dvbpsi_atsc_DeleteSTT( p_ctx->p_stt ); |
136 | 95 | if ( p_ctx->p_vct ) |
137 | 0 | dvbpsi_atsc_DeleteVCT( p_ctx->p_vct ); |
138 | 95 | if( p_ctx->p_a65 ) |
139 | 0 | atsc_a65_handle_Release( p_ctx->p_a65 ); |
140 | | /* Things only used for ETT/EIT */ |
141 | 95 | for( int i=0; i<p_ctx->etts.i_size; i++ ) |
142 | 0 | dvbpsi_atsc_DeleteETT( p_ctx->etts.p_elems[i] ); |
143 | 95 | for( int i=0; i<p_ctx->eits.i_size; i++ ) |
144 | 0 | dvbpsi_atsc_DeleteEIT( p_ctx->eits.p_elems[i] ); |
145 | 95 | ARRAY_RESET( p_ctx->etts ); |
146 | 95 | ARRAY_RESET( p_ctx->eits ); |
147 | 95 | free( p_ctx ); |
148 | 95 | } |
149 | | |
150 | | static ts_pid_t *ATSC_GetSiblingxTTPID( ts_pid_list_t *p_list, const dvbpsi_atsc_mgt_t *p_mgt, ts_psip_t *p_psip ) |
151 | 0 | { |
152 | 0 | uint16_t i_lookup; |
153 | 0 | assert( p_psip->p_ctx->i_tabletype ); |
154 | 0 | if( p_psip->p_ctx->i_tabletype >= ATSC_TABLE_TYPE_ETT_0 ) |
155 | 0 | i_lookup = p_psip->p_ctx->i_tabletype - ATSC_TABLE_TYPE_ETT_0 + ATSC_TABLE_TYPE_EIT_0; |
156 | 0 | else |
157 | 0 | i_lookup = p_psip->p_ctx->i_tabletype - ATSC_TABLE_TYPE_EIT_0 + ATSC_TABLE_TYPE_ETT_0; |
158 | |
|
159 | 0 | for( const dvbpsi_atsc_mgt_table_t *p_tab = p_mgt->p_first_table; |
160 | 0 | p_tab; p_tab = p_tab->p_next ) |
161 | 0 | { |
162 | 0 | if( p_tab->i_table_type == i_lookup ) |
163 | 0 | return ts_pid_Get( p_list, p_tab->i_table_type_pid ); |
164 | 0 | } |
165 | 0 | return NULL; |
166 | 0 | } |
167 | | |
168 | | static inline uint32_t toETMId( uint16_t i_vchannel, uint16_t i_event_id ) |
169 | 0 | { |
170 | 0 | return (i_vchannel << 16) | (i_event_id << 2) | 0x02; |
171 | 0 | } |
172 | | |
173 | | static inline void fromETMId( uint32_t i_etm_id, uint16_t *pi_vchannel, uint16_t *pi_event_id ) |
174 | 0 | { |
175 | 0 | *pi_vchannel = i_etm_id >> 16; |
176 | 0 | *pi_event_id = (i_etm_id & 0xFFFF) >> 2; |
177 | 0 | } |
178 | | |
179 | | static const dvbpsi_atsc_ett_t * ATSC_ETTFindByETMId( ts_psip_context_t *p_ettctx, uint32_t i_etm_id, uint8_t i_version ) |
180 | 0 | { |
181 | 0 | int i; |
182 | 0 | ARRAY_BSEARCH( p_ettctx->etts, ->i_etm_id, uint32_t, i_etm_id, i ); |
183 | 0 | if( i != -1 && p_ettctx->etts.p_elems[i]->i_version == i_version ) |
184 | 0 | return p_ettctx->etts.p_elems[i]; |
185 | 0 | return NULL; |
186 | 0 | } |
187 | | |
188 | | static const dvbpsi_atsc_eit_event_t * ATSC_EventFindByETMId( ts_psip_context_t *p_eitctx, |
189 | | uint32_t i_etm_id, uint8_t i_version ) |
190 | 0 | { |
191 | 0 | uint16_t i_vchannel_id, i_event_id; |
192 | 0 | fromETMId( i_etm_id, &i_vchannel_id, &i_event_id ); |
193 | |
|
194 | 0 | for( int i=0; i<p_eitctx->eits.i_size; i++ ) |
195 | 0 | { |
196 | 0 | dvbpsi_atsc_eit_t *p_eit = p_eitctx->eits.p_elems[i]; |
197 | 0 | if( p_eit->i_version != i_version || p_eit->i_source_id != i_vchannel_id ) |
198 | 0 | continue; |
199 | | |
200 | 0 | for( const dvbpsi_atsc_eit_event_t *p_evt = p_eit->p_first_event; |
201 | 0 | p_evt ; p_evt = p_evt->p_next ) |
202 | 0 | { |
203 | 0 | if( p_evt->i_event_id == i_event_id ) |
204 | 0 | return p_evt; |
205 | 0 | } |
206 | 0 | } |
207 | 0 | return NULL; |
208 | 0 | } |
209 | | |
210 | | static void ATSC_EITInsert( ts_psip_context_t *p_ctx, dvbpsi_atsc_eit_t *p_eit ) |
211 | 0 | { |
212 | 0 | for( int i=0; i<p_ctx->eits.i_size; i++ ) |
213 | 0 | { |
214 | 0 | dvbpsi_atsc_eit_t *p_cur_eit = p_ctx->eits.p_elems[i]; |
215 | 0 | if( p_cur_eit->i_source_id == p_eit->i_source_id ) |
216 | 0 | { |
217 | 0 | dvbpsi_atsc_DeleteEIT( p_cur_eit ); /* Updated version */ |
218 | 0 | p_ctx->eits.p_elems[i] = p_eit; |
219 | 0 | return; |
220 | 0 | } |
221 | 0 | } |
222 | 0 | ARRAY_APPEND( p_ctx->eits, p_eit ); |
223 | 0 | } |
224 | | |
225 | | static void ATSC_CleanETTByChannelVersion( ts_psip_context_t *p_ctx, uint16_t i_channel, uint8_t i_version ) |
226 | 0 | { |
227 | 0 | int i=0; |
228 | 0 | while( i<p_ctx->etts.i_size ) |
229 | 0 | { |
230 | 0 | dvbpsi_atsc_ett_t *p = p_ctx->etts.p_elems[i]; |
231 | 0 | uint16_t i_curchan = p->i_etm_id >> 16; |
232 | 0 | if( i_channel < i_curchan ) |
233 | 0 | break; /* because ordered */ |
234 | 0 | if( i_curchan == i_channel && p->i_version != i_version ) |
235 | 0 | { |
236 | 0 | dvbpsi_atsc_DeleteETT( p ); |
237 | 0 | ARRAY_REMOVE( p_ctx->etts, i ); |
238 | 0 | } |
239 | 0 | else i++; |
240 | 0 | } |
241 | 0 | } |
242 | | |
243 | | static void ATSC_InsertETTOrdered( ts_psip_context_t *p_ctx, dvbpsi_atsc_ett_t *p_ett ) |
244 | 0 | { |
245 | 0 | int i=0; |
246 | 0 | for( ; i<p_ctx->etts.i_size; i++ ) |
247 | 0 | { |
248 | 0 | dvbpsi_atsc_ett_t *p = p_ctx->etts.p_elems[i]; |
249 | 0 | if( p->i_etm_id >= p_ett->i_etm_id ) |
250 | 0 | { |
251 | 0 | if( p->i_etm_id == p_ett->i_etm_id ) |
252 | 0 | { |
253 | 0 | dvbpsi_atsc_DeleteETT( p ); |
254 | 0 | p_ctx->etts.p_elems[i] = p_ett; |
255 | 0 | return; |
256 | 0 | } |
257 | 0 | break; |
258 | 0 | } |
259 | 0 | } |
260 | 0 | ARRAY_INSERT( p_ctx->etts, p_ett, i ); |
261 | 0 | } |
262 | | |
263 | | static bool ATSC_TranslateVChannelToProgram( const dvbpsi_atsc_vct_t *p_vct, |
264 | | uint16_t i_channel, uint16_t *pi_program ) |
265 | 0 | { |
266 | 0 | for( const dvbpsi_atsc_vct_channel_t *p_channel = p_vct->p_first_channel; |
267 | 0 | p_channel; p_channel = p_channel->p_next ) |
268 | 0 | { |
269 | 0 | if( p_channel->i_source_id == i_channel ) |
270 | 0 | { |
271 | 0 | *pi_program = p_channel->i_program_number; |
272 | 0 | return true; |
273 | 0 | } |
274 | 0 | } |
275 | 0 | return false; |
276 | 0 | } |
277 | | |
278 | | static void ATSC_NewTable_Callback( dvbpsi_t *p_dvbpsi, uint8_t i_table_id, |
279 | | uint16_t i_extension, void *p_pid ); |
280 | | |
281 | | /* Just Hook a base demux, and let NewTableCallback handle decoders creation */ |
282 | | static bool ATSC_Ready_SubDecoders( dvbpsi_t *p_handle, void *p_cb_pid ) |
283 | 261 | { |
284 | 261 | if( !dvbpsi_decoder_present( p_handle ) ) |
285 | 95 | return dvbpsi_AttachDemux( p_handle, ATSC_NewTable_Callback, p_cb_pid ); |
286 | 166 | return true; |
287 | 261 | } |
288 | | |
289 | | static void ATSC_Detach_Dvbpsi_Decoders( dvbpsi_t *p_handle ) |
290 | 95 | { |
291 | 95 | if( dvbpsi_decoder_present( p_handle ) ) |
292 | 95 | dvbpsi_DetachDemux( p_handle ); |
293 | 95 | } |
294 | | |
295 | | #define ATSC_ATTACH( handle, type, table, extension, pid ) \ |
296 | 0 | ( ATSC_Ready_SubDecoders( handle, pid ) &&\ |
297 | 0 | ( dvbpsi_demuxGetSubDec( (dvbpsi_demux_t *) handle->p_decoder, table, extension ) ||\ |
298 | 0 | dvbpsi_atsc_Attach ## type( handle, table, extension, ATSC_ ## type ## _Callback, pid ) ) ) |
299 | | |
300 | | #define ATSC_ATTACH_WITH_FIXED_DECODER( handle, type, table, extension, pid ) \ |
301 | 261 | ( ATSC_Ready_SubDecoders( handle, pid ) &&\ |
302 | 261 | ( dvbpsi_demuxGetSubDec( (dvbpsi_demux_t *) handle->p_decoder, table, extension ) ||\ |
303 | 261 | ts_dvbpsi_AttachRawSubDecoder( handle, table, extension, ATSC_ ## type ## _RawCallback, pid ) ) ) |
304 | | |
305 | | static const char * const rgpsz_ATSC_A53_service_types[] = |
306 | | { |
307 | | "Analog Television", |
308 | | "ATSC Digital Television", |
309 | | "ATSC Audio", |
310 | | "ATSC Data Only Service", |
311 | | "ATSC Software Download Service", |
312 | | }; |
313 | | |
314 | | static const char * ATSC_A53_get_service_type( uint8_t i_type ) |
315 | 0 | { |
316 | 0 | if( i_type == 0 || i_type > 5 ) |
317 | 0 | return NULL; |
318 | 0 | return rgpsz_ATSC_A53_service_types[i_type - 1]; |
319 | 0 | } |
320 | | |
321 | | #ifndef ATSC_DEBUG_EIT |
322 | | #define EIT_DEBUG_TIMESHIFT(t) |
323 | | #else |
324 | | /* Define static time var used as anchor to current time to offset all eit entries */ |
325 | | static time_t i_eit_debug_offset = 0; |
326 | | #define EIT_DEBUG_TIMESHIFT(t) \ |
327 | | do {\ |
328 | | if( i_eit_debug_offset == 0 )\ |
329 | | i_eit_debug_offset = time(NULL) - t;\ |
330 | | t = t + i_eit_debug_offset;\ |
331 | | } while(0); |
332 | | #endif |
333 | | |
334 | | static vlc_epg_event_t * ATSC_CreateVLCEPGEvent( demux_t *p_demux, ts_psip_context_t *p_basectx, |
335 | | const dvbpsi_atsc_eit_event_t *p_evt, |
336 | | const dvbpsi_atsc_ett_t *p_ett ) |
337 | 0 | { |
338 | 0 | #ifndef ATSC_DEBUG_EIT |
339 | 0 | VLC_UNUSED(p_demux); |
340 | 0 | #endif |
341 | 0 | char *psz_title = atsc_a65_Decode_multiple_string( p_basectx->p_a65, |
342 | 0 | p_evt->i_title, p_evt->i_title_length ); |
343 | 0 | char *psz_shortdesc_text = NULL; |
344 | 0 | char *psz_longdesc_text = NULL; |
345 | 0 | vlc_epg_event_t *p_epgevt = NULL; |
346 | |
|
347 | 0 | time_t i_start = atsc_a65_GPSTimeToEpoch( p_evt->i_start_time, p_basectx->p_stt->i_gps_utc_offset ); |
348 | 0 | EIT_DEBUG_TIMESHIFT( i_start ); |
349 | |
|
350 | 0 | for( const dvbpsi_descriptor_t *p_dr = p_evt->p_first_descriptor; |
351 | 0 | p_dr; p_dr = p_dr->p_next ) |
352 | 0 | { |
353 | 0 | switch( p_dr->i_tag ) |
354 | 0 | { |
355 | 0 | case ATSC_DESCRIPTOR_CONTENT_ADVISORY: |
356 | 0 | { |
357 | 0 | const uint8_t *p_data = p_dr->p_data; |
358 | 0 | size_t i_data = p_dr->i_length; |
359 | 0 | uint8_t i_ratings_count = p_dr->p_data[0] & 0x3F; |
360 | 0 | p_data++; i_data--; |
361 | 0 | for( ; i_ratings_count && i_data > 3; i_ratings_count-- ) |
362 | 0 | { |
363 | 0 | uint8_t i_rated_dimensions = p_data[1]; |
364 | 0 | if( (size_t) i_rated_dimensions * 2 + 3 > i_data ) /* one more sanity check */ |
365 | 0 | break; |
366 | | |
367 | 0 | uint8_t desclen = p_data[(size_t) 2 + 2 * i_rated_dimensions]; |
368 | 0 | p_data += (size_t) 3 + 2 * i_rated_dimensions; |
369 | 0 | i_data -= (size_t) 3 + 2 * i_rated_dimensions; |
370 | 0 | if( desclen > i_data ) |
371 | 0 | break; |
372 | | |
373 | 0 | if( unlikely(psz_shortdesc_text) ) |
374 | 0 | free( psz_shortdesc_text ); |
375 | 0 | psz_shortdesc_text = atsc_a65_Decode_multiple_string( p_basectx->p_a65, p_data, desclen ); |
376 | 0 | if( psz_shortdesc_text ) /* Only keep first for now */ |
377 | 0 | break; |
378 | 0 | p_data += desclen; |
379 | 0 | i_data -= desclen; |
380 | 0 | } |
381 | 0 | } |
382 | 0 | default: |
383 | 0 | break; |
384 | 0 | } |
385 | 0 | } |
386 | | |
387 | | /* Try to match ETT */ |
388 | 0 | if( p_ett ) |
389 | 0 | { |
390 | 0 | psz_longdesc_text = atsc_a65_Decode_multiple_string( p_basectx->p_a65, |
391 | 0 | p_ett->p_etm_data, p_ett->i_etm_length ); |
392 | 0 | } |
393 | |
|
394 | 0 | if( i_start != VLC_TICK_INVALID && psz_title ) |
395 | 0 | { |
396 | | #ifdef ATSC_DEBUG_EIT |
397 | | msg_Dbg( p_demux, "EIT Event time %ld +%d %s id 0x%x", |
398 | | i_start, p_evt->i_length_seconds, psz_title, p_evt->i_event_id ); |
399 | | #endif |
400 | 0 | p_epgevt = vlc_epg_event_New( p_evt->i_event_id, i_start, p_evt->i_length_seconds ); |
401 | 0 | if( p_epgevt ) |
402 | 0 | { |
403 | 0 | p_epgevt->psz_name = grab_notempty( &psz_title ); |
404 | 0 | p_epgevt->psz_short_description = grab_notempty( &psz_shortdesc_text ); |
405 | 0 | p_epgevt->psz_description = grab_notempty( &psz_longdesc_text ); |
406 | 0 | } |
407 | 0 | } |
408 | |
|
409 | 0 | free( psz_title ); |
410 | 0 | free( psz_shortdesc_text ); |
411 | 0 | free( psz_longdesc_text ); |
412 | 0 | return p_epgevt; |
413 | 0 | } |
414 | | |
415 | | static time_t ATSC_AddVLCEPGEvent( demux_t *p_demux, ts_psip_context_t *p_basectx, |
416 | | const dvbpsi_atsc_eit_event_t *p_event, |
417 | | const dvbpsi_atsc_ett_t *p_ett, |
418 | | vlc_epg_t *p_epg ) |
419 | 0 | { |
420 | 0 | vlc_epg_event_t *p_evt = ATSC_CreateVLCEPGEvent( p_demux, p_basectx, |
421 | 0 | p_event, p_ett ); |
422 | 0 | if( p_evt ) |
423 | 0 | { |
424 | 0 | if( vlc_epg_AddEvent( p_epg, p_evt ) ) |
425 | 0 | return p_evt->i_start; |
426 | 0 | vlc_epg_event_Delete( p_evt ); |
427 | 0 | } |
428 | 0 | return VLC_TICK_INVALID; |
429 | 0 | } |
430 | | |
431 | | |
432 | | static void ATSC_EIT_Callback( void *p_pid, dvbpsi_atsc_eit_t* p_eit ) |
433 | 0 | { |
434 | 0 | ts_pid_t *p_eit_pid = (ts_pid_t *) p_pid; |
435 | 0 | if( unlikely(p_eit_pid->type != TYPE_PSIP) ) |
436 | 0 | { |
437 | 0 | assert( p_eit_pid->type == TYPE_PSIP ); |
438 | 0 | dvbpsi_atsc_DeleteEIT( p_eit ); |
439 | 0 | return; |
440 | 0 | } |
441 | | |
442 | 0 | demux_t *p_demux = (demux_t *) p_eit_pid->u.p_psip->p_ctx->p_handle->p_sys; |
443 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
444 | 0 | ts_pid_t *p_base_pid = GetPID(p_sys, ATSC_BASE_PID); |
445 | 0 | ts_psip_t *p_basepsip = p_base_pid->u.p_psip; |
446 | 0 | ts_psip_context_t *p_basectx = p_basepsip->p_ctx; |
447 | |
|
448 | 0 | if( !p_eit->b_current_next || |
449 | 0 | unlikely(p_base_pid->type != TYPE_PSIP || !p_basectx->p_stt || !p_basectx->p_vct) ) |
450 | 0 | { |
451 | 0 | dvbpsi_atsc_DeleteEIT( p_eit ); |
452 | 0 | return; |
453 | 0 | } |
454 | | |
455 | 0 | uint16_t i_program_number; |
456 | 0 | if ( !ATSC_TranslateVChannelToProgram( p_basectx->p_vct, p_eit->i_source_id, &i_program_number ) ) |
457 | 0 | { |
458 | 0 | msg_Warn( p_demux, "Received EIT for unknown channel %d", p_eit->i_source_id ); |
459 | 0 | dvbpsi_atsc_DeleteEIT( p_eit ); |
460 | 0 | return; |
461 | 0 | } |
462 | | |
463 | 0 | const ts_pid_t *pid_sibling_ett = ATSC_GetSiblingxTTPID( &p_sys->pids, p_basectx->p_mgt, |
464 | 0 | p_eit_pid->u.p_psip ); |
465 | | |
466 | | /* Get System Time for finding and setting current event */ |
467 | 0 | time_t i_current_time = atsc_a65_GPSTimeToEpoch( p_basectx->p_stt->i_system_time, |
468 | 0 | p_basectx->p_stt->i_gps_utc_offset ); |
469 | 0 | EIT_DEBUG_TIMESHIFT( i_current_time ); |
470 | |
|
471 | 0 | const uint16_t i_table_type = p_eit_pid->u.p_psip->p_ctx->i_tabletype; |
472 | 0 | assert(i_table_type); |
473 | | |
474 | | /* Use PID for segmenting our EPG tables updates. 1 EIT/PID transmits 3 hours, |
475 | | * with a max of 16 days over 128 EIT/PID. Unlike DVD, table ID is here fixed. |
476 | | * see ATSC A/65 5.0 */ |
477 | 0 | vlc_epg_t *p_epg = vlc_epg_New( i_table_type - ATSC_TABLE_TYPE_EIT_0, |
478 | 0 | i_program_number ); |
479 | 0 | if( !p_epg ) |
480 | 0 | { |
481 | 0 | dvbpsi_atsc_DeleteEIT( p_eit ); |
482 | 0 | return; |
483 | 0 | } |
484 | | |
485 | | /* Use first table as present/following (not split like DVB) */ |
486 | 0 | p_epg->b_present = (i_table_type == ATSC_TABLE_TYPE_EIT_0); |
487 | |
|
488 | 0 | if( !p_basectx->p_a65 && !(p_basectx->p_a65 = atsc_a65_handle_New( NULL )) ) |
489 | 0 | goto end; |
490 | | |
491 | 0 | time_t i_current_event_start_time = 0; |
492 | 0 | for( const dvbpsi_atsc_eit_event_t *p_evt = p_eit->p_first_event; |
493 | 0 | p_evt ; p_evt = p_evt->p_next ) |
494 | 0 | { |
495 | | /* Try to match ETT */ |
496 | 0 | const dvbpsi_atsc_ett_t *p_ett = NULL; |
497 | 0 | if( pid_sibling_ett ) |
498 | 0 | p_ett = ATSC_ETTFindByETMId( pid_sibling_ett->u.p_psip->p_ctx, |
499 | 0 | toETMId( p_eit->i_source_id, p_evt->i_event_id ), |
500 | 0 | p_eit->i_version ); |
501 | | |
502 | | /* Add Event to EPG based on EIT / available ETT */ |
503 | 0 | time_t i_start = ATSC_AddVLCEPGEvent( p_demux, p_basectx, p_evt, p_ett, p_epg ); |
504 | | |
505 | | /* Try to find current event */ |
506 | 0 | if( i_start <= i_current_time && i_start + p_evt->i_length_seconds > i_current_time ) |
507 | 0 | i_current_event_start_time = i_start; |
508 | 0 | } |
509 | | |
510 | | /* Update epg current time from system time ( required for pruning ) */ |
511 | 0 | if( p_epg->b_present && i_current_event_start_time ) |
512 | 0 | { |
513 | 0 | vlc_epg_SetCurrent( p_epg, i_current_event_start_time ); |
514 | 0 | ts_pat_t *p_pat = ts_pid_Get(&p_sys->pids, 0)->u.p_pat; |
515 | 0 | ts_pmt_t *p_pmt = ts_pat_Get_pmt(p_pat, i_program_number); |
516 | 0 | if(p_pmt) |
517 | 0 | { |
518 | 0 | p_pmt->eit.i_event_start = p_epg->p_current->i_start; |
519 | 0 | p_pmt->eit.i_event_length = p_epg->p_current->i_duration; |
520 | 0 | } |
521 | 0 | } |
522 | |
|
523 | 0 | if( p_epg->i_event > 0 ) |
524 | 0 | es_out_Control( p_demux->out, ES_OUT_SET_GROUP_EPG, (int)i_program_number, p_epg ); |
525 | |
|
526 | 0 | end: |
527 | 0 | vlc_epg_Delete( p_epg ); |
528 | 0 | ATSC_EITInsert( p_eit_pid->u.p_psip->p_ctx, p_eit ); |
529 | 0 | } |
530 | | |
531 | | static void ATSC_ETT_Callback( void *p_pid, dvbpsi_atsc_ett_t *p_ett ) |
532 | 0 | { |
533 | 0 | ts_pid_t *p_ett_pid = (ts_pid_t *) p_pid; |
534 | 0 | if( unlikely(p_ett_pid->type != TYPE_PSIP) ) |
535 | 0 | { |
536 | 0 | assert( p_ett_pid->type == TYPE_PSIP ); |
537 | 0 | dvbpsi_atsc_DeleteETT( p_ett ); |
538 | 0 | return; |
539 | 0 | } |
540 | | |
541 | 0 | demux_t *p_demux = (demux_t *) p_ett_pid->u.p_psip->p_ctx->p_handle->p_sys; |
542 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
543 | 0 | ts_pid_t *p_base_pid = GetPID(p_sys, ATSC_BASE_PID); |
544 | 0 | ts_psip_t *p_basepsip = p_base_pid->u.p_psip; |
545 | 0 | ts_psip_context_t *p_basectx = p_basepsip->p_ctx; |
546 | |
|
547 | 0 | if( p_ett->i_etm_id & 0x02 ) /* Event ETT */ |
548 | 0 | { |
549 | 0 | ts_psip_context_t *p_ctx = p_ett_pid->u.p_psip->p_ctx; |
550 | 0 | uint16_t i_vchannel_id, i_event_id; |
551 | 0 | fromETMId( p_ett->i_etm_id, &i_vchannel_id, &i_event_id ); |
552 | |
|
553 | 0 | uint16_t i_program_number; |
554 | 0 | if ( !ATSC_TranslateVChannelToProgram( p_basectx->p_vct, i_vchannel_id, &i_program_number ) ) |
555 | 0 | { |
556 | 0 | msg_Warn( p_demux, "Received EIT for unknown channel %d", i_vchannel_id ); |
557 | 0 | dvbpsi_atsc_DeleteETT( p_ett ); |
558 | 0 | return; |
559 | 0 | } |
560 | | |
561 | | /* If ETT with that version isn't already in list (inserted when matched eit is present) */ |
562 | 0 | if( ATSC_ETTFindByETMId( p_ctx, p_ett->i_etm_id, p_ett->i_version ) == NULL ) |
563 | 0 | { |
564 | 0 | const dvbpsi_atsc_mgt_t *p_mgt = ts_pid_Get( &p_sys->pids, ATSC_BASE_PID )->u.p_psip->p_ctx->p_mgt; |
565 | 0 | ts_pid_t *p_sibling_eit = ATSC_GetSiblingxTTPID( &p_sys->pids, p_mgt, p_ett_pid->u.p_psip ); |
566 | 0 | if( p_sibling_eit ) |
567 | 0 | { |
568 | 0 | const dvbpsi_atsc_eit_event_t *p_event = |
569 | 0 | ATSC_EventFindByETMId( p_sibling_eit->u.p_psip->p_ctx, p_ett->i_etm_id, p_ett->i_version ); |
570 | 0 | if( p_event ) |
571 | 0 | { |
572 | | #ifdef ATSC_DEBUG_EIT |
573 | | msg_Dbg( p_demux, "Should update EIT %x (matched EIT)", p_event->i_event_id ); |
574 | | #endif |
575 | 0 | vlc_epg_event_t *p_evt = ATSC_CreateVLCEPGEvent( p_demux, p_basectx, p_event, p_ett ); |
576 | 0 | if( likely(p_evt) ) |
577 | 0 | { |
578 | 0 | es_out_Control( p_demux->out, ES_OUT_SET_GROUP_EPG_EVENT, |
579 | 0 | (int)i_program_number, p_evt ); |
580 | | #ifdef ATSC_DEBUG_EIT |
581 | | msg_Dbg( p_demux, "Updated event %x with ETT", p_evt->i_id ); |
582 | | #endif |
583 | 0 | vlc_epg_event_Delete( p_evt ); |
584 | 0 | } |
585 | 0 | } |
586 | | /* Insert to avoid duplicated event, and to be available to EIT if didn't appear yet */ |
587 | 0 | ATSC_InsertETTOrdered( p_ctx, p_ett ); |
588 | 0 | ATSC_CleanETTByChannelVersion( p_ctx, i_vchannel_id, p_ett->i_version ); |
589 | 0 | return; |
590 | 0 | } |
591 | 0 | } |
592 | 0 | } |
593 | 0 | dvbpsi_atsc_DeleteETT( p_ett ); |
594 | 0 | } |
595 | | |
596 | | static void ATSC_ETT_RawCallback( dvbpsi_t *p_handle, const dvbpsi_psi_section_t* p_section, |
597 | | void *p_base_pid ) |
598 | 0 | { |
599 | 0 | VLC_UNUSED( p_handle ); |
600 | 0 | for( ; p_section; p_section = p_section->p_next ) |
601 | 0 | { |
602 | 0 | dvbpsi_atsc_ett_t *p_ett = DVBPlague_ETT_Decode( p_section ); |
603 | 0 | if( p_ett ) /* Send to real callback */ |
604 | 0 | ATSC_ETT_Callback( p_base_pid, p_ett ); |
605 | 0 | } |
606 | 0 | } |
607 | | |
608 | | static void ATSC_VCT_Callback( void *p_cb_basepid, dvbpsi_atsc_vct_t* p_vct ) |
609 | 0 | { |
610 | 0 | ts_pid_t *p_base_pid = (ts_pid_t *) p_cb_basepid; |
611 | 0 | if( unlikely(p_base_pid->type != TYPE_PSIP || p_base_pid->i_pid != ATSC_BASE_PID) ) |
612 | 0 | { |
613 | 0 | assert( p_base_pid->type == TYPE_PSIP ); |
614 | 0 | assert( p_base_pid->i_pid == ATSC_BASE_PID ); |
615 | 0 | dvbpsi_atsc_DeleteVCT( p_vct ); |
616 | 0 | return; |
617 | 0 | } |
618 | 0 | demux_t *p_demux = (demux_t *) p_base_pid->u.p_psip->p_ctx->p_handle->p_sys; |
619 | 0 | ts_psip_context_t *p_ctx = p_base_pid->u.p_psip->p_ctx; |
620 | |
|
621 | 0 | if( !p_ctx->p_a65 && !(p_ctx->p_a65 = atsc_a65_handle_New( NULL )) ) |
622 | 0 | goto end; |
623 | | |
624 | 0 | for( const dvbpsi_atsc_vct_channel_t *p_channel = p_vct->p_first_channel; |
625 | 0 | p_channel; p_channel = p_channel->p_next ) |
626 | 0 | { |
627 | 0 | vlc_meta_t *p_meta = vlc_meta_New(); |
628 | 0 | if( p_meta ) |
629 | 0 | { |
630 | 0 | char *psz_name = NULL; |
631 | |
|
632 | 0 | for( dvbpsi_descriptor_t *p_dr = p_channel->p_first_descriptor; |
633 | 0 | p_dr; p_dr = p_dr->p_next ) |
634 | 0 | { |
635 | 0 | switch( p_dr->i_tag ) |
636 | 0 | { |
637 | 0 | case ATSC_DESCRIPTOR_EXTENDED_CHANNEL_NAME: |
638 | 0 | { |
639 | 0 | dvbpsi_extended_channel_name_dr_t *p_ecndr = |
640 | 0 | dvbpsi_ExtendedChannelNameDr( p_dr ); |
641 | 0 | if( p_ecndr ) |
642 | 0 | { |
643 | 0 | if( unlikely(psz_name) ) |
644 | 0 | free( psz_name ); |
645 | 0 | psz_name = atsc_a65_Decode_multiple_string( p_ctx->p_a65, |
646 | 0 | p_ecndr->i_long_channel_name, |
647 | 0 | p_ecndr->i_long_channel_name_length ); |
648 | 0 | } |
649 | |
|
650 | 0 | } break; |
651 | | |
652 | 0 | default: |
653 | 0 | break; |
654 | 0 | } |
655 | 0 | } |
656 | | |
657 | 0 | if( !psz_name ) |
658 | 0 | psz_name = atsc_a65_Decode_simple_UTF16_string( p_ctx->p_a65, |
659 | 0 | p_channel->i_short_name, 14 ); |
660 | 0 | if( psz_name ) |
661 | 0 | { |
662 | 0 | vlc_meta_SetTitle( p_meta, psz_name ); |
663 | 0 | free( psz_name ); |
664 | 0 | } |
665 | |
|
666 | 0 | const char *psz_service_type = ATSC_A53_get_service_type( p_channel->i_service_type ); |
667 | 0 | if( psz_service_type ) |
668 | 0 | vlc_meta_SetExtra( p_meta, "Type", psz_service_type ); |
669 | |
|
670 | 0 | es_out_Control( p_demux->out, ES_OUT_SET_GROUP_META, |
671 | 0 | p_channel->i_program_number, p_meta ); |
672 | |
|
673 | 0 | vlc_meta_Delete( p_meta ); |
674 | 0 | } |
675 | 0 | } |
676 | | |
677 | 0 | end: |
678 | 0 | if( p_ctx->p_vct ) |
679 | 0 | dvbpsi_atsc_DeleteVCT( p_ctx->p_vct ); |
680 | 0 | p_ctx->p_vct = p_vct; |
681 | 0 | } |
682 | | |
683 | | static void ATSC_MGT_Callback( void *p_cb_basepid, dvbpsi_atsc_mgt_t* p_mgt ) |
684 | 0 | { |
685 | 0 | ts_pid_t *p_base_pid = (ts_pid_t *) p_cb_basepid; |
686 | 0 | if( unlikely(p_base_pid->type != TYPE_PSIP || p_base_pid->i_pid != ATSC_BASE_PID) ) |
687 | 0 | { |
688 | 0 | assert( p_base_pid->type == TYPE_PSIP ); |
689 | 0 | assert( p_base_pid->i_pid == ATSC_BASE_PID ); |
690 | 0 | dvbpsi_atsc_DeleteMGT( p_mgt ); |
691 | 0 | return; |
692 | 0 | } |
693 | 0 | ts_psip_t *p_mgtpsip = p_base_pid->u.p_psip; |
694 | 0 | demux_t *p_demux = (demux_t *) p_mgtpsip->p_ctx->p_handle->p_sys; |
695 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
696 | |
|
697 | 0 | if( ( p_mgtpsip->p_ctx->i_version != -1 && p_mgtpsip->p_ctx->i_version == p_mgt->i_version ) || |
698 | 0 | p_mgt->b_current_next == 0 ) |
699 | 0 | { |
700 | 0 | dvbpsi_atsc_DeleteMGT( p_mgt ); |
701 | 0 | return; |
702 | 0 | } |
703 | | |
704 | | /* Easy way, delete and recreate every child if any new version comes |
705 | | * (We don't need to keep PID active as with video/PMT update) */ |
706 | 0 | if( p_mgtpsip->p_ctx->i_version != -1 ) |
707 | 0 | { |
708 | 0 | if( p_mgtpsip->p_ctx->p_vct ) |
709 | 0 | { |
710 | 0 | dvbpsi_atsc_DeleteVCT( p_mgtpsip->p_ctx->p_vct ); |
711 | 0 | p_mgtpsip->p_ctx->p_vct = NULL; |
712 | 0 | } |
713 | | |
714 | | /* Remove EIT/ETT */ |
715 | 0 | for( int i=0; i < p_mgtpsip->eit.i_size; i++ ) |
716 | 0 | { |
717 | 0 | PIDRelease( p_demux, p_mgtpsip->eit.p_elems[i] ); |
718 | 0 | assert( p_mgtpsip->eit.p_elems[i]->type == TYPE_FREE ); |
719 | 0 | } |
720 | 0 | ARRAY_RESET(p_mgtpsip->eit); |
721 | | |
722 | | /* Remove EAS */ |
723 | 0 | dvbpsi_demux_t *p_dvbpsi_demux = (dvbpsi_demux_t *) p_mgtpsip->p_ctx->p_handle->p_decoder; |
724 | 0 | dvbpsi_demux_subdec_t *p_subdec = dvbpsi_demuxGetSubDec( p_dvbpsi_demux, SCTE18_TABLE_ID, 0x00 ); |
725 | 0 | if( p_subdec ) |
726 | 0 | { |
727 | 0 | dvbpsi_DetachDemuxSubDecoder( p_dvbpsi_demux, p_subdec ); |
728 | 0 | dvbpsi_DeleteDemuxSubDecoder( p_subdec ); |
729 | 0 | } |
730 | 0 | } |
731 | |
|
732 | 0 | if( p_mgtpsip->p_ctx->p_mgt ) |
733 | 0 | dvbpsi_atsc_DeleteMGT( p_mgtpsip->p_ctx->p_mgt ); |
734 | 0 | p_mgtpsip->p_ctx->p_mgt = p_mgt; |
735 | 0 | p_mgtpsip->p_ctx->i_version = p_mgt->i_version; |
736 | |
|
737 | 0 | for( const dvbpsi_atsc_mgt_table_t *p_tab = p_mgt->p_first_table; |
738 | 0 | p_tab; p_tab = p_tab->p_next ) |
739 | 0 | { |
740 | 0 | if( p_tab->i_table_type == ATSC_TABLE_TYPE_TVCT || |
741 | 0 | p_tab->i_table_type == ATSC_TABLE_TYPE_CVCT ) |
742 | 0 | { |
743 | 0 | const uint8_t i_table_id = (p_tab->i_table_type == ATSC_TABLE_TYPE_CVCT) |
744 | 0 | ? ATSC_CVCT_TABLE_ID |
745 | 0 | : ATSC_TVCT_TABLE_ID; |
746 | 0 | if( !ATSC_ATTACH( p_mgtpsip->p_ctx->p_handle, VCT, i_table_id, |
747 | 0 | GetPID(p_sys, 0)->u.p_pat->i_ts_id, p_base_pid ) ) |
748 | 0 | msg_Dbg( p_demux, " * pid=%d listening for ATSC VCT", p_base_pid->i_pid ); |
749 | 0 | } |
750 | 0 | else if( p_tab->i_table_type >= ATSC_TABLE_TYPE_EIT_0 && |
751 | 0 | p_tab->i_table_type <= ATSC_TABLE_TYPE_EIT_0 + ATSC_EIT_MAX_DEPTH_MIN1 && |
752 | 0 | p_tab->i_table_type <= ATSC_TABLE_TYPE_EIT_127 && |
753 | 0 | p_tab->i_table_type_pid != p_base_pid->i_pid ) |
754 | 0 | { |
755 | 0 | ts_pid_t *pid = GetPID(p_sys, p_tab->i_table_type_pid); |
756 | 0 | if( PIDSetup( p_demux, TYPE_PSIP, pid, NULL ) ) |
757 | 0 | { |
758 | 0 | SetPIDFilter( p_demux->p_sys, pid, true ); |
759 | 0 | pid->u.p_psip->p_ctx->i_tabletype = p_tab->i_table_type; |
760 | 0 | ATSC_Ready_SubDecoders( pid->u.p_psip->p_ctx->p_handle, pid ); |
761 | 0 | msg_Dbg( p_demux, " * pid=%d reserved for ATSC EIT", pid->i_pid ); |
762 | 0 | ARRAY_APPEND( p_mgtpsip->eit, pid ); |
763 | 0 | } |
764 | 0 | } |
765 | 0 | else if( p_tab->i_table_type >= ATSC_TABLE_TYPE_ETT_0 && |
766 | 0 | p_tab->i_table_type <= ATSC_TABLE_TYPE_ETT_0 + ATSC_EIT_MAX_DEPTH_MIN1 && |
767 | 0 | p_tab->i_table_type <= ATSC_TABLE_TYPE_ETT_127 && |
768 | 0 | p_tab->i_table_type_pid != p_base_pid->i_pid ) |
769 | 0 | { |
770 | 0 | ts_pid_t *pid = GetPID(p_sys, p_tab->i_table_type_pid); |
771 | 0 | if( PIDSetup( p_demux, TYPE_PSIP, pid, NULL ) ) |
772 | 0 | { |
773 | 0 | SetPIDFilter( p_sys, pid, true ); |
774 | 0 | pid->u.p_psip->p_ctx->i_tabletype = p_tab->i_table_type; |
775 | 0 | ATSC_Ready_SubDecoders( pid->u.p_psip->p_ctx->p_handle, pid ); |
776 | 0 | msg_Dbg( p_demux, " * pid=%d reserved for ATSC ETT", pid->i_pid ); |
777 | 0 | ARRAY_APPEND( p_mgtpsip->eit, pid ); |
778 | 0 | } |
779 | 0 | } |
780 | 0 | msg_Dbg( p_demux, " * pid=%d transport for ATSC PSIP type %x", |
781 | 0 | p_tab->i_table_type_pid, p_tab->i_table_type ); |
782 | 0 | } |
783 | | |
784 | 0 | if( SCTE18_SI_BASE_PID == ATSC_BASE_PID && |
785 | 0 | ts_dvbpsi_AttachRawSubDecoder( p_mgtpsip->p_ctx->p_handle, SCTE18_TABLE_ID, 0x00, |
786 | 0 | SCTE18_Section_Callback, p_base_pid ) ) |
787 | 0 | { |
788 | 0 | msg_Dbg( p_demux, " * pid=%d listening for EAS", p_base_pid->i_pid ); |
789 | 0 | } |
790 | 0 | } |
791 | | |
792 | | static void ATSC_STT_Callback( void *p_cb_basepid, dvbpsi_atsc_stt_t* p_stt ) |
793 | 0 | { |
794 | 0 | ts_pid_t *p_base_pid = (ts_pid_t *) p_cb_basepid; |
795 | 0 | if( unlikely(p_base_pid->type != TYPE_PSIP || p_base_pid->i_pid != ATSC_BASE_PID) ) |
796 | 0 | { |
797 | 0 | assert( p_base_pid->type == TYPE_PSIP ); |
798 | 0 | assert( p_base_pid->i_pid == ATSC_BASE_PID ); |
799 | 0 | dvbpsi_atsc_DeleteSTT( p_stt ); |
800 | 0 | return; |
801 | 0 | } |
802 | 0 | demux_t *p_demux = (demux_t *) p_base_pid->u.p_psip->p_ctx->p_handle->p_sys; |
803 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
804 | 0 | ts_psip_context_t *p_ctx = p_base_pid->u.p_psip->p_ctx; |
805 | 0 | dvbpsi_t *p_handle = p_base_pid->u.p_psip->p_ctx->p_handle; |
806 | |
|
807 | 0 | if( !p_ctx->p_stt ) /* First call */ |
808 | 0 | { |
809 | 0 | if( !ATSC_ATTACH( p_handle, MGT, ATSC_MGT_TABLE_ID, 0x00, p_base_pid ) ) |
810 | 0 | { |
811 | 0 | msg_Err( p_demux, "Can't attach MGT decoder to pid %d", ATSC_BASE_PID ); |
812 | 0 | ATSC_Detach_Dvbpsi_Decoders( p_handle ); |
813 | 0 | dvbpsi_atsc_DeleteSTT( p_ctx->p_stt ); |
814 | 0 | p_stt = NULL; |
815 | 0 | } |
816 | 0 | } |
817 | 0 | else |
818 | 0 | { |
819 | 0 | dvbpsi_atsc_DeleteSTT( p_ctx->p_stt ); |
820 | 0 | } |
821 | |
|
822 | 0 | if( p_stt ) |
823 | 0 | { |
824 | 0 | time_t i_current_time = atsc_a65_GPSTimeToEpoch( p_stt->i_system_time, |
825 | 0 | p_stt->i_gps_utc_offset ); |
826 | 0 | EIT_DEBUG_TIMESHIFT( i_current_time ); |
827 | 0 | p_sys->i_network_time = i_current_time; |
828 | 0 | p_sys->i_network_time_update = time(NULL); |
829 | |
|
830 | 0 | es_out_Control( p_demux->out, ES_OUT_SET_EPG_TIME, p_sys->i_network_time ); |
831 | 0 | } |
832 | |
|
833 | 0 | p_ctx->p_stt = p_stt; |
834 | 0 | } |
835 | | |
836 | | static void ATSC_STT_RawCallback( dvbpsi_t *p_handle, const dvbpsi_psi_section_t* p_section, |
837 | | void *p_base_pid ) |
838 | 0 | { |
839 | 0 | VLC_UNUSED( p_handle ); |
840 | 0 | for( ; p_section ; p_section = p_section->p_next ) |
841 | 0 | { |
842 | 0 | dvbpsi_atsc_stt_t *p_stt = DVBPlague_STT_Decode( p_section ); |
843 | 0 | if( p_stt ) /* Send to real callback */ |
844 | 0 | ATSC_STT_Callback( p_base_pid, p_stt ); |
845 | 0 | } |
846 | 0 | } |
847 | | |
848 | | bool ATSC_Attach_Dvbpsi_Base_Decoders( ts_psip_context_t *p_ctx, void *p_base_pid ) |
849 | 261 | { |
850 | 261 | if( !ATSC_ATTACH_WITH_FIXED_DECODER( p_ctx->p_handle, STT, ATSC_STT_TABLE_ID, 0x00, p_base_pid ) ) |
851 | 0 | { |
852 | 0 | ATSC_Detach_Dvbpsi_Decoders( p_ctx->p_handle ); /* shouldn't be any, except demux */ |
853 | 0 | return false; |
854 | 0 | } |
855 | 261 | return true; |
856 | 261 | } |
857 | | |
858 | | static void ATSC_NewTable_Callback( dvbpsi_t *p_dvbpsi, uint8_t i_table_id, |
859 | | uint16_t i_extension, void *p_cb_pid ) |
860 | 0 | { |
861 | 0 | demux_t *p_demux = (demux_t *) p_dvbpsi->p_sys; |
862 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
863 | 0 | assert( ((ts_pid_t *) p_cb_pid)->type == TYPE_PSIP ); |
864 | 0 | const ts_pid_t *p_base_pid = ts_pid_Get( &p_sys->pids, ATSC_BASE_PID ); |
865 | 0 | if( !p_base_pid->u.p_psip->p_ctx->p_vct ) |
866 | 0 | return; |
867 | | |
868 | 0 | switch( i_table_id ) |
869 | 0 | { |
870 | 0 | case ATSC_ETT_TABLE_ID: |
871 | 0 | if( !ATSC_ATTACH_WITH_FIXED_DECODER( p_dvbpsi, ETT, ATSC_ETT_TABLE_ID, i_extension, p_cb_pid ) ) |
872 | 0 | msg_Warn( p_demux, "Cannot attach ETT decoder source %" PRIu16, i_extension ); |
873 | 0 | break; |
874 | | |
875 | 0 | case ATSC_EIT_TABLE_ID: |
876 | 0 | if( !ATSC_ATTACH( p_dvbpsi, EIT, ATSC_EIT_TABLE_ID, i_extension, p_cb_pid ) ) |
877 | 0 | msg_Warn( p_demux, "Cannot attach EIT decoder source %" PRIu16, i_extension ); |
878 | 0 | break; |
879 | | |
880 | 0 | default: |
881 | 0 | break; |
882 | 0 | } |
883 | 0 | } |