*/
RB_HEAD(, mpegts_pid) mm_pids;
+ int mm_last_pid;
+ mpegts_pid_t *mm_last_mp;
int mm_num_tables;
LIST_HEAD(, mpegts_table) mm_tables;
int mpegts_mux_subscribe(mpegts_mux_t *mm, const char *name, int weight);
void mpegts_mux_unsubscribe_by_name(mpegts_mux_t *mm, const char *name);
+#define mpegts_mux_find_pid_fast(mm, pid, create) ({ \
+ mpegts_pid_t *__mp; \
+ if ((mm)->mm_last_pid != (pid)) \
+ __mp = mpegts_mux_find_pid(mm, pid, create); \
+ else \
+ __mp = (mm)->mm_last_mp; \
+ __mp; \
+})
+
mpegts_pid_t *mpegts_mux_find_pid(mpegts_mux_t *mm, int pid, int create);
size_t mpegts_input_recv_packets
void mpegts_table_dispatch
(const uint8_t *sec, size_t r, void *mt);
-void mpegts_table_release
+#define mpegts_table_release(t) \
+ do { if(--mt->mt_refcount == 0) mpegts_table_release_(mt); } while (0)
+void mpegts_table_release_
(mpegts_table_t *mt);
mpegts_table_t *mpegts_table_add
(mpegts_mux_t *mm, int tableid, int mask,
tvhdebug("pmt", " caid %04X (%s) provider %08X pid %04X",
caid, descrambler_caid2name(caid), provid, pid);
- if((st = service_stream_find((service_t*)t, pid)) == NULL) {
+ if((st = service_stream_find_fast((service_t*)t, pid)) == NULL) {
st = service_stream_create((service_t*)t, pid, SCT_CA);
r |= PMT_UPDATE_NEW_CA_STREAM;
}
// higher than normal MPEG TS (0x2000 ++)
int pid = DVB_TELETEXT_BASE + page;
- if((st = service_stream_find((service_t*)t, pid)) == NULL) {
+ if((st = service_stream_find_fast((service_t*)t, pid)) == NULL) {
r |= PMT_UPDATE_NEW_STREAM;
st = service_stream_create((service_t*)t, pid, SCT_TEXTSUB);
st->es_delete_me = 1;
if(hts_stream_type != SCT_UNKNOWN) {
- if((st = service_stream_find((service_t*)t, pid)) == NULL) {
+ if((st = service_stream_find_fast((service_t*)t, pid)) == NULL) {
update |= PMT_UPDATE_NEW_STREAM;
st = service_stream_create((service_t*)t, pid, hts_stream_type);
}
skel.mps_type = type;
skel.mps_owner = owner;
mps = RB_FIND(&mp->mp_subs, &skel, mps_link, mps_cmp);
+ if (pid == mm->mm_last_pid) {
+ mm->mm_last_pid = -1;
+ mm->mm_last_mp = NULL;
+ }
if (mps) {
RB_REMOVE(&mp->mp_subs, mps, mps_link);
free(mps);
name, pid, pid, mmi);
/* Find PID */
- if ((mp = mpegts_mux_find_pid(mm, pid, 0))) {
+ if ((mp = mpegts_mux_find_pid_fast(mm, pid, 0))) {
int stream = 0;
int table = 0;
mpegts_input_flush_mux(mi, mm);
/* Ensure PIDs are cleared */
+ mm->mm_last_pid = -1;
+ mm->mm_last_mp = NULL;
while ((mp = RB_FIRST(&mm->mm_pids))) {
while ((mps = RB_FIRST(&mp->mp_subs))) {
RB_REMOVE(&mp->mp_subs, mps, mps_link);
mm->mm_close_table = mpegts_mux_close_table;
TAILQ_INIT(&mm->mm_table_queue);
+ mm->mm_last_pid = -1;
+
/* Configuration */
if (conf)
idnode_load(&mm->mm_id, conf);
mp->mp_fd = -1;
}
}
+ if (mp) {
+ mm->mm_last_pid = pid;
+ mm->mm_last_mp = mp;
+ }
return mp;
}
}
void
-mpegts_table_release ( mpegts_table_t *mt )
+mpegts_table_release_ ( mpegts_table_t *mt )
{
- if(--mt->mt_refcount == 0) {
- free(mt->mt_name);
- free(mt);
- }
+ free(mt->mt_name);
+ free(mt);
}
void
{
int off, pusi, cc, error;
- service_set_streaming_status_flags((service_t*)t, TSS_MUX_PACKETS);
+ service_set_streaming_status_flags_fast((service_t*)t, TSS_MUX_PACKETS);
if(streaming_pad_probe_type(&t->s_streaming_pad, SMT_MPEGTS))
ts_remux(t, tsb);
pthread_mutex_lock(&t->s_stream_mutex);
- service_set_streaming_status_flags((service_t*)t, TSS_INPUT_HARDWARE);
+ service_set_streaming_status_flags_fast((service_t*)t, TSS_INPUT_HARDWARE);
if(error) {
/* Transport Error Indicator */
pid = (tsb[1] & 0x1f) << 8 | tsb[2];
- st = service_stream_find((service_t*)t, pid);
+ st = service_stream_find_fast((service_t*)t, pid);
/* Extract PCR */
if (pcr != PTS_UNSET)
}
if(!error)
- service_set_streaming_status_flags((service_t*)t, TSS_INPUT_SERVICE);
+ service_set_streaming_status_flags_fast((service_t*)t, TSS_INPUT_SERVICE);
avgstat_add(&t->s_rate, 188, dispatch_clock);
if(!error && t->s_scrambled != 0) {
if(n == 0) {
- service_set_streaming_status_flags((service_t*)t, TSS_NO_DESCRAMBLER);
+ service_set_streaming_status_flags_fast((service_t*)t, TSS_NO_DESCRAMBLER);
} else if(m == n) {
- service_set_streaming_status_flags((service_t*)t, TSS_NO_ACCESS);
+ service_set_streaming_status_flags_fast((service_t*)t, TSS_NO_ACCESS);
}
}
elementary_stream_t *st;
int pid = (tsb[1] & 0x1f) << 8 | tsb[2];
- if((st = service_stream_find((service_t*)t, pid)) != NULL)
+ if((st = service_stream_find_fast((service_t*)t, pid)) != NULL)
ts_recv_packet0(t, st, tsb);
}
pktbuf_ref_dec(pb);
- service_set_streaming_status_flags((service_t*)t, TSS_PACKETS);
+ service_set_streaming_status_flags_fast((service_t*)t, TSS_PACKETS);
sbuf_reset(sb);
}
avgstat_flush(&es->es_rate);
avgstat_flush(&es->es_cc_errors);
+ if (t->s_last_es == es) {
+ t->s_last_pid = -1;
+ t->s_last_es = NULL;
+ }
+
TAILQ_REMOVE(&t->s_components, es, es_link);
while ((c = LIST_FIRST(&es->es_caids)) != NULL) {
t->s_channel_name = service_channel_name;
t->s_provider_name = service_provider_name;
TAILQ_INIT(&t->s_components);
+ t->s_last_pid = -1;
streaming_pad_init(&t->s_streaming_pad);
/**
- * Add a new stream to a service
+ * Find an elementary stream in a service
*/
elementary_stream_t *
service_stream_find(service_t *t, int pid)
lock_assert(&t->s_stream_mutex);
TAILQ_FOREACH(st, &t->s_components, es_link) {
- if(st->es_pid == pid)
+ if(st->es_pid == pid) {
+ t->s_last_es = st;
+ t->s_last_pid = pid;
return st;
+ }
}
return NULL;
}
* List of all components.
*/
struct elementary_stream_queue s_components;
+ int s_last_pid;
+ elementary_stream_t *s_last_es;
/**
int *error,
int weight);
+#define service_stream_find_fast(t, pid) ({ \
+ elementary_stream_t *__es; \
+ if ((t)->s_last_pid != (pid)) \
+ __es = service_stream_find(t, pid); \
+ else \
+ __es = (t)->s_last_es; \
+ __es; \
+})
+
elementary_stream_t *service_stream_find(service_t *t, int pid);
elementary_stream_t *service_stream_create(service_t *t, int pid,
void service_set_streaming_status_flags(service_t *t, int flag);
+#define service_set_streaming_status_flags_fast(t, flag) \
+ do { if (((t)->s_streaming_status & flag) != flag) \
+ service_set_streaming_status_flags(t, flag); } while (0)
+
struct streaming_start;
struct streaming_start *service_build_stream_start(service_t *t);
streaming_pad_init(streaming_pad_t *sp)
{
LIST_INIT(&sp->sp_targets);
+ sp->sp_ntargets = 0;
+ sp->sp_reject_filter = 0;
}
/**
sp->sp_ntargets++;
st->st_pad = sp;
LIST_INSERT_HEAD(&sp->sp_targets, st, st_link);
+ sp->sp_reject_filter |= st->st_reject_filter;
}
void
streaming_target_disconnect(streaming_pad_t *sp, streaming_target_t *st)
{
+ int filter;
+
sp->sp_ntargets--;
st->st_pad = NULL;
LIST_REMOVE(st, st_link);
+
+ filter = 0;
+ LIST_FOREACH(st, &sp->sp_targets, st_link)
+ filter |= st->st_reject_filter;
+ sp->sp_reject_filter = filter;
}
}
-/**
- *
- */
-int
-streaming_pad_probe_type(streaming_pad_t *sp, streaming_message_type_t smt)
-{
- streaming_target_t *st;
-
- LIST_FOREACH(st, &sp->sp_targets, st_link) {
- if(!(st->st_reject_filter & SMT_TO_MASK(smt)))
- return 1;
- }
- return 0;
-}
-
-
/**
*
*/
streaming_start_t *streaming_start_copy(const streaming_start_t *src);
-int streaming_pad_probe_type(streaming_pad_t *sp,
- streaming_message_type_t smt);
+#define streaming_pad_probe_type(sp, smt) \
+ (((sp)->sp_reject_filter & SMT_TO_MASK(smt)) == 0)
const char *streaming_code2txt(int code);
typedef struct streaming_pad {
struct streaming_target_list sp_targets;
int sp_ntargets;
+ int sp_reject_filter;
} streaming_pad_t;
sbuf_alloc(sbuf_t *sb, int len)
{
if(sb->sb_data == NULL) {
- sb->sb_size = 4000;
+ sb->sb_size = len * 4 > 4000 ? len * 4 : 4000;
sb->sb_data = malloc(sb->sb_size);
+ return;
}
if(sb->sb_ptr + len >= sb->sb_size) {
}
}
+static void
+sbuf_alloc1(sbuf_t *sb, int len)
+{
+ if(sb->sb_data == NULL) {
+ sb->sb_size = len * 4 > 4000 ? len * 4 : 4000;
+ sb->sb_data = malloc(sb->sb_size);
+ return;
+ }
+
+ sb->sb_size += len * 4;
+ sb->sb_data = realloc(sb->sb_data, sb->sb_size);
+}
+
void
sbuf_append(sbuf_t *sb, const void *data, int len)
{
- sbuf_alloc(sb, len);
+ if(sb->sb_ptr + len >= sb->sb_size)
+ sbuf_alloc1(sb, len);
memcpy(sb->sb_data + sb->sb_ptr, data, len);
sb->sb_ptr += len;
}