Fix MPEG TS section reassembly code

Const'ify lots of places where we pass transport stream blocks
This commit is contained in:
Andreas Öman 2010-01-16 21:51:43 +00:00
parent ac1393357d
commit 4d992cca57
14 changed files with 109 additions and 122 deletions

View file

@ -410,7 +410,7 @@ capmt_thread(void *aux)
*/
static void
capmt_table_input(struct th_descrambler *td, struct th_transport *t,
struct th_stream *st, uint8_t *data, int len)
struct th_stream *st, const uint8_t *data, int len)
{
capmt_transport_t *ct = (capmt_transport_t *)td;
capmt_t *capmt = ct->ct_capmt;
@ -572,7 +572,8 @@ capmt_table_input(struct th_descrambler *td, struct th_transport *t,
*
*/
static int
capmt_descramble(th_descrambler_t *td, th_transport_t *t, struct th_stream *st, uint8_t *tsb)
capmt_descramble(th_descrambler_t *td, th_transport_t *t, struct th_stream *st,
const uint8_t *tsb)
{
capmt_transport_t *ct = (capmt_transport_t *)td;
int r, i;

View file

@ -1045,7 +1045,7 @@ cwc_emm(uint8_t *data, int len)
*/
static void
cwc_table_input(struct th_descrambler *td, struct th_transport *t,
struct th_stream *st, uint8_t *data, int len)
struct th_stream *st, const uint8_t *data, int len)
{
cwc_transport_t *ct = (cwc_transport_t *)td;
uint16_t sid = t->tht_dvb_service_id;
@ -1130,7 +1130,7 @@ cwc_table_input(struct th_descrambler *td, struct th_transport *t,
*/
static int
cwc_descramble(th_descrambler_t *td, th_transport_t *t, struct th_stream *st,
uint8_t *tsb)
const uint8_t *tsb)
{
cwc_transport_t *ct = (cwc_transport_t *)td;
int r, i;

View file

@ -55,7 +55,7 @@ static struct th_transport_list iptv_active_transports; /* Currently enabled */
* PAT parser. We only parse a single program. CRC has already been verified
*/
static void
iptv_got_pat(const uint8_t *ptr, int len, void *aux)
iptv_got_pat(const uint8_t *ptr, size_t len, void *aux)
{
th_transport_t *t = aux;
uint16_t prognum, pmt;
@ -77,7 +77,7 @@ iptv_got_pat(const uint8_t *ptr, int len, void *aux)
* PMT parser. CRC has already been verified
*/
static void
iptv_got_pmt(const uint8_t *ptr, int len, void *aux)
iptv_got_pmt(const uint8_t *ptr, size_t len, void *aux)
{
th_transport_t *t = aux;
@ -94,7 +94,7 @@ iptv_got_pmt(const uint8_t *ptr, int len, void *aux)
* Handle a single TS packet for the given IPTV transport
*/
static void
iptv_ts_input(th_transport_t *t, uint8_t *tsb)
iptv_ts_input(th_transport_t *t, const uint8_t *tsb)
{
uint16_t pid = ((tsb[1] & 0x1f) << 8) | tsb[2];
@ -102,13 +102,13 @@ iptv_ts_input(th_transport_t *t, uint8_t *tsb)
if(t->tht_pat_section == NULL)
t->tht_pat_section = calloc(1, sizeof(psi_section_t));
psi_rawts_table_parser(t->tht_pat_section, tsb, iptv_got_pat, t);
psi_section_reassemble(t->tht_pat_section, tsb, 1, iptv_got_pat, t);
} else if(pid == t->tht_pmt_pid) {
if(t->tht_pmt_section == NULL)
t->tht_pmt_section = calloc(1, sizeof(psi_section_t));
psi_rawts_table_parser(t->tht_pmt_section, tsb, iptv_got_pmt, t);
psi_section_reassemble(t->tht_pmt_section, tsb, 1, iptv_got_pmt, t);
} else {
ts_recv_packet1(t, tsb, NULL);

View file

@ -80,20 +80,20 @@ typedef int (vparser_t)(th_transport_t *t, th_stream_t *st, size_t len,
typedef void (aparser_t)(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt);
static void parse_video(th_transport_t *t, th_stream_t *st, uint8_t *data,
static void parse_video(th_transport_t *t, th_stream_t *st, const uint8_t *data,
int len, vparser_t *vp);
static void parse_audio_with_lavc(th_transport_t *t, th_stream_t *st,
uint8_t *data, int len, aparser_t *ap);
const uint8_t *data, int len, aparser_t *ap);
static void parse_audio(th_transport_t *t, th_stream_t *st, uint8_t *data,
static void parse_audio(th_transport_t *t, th_stream_t *st, const uint8_t *data,
int len, int start, aparser_t *vp);
static void parse_aac(th_transport_t *t, th_stream_t *st, uint8_t *data,
static void parse_aac(th_transport_t *t, th_stream_t *st, const uint8_t *data,
int len, int start);
static void parse_subtitles(th_transport_t *t, th_stream_t *st, uint8_t *data,
int len, int start);
static void parse_subtitles(th_transport_t *t, th_stream_t *st,
const uint8_t *data, int len, int start);
static void parse_mpegaudio(th_transport_t *t, th_stream_t *st, th_pkt_t *pkt);
@ -115,7 +115,7 @@ static void parser_compute_duration(th_transport_t *t, th_stream_t *st,
* Parse raw mpeg data
*/
void
parse_mpeg_ts(th_transport_t *t, th_stream_t *st, uint8_t *data,
parse_mpeg_ts(th_transport_t *t, th_stream_t *st, const uint8_t *data,
int len, int start, int err)
{
switch(st->st_type) {
@ -191,7 +191,7 @@ parse_mpeg_ps(th_transport_t *t, th_stream_t *st, uint8_t *data, int len)
* Parse AAC LATM
*/
static void
parse_aac(th_transport_t *t, th_stream_t *st, uint8_t *data,
parse_aac(th_transport_t *t, th_stream_t *st, const uint8_t *data,
int len, int start)
{
int l, muxlen, p;
@ -268,7 +268,7 @@ parse_aac(th_transport_t *t, th_stream_t *st, uint8_t *data,
* derive further information.
*/
static void
parse_video(th_transport_t *t, th_stream_t *st, uint8_t *data, int len,
parse_video(th_transport_t *t, th_stream_t *st, const uint8_t *data, int len,
vparser_t *vp)
{
uint32_t sc;
@ -329,7 +329,7 @@ parse_video(th_transport_t *t, th_stream_t *st, uint8_t *data, int len,
* We then trust ffmpeg to parse and extract packets for use
*/
static void
parse_audio(th_transport_t *t, th_stream_t *st, uint8_t *data,
parse_audio(th_transport_t *t, th_stream_t *st, const uint8_t *data,
int len, int start, aparser_t *ap)
{
int hlen;
@ -378,7 +378,7 @@ parse_audio(th_transport_t *t, th_stream_t *st, uint8_t *data,
* Use libavcodec's parsers for audio parsing
*/
static void
parse_audio_with_lavc(th_transport_t *t, th_stream_t *st, uint8_t *data,
parse_audio_with_lavc(th_transport_t *t, th_stream_t *st, const uint8_t *data,
int len, aparser_t *ap)
{
uint8_t *outbuf;
@ -846,7 +846,7 @@ parse_h264(th_transport_t *t, th_stream_t *st, size_t len,
* http://broadcasting.ru/pdf-standard-specifications/subtitling/dvb-sub/en300743.v1.2.1.pdf
*/
static void
parse_subtitles(th_transport_t *t, th_stream_t *st, uint8_t *data,
parse_subtitles(th_transport_t *t, th_stream_t *st, const uint8_t *data,
int len, int start)
{
th_pkt_t *pkt;

View file

@ -21,7 +21,7 @@
#include "packet.h"
void parse_mpeg_ts(th_transport_t *t, th_stream_t *st, uint8_t *data,
void parse_mpeg_ts(th_transport_t *t, th_stream_t *st, const uint8_t *data,
int len, int start, int err);
void parse_mpeg_ps(th_transport_t *t, th_stream_t *st, uint8_t *data, int len);

View file

@ -32,64 +32,85 @@
#include "tsdemux.h"
#include "parsers.h"
int
psi_section_reassemble(psi_section_t *ps, uint8_t *data, int len,
int start, int chkcrc)
static int
psi_section_reassemble0(psi_section_t *ps, const uint8_t *data,
int len, int start, int crc,
section_handler_t *cb, void *opaque)
{
int remain, a, tsize;
int excess, tsize, s;
if(start)
if(start) {
// Payload unit start indicator
ps->ps_offset = 0;
ps->ps_lock = 1;
}
if(ps->ps_offset < 0)
if(!ps->ps_lock)
return -1;
remain = PSI_SECTION_SIZE - ps->ps_offset;
memcpy(ps->ps_data + ps->ps_offset, data, len);
ps->ps_offset += len;
a = FFMAX(0, FFMIN(remain, len));
if(ps->ps_offset < 3) {
/* We don't know the total length yet */
return len;
}
memcpy(ps->ps_data + ps->ps_offset, data, a);
ps->ps_offset += a;
tsize = 3 + (((ps->ps_data[1] & 0xf) << 8) | ps->ps_data[2]);
if(ps->ps_offset < tsize)
return len; // Not there yet
excess = ps->ps_offset - tsize;
if(crc && psi_crc32(ps->ps_data, tsize))
return -1;
if(chkcrc && psi_crc32(ps->ps_data, tsize))
return -1;
s = tsize - (crc ? 4 : 0);
ps->ps_offset = tsize - (chkcrc ? 4 : 0);
return 0;
cb(ps->ps_data, s, opaque);
return len - excess;
}
/**
* TS table parser
*
*/
void
psi_rawts_table_parser(psi_section_t *section, uint8_t *tsb,
void (*gotsection)(const uint8_t *data, int len,
void *opauqe), void *opaque)
psi_section_reassemble(psi_section_t *ps, const uint8_t *tsb, int crc,
section_handler_t *cb, void *opaque)
{
int off = tsb[3] & 0x20 ? tsb[4] + 5 : 4;
int off = tsb[3] & 0x20 ? tsb[4] + 5 : 4;
int pusi = tsb[1] & 0x40;
int len;
int r;
if(off >= 188)
if(off >= 188) {
ps->ps_lock = 0;
return;
}
if(pusi) {
len = tsb[off++];
int len = tsb[off++];
if(len > 0) {
if(len > 188 - off)
if(len > 188 - off) {
ps->ps_lock = 0;
return;
if(!psi_section_reassemble(section, tsb + off, len, 0, 1))
gotsection(section->ps_data, section->ps_offset, opaque);
}
psi_section_reassemble0(ps, tsb + off, len, 0, crc, cb, opaque);
off += len;
}
}
if(!psi_section_reassemble(section, tsb + off, 188 - off, pusi, 1))
gotsection(section->ps_data, section->ps_offset, opaque);
while(off < 188 && tsb[off] != 0xff) {
r = psi_section_reassemble0(ps, tsb + off, 188 - off, pusi, crc,
cb, opaque);
if(r < 0) {
ps->ps_lock = 0;
break;
}
off += r;
pusi = 0;
}
}

View file

@ -22,16 +22,19 @@
#include "htsmsg.h"
#include "streaming.h"
#define PSI_SECTION_SIZE 4096
#define PSI_SECTION_SIZE 5000
typedef void (section_handler_t)(const uint8_t *data, size_t len, void *opaque);
typedef struct psi_section {
int ps_offset;
int ps_lock;
uint8_t ps_data[PSI_SECTION_SIZE];
} psi_section_t;
int psi_section_reassemble(psi_section_t *ps, uint8_t *data, int len,
int pusi, int chkcrc);
void psi_section_reassemble(psi_section_t *ps, const uint8_t *tsb, int crc,
section_handler_t *cb, void *opaque);
int psi_parse_pat(th_transport_t *t, uint8_t *ptr, int len,
pid_section_callback_t *pmt_callback);
@ -50,8 +53,4 @@ const char *psi_caid2name(uint16_t caid);
void psi_load_transport_settings(htsmsg_t *m, th_transport_t *t);
void psi_save_transport_settings(htsmsg_t *m, th_transport_t *t);
void psi_rawts_table_parser(psi_section_t *section, uint8_t *tsb,
void (*gotsection)(const uint8_t *data, int len,
void *opauqe), void *opaque);
#endif /* PSI_H_ */

View file

@ -147,7 +147,7 @@ rawts_transport_add(rawts_t *rt, uint16_t sid, int pmt_pid)
static void
got_pmt(struct th_transport *t, th_stream_t *st,
uint8_t *table, int table_len)
const uint8_t *table, int table_len)
{
if(table[0] != 2)
return;
@ -163,12 +163,11 @@ got_pmt(struct th_transport *t, th_stream_t *st,
*
*/
static void
got_pat(rawts_t *rt)
got_pat(const uint8_t *ptr, size_t len, void *opaque)
{
rawts_t *rt = opaque;
th_transport_t *t;
th_stream_t *st;
int len = rt->rt_pat.ps_offset;
uint8_t *ptr = rt->rt_pat.ps_data;
uint16_t prognum;
uint16_t pid;
@ -209,28 +208,9 @@ got_pat(rawts_t *rt)
*
*/
static void
rawts_pat(rawts_t *rt, uint8_t *tsb)
rawts_pat(rawts_t *rt, const uint8_t *tsb)
{
int off = tsb[3] & 0x20 ? tsb[4] + 5 : 4;
int pusi = tsb[1] & 0x40;
int len;
if(off >= 188)
return;
if(pusi) {
len = tsb[off++];
if(len > 0) {
if(len > 188 - off)
return;
if(!psi_section_reassemble(&rt->rt_pat, tsb + off, len, 0, 1))
got_pat(rt);
off += len;
}
}
if(!psi_section_reassemble(&rt->rt_pat, tsb + off, 188 - off, pusi, 1))
got_pat(rt);
psi_section_reassemble(&rt->rt_pat, tsb, 1, got_pat, rt);
}

View file

@ -306,10 +306,11 @@ tt_decode_line(th_transport_t *t, th_stream_t *st, uint8_t *buf)
*
*/
void
teletext_input(th_transport_t *t, th_stream_t *st, uint8_t *tsb)
teletext_input(th_transport_t *t, th_stream_t *st, const uint8_t *tsb)
{
int i, j;
uint8_t *x, buf[42];
const uint8_t *x;
uint8_t buf[42];
x = tsb + 4;
for(i = 0; i < 4; i++) {

View file

@ -19,6 +19,6 @@
#ifndef TELETEXT_H
#define TELETEXT_H
void teletext_input(th_transport_t *t, th_stream_t *st, uint8_t *tsb);
void teletext_input(th_transport_t *t, th_stream_t *st, const uint8_t *tsb);
#endif /* TELETEXT_H */

View file

@ -698,6 +698,7 @@ transport_stream_create(th_transport_t *t, int pid,
st->st_type = type;
LIST_INSERT_HEAD(&t->tht_components, st, st_link);
st->st_transport = t;
st->st_pid = pid;
st->st_demuxer_fd = -1;

View file

@ -50,17 +50,17 @@ static void ts_remux(th_transport_t *t, const uint8_t *tsb);
* Code for dealing with a complete section
*/
static void
got_section(th_transport_t *t, th_stream_t *st)
got_section(const uint8_t *data, size_t len, void *opaque)
{
th_descrambler_t *td;
th_stream_t *st = opaque;
th_transport_t *t = st->st_transport;
if(st->st_type == SCT_CA) {
LIST_FOREACH(td, &t->tht_descramblers, td_transport_link)
td->td_table(td, t, st,
st->st_section->ps_data, st->st_section->ps_offset);
td->td_table(td, t, st, data, len);
} else if(st->st_got_section != NULL) {
st->st_got_section(t, st, st->st_section->ps_data,
st->st_section->ps_offset);
st->st_got_section(t, st, data, len);
}
}
@ -69,9 +69,9 @@ got_section(th_transport_t *t, th_stream_t *st)
* Continue processing of transport stream packets
*/
static void
ts_recv_packet0(th_transport_t *t, th_stream_t *st, uint8_t *tsb)
ts_recv_packet0(th_transport_t *t, th_stream_t *st, const uint8_t *tsb)
{
int off, len, pusi, cc, err = 0;
int off, pusi, cc, err = 0;
transport_set_streaming_status_flags(t, TSS_MUX_PACKETS);
@ -105,26 +105,8 @@ ts_recv_packet0(th_transport_t *t, th_stream_t *st, uint8_t *tsb)
if(st->st_section == NULL)
st->st_section = calloc(1, sizeof(struct psi_section));
if(err || off >= 188) {
st->st_section->ps_offset = -1; /* hold parser until next pusi */
break;
}
if(pusi) {
len = tsb[off++];
if(len > 0) {
if(len > 188 - off)
break;
if(!psi_section_reassemble(st->st_section, tsb + off, len, 0,
st->st_section_docrc))
got_section(t, st);
off += len;
}
}
if(!psi_section_reassemble(st->st_section, tsb + off, 188 - off, pusi,
st->st_section_docrc))
got_section(t, st);
psi_section_reassemble(st->st_section, tsb, st->st_section_docrc,
got_section, st);
break;
case SCT_TELETEXT:
@ -150,7 +132,7 @@ static const AVRational mpeg_tc = {1, 90000};
* than the stream PCR
*/
static void
ts_extract_pcr(th_transport_t *t, th_stream_t *st, uint8_t *tsb,
ts_extract_pcr(th_transport_t *t, th_stream_t *st, const uint8_t *tsb,
int64_t *pcrp)
{
int64_t real, pcr, d;
@ -200,7 +182,7 @@ ts_extract_pcr(th_transport_t *t, th_stream_t *st, uint8_t *tsb,
* Process transport stream packets, extract PCR and optionally descramble
*/
void
ts_recv_packet1(th_transport_t *t, uint8_t *tsb, int64_t *pcrp)
ts_recv_packet1(th_transport_t *t, const uint8_t *tsb, int64_t *pcrp)
{
th_stream_t *st;
int pid, n, m, r;
@ -273,7 +255,7 @@ ts_recv_packet1(th_transport_t *t, uint8_t *tsb, int64_t *pcrp)
* Process transport stream packets, simple version
*/
void
ts_recv_packet2(th_transport_t *t, uint8_t *tsb)
ts_recv_packet2(th_transport_t *t, const uint8_t *tsb)
{
th_stream_t *st;
int pid = (tsb[1] & 0x1f) << 8 | tsb[2];

View file

@ -19,8 +19,8 @@
#ifndef TSDEMUX_H
#define TSDEMUX_H
void ts_recv_packet1(th_transport_t *t, uint8_t *tsb, int64_t *pcrp);
void ts_recv_packet1(th_transport_t *t, const uint8_t *tsb, int64_t *pcrp);
void ts_recv_packet2(th_transport_t *t, uint8_t *tsb);
void ts_recv_packet2(th_transport_t *t, const uint8_t *tsb);
#endif /* TSDEMUX_H */

View file

@ -253,10 +253,11 @@ typedef struct th_descrambler {
LIST_ENTRY(th_descrambler) td_transport_link;
void (*td_table)(struct th_descrambler *d, struct th_transport *t,
struct th_stream *st, uint8_t *section, int section_len);
struct th_stream *st,
const uint8_t *section, int section_len);
int (*td_descramble)(struct th_descrambler *d, struct th_transport *t,
struct th_stream *st, uint8_t *tsb);
struct th_stream *st, const uint8_t *tsb);
void (*td_stop)(struct th_descrambler *d);
@ -269,7 +270,7 @@ typedef struct th_descrambler {
*/
typedef void (pid_section_callback_t)(struct th_transport *t,
struct th_stream *pi,
uint8_t *section, int section_len);
const uint8_t *section, int section_len);
/*
* Stream, one media component for a transport.
@ -279,7 +280,8 @@ typedef void (pid_section_callback_t)(struct th_transport *t,
typedef struct th_stream {
LIST_ENTRY(th_stream) st_link;
struct th_transport *st_transport;
streaming_component_type_t st_type;
int st_index;