/src/vlc/modules/demux/mpeg/ts_sl.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * ts_sl.c : MPEG SL/FMC handling for TS demuxer |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2014-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 | | |
26 | | #include "ts_streams.h" |
27 | | #include "ts_pid.h" |
28 | | #include "ts_streams_private.h" |
29 | | #include "ts.h" |
30 | | |
31 | | #include "ts_sl.h" |
32 | | |
33 | | const es_mpeg4_descriptor_t * GetMPEG4DescByEsId( const ts_pmt_t *pmt, uint16_t i_es_id ) |
34 | 1.71M | { |
35 | 395M | for( int i = 0; pmt->iod && i < ES_DESCRIPTOR_COUNT; i++ ) |
36 | 394M | { |
37 | 394M | const es_mpeg4_descriptor_t *es_descr = &pmt->iod->es_descr[i]; |
38 | 394M | if( es_descr->i_es_id == i_es_id && es_descr->b_ok ) |
39 | 174k | return es_descr; |
40 | 394M | } |
41 | 2.28M | for( int i=0; i<pmt->od.objects.i_size; i++ ) |
42 | 2.12M | { |
43 | 2.12M | const od_descriptor_t *od = pmt->od.objects.p_elems[i]; |
44 | 190M | for( int j = 0; j < ES_DESCRIPTOR_COUNT; j++ ) |
45 | 190M | { |
46 | 190M | const es_mpeg4_descriptor_t *es_descr = &od->es_descr[j]; |
47 | 190M | if( es_descr->i_es_id == i_es_id && es_descr->b_ok ) |
48 | 1.38M | return es_descr; |
49 | 190M | } |
50 | 2.12M | } |
51 | 161k | return NULL; |
52 | 1.54M | } |
53 | | |
54 | | static ts_es_t * GetPMTESBySLEsId( ts_pmt_t *pmt, uint16_t i_sl_es_id ) |
55 | 329k | { |
56 | 1.21M | for( int i=0; i< pmt->e_streams.i_size; i++ ) |
57 | 1.21M | { |
58 | 1.21M | ts_es_t *p_es = pmt->e_streams.p_elems[i]->u.p_stream->p_es; |
59 | 1.21M | if( p_es->i_sl_es_id == i_sl_es_id ) |
60 | 328k | return p_es; |
61 | 1.21M | } |
62 | 754 | return NULL; |
63 | 329k | } |
64 | | |
65 | | bool SetupISO14496LogicalStream( demux_t *p_demux, const decoder_config_descriptor_t *dcd, |
66 | | es_format_t *p_fmt ) |
67 | 395k | { |
68 | 395k | msg_Dbg( p_demux, " - IOD objecttype: %"PRIx8" streamtype:%"PRIx8, |
69 | 395k | dcd->i_objectTypeIndication, dcd->i_streamType ); |
70 | | |
71 | 395k | if( dcd->i_streamType == 0x04 ) /* VisualStream */ |
72 | 183k | { |
73 | 183k | switch( dcd->i_objectTypeIndication ) |
74 | 183k | { |
75 | 3.41k | case 0x0B: /* mpeg4 sub */ |
76 | 3.41k | es_format_Change( p_fmt, SPU_ES, VLC_CODEC_SUBT ); |
77 | 3.41k | break; |
78 | | |
79 | 9.40k | case 0x20: /* mpeg4 */ |
80 | 9.40k | es_format_Change( p_fmt, VIDEO_ES, VLC_CODEC_MP4V ); |
81 | 9.40k | break; |
82 | 113k | case 0x21: /* h264 */ |
83 | 113k | es_format_Change( p_fmt, VIDEO_ES, VLC_CODEC_H264 ); |
84 | 113k | break; |
85 | 735 | case 0x60: |
86 | 39.9k | case 0x61: |
87 | 40.9k | case 0x62: |
88 | 41.3k | case 0x63: |
89 | 42.3k | case 0x64: |
90 | 42.6k | case 0x65: /* mpeg2 */ |
91 | 42.7k | case 0x6a: /* mpeg1 */ |
92 | 42.7k | es_format_Change( p_fmt, VIDEO_ES, VLC_CODEC_MPGV ); |
93 | 42.7k | break; |
94 | 2.58k | case 0x6c: /* mpeg1 */ |
95 | 2.58k | es_format_Change( p_fmt, VIDEO_ES, VLC_CODEC_JPEG ); |
96 | 2.58k | break; |
97 | 11.3k | default: |
98 | 11.3k | break; |
99 | 183k | } |
100 | 183k | } |
101 | 212k | else if( dcd->i_streamType == 0x05 ) /* AudioStream */ |
102 | 150k | { |
103 | 150k | switch( dcd->i_objectTypeIndication ) |
104 | 150k | { |
105 | 113k | case 0x40: /* mpeg4 */ |
106 | 113k | case 0x66: |
107 | 114k | case 0x67: |
108 | 118k | case 0x68: /* mpeg2 aac */ |
109 | 118k | es_format_Change( p_fmt, AUDIO_ES, VLC_CODEC_MP4A ); |
110 | 118k | break; |
111 | 664 | case 0x69: /* mpeg2 */ |
112 | 31.6k | case 0x6b: /* mpeg1 */ |
113 | 31.6k | es_format_Change( p_fmt, AUDIO_ES, VLC_CODEC_MPGA ); |
114 | 31.6k | break; |
115 | 794 | default: |
116 | 794 | break; |
117 | 150k | } |
118 | 150k | } |
119 | | |
120 | 395k | if( p_fmt->i_cat != UNKNOWN_ES ) |
121 | 321k | { |
122 | 321k | p_fmt->i_extra = __MIN(dcd->i_extra, INT32_MAX); |
123 | 321k | if( p_fmt->i_extra > 0 ) |
124 | 213k | { |
125 | 213k | p_fmt->p_extra = malloc( p_fmt->i_extra ); |
126 | 213k | if( p_fmt->p_extra ) |
127 | 213k | memcpy( p_fmt->p_extra, dcd->p_extra, p_fmt->i_extra ); |
128 | 0 | else |
129 | 0 | p_fmt->i_extra = 0; |
130 | 213k | } |
131 | 321k | } |
132 | | |
133 | 395k | return true; |
134 | 395k | } |
135 | | |
136 | | /* Object stream SL in table sections */ |
137 | | void SLPackets_Section_Handler( demux_t *p_demux, |
138 | | const uint8_t *p_sectiondata, size_t i_sectiondata, |
139 | | const uint8_t *p_payloaddata, size_t i_payloaddata, |
140 | | void *p_pes_cbdata ) |
141 | 122k | { |
142 | 122k | VLC_UNUSED(p_sectiondata); VLC_UNUSED(i_sectiondata); |
143 | 122k | demux_sys_t *p_sys = p_demux->p_sys; |
144 | 122k | ts_stream_t *p_pes = (ts_stream_t *) p_pes_cbdata; |
145 | 122k | ts_pmt_t *p_pmt = p_pes->p_es->p_program; |
146 | | |
147 | 122k | const es_mpeg4_descriptor_t *p_mpeg4desc = GetMPEG4DescByEsId( p_pmt, p_pes->p_es->i_sl_es_id ); |
148 | 122k | if( p_mpeg4desc && p_mpeg4desc->dec_descr.i_objectTypeIndication == 0x01 && |
149 | 122k | p_mpeg4desc->dec_descr.i_streamType == 0x01 /* Object */ ) |
150 | 122k | { |
151 | 122k | const uint8_t *p_data = p_payloaddata; |
152 | 122k | size_t i_data = i_payloaddata; |
153 | | |
154 | 122k | od_descriptors_t *p_ods = &p_pmt->od; |
155 | 122k | sl_header_data header = DecodeSLHeader( i_data, p_data, &p_mpeg4desc->sl_descr ); |
156 | | |
157 | 122k | DecodeODCommand( VLC_OBJECT(p_demux), p_ods, i_data - header.i_size, &p_data[header.i_size] ); |
158 | 122k | bool b_changed = false; |
159 | | |
160 | 461k | for( int i=0; i<p_ods->objects.i_size; i++ ) |
161 | 339k | { |
162 | 339k | od_descriptor_t *p_od = p_ods->objects.p_elems[i]; |
163 | 668k | for( int j = 0; j < ES_DESCRIPTOR_COUNT && p_od->es_descr[j].b_ok; j++ ) |
164 | 329k | { |
165 | 329k | p_mpeg4desc = &p_od->es_descr[j]; |
166 | 329k | ts_es_t *p_es = GetPMTESBySLEsId( p_pmt, p_mpeg4desc->i_es_id ); |
167 | 329k | es_format_t fmt; |
168 | 329k | es_format_Init( &fmt, UNKNOWN_ES, 0 ); |
169 | | |
170 | 329k | if ( p_mpeg4desc && p_mpeg4desc->b_ok && p_es && |
171 | 328k | SetupISO14496LogicalStream( p_demux, &p_mpeg4desc->dec_descr, &fmt ) && |
172 | 328k | !es_format_IsSimilar( &fmt, &p_es->fmt ) ) |
173 | 213k | { |
174 | 213k | fmt.i_id = p_es->fmt.i_id; |
175 | 213k | fmt.i_group = p_es->fmt.i_group; |
176 | 213k | es_format_Clean( &p_es->fmt ); |
177 | 213k | p_es->fmt = fmt; |
178 | | |
179 | 213k | if( p_es->id ) |
180 | 195k | { |
181 | 195k | es_out_Del( p_demux->out, p_es->id ); |
182 | 195k | p_sys->i_pmt_es--; |
183 | 195k | } |
184 | 213k | p_es->fmt.b_packetized = true; /* Split by access unit, no sync code */ |
185 | 213k | p_es->id = es_out_Add( p_demux->out, &p_es->fmt ); |
186 | 213k | if( p_es->id ) |
187 | 213k | p_sys->i_pmt_es++; |
188 | 213k | b_changed = true; |
189 | 213k | } |
190 | 115k | else |
191 | 115k | es_format_Clean( &fmt ); |
192 | 329k | } |
193 | 339k | } |
194 | | |
195 | 122k | if( b_changed ) |
196 | 96.5k | UpdatePESFilters( p_demux, p_sys->seltype == PROGRAM_ALL ); |
197 | 122k | } |
198 | 122k | } |
199 | | |
200 | | typedef struct |
201 | | { |
202 | | block_t *p_au; |
203 | | block_t **pp_au_last; |
204 | | ts_stream_t *p_stream; |
205 | | |
206 | | } SL_stream_processor_context_t; |
207 | | |
208 | | static void SL_stream_processor_Delete( ts_stream_processor_t *h ) |
209 | 51.5k | { |
210 | 51.5k | SL_stream_processor_context_t *ctx = (SL_stream_processor_context_t *) h->priv; |
211 | 51.5k | block_ChainRelease( ctx->p_au ); |
212 | 51.5k | free( ctx ); |
213 | 51.5k | free( h ); |
214 | 51.5k | } |
215 | | |
216 | | static void SL_stream_processor_Reset( ts_stream_processor_t *h ) |
217 | 144 | { |
218 | 144 | SL_stream_processor_context_t *ctx = (SL_stream_processor_context_t *) h->priv; |
219 | 144 | block_ChainRelease( ctx->p_au ); |
220 | 144 | ctx->p_au = NULL; |
221 | 144 | ctx->pp_au_last = &ctx->p_au; |
222 | 144 | } |
223 | | |
224 | | static block_t * SL_stream_processor_Push( ts_stream_processor_t *h, uint8_t i_stream_id, block_t *p_block ) |
225 | 770k | { |
226 | 770k | SL_stream_processor_context_t *ctx = (SL_stream_processor_context_t *) h->priv; |
227 | 770k | ts_es_t *p_es = ctx->p_stream->p_es; |
228 | 770k | ts_pmt_t *p_pmt = p_es->p_program; |
229 | | |
230 | 770k | if( ((i_stream_id & 0xFE) != 0xFA) /* 0xFA || 0xFB */ ) |
231 | 14.4k | { |
232 | 14.4k | block_Release( p_block ); |
233 | 14.4k | return NULL; |
234 | 14.4k | } |
235 | | |
236 | 756k | const es_mpeg4_descriptor_t *p_desc = GetMPEG4DescByEsId( p_pmt, p_es->i_sl_es_id ); |
237 | 756k | if(!p_desc) |
238 | 61.1k | { |
239 | 61.1k | block_Release( p_block ); |
240 | 61.1k | p_block = NULL; |
241 | 61.1k | } |
242 | 695k | else |
243 | 695k | { |
244 | 695k | sl_header_data header = DecodeSLHeader( p_block->i_buffer, p_block->p_buffer, |
245 | 695k | &p_desc->sl_descr ); |
246 | 695k | p_block->i_buffer -= header.i_size; |
247 | 695k | p_block->p_buffer += header.i_size; |
248 | 695k | p_block->i_dts = header.i_dts ? header.i_dts : p_block->i_dts; |
249 | 695k | p_block->i_pts = header.i_pts ? header.i_pts : p_block->i_pts; |
250 | | |
251 | | /* Assemble access units */ |
252 | 695k | if( header.b_au_start && ctx->p_au ) |
253 | 4.70k | { |
254 | 4.70k | block_ChainRelease( ctx->p_au ); |
255 | 4.70k | ctx->p_au = NULL; |
256 | 4.70k | ctx->pp_au_last = &ctx->p_au; |
257 | 4.70k | } |
258 | 695k | block_ChainLastAppend( &ctx->pp_au_last, p_block ); |
259 | 695k | p_block = NULL; |
260 | 695k | if( header.b_au_end && ctx->p_au ) |
261 | 689k | { |
262 | 689k | p_block = block_ChainGather( ctx->p_au ); |
263 | 689k | ctx->p_au = NULL; |
264 | 689k | ctx->pp_au_last = &ctx->p_au; |
265 | 689k | } |
266 | 695k | } |
267 | | |
268 | 756k | return p_block; |
269 | 770k | } |
270 | | |
271 | | ts_stream_processor_t *SL_stream_processor_New( ts_stream_t *p_stream ) |
272 | 51.5k | { |
273 | 51.5k | ts_stream_processor_t *h = malloc(sizeof(*h)); |
274 | 51.5k | if(!h) |
275 | 0 | return NULL; |
276 | | |
277 | 51.5k | SL_stream_processor_context_t *ctx = malloc( sizeof(SL_stream_processor_context_t) ); |
278 | 51.5k | if(!ctx) |
279 | 0 | { |
280 | 0 | free(h); |
281 | 0 | return NULL; |
282 | 0 | } |
283 | 51.5k | ctx->p_au = NULL; |
284 | 51.5k | ctx->pp_au_last = &ctx->p_au; |
285 | 51.5k | ctx->p_stream = p_stream; |
286 | | |
287 | 51.5k | h->priv = ctx; |
288 | 51.5k | h->pf_delete = SL_stream_processor_Delete; |
289 | 51.5k | h->pf_push = SL_stream_processor_Push; |
290 | 51.5k | h->pf_reset = SL_stream_processor_Reset; |
291 | | |
292 | 51.5k | return h; |
293 | 51.5k | } |