Maintain the order of PIDs as they appear in the PMT. Fixes bug #218

This commit is contained in:
Andreas Öman 2010-06-04 20:33:16 +00:00
parent cb300661c5
commit 14ff47028b
12 changed files with 106 additions and 53 deletions

View file

@ -624,7 +624,7 @@ capmt_transport_start(th_transport_t *t)
ct->ct_tsbcluster = malloc(ct->ct_cluster_size * 188);
ct->ct_seq = capmt->capmt_seq++;
LIST_FOREACH(st, &t->tht_components, st_link) {
TAILQ_FOREACH(st, &t->tht_components, st_link) {
caid_t *c = LIST_FIRST(&st->st_caids);
if(c == NULL)
continue;

View file

@ -1367,7 +1367,7 @@ cwc_find_stream_by_caid(th_transport_t *t, int caid)
th_stream_t *st;
caid_t *c;
LIST_FOREACH(st, &t->tht_components, st_link) {
TAILQ_FOREACH(st, &t->tht_components, st_link) {
LIST_FOREACH(c, &st->st_caids, link) {
if(c->caid == caid)
return st;

View file

@ -1110,7 +1110,7 @@ dvb_mux_copy(th_dvb_adapter_t *dst, th_dvb_mux_instance_t *tdmi_src)
pthread_mutex_lock(&t_src->tht_stream_mutex);
pthread_mutex_lock(&t_dst->tht_stream_mutex);
LIST_FOREACH(st_src, &t_src->tht_components, st_link) {
TAILQ_FOREACH(st_src, &t_src->tht_components, st_link) {
st_dst = transport_stream_create(t_dst,

View file

@ -55,7 +55,7 @@ dvb_transport_open_demuxers(th_dvb_adapter_t *tda, th_transport_t *t)
int fd;
th_stream_t *st;
LIST_FOREACH(st, &t->tht_components, st_link) {
TAILQ_FOREACH(st, &t->tht_components, st_link) {
if(st->st_pid >= 0x2000)
continue;
@ -162,7 +162,7 @@ dvb_transport_stop(th_transport_t *t)
LIST_REMOVE(t, tht_active_link);
pthread_mutex_unlock(&tda->tda_delivery_mutex);
LIST_FOREACH(st, &t->tht_components, st_link) {
TAILQ_FOREACH(st, &t->tht_components, st_link) {
if(st->st_demuxer_fd != -1) {
close(st->st_demuxer_fd);
st->st_demuxer_fd = -1;

View file

@ -222,6 +222,7 @@ psi_build_pat(th_transport_t *t, uint8_t *buf, int maxlen, int pmtpid)
#define PMT_UPDATE_CA_PROVIDER_CHANGE 0x200
#define PMT_UPDATE_PARENT_PID 0x400
#define PMT_UPDATE_CAID_DELETED 0x800
#define PMT_REORDERED 0x1000
/**
* Add a CA descriptor
@ -240,6 +241,8 @@ psi_desc_add_ca(th_transport_t *t, uint16_t caid, uint32_t provid, uint16_t pid)
st->st_delete_me = 0;
st->st_position = 0x40000;
LIST_FOREACH(c, &st->st_caids, link) {
if(c->caid == caid) {
c->delete_me = 0;
@ -288,10 +291,10 @@ psi_desc_ca(th_transport_t *t, const uint8_t *buffer, int size)
//Add extra providers, if any
for (i = 17; i < size; i += 15){
uint16_t _pid = ((buffer[i]&0x1F) << 8) | buffer[i + 1];
uint16_t _provid = (buffer[i + 2] << 8) | buffer[i + 3];
uint16_t xpid = ((buffer[i]&0x1F) << 8) | buffer[i + 1];
uint16_t xprovid = (buffer[i + 2] << 8) | buffer[i + 3];
r |= psi_desc_add_ca(t, caid, _provid, _pid);
r |= psi_desc_add_ca(t, caid, xprovid, xpid);
}
break;
case 0x0500:// Viaccess
@ -322,7 +325,7 @@ psi_desc_ca(th_transport_t *t, const uint8_t *buffer, int size)
*/
static int
psi_desc_teletext(th_transport_t *t, const uint8_t *ptr, int size,
int parent_pid)
int parent_pid, int *position)
{
int r = 0;
th_stream_t *st;
@ -354,6 +357,12 @@ psi_desc_teletext(th_transport_t *t, const uint8_t *ptr, int size,
r |= PMT_UPDATE_PARENT_PID;
st->st_parent_pid = parent_pid;
}
if(st->st_position != *position) {
st->st_position = *position;
r |= PMT_REORDERED;
}
(*position)++;
}
ptr += 5;
size -= 5;
@ -361,6 +370,42 @@ psi_desc_teletext(th_transport_t *t, const uint8_t *ptr, int size,
return r;
}
/**
*
*/
static int
pidcmp(const void *A, const void *B)
{
th_stream_t *a = *(th_stream_t **)A;
th_stream_t *b = *(th_stream_t **)B;
return a->st_position - b->st_position;
}
/**
*
*/
static void
sort_pids(th_transport_t *t)
{
th_stream_t *st, **v;
int num = 0, i = 0;
TAILQ_FOREACH(st, &t->tht_components, st_link)
num++;
v = alloca(num * sizeof(th_stream_t *));
TAILQ_FOREACH(st, &t->tht_components, st_link)
v[i++] = st;
qsort(v, num, sizeof(th_stream_t *), pidcmp);
TAILQ_INIT(&t->tht_components);
for(i = 0; i < num; i++)
TAILQ_INSERT_TAIL(&t->tht_components, v[i], st_link);
}
/**
* PMT parser, from ISO 13818-1 and ETSI EN 300 468
@ -383,6 +428,9 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
int composition_id;
int ancillary_id;
int version;
int position = 0;
int tt_position = 1000;
caid_t *c, *cn;
if(len < 9)
@ -390,7 +438,7 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
lock_assert(&t->tht_stream_mutex);
had_components = !!LIST_FIRST(&t->tht_components);
had_components = !!TAILQ_FIRST(&t->tht_components);
sid = ptr[0] << 8 | ptr[1];
version = ptr[2] >> 1 & 0x1f;
@ -416,15 +464,15 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
/* Mark all streams for deletion */
if(delete) {
LIST_FOREACH(st, &t->tht_components, st_link) {
TAILQ_FOREACH(st, &t->tht_components, st_link) {
st->st_delete_me = 1;
LIST_FOREACH(c, &st->st_caids, link)
c->delete_me = 1;
}
}
// Common descriptors
while(dllen > 1) {
dtag = ptr[0];
dlen = ptr[1];
@ -441,11 +489,11 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
default:
break;
}
len -= dlen; ptr += dlen; dllen -= dlen;
}
while(len >= 5) {
estype = ptr[0];
pid = (ptr[1] & 0x1f) << 8 | ptr[2];
@ -515,7 +563,7 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
if(estype == 0x06)
hts_stream_type = SCT_TELETEXT;
update |= psi_desc_teletext(t, ptr, dlen, pid);
update |= psi_desc_teletext(t, ptr, dlen, pid, &tt_position);
break;
case DVB_DESC_AC3:
@ -553,6 +601,11 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
st->st_delete_me = 0;
if(st->st_position != position) {
update |= PMT_REORDERED;
st->st_position = position;
}
st->st_tb = (AVRational){1, 90000};
if(memcmp(st->st_lang, lang, 4)) {
@ -575,11 +628,12 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
update |= PMT_UPDATE_ANCILLARY_ID;
}
}
position++;
}
/* Scan again to see if any streams should be deleted */
for(st = LIST_FIRST(&t->tht_components); st != NULL; st = next) {
next = LIST_NEXT(st, st_link);
for(st = TAILQ_FIRST(&t->tht_components); st != NULL; st = next) {
next = TAILQ_NEXT(st, st_link);
for(c = LIST_FIRST(&st->st_caids); c != NULL; c = cn) {
cn = LIST_NEXT(c, link);
@ -597,9 +651,12 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
}
}
if(update & PMT_REORDERED)
sort_pids(t);
if(update) {
tvhlog(LOG_DEBUG, "PSI", "Transport \"%s\" PMT (version %d) updated"
"%s%s%s%s%s%s%s%s%s%s%s%s",
"%s%s%s%s%s%s%s%s%s%s%s%s%s",
transport_nicename(t), version,
update&PMT_UPDATE_PCR ? ", PCR PID changed":"",
update&PMT_UPDATE_NEW_STREAM ? ", New elementary stream":"",
@ -612,7 +669,8 @@ psi_parse_pmt(th_transport_t *t, const uint8_t *ptr, int len, int chksvcid,
update&PMT_UPDATE_NEW_CAID ? ", New CAID":"",
update&PMT_UPDATE_CA_PROVIDER_CHANGE? ", CA provider changed":"",
update&PMT_UPDATE_PARENT_PID ? ", Parent PID changed":"",
update&PMT_UPDATE_CAID_DELETED ? ", CAID deleted":"");
update&PMT_UPDATE_CAID_DELETED ? ", CAID deleted":"",
update&PMT_REORDERED ? ", PIDs reordered":"");
transport_request_save(t);
@ -882,12 +940,13 @@ psi_save_transport_settings(htsmsg_t *m, th_transport_t *t)
lock_assert(&t->tht_stream_mutex);
LIST_FOREACH(st, &t->tht_components, st_link) {
TAILQ_FOREACH(st, &t->tht_components, st_link) {
sub = htsmsg_create_map();
htsmsg_add_u32(sub, "pid", st->st_pid);
htsmsg_add_str(sub, "type", val2str(st->st_type, streamtypetab) ?: "?");
htsmsg_add_u32(sub, "position", st->st_position);
if(st->st_lang[0])
htsmsg_add_str(sub, "language", st->st_lang);
@ -1039,6 +1098,8 @@ psi_load_transport_settings(htsmsg_t *m, th_transport_t *t)
if(!htsmsg_get_u32(c, "frameduration", &u32))
st->st_frame_duration = u32;
if(!htsmsg_get_u32(c, "position", &u32))
st->st_position = u32;
load_legacy_caid(c, st);
load_caid(c, st);
@ -1056,4 +1117,5 @@ psi_load_transport_settings(htsmsg_t *m, th_transport_t *t)
st->st_parent_pid = u32;
}
}
sort_pids(t);
}

View file

@ -74,7 +74,7 @@ subscription_link_transport(th_subscription_t *s, th_transport_t *t)
pthread_mutex_lock(&t->tht_stream_mutex);
if(LIST_FIRST(&t->tht_components) != NULL)
if(TAILQ_FIRST(&t->tht_components) != NULL)
s->ths_start_message =
streaming_msg_create_data(SMT_START, transport_build_stream_start(t));
@ -114,7 +114,7 @@ subscription_unlink_transport(th_subscription_t *s, int reason)
// Unlink from transport output
streaming_target_disconnect(&t->tht_streaming_pad, &s->ths_input);
if(LIST_FIRST(&t->tht_components) != NULL &&
if(TAILQ_FIRST(&t->tht_components) != NULL &&
s->ths_state == SUBSCRIPTION_GOT_TRANSPORT) {
// Send a STOP message to the subscription client
sm = streaming_msg_create_code(SMT_STOP, reason);

View file

@ -173,7 +173,7 @@ transport_stream_destroy(th_transport_t *t, th_stream_t *st)
{
if(t->tht_status == TRANSPORT_RUNNING)
stream_clean(st);
LIST_REMOVE(st, st_link);
TAILQ_REMOVE(&t->tht_components, st, st_link);
free(st->st_nicename);
free(st);
}
@ -204,7 +204,7 @@ transport_stop(th_transport_t *t)
/**
* Clean up each stream
*/
LIST_FOREACH(st, &t->tht_components, st_link)
TAILQ_FOREACH(st, &t->tht_components, st_link)
stream_clean(st);
t->tht_status = TRANSPORT_IDLE;
@ -268,7 +268,7 @@ transport_start(th_transport_t *t, unsigned int weight, int force_start)
/**
* Initialize stream
*/
LIST_FOREACH(st, &t->tht_components, st_link)
TAILQ_FOREACH(st, &t->tht_components, st_link)
stream_init(st);
pthread_mutex_unlock(&t->tht_stream_mutex);
@ -514,8 +514,8 @@ transport_destroy(th_transport_t *t)
free(t->tht_svcname);
free(t->tht_provider);
while((st = LIST_FIRST(&t->tht_components)) != NULL) {
LIST_REMOVE(st, st_link);
while((st = TAILQ_FIRST(&t->tht_components)) != NULL) {
TAILQ_REMOVE(&t->tht_components, st, st_link);
free(st->st_nicename);
free(st);
}
@ -546,6 +546,7 @@ transport_create(const char *identifier, int type, int source_type)
t->tht_refcount = 1;
t->tht_enabled = 1;
t->tht_pcr_last = AV_NOPTS_VALUE;
TAILQ_INIT(&t->tht_components);
streaming_pad_init(&t->tht_streaming_pad);
@ -617,7 +618,7 @@ transport_make_nicename(th_transport_t *t)
free(t->tht_nicename);
t->tht_nicename = strdup(buf);
LIST_FOREACH(st, &t->tht_components, st_link)
TAILQ_FOREACH(st, &t->tht_components, st_link)
transport_stream_make_nicename(t, st);
}
@ -634,7 +635,7 @@ transport_stream_create(th_transport_t *t, int pid,
int idx = 0;
lock_assert(&t->tht_stream_mutex);
LIST_FOREACH(st, &t->tht_components, st_link) {
TAILQ_FOREACH(st, &t->tht_components, st_link) {
if(st->st_index > idx)
idx = st->st_index;
i++;
@ -646,7 +647,7 @@ transport_stream_create(th_transport_t *t, int pid,
st->st_index = idx + 1;
st->st_type = type;
LIST_INSERT_HEAD(&t->tht_components, st, st_link);
TAILQ_INSERT_TAIL(&t->tht_components, st, st_link);
st->st_transport = t;
st->st_pid = pid;
@ -682,7 +683,7 @@ transport_stream_find(th_transport_t *t, int pid)
lock_assert(&t->tht_stream_mutex);
LIST_FOREACH(st, &t->tht_components, st_link) {
TAILQ_FOREACH(st, &t->tht_components, st_link) {
if(st->st_pid == pid)
return st;
}
@ -825,7 +826,7 @@ transport_restart(th_transport_t *t, int had_components)
if(t->tht_refresh_feed != NULL)
t->tht_refresh_feed(t);
if(LIST_FIRST(&t->tht_components) != NULL) {
if(TAILQ_FIRST(&t->tht_components) != NULL) {
sm = streaming_msg_create_data(SMT_START,
transport_build_stream_start(t));
@ -847,7 +848,7 @@ transport_build_stream_start(th_transport_t *t)
lock_assert(&t->tht_stream_mutex);
LIST_FOREACH(st, &t->tht_components, st_link)
TAILQ_FOREACH(st, &t->tht_components, st_link)
n++;
ss = calloc(1, sizeof(streaming_start_t) +
@ -856,7 +857,7 @@ transport_build_stream_start(th_transport_t *t)
ss->ss_num_components = n;
n = 0;
LIST_FOREACH(st, &t->tht_components, st_link) {
TAILQ_FOREACH(st, &t->tht_components, st_link) {
streaming_start_component_t *ssc = &ss->ss_components[n++];
ssc->ssc_index = st->st_index;
ssc->ssc_type = st->st_type;

View file

@ -66,18 +66,6 @@ void transport_remove_subscriber(th_transport_t *t, th_subscription_t *s,
void transport_set_streaming_status_flags(th_transport_t *t, int flag);
static inline th_stream_t *
transport_find_stream_by_pid(th_transport_t *t, int pid)
{
th_stream_t *st;
LIST_FOREACH(st, &t->tht_components, st_link) {
if(st->st_pid == pid)
return st;
}
return NULL;
}
struct streaming_start;
struct streaming_start *transport_build_stream_start(th_transport_t *t);

View file

@ -202,7 +202,7 @@ ts_recv_packet1(th_transport_t *t, const uint8_t *tsb, int64_t *pcrp)
pid = (tsb[1] & 0x1f) << 8 | tsb[2];
st = transport_find_stream_by_pid(t, pid);
st = transport_stream_find(t, pid);
/* Extract PCR */
if(tsb[3] & 0x20 && tsb[4] > 0 && tsb[5] & 0x10)
@ -260,7 +260,7 @@ ts_recv_packet2(th_transport_t *t, const uint8_t *tsb)
th_stream_t *st;
int pid = (tsb[1] & 0x1f) << 8 | tsb[2];
if((st = transport_find_stream_by_pid(t, pid)) != NULL)
if((st = transport_stream_find(t, pid)) != NULL)
ts_recv_packet0(t, st, tsb);
}

View file

@ -110,6 +110,7 @@ LIST_HEAD(th_transport_list, th_transport);
RB_HEAD(th_transport_tree, th_transport);
TAILQ_HEAD(th_transport_queue, th_transport);
LIST_HEAD(th_stream_list, th_stream);
TAILQ_HEAD(th_stream_queue, th_stream);
LIST_HEAD(th_muxer_list, th_muxer);
LIST_HEAD(th_muxstream_list, th_muxstream);
LIST_HEAD(th_descrambler_list, th_descrambler);
@ -359,7 +360,8 @@ typedef struct caid {
*/
typedef struct th_stream {
LIST_ENTRY(th_stream) st_link;
TAILQ_ENTRY(th_stream) st_link;
int st_position;
struct th_transport *st_transport;
streaming_component_type_t st_type;
@ -759,7 +761,7 @@ typedef struct th_transport {
/**
* List of all components.
*/
struct th_stream_list tht_components;
struct th_stream_queue tht_components;
/**

View file

@ -1054,7 +1054,7 @@ extjs_servicedetails(http_connection_t *hc,
streams = htsmsg_create_list();
LIST_FOREACH(st, &t->tht_components, st_link) {
TAILQ_FOREACH(st, &t->tht_components, st_link) {
c = htsmsg_create_map();
htsmsg_add_u32(c, "pid", st->st_pid);

View file

@ -106,7 +106,7 @@ dumptransports(htsbuf_queue_t *hq, struct th_transport_list *l, int indent)
htsbuf_qprintf(hq, "%*.s-------------------------------------------\n",
indent + 4, "");
LIST_FOREACH(st, &t->tht_components, st_link) {
TAILQ_FOREACH(st, &t->tht_components, st_link) {
caid_t *caid;
htsbuf_qprintf(hq, "%*.s%-16s %-5d %-5d %-5s\n", indent + 4, "",
streaming_component_type2txt(st->st_type),