/src/vlc/modules/demux/mpeg/sections.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * sections.c: Transport Stream sections assembler |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2016 VLC authors and VideoLAN |
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 Lesser General Public License |
17 | | * along with this program; if not, write to the Free Software Foundation, |
18 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
19 | | *****************************************************************************/ |
20 | | #ifdef HAVE_CONFIG_H |
21 | | # include "config.h" |
22 | | #endif |
23 | | |
24 | | #include <vlc_common.h> |
25 | | #include <vlc_demux.h> |
26 | | |
27 | | #include "ts_pid.h" |
28 | | #include "sections.h" |
29 | | |
30 | | #ifndef _DVBPSI_DVBPSI_H_ |
31 | | #include <dvbpsi/dvbpsi.h> |
32 | | #endif |
33 | | #ifndef _DVBPSI_DEMUX_H_ |
34 | | #include <dvbpsi/demux.h> |
35 | | #endif |
36 | | #include <dvbpsi/psi.h> |
37 | | #include "../../mux/mpeg/dvbpsi_compat.h" /* dvbpsi_messages */ |
38 | | |
39 | | #include "ts_decoders.h" |
40 | | |
41 | | #include <assert.h> |
42 | | |
43 | | struct ts_sections_processor_t |
44 | | { |
45 | | uint8_t i_stream_type; |
46 | | uint8_t i_table_id; |
47 | | uint16_t i_extension_id; |
48 | | dvbpsi_t *p_dvbpsi; |
49 | | ts_section_processor_callback_t pf_callback; |
50 | | ts_sections_processor_t *p_next; |
51 | | void *p_callback_data; |
52 | | }; |
53 | | |
54 | | static void ts_subdecoder_rawsection_Callback( dvbpsi_t *p_dvbpsi, |
55 | | const dvbpsi_psi_section_t* p_section, |
56 | | void* p_proc_cb_data ) |
57 | 176k | { |
58 | 176k | ts_sections_processor_t *p_proc = (ts_sections_processor_t *) p_proc_cb_data; |
59 | 176k | if( likely(p_proc->pf_callback) ) |
60 | 176k | { |
61 | 352k | for( const dvbpsi_psi_section_t *p_sec = p_section; p_sec; p_sec = p_sec->p_next ) |
62 | 176k | { |
63 | 176k | size_t i_rawlength = p_sec->p_payload_end - p_sec->p_data; |
64 | 176k | if ( p_sec->b_syntax_indicator ) |
65 | 67.9k | i_rawlength += 4; |
66 | | |
67 | 176k | if( p_proc->i_table_id && p_section->i_table_id != p_proc->i_table_id ) |
68 | 50.5k | continue; |
69 | | |
70 | 125k | if( p_proc->i_extension_id && p_section->i_extension != p_proc->i_extension_id ) |
71 | 0 | continue; |
72 | | |
73 | 125k | p_proc->pf_callback( (demux_t *) p_dvbpsi->p_sys, |
74 | 125k | p_sec->p_data, i_rawlength, |
75 | 125k | p_sec->p_payload_start, |
76 | 125k | p_sec->p_payload_end - p_sec->p_payload_start, |
77 | 125k | p_proc->p_callback_data ); |
78 | 125k | } |
79 | 176k | } |
80 | 176k | } |
81 | | |
82 | | void ts_sections_processor_Add( demux_t *p_demux, |
83 | | ts_sections_processor_t **pp_chain, |
84 | | uint8_t i_table_id, uint16_t i_extension_id, |
85 | | ts_section_processor_callback_t pf_callback, |
86 | | void *p_callback_data ) |
87 | 52.8k | { |
88 | 52.8k | ts_sections_processor_t *p_proc = *pp_chain; |
89 | 52.8k | for( ; p_proc; p_proc = p_proc->p_next ) |
90 | 0 | { |
91 | | /* Avoid duplicates */ |
92 | 0 | if ( p_proc->i_extension_id == i_extension_id && |
93 | 0 | p_proc->i_table_id == i_table_id && |
94 | 0 | p_proc->pf_callback == pf_callback ) |
95 | 0 | return; |
96 | 0 | } |
97 | | |
98 | 52.8k | p_proc = malloc( sizeof(ts_sections_processor_t) ); |
99 | 52.8k | if( p_proc ) |
100 | 52.8k | { |
101 | 52.8k | p_proc->pf_callback = pf_callback; |
102 | 52.8k | p_proc->i_extension_id = i_extension_id; |
103 | 52.8k | p_proc->i_table_id = i_table_id; |
104 | 52.8k | p_proc->p_dvbpsi = dvbpsi_new( &dvbpsi_messages, DVBPSI_MSG_DEBUG ); |
105 | 52.8k | p_proc->p_dvbpsi->p_sys = p_demux; |
106 | 52.8k | p_proc->p_callback_data = p_callback_data; |
107 | | |
108 | 52.8k | if( !ts_dvbpsi_AttachRawDecoder( p_proc->p_dvbpsi, |
109 | 52.8k | ts_subdecoder_rawsection_Callback, p_proc ) ) |
110 | 0 | { |
111 | 0 | ts_sections_processor_ChainDelete( p_proc ); |
112 | 0 | return; |
113 | 0 | } |
114 | | /* Insert as head */ |
115 | 52.8k | p_proc->p_next = *pp_chain; |
116 | 52.8k | *pp_chain = p_proc; |
117 | 52.8k | } |
118 | 52.8k | } |
119 | | |
120 | | void ts_sections_processor_ChainDelete( ts_sections_processor_t *p_chain ) |
121 | 52.8k | { |
122 | 105k | while( p_chain ) |
123 | 52.8k | { |
124 | 52.8k | ts_dvbpsi_DetachRawDecoder( p_chain->p_dvbpsi ); |
125 | 52.8k | dvbpsi_delete( p_chain->p_dvbpsi ); |
126 | 52.8k | ts_sections_processor_t *p_next = p_chain->p_next; |
127 | 52.8k | free( p_chain ); |
128 | 52.8k | p_chain = p_next; |
129 | 52.8k | } |
130 | 52.8k | } |
131 | | |
132 | | void ts_sections_processor_Reset( ts_sections_processor_t *p_chain ) |
133 | 0 | { |
134 | 0 | while( p_chain ) |
135 | 0 | { |
136 | 0 | dvbpsi_decoder_reset( p_chain->p_dvbpsi->p_decoder, true ); |
137 | 0 | p_chain = p_chain->p_next; |
138 | 0 | } |
139 | 0 | } |
140 | | |
141 | | void ts_sections_processor_Push( ts_sections_processor_t *p_chain, |
142 | | const uint8_t *p_buf ) |
143 | 248k | { |
144 | 248k | for( ts_sections_processor_t *p_proc = p_chain; |
145 | 497k | p_proc; p_proc = p_proc->p_next ) |
146 | 248k | { |
147 | 248k | dvbpsi_packet_push( p_chain->p_dvbpsi, (uint8_t *) p_buf ); |
148 | 248k | } |
149 | 248k | } |