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 *****************************************************************************/
23 #include <vlc_common.h>
24 #include <vlc_demux.h>
26 #include "ts_streams.h"
28 #include "ts_streams_private.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
)
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
)
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
)
65 bool SetupISO14496LogicalStream( demux_t
*p_demux
, const decoder_config_descriptor_t
*dcd
,
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
);
79 case 0x20: /* mpeg4 */
80 es_format_Change( p_fmt
, VIDEO_ES
, VLC_CODEC_MP4V
);
83 es_format_Change( p_fmt
, VIDEO_ES
, VLC_CODEC_H264
);
90 case 0x65: /* mpeg2 */
91 case 0x6a: /* mpeg1 */
92 es_format_Change( p_fmt
, VIDEO_ES
, VLC_CODEC_MPGV
);
94 case 0x6c: /* mpeg1 */
95 es_format_Change( p_fmt
, VIDEO_ES
, VLC_CODEC_JPEG
);
101 else if( dcd
->i_streamType
== 0x05 ) /* AudioStream */
103 switch( dcd
->i_objectTypeIndication
)
105 case 0x40: /* mpeg4 */
108 case 0x68: /* mpeg2 aac */
109 es_format_Change( p_fmt
, AUDIO_ES
, VLC_CODEC_MP4A
);
111 case 0x69: /* mpeg2 */
112 case 0x6b: /* mpeg1 */
113 es_format_Change( p_fmt
, AUDIO_ES
, VLC_CODEC_MPGA
);
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
);
127 memcpy( p_fmt
->p_extra
, dcd
->p_extra
, p_fmt
->i_extra
);
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
,
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
);
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
);
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
);
189 UpdatePESFilters( p_demux
, p_demux
->p_sys
->b_es_all
);
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
);
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
);
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
);
229 const es_mpeg4_descriptor_t
*p_desc
= GetMPEG4DescByEsId( p_pmt
, p_es
->i_sl_es_id
);
232 block_Release( p_block
);
237 sl_header_data header
= DecodeSLHeader( p_block
->i_buffer
, p_block
->p_buffer
,
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
);
249 ctx
->pp_au_last
= &ctx
->p_au
;
251 block_ChainLastAppend( &ctx
->pp_au_last
, p_block
);
253 if( header
.b_au_end
)
255 p_block
= block_ChainGather( ctx
->p_au
);
257 ctx
->pp_au_last
= &ctx
->p_au
;
264 ts_stream_processor_t
*SL_stream_processor_New( ts_stream_t
*p_stream
)
266 ts_stream_processor_t
*h
= malloc(sizeof(*h
));
270 SL_stream_processor_context_t
*ctx
= malloc( sizeof(SL_stream_processor_context_t
) );
277 ctx
->pp_au_last
= &ctx
->p_au
;
278 ctx
->p_stream
= p_stream
;
281 h
->pf_delete
= SL_stream_processor_Delete
;
282 h
->pf_push
= SL_stream_processor_Push
;
283 h
->pf_reset
= SL_stream_processor_Reset
;