demux: ts: use es_format_Change for mpeg-sl
[vlc.git] / modules / demux / mpeg / ts_sl.c
blob594f3080b42da02fb40992d93c80b0485f32910f
1 /*****************************************************************************
2 * ts_sl.c : MPEG SL/FMC handling for TS demuxer
3 *****************************************************************************
4 * Copyright (C) 2014-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 *****************************************************************************/
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
23 #include <vlc_common.h>
24 #include <vlc_demux.h>
26 #include "ts_streams.h"
27 #include "ts_pid.h"
28 #include "ts_streams_private.h"
29 #include "ts.h"
31 #include "ts_sl.h"
33 const es_mpeg4_descriptor_t * GetMPEG4DescByEsId( const ts_pmt_t *pmt, uint16_t i_es_id )
35 for( int i = 0; i < ES_DESCRIPTOR_COUNT; i++ )
37 const es_mpeg4_descriptor_t *es_descr = &pmt->iod->es_descr[i];
38 if( es_descr->i_es_id == i_es_id && es_descr->b_ok )
39 return es_descr;
41 for( int i=0; i<pmt->od.objects.i_size; i++ )
43 const od_descriptor_t *od = pmt->od.objects.p_elems[i];
44 for( int j = 0; j < ES_DESCRIPTOR_COUNT; j++ )
46 const es_mpeg4_descriptor_t *es_descr = &od->es_descr[j];
47 if( es_descr->i_es_id == i_es_id && es_descr->b_ok )
48 return es_descr;
51 return NULL;
54 static ts_es_t * GetPMTESBySLEsId( ts_pmt_t *pmt, uint16_t i_sl_es_id )
56 for( int i=0; i< pmt->e_streams.i_size; i++ )
58 ts_es_t *p_es = pmt->e_streams.p_elems[i]->u.p_stream->p_es;
59 if( p_es->i_sl_es_id == i_sl_es_id )
60 return p_es;
62 return NULL;
65 bool SetupISO14496LogicalStream( demux_t *p_demux, const decoder_config_descriptor_t *dcd,
66 es_format_t *p_fmt )
68 msg_Dbg( p_demux, " - IOD objecttype: %"PRIx8" streamtype:%"PRIx8,
69 dcd->i_objectTypeIndication, dcd->i_streamType );
71 if( dcd->i_streamType == 0x04 ) /* VisualStream */
73 switch( dcd->i_objectTypeIndication )
75 case 0x0B: /* mpeg4 sub */
76 es_format_Change( p_fmt, SPU_ES, VLC_CODEC_SUBT );
77 break;
79 case 0x20: /* mpeg4 */
80 es_format_Change( p_fmt, VIDEO_ES, VLC_CODEC_MP4V );
81 break;
82 case 0x21: /* h264 */
83 es_format_Change( p_fmt, VIDEO_ES, VLC_CODEC_H264 );
84 break;
85 case 0x60:
86 case 0x61:
87 case 0x62:
88 case 0x63:
89 case 0x64:
90 case 0x65: /* mpeg2 */
91 case 0x6a: /* mpeg1 */
92 es_format_Change( p_fmt, VIDEO_ES, VLC_CODEC_MPGV );
93 break;
94 case 0x6c: /* mpeg1 */
95 es_format_Change( p_fmt, VIDEO_ES, VLC_CODEC_JPEG );
96 break;
97 default:
98 break;
101 else if( dcd->i_streamType == 0x05 ) /* AudioStream */
103 switch( dcd->i_objectTypeIndication )
105 case 0x40: /* mpeg4 */
106 case 0x66:
107 case 0x67:
108 case 0x68: /* mpeg2 aac */
109 es_format_Change( p_fmt, AUDIO_ES, VLC_CODEC_MP4A );
110 break;
111 case 0x69: /* mpeg2 */
112 case 0x6b: /* mpeg1 */
113 es_format_Change( p_fmt, AUDIO_ES, VLC_CODEC_MPGA );
114 break;
115 default:
116 break;
120 if( p_fmt->i_cat != UNKNOWN_ES )
122 p_fmt->i_extra = __MIN(dcd->i_extra, INT32_MAX);
123 if( p_fmt->i_extra > 0 )
125 p_fmt->p_extra = malloc( p_fmt->i_extra );
126 if( p_fmt->p_extra )
127 memcpy( p_fmt->p_extra, dcd->p_extra, p_fmt->i_extra );
128 else
129 p_fmt->i_extra = 0;
133 return true;
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 )
142 VLC_UNUSED(p_sectiondata); VLC_UNUSED(i_sectiondata);
143 ts_stream_t *p_pes = (ts_stream_t *) p_pes_cbdata;
144 ts_pmt_t *p_pmt = p_pes->p_es->p_program;
146 const es_mpeg4_descriptor_t *p_mpeg4desc = GetMPEG4DescByEsId( p_pmt, p_pes->p_es->i_sl_es_id );
147 if( p_mpeg4desc && p_mpeg4desc->dec_descr.i_objectTypeIndication == 0x01 &&
148 p_mpeg4desc->dec_descr.i_streamType == 0x01 /* Object */ )
150 const uint8_t *p_data = p_payloaddata;
151 size_t i_data = i_payloaddata;
153 od_descriptors_t *p_ods = &p_pmt->od;
154 sl_header_data header = DecodeSLHeader( i_data, p_data, &p_mpeg4desc->sl_descr );
156 DecodeODCommand( VLC_OBJECT(p_demux), p_ods, i_data - header.i_size, &p_data[header.i_size] );
157 bool b_changed = false;
159 for( int i=0; i<p_ods->objects.i_size; i++ )
161 od_descriptor_t *p_od = p_ods->objects.p_elems[i];
162 for( int j = 0; j < ES_DESCRIPTOR_COUNT && p_od->es_descr[j].b_ok; j++ )
164 p_mpeg4desc = &p_od->es_descr[j];
165 ts_es_t *p_es = GetPMTESBySLEsId( p_pmt, p_mpeg4desc->i_es_id );
166 es_format_t fmt;
167 es_format_Init( &fmt, UNKNOWN_ES, 0 );
169 if ( p_mpeg4desc && p_mpeg4desc->b_ok && p_es &&
170 SetupISO14496LogicalStream( p_demux, &p_mpeg4desc->dec_descr, &fmt ) &&
171 !es_format_IsSimilar( &fmt, &p_es->fmt ) )
173 fmt.i_id = p_es->fmt.i_id;
174 fmt.i_group = p_es->fmt.i_group;
175 es_format_Clean( &p_es->fmt );
176 p_es->fmt = fmt;
178 if( p_es->id )
179 es_out_Del( p_demux->out, p_es->id );
180 p_es->fmt.b_packetized = true; /* Split by access unit, no sync code */
181 FREENULL( p_es->fmt.psz_description );
182 p_es->id = es_out_Add( p_demux->out, &p_es->fmt );
183 b_changed = true;
188 if( b_changed )
189 UpdatePESFilters( p_demux, p_demux->p_sys->b_es_all );
193 typedef struct
195 block_t *p_au;
196 block_t **pp_au_last;
197 ts_stream_t *p_stream;
199 } SL_stream_processor_context_t;
201 static void SL_stream_processor_Delete( ts_stream_processor_t *h )
203 SL_stream_processor_context_t *ctx = (SL_stream_processor_context_t *) h->priv;
204 block_ChainRelease( ctx->p_au );
205 free( ctx );
206 free( h );
209 static void SL_stream_processor_Reset( ts_stream_processor_t *h )
211 SL_stream_processor_context_t *ctx = (SL_stream_processor_context_t *) h->priv;
212 block_ChainRelease( ctx->p_au );
213 ctx->p_au = NULL;
214 ctx->pp_au_last = &ctx->p_au;
217 static block_t * SL_stream_processor_Push( ts_stream_processor_t *h, uint8_t i_stream_id, block_t *p_block )
219 SL_stream_processor_context_t *ctx = (SL_stream_processor_context_t *) h->priv;
220 ts_es_t *p_es = ctx->p_stream->p_es;
221 ts_pmt_t *p_pmt = p_es->p_program;
223 if( ((i_stream_id & 0xFE) != 0xFA) /* 0xFA || 0xFB */ )
225 block_Release( p_block );
226 return NULL;
229 const es_mpeg4_descriptor_t *p_desc = GetMPEG4DescByEsId( p_pmt, p_es->i_sl_es_id );
230 if(!p_desc)
232 block_Release( p_block );
233 p_block = NULL;
235 else
237 sl_header_data header = DecodeSLHeader( p_block->i_buffer, p_block->p_buffer,
238 &p_desc->sl_descr );
239 p_block->i_buffer -= header.i_size;
240 p_block->p_buffer += header.i_size;
241 p_block->i_dts = header.i_dts ? header.i_dts : p_block->i_dts;
242 p_block->i_pts = header.i_pts ? header.i_pts : p_block->i_pts;
244 /* Assemble access units */
245 if( header.b_au_start && ctx->p_au )
247 block_ChainRelease( ctx->p_au );
248 ctx->p_au = NULL;
249 ctx->pp_au_last = &ctx->p_au;
251 block_ChainLastAppend( &ctx->pp_au_last, p_block );
252 p_block = NULL;
253 if( header.b_au_end )
255 p_block = block_ChainGather( ctx->p_au );
256 ctx->p_au = NULL;
257 ctx->pp_au_last = &ctx->p_au;
261 return p_block;
264 ts_stream_processor_t *SL_stream_processor_New( ts_stream_t *p_stream )
266 ts_stream_processor_t *h = malloc(sizeof(*h));
267 if(!h)
268 return NULL;
270 SL_stream_processor_context_t *ctx = malloc( sizeof(SL_stream_processor_context_t) );
271 if(!ctx)
273 free(h);
274 return NULL;
276 ctx->p_au = NULL;
277 ctx->pp_au_last = &ctx->p_au;
278 ctx->p_stream = p_stream;
280 h->priv = ctx;
281 h->pf_delete = SL_stream_processor_Delete;
282 h->pf_push = SL_stream_processor_Push;
283 h->pf_reset = SL_stream_processor_Reset;
285 return h;