mpegts pass muxer: add possibility to rewrite/filter SDT and EIT tables, fixes #2043

This commit is contained in:
Jaroslav Kysela 2015-03-25 12:28:26 +01:00
parent d5c5f67bfe
commit 9ee27b671b
3 changed files with 134 additions and 4 deletions

View file

@ -50,6 +50,8 @@ typedef struct muxer_config {
int m_rewrite_pat;
int m_rewrite_pmt;
int m_rewrite_sdt;
int m_rewrite_eit;
int m_cache;
/*

View file

@ -48,9 +48,17 @@ typedef struct pass_muxer {
uint8_t *pm_pmt;
uint16_t pm_pmt_version;
uint16_t pm_service_id;
uint32_t pm_streams[256]; /* lookup table identifying which streams to include in the PMT */
mpegts_psi_table_t pm_sdt;
mpegts_psi_table_t pm_eit;
} pass_muxer_t;
static void
pass_muxer_write(muxer_t *m, const void *data, size_t size);
/**
* Append CRC
*/
@ -275,6 +283,87 @@ pass_muxer_rewrite_pat(pass_muxer_t* pm, unsigned char* tsb)
return 1;
}
/*
*
*/
static void
pass_muxer_sdt_cb(mpegts_psi_table_t *mt, const uint8_t *buf, int len)
{
pass_muxer_t *pm;
uint8_t out[1024], *ob;
uint16_t sid;
int l, ol;
/* filter out the other transponders */
if (buf[0] != 0x42)
return;
pm = (pass_muxer_t*)mt->mt_opaque;
ol = 8 + 3;
memcpy(out, buf, ol);
buf += ol;
len -= ol;
while (len >= 5) {
sid = (buf[0] << 8) | buf[1];
l = (buf[3] & 0x0f) << 8 | buf[4];
if (sid != pm->pm_service_id) {
buf += l + 5;
len -= l + 5;
continue;
}
if (sizeof(out) < ol + l + 5 + 4 /* crc */) {
tvherror("pass", "SDT entry too long (%i)", l);
return;
}
memcpy(out + ol, buf, l + 5);
/* set free CA */
out[ol + 3] = out[ol + 3] & ~0x10;
ol += l + 5;
break;
}
/* update section length */
out[1] = (out[1] & 0xf0) | ((ol + 4 - 3) >> 8);
out[2] = (ol + 4 - 3) & 0xff;
ol = dvb_table_append_crc32(out, ol, sizeof(out));
if (ol > 0 && (l = dvb_table_remux(mt, out, ol, &ob)) > 0) {
pass_muxer_write((muxer_t *)pm, ob, l);
free(ob);
}
}
/*
*
*/
static void
pass_muxer_eit_cb(mpegts_psi_table_t *mt, const uint8_t *buf, int len)
{
pass_muxer_t *pm;
uint16_t sid;
uint8_t *out;
int olen;
/* filter out the other transponders */
if ((buf[0] < 0x50 && buf[0] != 0x4e) || buf[0] > 0x5f || len < 14)
return;
pm = (pass_muxer_t*)mt->mt_opaque;
sid = (buf[3] << 8) | buf[4];
if (sid != pm->pm_service_id)
return;
/* TODO: set free_CA_mode bit to zero */
len = dvb_table_append_crc32((uint8_t *)buf, len, len + 4);
if (len > 0 && (olen = dvb_table_remux(mt, buf, len, &out)) > 0) {
pass_muxer_write((muxer_t *)pm, out, olen);
free(out);
}
}
/**
* Figure out the mime-type for the muxed data stream
*/
@ -451,8 +540,10 @@ pass_muxer_write_ts(muxer_t *m, pktbuf_t *pb)
int pid = (tsb[1] & 0x1f) << 8 | tsb[2];
/* Process */
if ( (pm->m_config.m_rewrite_pat && (pid == 0)) ||
(pm->m_config.m_rewrite_pmt && (pid == pm->pm_pmt_pid)) ) {
if ( (pm->m_config.m_rewrite_pat && pid == DVB_PAT_PID) ||
(pm->m_config.m_rewrite_pmt && pid == pm->pm_pmt_pid) ||
(pm->m_config.m_rewrite_sdt && pid == DVB_SDT_PID) ||
(pm->m_config.m_rewrite_eit && pid == DVB_EIT_PID) ) {
/* Flush */
if (len)
@ -463,7 +554,8 @@ pass_muxer_write_ts(muxer_t *m, pktbuf_t *pb)
len = 0;
/* PAT */
if (pid == 0) {
if (pid == DVB_PAT_PID) {
memcpy(tmp, tsb, sizeof(tmp));
e = pass_muxer_rewrite_pat(pm, tmp);
if (e < 0) {
@ -473,11 +565,23 @@ pass_muxer_write_ts(muxer_t *m, pktbuf_t *pb)
if (e)
pass_muxer_write(m, tmp, 188);
/* SDT */
} else if (pid == DVB_SDT_PID) {
dvb_table_parse(&pm->pm_sdt, tsb, 188, 1, 0, pass_muxer_sdt_cb);
/* EIT */
} else if (pid == DVB_EIT_PID) {
dvb_table_parse(&pm->pm_eit, tsb, 188, 1, 0, pass_muxer_eit_cb);
/* PMT */
} else if (tsb[1] & 0x40) { /* pusi - the first PMT packet */
pm->pm_pmt[3] = (pm->pm_pmt[3] & 0xf0) | pm->pm_pmt_cc;
pm->pm_pmt_cc = (pm->pm_pmt_cc + 1) & 0xf;
pass_muxer_write(m, pm->pm_pmt, 188);
}
/* Record */
@ -565,6 +669,9 @@ pass_muxer_destroy(muxer_t *m)
if(pm->pm_pmt)
free(pm->pm_pmt);
dvb_table_parse_done(&pm->pm_sdt);
dvb_table_parse_done(&pm->pm_eit);
free(pm);
}
@ -592,6 +699,9 @@ pass_muxer_create(const muxer_config_t *m_cfg)
pm->m_destroy = pass_muxer_destroy;
pm->pm_fd = -1;
dvb_table_parse_init(&pm->pm_sdt, "pass-sdt", DVB_SDT_PID, pm);
dvb_table_parse_init(&pm->pm_eit, "pass-eit", DVB_EIT_PID, pm);
return (muxer_t *)pm;
}

View file

@ -865,6 +865,8 @@ typedef struct profile_mpegts {
profile_t;
int pro_rewrite_pmt;
int pro_rewrite_pat;
int pro_rewrite_sdt;
int pro_rewrite_eit;
} profile_mpegts_t;
const idclass_t profile_mpegts_pass_class =
@ -887,6 +889,20 @@ const idclass_t profile_mpegts_pass_class =
.off = offsetof(profile_mpegts_t, pro_rewrite_pat),
.def.i = 1,
},
{
.type = PT_BOOL,
.id = "rewrite_sdt",
.name = "Rewrite SDT",
.off = offsetof(profile_mpegts_t, pro_rewrite_sdt),
.def.i = 1,
},
{
.type = PT_BOOL,
.id = "rewrite_eit",
.name = "Rewrite EIT",
.off = offsetof(profile_mpegts_t, pro_rewrite_eit),
.def.i = 1,
},
{ }
}
};
@ -906,6 +922,8 @@ profile_mpegts_pass_reopen(profile_chain_t *prch,
c.m_type = MC_PASS;
c.m_rewrite_pat = pro->pro_rewrite_pat;
c.m_rewrite_pmt = pro->pro_rewrite_pmt;
c.m_rewrite_sdt = pro->pro_rewrite_sdt;
c.m_rewrite_eit = pro->pro_rewrite_eit;
assert(!prch->prch_muxer);
prch->prch_muxer = muxer_create(&c);