1 /*****************************************************************************
2  * ts_hotfixes.c : MPEG PMT/PAT less streams fixups
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 #include <vlc_es.h>
26 
27 #ifndef _DVBPSI_DVBPSI_H_
28  #include <dvbpsi/dvbpsi.h>
29 #endif
30 #include <dvbpsi/descriptor.h>
31 #include <dvbpsi/pat.h>
32 #include <dvbpsi/pmt.h>
33 
34 #include "../../mux/mpeg/streams.h"
35 #include "../../mux/mpeg/tsutil.h"
36 #include "../../mux/mpeg/tables.h"
37 
38 #include "timestamps.h"
39 #include "pes.h"
40 
41 #include "ts_streams.h"
42 #include "ts_psi.h"
43 #include "ts_pid.h"
44 #include "ts_streams_private.h"
45 #include "ts.h"
46 #include "ts_hotfixes.h"
47 
48 #include <assert.h>
49 
ProbePES(demux_t * p_demux,ts_pid_t * pid,const uint8_t * p_pesstart,size_t i_data,bool b_adaptfield)50 void ProbePES( demux_t *p_demux, ts_pid_t *pid, const uint8_t *p_pesstart, size_t i_data, bool b_adaptfield )
51 {
52     demux_sys_t *p_sys = p_demux->p_sys;
53     const uint8_t *p_pes = p_pesstart;
54 
55     if( b_adaptfield )
56     {
57         if ( i_data < 2 )
58             return;
59 
60         uint8_t len = *p_pes;
61         p_pes++; i_data--;
62 
63         if(len == 0)
64         {
65             p_pes++; i_data--;/* stuffing */
66         }
67         else
68         {
69             if( i_data < len )
70                 return;
71             if( len >= 7 && (p_pes[0] & 0x10) )
72                 pid->probed.i_pcr_count++;
73             p_pes += len;
74             i_data -= len;
75         }
76     }
77 
78     if( i_data < 9 )
79         return;
80 
81     if( p_pes[0] != 0 || p_pes[1] != 0 || p_pes[2] != 1 )
82         return;
83 
84     size_t i_pesextoffset = 8;
85     mtime_t i_dts = -1;
86     if( p_pes[7] & 0x80 ) // PTS
87     {
88         i_pesextoffset += 5;
89         if ( i_data < i_pesextoffset ||
90             !ExtractPESTimestamp( &p_pes[9], p_pes[7] >> 6, &i_dts ) )
91             return;
92     }
93     if( p_pes[7] & 0x40 ) // DTS
94     {
95         i_pesextoffset += 5;
96         if ( i_data < i_pesextoffset ||
97             !ExtractPESTimestamp( &p_pes[14], 0x01, &i_dts ) )
98             return;
99     }
100     if( p_pes[7] & 0x20 ) // ESCR
101         i_pesextoffset += 6;
102     if( p_pes[7] & 0x10 ) // ESrate
103         i_pesextoffset += 3;
104     if( p_pes[7] & 0x08 ) // DSM
105         i_pesextoffset += 1;
106     if( p_pes[7] & 0x04 ) // CopyInfo
107         i_pesextoffset += 1;
108     if( p_pes[7] & 0x02 ) // PESCRC
109         i_pesextoffset += 2;
110 
111     if ( i_data < i_pesextoffset )
112         return;
113 
114      /* HeaderdataLength */
115     const size_t i_payloadoffset = 8 + 1 + p_pes[8];
116     i_pesextoffset += 1;
117 
118     if ( i_data < i_pesextoffset || i_data < i_payloadoffset )
119         return;
120 
121     i_data -= 8 + 1 + p_pes[8];
122 
123     if( p_pes[7] & 0x01 ) // PESExt
124     {
125         size_t i_extension2_offset = 1;
126         if ( p_pes[i_pesextoffset] & 0x80 ) // private data
127             i_extension2_offset += 16;
128         if ( p_pes[i_pesextoffset] & 0x40 ) // pack
129             i_extension2_offset += 1;
130         if ( p_pes[i_pesextoffset] & 0x20 ) // seq
131             i_extension2_offset += 2;
132         if ( p_pes[i_pesextoffset] & 0x10 ) // P-STD
133             i_extension2_offset += 2;
134         if ( p_pes[i_pesextoffset] & 0x01 ) // Extension 2
135         {
136             uint8_t i_len = p_pes[i_pesextoffset + i_extension2_offset] & 0x7F;
137             i_extension2_offset += i_len;
138         }
139         if( i_data < i_extension2_offset )
140             return;
141 
142         i_data -= i_extension2_offset;
143     }
144     /* (i_payloadoffset - i_pesextoffset) 0xFF stuffing */
145 
146     if ( i_data < 4 )
147         return;
148 
149     const uint8_t *p_data = &p_pes[i_payloadoffset];
150     const uint8_t i_stream_id = pid->probed.i_stream_id = p_pes[3];
151     /* NON MPEG audio & subpictures STREAM */
152     if(i_stream_id == 0xBD)
153     {
154         if( !memcmp( p_data, "\x7F\xFE\x80\x01", 4 ) )
155         {
156             pid->probed.i_fourcc = VLC_CODEC_DTS;
157             pid->probed.i_cat = AUDIO_ES;
158         }
159         else if( !memcmp( p_data, "\x0B\x77", 2 ) )
160         {
161             pid->probed.i_fourcc = VLC_CODEC_EAC3;
162             pid->probed.i_cat = AUDIO_ES;
163         }
164     }
165     /* MPEG AUDIO STREAM */
166     else if(i_stream_id >= 0xC0 && i_stream_id <= 0xDF)
167     {
168         pid->probed.i_cat = AUDIO_ES;
169         if( p_data[0] == 0xFF && (p_data[1] & 0xE0) == 0xE0 &&
170            (p_data[1] & 0x18) != 0x08 && (p_data[1] & 0x06) != 0x00 )
171         {
172             pid->probed.i_fourcc = VLC_CODEC_MPGA;
173         }
174         else if( p_data[0] == 0xFF && (p_data[1] & 0xF6) == 0xF0 )
175         {
176             pid->probed.i_fourcc = VLC_CODEC_MP4A; /* ADTS */
177             pid->probed.i_original_fourcc = VLC_FOURCC('A','D','T','S');
178         }
179     }
180     /* VIDEO STREAM */
181     else if( i_stream_id >= 0xE0 && i_stream_id <= 0xEF )
182     {
183         pid->probed.i_cat = VIDEO_ES;
184         if( !memcmp( p_data, "\x00\x00\x00\x01", 4 ) )
185         {
186             pid->probed.i_fourcc = VLC_CODEC_H264;
187         }
188         else if( !memcmp( p_data, "\x00\x00\x01", 4 ) )
189         {
190             pid->probed.i_fourcc = VLC_CODEC_MPGV;
191         }
192     }
193 
194     /* Track timestamps and flag missing PAT */
195     if( !p_sys->patfix.i_timesourcepid && i_dts > -1 )
196     {
197         p_sys->patfix.i_first_dts = i_dts;
198         p_sys->patfix.i_timesourcepid = pid->i_pid;
199     }
200     else if( p_sys->patfix.i_timesourcepid == pid->i_pid && i_dts > -1 &&
201              p_sys->patfix.status == PAT_WAITING )
202     {
203         if( i_dts - p_sys->patfix.i_first_dts > TO_SCALE(MIN_PAT_INTERVAL) )
204             p_sys->patfix.status = PAT_MISSING;
205     }
206 
207 }
208 
BuildPATCallback(void * p_opaque,block_t * p_block)209 static void BuildPATCallback( void *p_opaque, block_t *p_block )
210 {
211     ts_pid_t *pat_pid = (ts_pid_t *) p_opaque;
212     dvbpsi_packet_push( pat_pid->u.p_pat->handle, p_block->p_buffer );
213     block_Release( p_block );
214 }
215 
BuildPMTCallback(void * p_opaque,block_t * p_block)216 static void BuildPMTCallback( void *p_opaque, block_t *p_block )
217 {
218     ts_pid_t *program_pid = (ts_pid_t *) p_opaque;
219     assert(program_pid->type == TYPE_PMT);
220     while( p_block )
221     {
222         dvbpsi_packet_push( program_pid->u.p_pmt->handle,
223                             p_block->p_buffer );
224         block_t *p_next = p_block->p_next;
225         block_Release( p_block );
226         p_block = p_next;
227     }
228 }
229 
MissingPATPMTFixup(demux_t * p_demux)230 void MissingPATPMTFixup( demux_t *p_demux )
231 {
232     demux_sys_t *p_sys = p_demux->p_sys;
233     int i_program_number = 1234;
234     int i_program_pid = 1337;
235     int i_pcr_pid = 0x1FFF;
236     int i_num_pes = 0;
237 
238     ts_pid_t *p_program_pid = GetPID( p_sys, i_program_pid );
239     if( SEEN(p_program_pid) )
240     {
241         /* Find a free one */
242         for( i_program_pid = MIN_ES_PID;
243              i_program_pid <= MAX_ES_PID && SEEN(p_program_pid);
244              i_program_pid++ )
245         {
246             p_program_pid = GetPID( p_sys, i_program_pid );
247         }
248     }
249 
250     const ts_pid_t *p_pid = NULL;
251     ts_pid_next_context_t pidnextctx = ts_pid_NextContextInitValue;
252     while( (p_pid = ts_pid_Next( &p_sys->pids, &pidnextctx )) )
253     {
254         if( !SEEN(p_pid) || p_pid->probed.i_fourcc == 0 )
255             continue;
256 
257         if( i_pcr_pid == 0x1FFF && ( p_pid->probed.i_cat == AUDIO_ES ||
258                                      p_pid->probed.i_pcr_count ) )
259             i_pcr_pid = p_pid->i_pid;
260 
261         i_num_pes++;
262     }
263 
264     if( i_num_pes == 0 )
265         return;
266 
267     tsmux_stream_t patstream =
268     {
269         .i_pid = 0,
270         .i_continuity_counter = 0x10,
271         .b_discontinuity = false
272     };
273 
274     tsmux_stream_t pmtprogramstream =
275     {
276         .i_pid = i_program_pid,
277         .i_continuity_counter = 0x0,
278         .b_discontinuity = false
279     };
280 
281     BuildPAT( GetPID(p_sys, 0)->u.p_pat->handle,
282             &p_sys->pids.pat, BuildPATCallback,
283             0, 1,
284             &patstream,
285             1, &pmtprogramstream, &i_program_number );
286 
287     /* PAT callback should have been triggered */
288     if( p_program_pid->type != TYPE_PMT )
289     {
290         msg_Err( p_demux, "PAT creation failed" );
291         return;
292     }
293 
294     ts_mux_standard mux_standard = (p_sys->standard == TS_STANDARD_ATSC) ? TS_MUX_STANDARD_ATSC
295                                                                          : TS_MUX_STANDARD_DVB;
296     struct esstreams_t
297     {
298         pesmux_stream_t pes;
299         tsmux_stream_t ts;
300         es_format_t fmt;
301     };
302 
303     struct esstreams_t *esstreams = calloc( i_num_pes, sizeof(struct esstreams_t) );
304     pes_mapped_stream_t *mapped = calloc( i_num_pes, sizeof(pes_mapped_stream_t) );
305     if( esstreams && mapped )
306     {
307         int j=0;
308         for( int i=0; i<p_sys->pids.i_all; i++ )
309         {
310             p_pid = p_sys->pids.pp_all[i];
311 
312             if( !SEEN(p_pid) ||
313                 p_pid->probed.i_fourcc == 0 )
314                 continue;
315 
316             es_format_Init(&esstreams[j].fmt, p_pid->probed.i_cat, p_pid->probed.i_fourcc);
317             esstreams[j].fmt.i_original_fourcc = p_pid->probed.i_original_fourcc;
318 
319             if( VLC_SUCCESS !=
320                 FillPMTESParams(mux_standard, &esstreams[j].fmt, &esstreams[j].ts, &esstreams[j].pes ) )
321             {
322                 es_format_Clean( &esstreams[j].fmt );
323                 continue;
324             }
325 
326             /* Important for correct remapping: Enforce probed PES stream id */
327             esstreams[j].pes.i_stream_id = p_pid->probed.i_stream_id;
328 
329             esstreams[j].ts.i_pid = p_pid->i_pid;
330             mapped[j].pes = &esstreams[j].pes;
331             mapped[j].ts = &esstreams[j].ts;
332             mapped[j].fmt = &esstreams[j].fmt;
333             j++;
334         }
335 
336         BuildPMT( GetPID(p_sys, 0)->u.p_pat->handle, VLC_OBJECT(p_demux),
337                  mux_standard,
338                 p_program_pid, BuildPMTCallback,
339                 0, 1,
340                 i_pcr_pid,
341                 NULL,
342                 1, &pmtprogramstream, &i_program_number,
343                 j, mapped );
344 
345         /* Cleanup */
346         for( int i=0; i<j; i++ )
347             es_format_Clean( &esstreams[i].fmt );
348     }
349     free(esstreams);
350     free(mapped);
351 }
352