1 /*
2 * tvheadend, simple muxer that just passes the input along
3 * Copyright (C) 2012 John Törnblom
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <htmlui://www.gnu.org/licenses/>.
17 */
18
19 #include <string.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <assert.h>
23 #include <sys/stat.h>
24
25 #include "tvheadend.h"
26 #include "streaming.h"
27 #include "epg.h"
28 #include "service.h"
29 #include "input/mpegts/dvb.h"
30 #include "muxer_pass.h"
31 #include "dvr/dvr.h"
32
33 typedef struct pass_muxer {
34 muxer_t;
35
36 /* File descriptor stuff */
37 off_t pm_off;
38 int pm_fd;
39 int pm_seekable;
40 int pm_error;
41
42 /* Filename is also used for logging */
43 char *pm_filename;
44
45 /* Streaming components */
46 streaming_start_t *pm_ss;
47
48 /* TS muxing */
49 uint8_t pm_rewrite_sdt;
50 uint8_t pm_rewrite_eit;
51
52 uint16_t pm_pmt_pid;
53 uint16_t pm_service_id;
54
55 mpegts_psi_table_t pm_pat;
56 mpegts_psi_table_t pm_pmt;
57 mpegts_psi_table_t pm_sdt;
58 mpegts_psi_table_t pm_eit;
59
60 } pass_muxer_t;
61
62
63 static void
64 pass_muxer_write(muxer_t *m, const void *data, size_t size);
65
66 /*
67 * Rewrite a PAT packet to only include the service included in the transport stream.
68 */
69
70 static void
pass_muxer_pat_cb(mpegts_psi_table_t * mt,const uint8_t * buf,int len)71 pass_muxer_pat_cb(mpegts_psi_table_t *mt, const uint8_t *buf, int len)
72 {
73 pass_muxer_t *pm;
74 uint8_t out[16], *ob;
75 int ol, l;
76
77 if (buf[0])
78 return;
79
80 pm = (pass_muxer_t*)mt->mt_opaque;
81
82 memcpy(out, buf, 5 + 3);
83
84 out[1] = 0x80;
85 out[2] = 13; /* section_length (number of bytes after this field, including CRC) */
86 out[7] = 0;
87
88 out[8] = (pm->pm_service_id & 0xff00) >> 8;
89 out[9] = pm->pm_service_id & 0x00ff;
90 out[10] = 0xe0 | ((pm->pm_pmt_pid & 0x1f00) >> 8);
91 out[11] = pm->pm_pmt_pid & 0x00ff;
92
93 ol = dvb_table_append_crc32(out, 12, sizeof(out));
94
95 if (ol > 0 && (l = dvb_table_remux(mt, out, ol, &ob)) > 0) {
96 pass_muxer_write((muxer_t *)pm, ob, l);
97 free(ob);
98 }
99 }
100
101 /*
102 *
103 */
104 static void
pass_muxer_pmt_cb(mpegts_psi_table_t * mt,const uint8_t * buf,int len)105 pass_muxer_pmt_cb(mpegts_psi_table_t *mt, const uint8_t *buf, int len)
106 {
107 pass_muxer_t *pm;
108 uint8_t out[1024], *ob;
109 uint16_t sid, pid;
110 int l, ol, i;
111 const streaming_start_component_t *ssc;
112
113 memcpy(out, buf, ol = 3);
114 buf += ol;
115 len -= ol;
116
117 sid = (buf[0] << 8) | buf[1];
118 l = (buf[7] & 0x0f) << 8 | buf[8];
119
120 if (l > len - 9)
121 return;
122
123 pm = (pass_muxer_t*)mt->mt_opaque;
124 if (sid != pm->pm_service_id)
125 return;
126
127 memcpy(out + ol, buf, 9);
128
129 ol += 9; /* skip common descriptors */
130 buf += 9 + l;
131 len -= 9 + l;
132
133 /* no common descriptors */
134 out[7+3] &= 0xf0;
135 out[8+3] = 0;
136
137 while (len >= 5) {
138 pid = (buf[1] & 0x1f) << 8 | buf[2];
139 l = (buf[3] & 0xf) << 8 | buf[4];
140
141 if (l > len - 5)
142 return;
143
144 if (sizeof(out) < ol + l + 5 + 4 /* crc */) {
145 tvherror(LS_PASS, "PMT entry too long (%i)", l);
146 return;
147 }
148
149 for (i = 0; i < pm->pm_ss->ss_num_components; i++) {
150 ssc = &pm->pm_ss->ss_components[i];
151 if (ssc->ssc_pid == pid)
152 break;
153 }
154 if (i < pm->pm_ss->ss_num_components) {
155 memcpy(out + ol, buf, 5 + l);
156 ol += 5 + l;
157 }
158
159 buf += 5 + l;
160 len -= 5 + l;
161 }
162
163 /* update section length */
164 out[1] = (out[1] & 0xf0) | ((ol + 4 - 3) >> 8);
165 out[2] = (ol + 4 - 3) & 0xff;
166
167 ol = dvb_table_append_crc32(out, ol, sizeof(out));
168
169 if (ol > 0 && (l = dvb_table_remux(mt, out, ol, &ob)) > 0) {
170 pass_muxer_write((muxer_t *)pm, ob, l);
171 free(ob);
172 }
173 }
174
175 /*
176 *
177 */
178 static void
pass_muxer_sdt_cb(mpegts_psi_table_t * mt,const uint8_t * buf,int len)179 pass_muxer_sdt_cb(mpegts_psi_table_t *mt, const uint8_t *buf, int len)
180 {
181 pass_muxer_t *pm;
182 uint8_t out[1024], *ob;
183 uint16_t sid;
184 int l, ol;
185
186 /* filter out the other transponders */
187 if (buf[0] != 0x42)
188 return;
189
190 pm = (pass_muxer_t*)mt->mt_opaque;
191 ol = 8 + 3;
192 memcpy(out, buf, ol);
193 buf += ol;
194 len -= ol;
195 while (len >= 5) {
196 sid = (buf[0] << 8) | buf[1];
197 l = (buf[3] & 0x0f) << 8 | buf[4];
198 if (sid != pm->pm_service_id) {
199 buf += l + 5;
200 len -= l + 5;
201 continue;
202 }
203 if (sizeof(out) < ol + l + 5 + 4 /* crc */) {
204 tvherror(LS_PASS, "SDT entry too long (%i)", l);
205 return;
206 }
207 memcpy(out + ol, buf, l + 5);
208 /* set free CA */
209 out[ol + 3] = out[ol + 3] & ~0x10;
210 ol += l + 5;
211 break;
212 }
213
214 /* update section length */
215 out[1] = (out[1] & 0xf0) | ((ol + 4 - 3) >> 8);
216 out[2] = (ol + 4 - 3) & 0xff;
217
218 ol = dvb_table_append_crc32(out, ol, sizeof(out));
219
220 if (ol > 0 && (l = dvb_table_remux(mt, out, ol, &ob)) > 0) {
221 pass_muxer_write((muxer_t *)pm, ob, l);
222 free(ob);
223 }
224 }
225
226 /*
227 *
228 */
229 static void
pass_muxer_eit_cb(mpegts_psi_table_t * mt,const uint8_t * buf,int len)230 pass_muxer_eit_cb(mpegts_psi_table_t *mt, const uint8_t *buf, int len)
231 {
232 pass_muxer_t *pm;
233 uint16_t sid;
234 uint8_t *out;
235 int olen;
236
237 /* filter out the other transponders */
238 if ((buf[0] < 0x50 && buf[0] != 0x4e) || buf[0] > 0x5f || len < 14)
239 return;
240
241 pm = (pass_muxer_t*)mt->mt_opaque;
242 sid = (buf[3] << 8) | buf[4];
243 if (sid != pm->pm_service_id)
244 return;
245
246 /* TODO: set free_CA_mode bit to zero */
247
248 len = dvb_table_append_crc32((uint8_t *)buf, len, len + 4);
249
250 if (len > 0 && (olen = dvb_table_remux(mt, buf, len, &out)) > 0) {
251 pass_muxer_write((muxer_t *)pm, out, olen);
252 free(out);
253 }
254 }
255
256 /**
257 * Figure out the mime-type for the muxed data stream
258 */
259 static const char*
pass_muxer_mime(muxer_t * m,const struct streaming_start * ss)260 pass_muxer_mime(muxer_t* m, const struct streaming_start *ss)
261 {
262 int i;
263 int has_audio;
264 int has_video;
265 muxer_container_type_t mc;
266 const streaming_start_component_t *ssc;
267 const source_info_t *si = &ss->ss_si;
268
269 has_audio = 0;
270 has_video = 0;
271
272 for(i=0; i < ss->ss_num_components; i++) {
273 ssc = &ss->ss_components[i];
274
275 if(ssc->ssc_disabled)
276 continue;
277
278 has_video |= SCT_ISVIDEO(ssc->ssc_type);
279 has_audio |= SCT_ISAUDIO(ssc->ssc_type);
280 }
281
282 if(si->si_type == S_MPEG_TS)
283 mc = MC_MPEGTS;
284 else if(si->si_type == S_MPEG_PS)
285 mc = MC_MPEGPS;
286 else
287 mc = MC_UNKNOWN;
288
289 if(has_video)
290 return muxer_container_type2mime(mc, 1);
291 else if(has_audio)
292 return muxer_container_type2mime(mc, 0);
293 else
294 return muxer_container_type2mime(MC_UNKNOWN, 0);
295 }
296
297
298 /**
299 * Generate the pmt and pat from a streaming start message
300 */
301 static int
pass_muxer_reconfigure(muxer_t * m,const struct streaming_start * ss)302 pass_muxer_reconfigure(muxer_t* m, const struct streaming_start *ss)
303 {
304 pass_muxer_t *pm = (pass_muxer_t*)m;
305 const streaming_start_component_t *ssc;
306 int i;
307
308 pm->pm_service_id = ss->ss_service_id;
309 pm->pm_pmt_pid = ss->ss_pmt_pid;
310 pm->pm_rewrite_sdt = !!pm->m_config.m_rewrite_sdt;
311 pm->pm_rewrite_eit = !!pm->m_config.m_rewrite_eit;
312
313 for(i=0; i < ss->ss_num_components; i++) {
314 ssc = &ss->ss_components[i];
315 if (!SCT_ISVIDEO(ssc->ssc_type) && !SCT_ISAUDIO(ssc->ssc_type))
316 continue;
317 if (ssc->ssc_pid == DVB_SDT_PID && pm->pm_rewrite_sdt) {
318 tvhwarn(LS_PASS, "SDT PID shared with A/V, rewrite disabled");
319 pm->pm_rewrite_sdt = 0;
320 }
321 if (ssc->ssc_pid == DVB_EIT_PID && pm->pm_rewrite_eit) {
322 tvhwarn(LS_PASS, "EIT PID shared with A/V, rewrite disabled");
323 pm->pm_rewrite_eit = 0;
324 }
325 }
326
327
328 if (pm->m_config.m_rewrite_pmt) {
329
330 if (pm->pm_ss)
331 streaming_start_unref(pm->pm_ss);
332 pm->pm_ss = streaming_start_copy(ss);
333
334 dvb_table_parse_done(&pm->pm_pmt);
335 dvb_table_parse_init(&pm->pm_pmt, "pass-pmt", LS_TBL_PASS, pm->pm_pmt_pid,
336 DVB_PMT_BASE, DVB_PMT_MASK, pm);
337 }
338
339 return 0;
340 }
341
342
343 /**
344 * Init the passthrough muxer with streams
345 */
346 static int
pass_muxer_init(muxer_t * m,struct streaming_start * ss,const char * name)347 pass_muxer_init(muxer_t* m, struct streaming_start *ss, const char *name)
348 {
349 return pass_muxer_reconfigure(m, ss);
350 }
351
352
353 /**
354 * Open the muxer as a stream muxer (using a non-seekable socket)
355 */
356 static int
pass_muxer_open_stream(muxer_t * m,int fd)357 pass_muxer_open_stream(muxer_t *m, int fd)
358 {
359 pass_muxer_t *pm = (pass_muxer_t*)m;
360
361 pm->pm_off = 0;
362 pm->pm_fd = fd;
363 pm->pm_seekable = 0;
364 pm->pm_filename = strdup("Live stream");
365
366 return 0;
367 }
368
369
370 /**
371 * Open the file and set the file descriptor
372 */
373 static int
pass_muxer_open_file(muxer_t * m,const char * filename)374 pass_muxer_open_file(muxer_t *m, const char *filename)
375 {
376 int fd;
377 pass_muxer_t *pm = (pass_muxer_t*)m;
378
379 tvhtrace(LS_PASS, "Creating file \"%s\" with file permissions \"%o\"", filename, pm->m_config.m_file_permissions);
380
381 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, pm->m_config.m_file_permissions);
382
383 if(fd < 0) {
384 pm->pm_error = errno;
385 tvherror(LS_PASS, "%s: Unable to create file, open failed -- %s",
386 filename, strerror(errno));
387 pm->m_errors++;
388 return -1;
389 }
390
391 /* bypass umask settings */
392 if (fchmod(fd, pm->m_config.m_file_permissions))
393 tvherror(LS_PASS, "%s: Unable to change permissions -- %s",
394 filename, strerror(errno));
395
396 pm->pm_off = 0;
397 pm->pm_seekable = 1;
398 pm->pm_fd = fd;
399 pm->pm_filename = strdup(filename);
400 return 0;
401 }
402
403
404 /**
405 * Write data to the file descriptor
406 */
407 static void
pass_muxer_write(muxer_t * m,const void * data,size_t size)408 pass_muxer_write(muxer_t *m, const void *data, size_t size)
409 {
410 pass_muxer_t *pm = (pass_muxer_t*)m;
411
412 if(pm->pm_error) {
413 pm->m_errors++;
414 } else if(tvh_write(pm->pm_fd, data, size)) {
415 pm->pm_error = errno;
416 if (!MC_IS_EOS_ERROR(errno))
417 tvherror(LS_PASS, "%s: Write failed -- %s", pm->pm_filename,
418 strerror(errno));
419 else
420 /* this is an end-of-streaming notification */
421 m->m_eos = 1;
422 m->m_errors++;
423 if (pm->pm_seekable) {
424 muxer_cache_update(m, pm->pm_fd, pm->pm_off, 0);
425 pm->pm_off = lseek(pm->pm_fd, 0, SEEK_CUR);
426 }
427 } else {
428 if (pm->pm_seekable)
429 muxer_cache_update(m, pm->pm_fd, pm->pm_off, 0);
430 pm->pm_off += size;
431 }
432 }
433
434
435 /**
436 * Write TS packets to the file descriptor
437 */
438 static void
pass_muxer_write_ts(muxer_t * m,pktbuf_t * pb)439 pass_muxer_write_ts(muxer_t *m, pktbuf_t *pb)
440 {
441 pass_muxer_t *pm = (pass_muxer_t*)m;
442 int l, pid;
443 uint8_t *tsb, *pkt = pktbuf_ptr(pb);
444 size_t len = pktbuf_len(pb), len2;
445
446 /* Rewrite PAT/PMT in operation */
447 if (pm->m_config.m_rewrite_pat || pm->m_config.m_rewrite_pmt ||
448 pm->pm_rewrite_sdt || pm->pm_rewrite_eit) {
449
450 for (tsb = pktbuf_ptr(pb), len2 = pktbuf_len(pb), len = 0;
451 len2 > 0; tsb += l, len2 -= l) {
452
453 pid = (tsb[1] & 0x1f) << 8 | tsb[2];
454 l = mpegts_word_count(tsb, len2, 0x001FFF00);
455
456 /* Process */
457 if ( (pm->m_config.m_rewrite_pat && pid == DVB_PAT_PID) ||
458 (pm->m_config.m_rewrite_pmt && pid == pm->pm_pmt_pid) ||
459 (pm->pm_rewrite_sdt && pid == DVB_SDT_PID) ||
460 (pm->pm_rewrite_eit && pid == DVB_EIT_PID) ) {
461
462 /* Flush */
463 if (len)
464 pass_muxer_write(m, pkt, len);
465
466 /* Store new start point (after these packets) */
467 pkt = tsb + l;
468 len = 0;
469
470 /* PAT */
471 if (pid == DVB_PAT_PID) {
472
473 dvb_table_parse(&pm->pm_pat, "-", tsb, l, 1, 0, pass_muxer_pat_cb);
474
475 /* SDT */
476 } else if (pid == DVB_SDT_PID) {
477
478 dvb_table_parse(&pm->pm_sdt, "-", tsb, l, 1, 0, pass_muxer_sdt_cb);
479
480 /* EIT */
481 } else if (pid == DVB_EIT_PID) {
482
483 dvb_table_parse(&pm->pm_eit, "-", tsb, l, 1, 0, pass_muxer_eit_cb);
484
485 /* PMT */
486 } else {
487
488 dvb_table_parse(&pm->pm_pmt, "-", tsb, l, 1, 0, pass_muxer_pmt_cb);
489
490 }
491
492 /* Record */
493 } else {
494 len += l;
495 }
496 }
497 }
498
499 if (len)
500 pass_muxer_write(m, pkt, len);
501 }
502
503
504 /**
505 * Write a packet directly to the file descriptor
506 */
507 static int
pass_muxer_write_pkt(muxer_t * m,streaming_message_type_t smt,void * data)508 pass_muxer_write_pkt(muxer_t *m, streaming_message_type_t smt, void *data)
509 {
510 pktbuf_t *pb = (pktbuf_t*)data;
511 pass_muxer_t *pm = (pass_muxer_t*)m;
512
513 assert(smt == SMT_MPEGTS);
514
515 switch(smt) {
516 case SMT_MPEGTS:
517 pass_muxer_write_ts(m, pb);
518 break;
519 default:
520 //TODO: add support for v4l (MPEG-PS)
521 break;
522 }
523
524 pktbuf_ref_dec(pb);
525
526 return pm->pm_error;
527 }
528
529
530 /**
531 * NOP
532 */
533 static int
pass_muxer_write_meta(muxer_t * m,struct epg_broadcast * eb,const char * comment)534 pass_muxer_write_meta(muxer_t *m, struct epg_broadcast *eb, const char *comment)
535 {
536 return 0;
537 }
538
539
540 /**
541 * Close the file descriptor
542 */
543 static int
pass_muxer_close(muxer_t * m)544 pass_muxer_close(muxer_t *m)
545 {
546 pass_muxer_t *pm = (pass_muxer_t*)m;
547
548 if(pm->pm_seekable && close(pm->pm_fd)) {
549 pm->pm_error = errno;
550 tvherror(LS_PASS, "%s: Unable to close file, close failed -- %s",
551 pm->pm_filename, strerror(errno));
552 pm->m_errors++;
553 return -1;
554 }
555
556 return 0;
557 }
558
559
560 /**
561 * Free all memory associated with the muxer
562 */
563 static void
pass_muxer_destroy(muxer_t * m)564 pass_muxer_destroy(muxer_t *m)
565 {
566 pass_muxer_t *pm = (pass_muxer_t*)m;
567
568 if(pm->pm_filename)
569 free(pm->pm_filename);
570
571 if (pm->pm_ss)
572 streaming_start_unref(pm->pm_ss);
573
574 dvb_table_parse_done(&pm->pm_pat);
575 dvb_table_parse_done(&pm->pm_pmt);
576 dvb_table_parse_done(&pm->pm_sdt);
577 dvb_table_parse_done(&pm->pm_eit);
578
579 free(pm);
580 }
581
582
583 /**
584 * Create a new passthrough muxer
585 */
586 muxer_t*
pass_muxer_create(const muxer_config_t * m_cfg)587 pass_muxer_create(const muxer_config_t *m_cfg)
588 {
589 pass_muxer_t *pm;
590
591 if(m_cfg->m_type != MC_PASS && m_cfg->m_type != MC_RAW)
592 return NULL;
593
594 pm = calloc(1, sizeof(pass_muxer_t));
595 pm->m_open_stream = pass_muxer_open_stream;
596 pm->m_open_file = pass_muxer_open_file;
597 pm->m_init = pass_muxer_init;
598 pm->m_reconfigure = pass_muxer_reconfigure;
599 pm->m_mime = pass_muxer_mime;
600 pm->m_write_meta = pass_muxer_write_meta;
601 pm->m_write_pkt = pass_muxer_write_pkt;
602 pm->m_close = pass_muxer_close;
603 pm->m_destroy = pass_muxer_destroy;
604 pm->pm_fd = -1;
605
606 dvb_table_parse_init(&pm->pm_pat, "pass-pat", LS_TBL_PASS, DVB_PAT_PID,
607 DVB_PAT_BASE, DVB_PAT_MASK, pm);
608 dvb_table_parse_init(&pm->pm_pmt, "pass-pmt", LS_TBL_PASS, 100,
609 DVB_PMT_BASE, DVB_PMT_MASK, pm);
610 dvb_table_parse_init(&pm->pm_sdt, "pass-sdt", LS_TBL_PASS, DVB_SDT_PID,
611 DVB_SDT_BASE, DVB_SDT_MASK, pm);
612 dvb_table_parse_init(&pm->pm_eit, "pass-eit", LS_TBL_PASS, DVB_EIT_PID,
613 0, 0, pm);
614
615 return (muxer_t *)pm;
616 }
617
618