capmt/cwc/mpegts: descrambler changes - register CA PIDs on demand
- capmt code was a bit restructured again
This commit is contained in:
parent
db59cf12a5
commit
8c4597022b
10 changed files with 382 additions and 159 deletions
|
@ -26,6 +26,8 @@
|
|||
struct service;
|
||||
struct elementary_stream;
|
||||
struct tvhcsa;
|
||||
struct mpegts_table;
|
||||
struct mpegts_mux;
|
||||
|
||||
/**
|
||||
* Descrambler superclass
|
||||
|
@ -45,13 +47,28 @@ typedef struct th_descrambler {
|
|||
struct service *td_service;
|
||||
struct tvhcsa *td_csa;
|
||||
|
||||
void (*td_table)(struct th_descrambler *d, struct elementary_stream *st,
|
||||
const uint8_t *section, int section_len);
|
||||
|
||||
void (*td_stop)(struct th_descrambler *d);
|
||||
void (*td_stop) (struct th_descrambler *d);
|
||||
void (*td_caid_change)(struct th_descrambler *d);
|
||||
|
||||
} th_descrambler_t;
|
||||
|
||||
typedef void (*descrambler_section_callback_t)
|
||||
(void *opaque, int pid, const uint8_t *section, int section_len);
|
||||
|
||||
/**
|
||||
* Track required PIDs
|
||||
*/
|
||||
typedef struct descrambler_section {
|
||||
TAILQ_ENTRY(descrambler_section) link;
|
||||
descrambler_section_callback_t callback;
|
||||
void *opaque;
|
||||
} descrambler_section_t;
|
||||
|
||||
typedef struct descrambler_table {
|
||||
TAILQ_ENTRY(descrambler_table) link;
|
||||
struct mpegts_table *table;
|
||||
TAILQ_HEAD(,descrambler_section) sections;
|
||||
} descrambler_table_t;
|
||||
|
||||
/**
|
||||
* List of CA ids
|
||||
|
@ -87,11 +104,14 @@ void descrambler_init ( void );
|
|||
void descrambler_done ( void );
|
||||
void descrambler_service_start ( struct service *t );
|
||||
void descrambler_service_stop ( struct service *t );
|
||||
void descrambler_caid_changed ( struct service *t );
|
||||
int descrambler_descramble ( struct service *t,
|
||||
struct elementary_stream *st,
|
||||
const uint8_t *tsb );
|
||||
void descrambler_ca_section ( struct elementary_stream *st,
|
||||
const uint8_t *data, size_t len );
|
||||
int descrambler_open_pid ( struct mpegts_mux *mux, void *opaque, int pid,
|
||||
descrambler_section_callback_t callback );
|
||||
int descrambler_close_pid ( struct mpegts_mux *mux, void *opaque, int pid );
|
||||
void descrambler_flush_tables ( struct mpegts_mux *mux );
|
||||
const char *descrambler_caid2name( uint16_t caid );
|
||||
uint16_t descrambler_name2caid ( const char *str );
|
||||
card_type_t detect_card_type ( const uint16_t caid );
|
||||
|
|
|
@ -116,6 +116,7 @@ typedef struct dmx_sct_filter_params {
|
|||
#define MAX_INDEX 64
|
||||
#define MAX_FILTER 64
|
||||
#define MAX_SOCKETS 16 // max sockets (simultaneous channels) per demux
|
||||
#define MAX_PIDS 64 // max opened pids
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -215,6 +216,23 @@ typedef struct capmt_message {
|
|||
sbuf_t cm_sb;
|
||||
} capmt_message_t;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
struct capmt;
|
||||
typedef struct capmt_opaque {
|
||||
struct capmt *capmt;
|
||||
uint16_t adapter;
|
||||
uint16_t pid;
|
||||
} capmt_opaque_t;
|
||||
|
||||
typedef struct capmt_adapter {
|
||||
ca_info_t ca_info[MAX_INDEX];
|
||||
int ca_sock;
|
||||
mpegts_input_t *ca_tuner;
|
||||
capmt_opaque_t ca_pids[MAX_PIDS];
|
||||
} capmt_adapter_t;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -244,7 +262,6 @@ typedef struct capmt {
|
|||
int sids[MAX_SOCKETS];
|
||||
int capmt_sock[MAX_SOCKETS];
|
||||
int capmt_sock_reconnect[MAX_SOCKETS];
|
||||
int capmt_sock_ca0[MAX_CA];
|
||||
|
||||
/* thread flags */
|
||||
int capmt_connected;
|
||||
|
@ -258,15 +275,16 @@ typedef struct capmt {
|
|||
/* runtime status */
|
||||
tvhpoll_t *capmt_poll;
|
||||
th_pipe_t capmt_pipe;
|
||||
mpegts_input_t *capmt_tuners[MAX_CA];
|
||||
capmt_demuxes_t capmt_demuxes;
|
||||
ca_info_t capmt_ca_info[MAX_CA][MAX_INDEX];
|
||||
capmt_adapter_t capmt_adapters[MAX_CA];
|
||||
TAILQ_HEAD(, capmt_message) capmt_writeq;
|
||||
pthread_mutex_t capmt_mutex;
|
||||
} capmt_t;
|
||||
|
||||
static void capmt_enumerate_services(capmt_t *capmt, int force);
|
||||
static void capmt_send_request(capmt_service_t *ct, int lm);
|
||||
static void capmt_table_input(void *opaque, int pid,
|
||||
const uint8_t *data, int len);
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -325,6 +343,73 @@ capmt_poll_rem(capmt_t *capmt, int fd)
|
|||
tvhpoll_rem(capmt->capmt_poll, &ev, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
capmt_pid_add(capmt_t *capmt, int adapter, int pid)
|
||||
{
|
||||
capmt_adapter_t *ca = &capmt->capmt_adapters[adapter];
|
||||
capmt_opaque_t *o = NULL, *t;
|
||||
mpegts_mux_instance_t *mmi;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < MAX_PIDS; i++) {
|
||||
t = &ca->ca_pids[i];
|
||||
if (t->pid == pid)
|
||||
return;
|
||||
if (t->pid == 0)
|
||||
o = t;
|
||||
}
|
||||
if (o) {
|
||||
o->capmt = capmt;
|
||||
o->adapter = adapter;
|
||||
o->pid = pid;
|
||||
mmi = LIST_FIRST(&capmt->capmt_adapters[adapter].ca_tuner->mi_mux_active);
|
||||
descrambler_open_pid(mmi->mmi_mux, o, pid, capmt_table_input);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
capmt_pid_remove(capmt_t *capmt, int adapter, int pid)
|
||||
{
|
||||
capmt_adapter_t *ca = &capmt->capmt_adapters[adapter];
|
||||
mpegts_mux_instance_t *mmi;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < MAX_PIDS; i++)
|
||||
if (ca->ca_pids[i].pid == pid)
|
||||
break;
|
||||
if (i >= MAX_PIDS);
|
||||
return;
|
||||
mmi = LIST_FIRST(&capmt->capmt_adapters[adapter].ca_tuner->mi_mux_active);
|
||||
descrambler_close_pid(mmi->mmi_mux, &ca->ca_pids[i], pid);
|
||||
ca->ca_pids[i].pid = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
capmt_pid_flush(capmt_t *capmt)
|
||||
{
|
||||
capmt_adapter_t *ca;
|
||||
mpegts_mux_instance_t *mmi;
|
||||
mpegts_input_t *tuner;
|
||||
capmt_opaque_t *o;
|
||||
int adapter, i;
|
||||
|
||||
for (adapter = 0; adapter < MAX_CA; adapter++) {
|
||||
tuner = capmt->capmt_adapters[adapter].ca_tuner;
|
||||
if (tuner == NULL)
|
||||
continue;
|
||||
ca = &capmt->capmt_adapters[adapter];
|
||||
mmi = LIST_FIRST(&tuner->mi_mux_active);
|
||||
for (i = 0; i < MAX_PIDS; i++) {
|
||||
o = &ca->ca_pids[i];
|
||||
if (o->pid) {
|
||||
if (mmi)
|
||||
descrambler_close_pid(mmi->mmi_mux, &ca->ca_pids[i], o->pid);
|
||||
o->pid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -399,14 +484,16 @@ capmt_connect(capmt_t *capmt, int i)
|
|||
*
|
||||
*/
|
||||
static void
|
||||
capmt_socket_close(capmt_t *capmt, int i)
|
||||
capmt_socket_close(capmt_t *capmt, int sock_idx)
|
||||
{
|
||||
int fd = capmt->capmt_sock[i];
|
||||
int fd = capmt->capmt_sock[sock_idx];
|
||||
if (fd < 0)
|
||||
return;
|
||||
capmt_poll_rem(capmt, fd);
|
||||
close(fd);
|
||||
capmt->capmt_sock[i] = -1;
|
||||
capmt->capmt_sock[sock_idx] = -1;
|
||||
if (capmt_oscam_new(capmt))
|
||||
capmt_pid_flush(capmt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -505,7 +592,7 @@ capmt_queue_msg(capmt_t *capmt, int sid, const uint8_t *buf, size_t len)
|
|||
|
||||
sbuf_init_fixed(&msg->cm_sb, len);
|
||||
sbuf_append(&msg->cm_sb, buf, len);
|
||||
msg->cm_sid = sid;
|
||||
msg->cm_sid = sid;
|
||||
pthread_mutex_lock(&capmt->capmt_mutex);
|
||||
TAILQ_INSERT_TAIL(&capmt->capmt_writeq, msg, cm_link);
|
||||
pthread_mutex_unlock(&capmt->capmt_mutex);
|
||||
|
@ -630,7 +717,7 @@ capmt_service_destroy(th_descrambler_t *td)
|
|||
capmt_enumerate_services(ct->ct_capmt, 1);
|
||||
|
||||
if (LIST_EMPTY(&ct->ct_capmt->capmt_services)) {
|
||||
ct->ct_capmt->capmt_tuners[ct->ct_adapter] = NULL;
|
||||
ct->ct_capmt->capmt_adapters[ct->ct_adapter].ca_tuner = NULL;
|
||||
memset(&ct->ct_capmt->capmt_demuxes, 0, sizeof(ct->ct_capmt->capmt_demuxes));
|
||||
}
|
||||
|
||||
|
@ -639,7 +726,7 @@ capmt_service_destroy(th_descrambler_t *td)
|
|||
}
|
||||
|
||||
static void
|
||||
capmt_filter_data(capmt_t *capmt, int sid, uint8_t adapter, uint8_t demux_index,
|
||||
capmt_filter_data(capmt_t *capmt, uint8_t adapter, uint8_t demux_index,
|
||||
uint8_t filter_index, const uint8_t *data, int len)
|
||||
{
|
||||
uint8_t *buf = alloca(len + 6);
|
||||
|
@ -649,7 +736,7 @@ capmt_filter_data(capmt_t *capmt, int sid, uint8_t adapter, uint8_t demux_index,
|
|||
buf[5] = filter_index;
|
||||
memcpy(buf + 6, data, len);
|
||||
if (len - 3 == ((((uint16_t)buf[7] << 8) | buf[8]) & 0xfff))
|
||||
capmt_queue_msg(capmt, sid, buf, len + 6);
|
||||
capmt_queue_msg(capmt, 0, buf, len + 6);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -657,7 +744,7 @@ capmt_set_filter(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
|
|||
{
|
||||
uint8_t demux_index = sbuf_peek_u8 (sb, offset + 4);
|
||||
uint8_t filter_index = sbuf_peek_u8 (sb, offset + 5);
|
||||
int pid = sbuf_peek_s32(sb, offset + 6);
|
||||
uint16_t pid = sbuf_peek_u16(sb, offset + 6);
|
||||
dmx_filter_params_t *filter;
|
||||
dmx_filter_params_t *params = (dmx_filter_params_t *)sbuf_peek(sb, offset + 6);
|
||||
capmt_filters_t *cf;
|
||||
|
@ -666,7 +753,8 @@ capmt_set_filter(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
|
|||
adapter, demux_index, filter_index, pid);
|
||||
if (adapter >= MAX_CA ||
|
||||
demux_index >= MAX_INDEX ||
|
||||
filter_index >= MAX_FILTER)
|
||||
filter_index >= MAX_FILTER ||
|
||||
(pid < 0 || pid > 8191))
|
||||
return;
|
||||
cf = &capmt->capmt_demuxes.filters[demux_index];
|
||||
if (cf->max && cf->adapter != adapter)
|
||||
|
@ -674,6 +762,7 @@ capmt_set_filter(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
|
|||
cf->adapter = adapter;
|
||||
filter = &cf->dmx[filter_index];
|
||||
filter->pid = pid;
|
||||
capmt_pid_add(capmt, adapter, pid);
|
||||
memcpy(&filter->filter, ¶ms->filter, sizeof(params->filter));
|
||||
filter->timeout = filter->flags = 0;
|
||||
if (capmt->capmt_demuxes.max <= demux_index)
|
||||
|
@ -707,6 +796,7 @@ capmt_stop_filter(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
|
|||
if (filter->pid != pid)
|
||||
return;
|
||||
memset(filter, 0, sizeof(*filter));
|
||||
capmt_pid_remove(capmt, adapter, pid);
|
||||
/* short the max values */
|
||||
filter_index = cf->max - 1;
|
||||
while (filter_index != 255 && cf->dmx[filter_index].pid == 0)
|
||||
|
@ -733,6 +823,28 @@ capmt_notify_server(capmt_t *capmt, capmt_service_t *ct)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
capmt_abort(capmt_t *capmt, int keystate)
|
||||
{
|
||||
mpegts_service_t *t;
|
||||
capmt_service_t *ct;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
LIST_FOREACH(ct, &capmt->capmt_services, ct_link) {
|
||||
t = (mpegts_service_t *)ct->td_service;
|
||||
|
||||
if (ct->td_keystate != keystate) {
|
||||
tvhlog(LOG_ERR, "capmt",
|
||||
"Can not descramble service \"%s\", %s",
|
||||
t->s_dvb_svcname,
|
||||
keystate == DS_FORBIDDEN ?
|
||||
"access denied" : "connection close");
|
||||
ct->td_keystate = keystate;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
capmt_process_key(capmt_t *capmt, uint8_t adapter, uint16_t seq,
|
||||
const uint8_t *even, const uint8_t *odd,
|
||||
|
@ -785,6 +897,7 @@ static int
|
|||
capmt_msg_size(capmt_t *capmt, sbuf_t *sb, int offset)
|
||||
{
|
||||
uint32_t cmd;
|
||||
int oscam_new = capmt_oscam_new(capmt);
|
||||
|
||||
if (sb->sb_ptr - offset < 4)
|
||||
return 0;
|
||||
|
@ -803,9 +916,9 @@ capmt_msg_size(capmt_t *capmt, sbuf_t *sb, int offset)
|
|||
return 4 + 8;
|
||||
else if (cmd == CA_SET_DESCR)
|
||||
return 4 + 16;
|
||||
else if (cmd == DMX_SET_FILTER)
|
||||
else if (oscam_new && cmd == DMX_SET_FILTER)
|
||||
return 4 + 2 + sizeof(dmx_filter_params_t);
|
||||
else if (cmd == DMX_STOP)
|
||||
else if (oscam_new && cmd == DMX_STOP)
|
||||
return 4 + 4;
|
||||
else {
|
||||
sb->sb_err = 0;
|
||||
|
@ -826,9 +939,10 @@ capmt_analyze_cmd(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
|
|||
int32_t index = sbuf_peek_s32(sb, offset + 8);
|
||||
tvhlog(LOG_DEBUG, "capmt", "CA_SET_PID adapter %d index %d pid 0x%04x", adapter, index, pid);
|
||||
if (adapter < MAX_CA && index >= 0 && index < MAX_INDEX) {
|
||||
capmt->capmt_ca_info[adapter][index].pid = pid;
|
||||
capmt->capmt_adapters[adapter].ca_info[index].pid = pid;
|
||||
} else if (index < 0) {
|
||||
memset(&capmt->capmt_ca_info[adapter], 0, sizeof(capmt->capmt_ca_info[adapter]));
|
||||
memset(&capmt->capmt_adapters[adapter].ca_info, 0,
|
||||
sizeof(capmt->capmt_adapters[adapter].ca_info));
|
||||
} else
|
||||
tvhlog(LOG_ERR, "capmt", "Invalid index %d in CA_SET_PID (%d) for adapter %d", index, MAX_INDEX, adapter);
|
||||
|
||||
|
@ -844,7 +958,7 @@ capmt_analyze_cmd(capmt_t *capmt, int adapter, sbuf_t *sb, int offset)
|
|||
return;
|
||||
if (adapter >= MAX_CA || index >= MAX_INDEX)
|
||||
return;
|
||||
cai = &capmt->capmt_ca_info[adapter][index];
|
||||
cai = &capmt->capmt_adapters[adapter].ca_info[index];
|
||||
if (parity == 0) {
|
||||
memcpy(cai->even, cw, 8); // even key
|
||||
capmt_process_key(capmt, adapter, cai->pid, cai->even, cai->odd, 1);
|
||||
|
@ -909,8 +1023,8 @@ handle_ca0(capmt_t *capmt) {
|
|||
capmt->capmt_poll = tvhpoll_create(MAX_CA + 1);
|
||||
capmt_poll_add(capmt, capmt->capmt_pipe.rd, 0);
|
||||
for (i = 0; i < MAX_CA; i++)
|
||||
if (capmt->capmt_sock_ca0[i])
|
||||
capmt_poll_add(capmt, capmt->capmt_sock_ca0[i], i + 1);
|
||||
if (capmt->capmt_adapters[i].ca_sock)
|
||||
capmt_poll_add(capmt, capmt->capmt_adapters[i].ca_sock, i + 1);
|
||||
|
||||
i = 0;
|
||||
adapter = -1;
|
||||
|
@ -941,7 +1055,7 @@ handle_ca0(capmt_t *capmt) {
|
|||
if (adapter >= MAX_CA)
|
||||
continue;
|
||||
|
||||
recvsock = capmt->capmt_sock_ca0[adapter];
|
||||
recvsock = capmt->capmt_adapters[adapter].ca_sock;
|
||||
|
||||
if (recvsock <= 0)
|
||||
continue;
|
||||
|
@ -953,7 +1067,7 @@ handle_ca0(capmt_t *capmt) {
|
|||
|
||||
close(recvsock);
|
||||
capmt_poll_rem(capmt, recvsock);
|
||||
capmt->capmt_sock_ca0[adapter] = -1;
|
||||
capmt->capmt_adapters[adapter].ca_sock = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1013,14 +1127,11 @@ handle_single(capmt_t *capmt)
|
|||
|
||||
while (capmt->capmt_running) {
|
||||
|
||||
tvhtrace("capmt", "poll");
|
||||
nfds = tvhpoll_wait(capmt->capmt_poll, &ev, 1, 500);
|
||||
|
||||
if (nfds <= 0)
|
||||
continue;
|
||||
|
||||
tvhtrace("capmt", "poll ok for %i", ev.data.u32);
|
||||
|
||||
if (ev.data.u32 == 0) {
|
||||
ret = read(capmt->capmt_pipe.rd, buf, 1);
|
||||
if (ret == 1 && buf[0] == 'c') {
|
||||
|
@ -1082,7 +1193,6 @@ handle_single(capmt_t *capmt)
|
|||
tvhpoll_destroy(capmt->capmt_poll);
|
||||
capmt->capmt_poll = NULL;
|
||||
}
|
||||
|
||||
#if CONFIG_LINUXDVB
|
||||
static void
|
||||
handle_ca0_wrapper(capmt_t *capmt)
|
||||
|
@ -1098,8 +1208,11 @@ handle_ca0_wrapper(capmt_t *capmt)
|
|||
|
||||
while (capmt->capmt_running) {
|
||||
|
||||
if (capmt->capmt_sock[0] < 0)
|
||||
break;
|
||||
|
||||
/* receiving data from UDP socket */
|
||||
ret = recv(capmt->capmt_sock_ca0[0], buffer, 18, MSG_WAITALL);
|
||||
ret = recv(capmt->capmt_adapters[0].ca_sock, buffer, 18, MSG_WAITALL);
|
||||
|
||||
if (ret < 0) {
|
||||
tvhlog(LOG_ERR, "capmt", "error receiving over socket");
|
||||
|
@ -1110,7 +1223,7 @@ handle_ca0_wrapper(capmt_t *capmt)
|
|||
break;
|
||||
} else {
|
||||
|
||||
tvhtrace("capmt", "Received message from socket %i", capmt->capmt_sock_ca0[0]);
|
||||
tvhtrace("capmt", "Received message from socket %i", capmt->capmt_adapters[0].ca_sock);
|
||||
tvhlog_hexdump("capmt", buffer, ret);
|
||||
|
||||
capmt_process_key(capmt, 0,
|
||||
|
@ -1120,6 +1233,7 @@ handle_ca0_wrapper(capmt_t *capmt)
|
|||
}
|
||||
}
|
||||
|
||||
capmt_abort(capmt, DS_UNKNOWN);
|
||||
tvhlog(LOG_INFO, "capmt", "connection from client closed ...");
|
||||
}
|
||||
#endif
|
||||
|
@ -1158,7 +1272,7 @@ capmt_thread(void *aux)
|
|||
while (capmt->capmt_running) {
|
||||
fatal = 0;
|
||||
for (i = 0; i < MAX_CA; i++)
|
||||
capmt->capmt_sock_ca0[i] = -1;
|
||||
capmt->capmt_adapters[i].ca_sock = -1;
|
||||
for (i = 0; i < MAX_SOCKETS; i++) {
|
||||
capmt->sids[i] = 0;
|
||||
capmt->capmt_sock[i] = -1;
|
||||
|
@ -1191,7 +1305,8 @@ capmt_thread(void *aux)
|
|||
int bind_ok = 0;
|
||||
/* open connection to emulated ca0 device */
|
||||
if (capmt->capmt_oscam == CAPMT_OSCAM_SO_WRAPPER) {
|
||||
bind_ok = capmt_create_udp_socket(&capmt->capmt_sock_ca0[0], capmt->capmt_port);
|
||||
bind_ok = capmt_create_udp_socket(&capmt->capmt_adapters[0].ca_sock,
|
||||
capmt->capmt_port);
|
||||
if (bind_ok)
|
||||
handle_ca0_wrapper(capmt);
|
||||
} else {
|
||||
|
@ -1208,7 +1323,8 @@ capmt_thread(void *aux)
|
|||
continue;
|
||||
}
|
||||
tvhlog(LOG_INFO, "capmt", "created UDP socket %d", n);
|
||||
bind_ok = capmt_create_udp_socket(&capmt->capmt_sock_ca0[n], capmt->capmt_port + n);
|
||||
bind_ok = capmt_create_udp_socket(&capmt->capmt_adapters[n].ca_sock,
|
||||
capmt->capmt_port + n);
|
||||
}
|
||||
if (bind_ok)
|
||||
handle_ca0(capmt);
|
||||
|
@ -1231,11 +1347,10 @@ capmt_thread(void *aux)
|
|||
|
||||
/* close opened sockets */
|
||||
for (i = 0; i < MAX_SOCKETS; i++)
|
||||
if (capmt->capmt_sock[i] >= 0)
|
||||
close(capmt->capmt_sock[i]);
|
||||
capmt_socket_close(capmt, i);
|
||||
for (i = 0; i < MAX_CA; i++)
|
||||
if (capmt->capmt_sock_ca0[i] >= 0)
|
||||
close(capmt->capmt_sock_ca0[i]);
|
||||
if (capmt->capmt_adapters[i].ca_sock >= 0)
|
||||
close(capmt->capmt_adapters[i].ca_sock);
|
||||
|
||||
if (!capmt->capmt_running)
|
||||
break;
|
||||
|
@ -1268,30 +1383,23 @@ capmt_thread(void *aux)
|
|||
*
|
||||
*/
|
||||
static void
|
||||
capmt_table_input(struct th_descrambler *td,
|
||||
struct elementary_stream *st, const uint8_t *data, int len)
|
||||
capmt_table_input(void *opaque, int pid, const uint8_t *data, int len)
|
||||
{
|
||||
capmt_service_t *ct = (capmt_service_t *)td;
|
||||
capmt_t *capmt = ct->ct_capmt;
|
||||
mpegts_service_t *t = (mpegts_service_t*)td->td_service;
|
||||
capmt_caid_ecm_t *cce;
|
||||
int i, change, demux_index, filter_index;
|
||||
capmt_opaque_t *o = opaque;
|
||||
capmt_t *capmt = o->capmt;
|
||||
int i, demux_index, filter_index;
|
||||
capmt_filters_t *cf;
|
||||
dmx_filter_t *f;
|
||||
caid_t *c;
|
||||
|
||||
/* Validate */
|
||||
if (!idnode_is_instance(&td->td_service->s_id, &mpegts_service_class))
|
||||
return;
|
||||
if (!t->s_dvb_active_input) return;
|
||||
if (len > 4096) return;
|
||||
|
||||
for (demux_index = 0; demux_index < capmt->capmt_demuxes.max; demux_index++) {
|
||||
cf = &capmt->capmt_demuxes.filters[demux_index];
|
||||
if (cf->adapter != ct->ct_adapter)
|
||||
if (cf->adapter != o->adapter)
|
||||
continue;
|
||||
for (filter_index = 0; filter_index < cf->max; filter_index++)
|
||||
if (cf->dmx[filter_index].pid == st->es_pid) {
|
||||
if (cf->dmx[filter_index].pid == pid) {
|
||||
f = &cf->dmx[filter_index].filter;
|
||||
for (i = 0; i < DMX_FILTER_SIZE && i < len; i++) {
|
||||
if (f->mode[i] != 0)
|
||||
|
@ -1300,40 +1408,46 @@ capmt_table_input(struct th_descrambler *td,
|
|||
break;
|
||||
}
|
||||
if (i >= DMX_FILTER_SIZE && i <= len) {
|
||||
capmt_filter_data(capmt, t->s_dvb_service_id,
|
||||
ct->ct_adapter, demux_index,
|
||||
capmt_filter_data(capmt,
|
||||
o->adapter, demux_index,
|
||||
filter_index, data, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add new caids, no ecm management */
|
||||
if (data[0] != 0x80 && data[0] != 0x81) return; /* ignore EMM */
|
||||
change = 0;
|
||||
LIST_FOREACH(c, &st->es_caids, link) {
|
||||
/* search ecmpid in list */
|
||||
LIST_FOREACH(cce, &ct->ct_caid_ecm, cce_link)
|
||||
if (cce->cce_caid == c->caid)
|
||||
break;
|
||||
if (cce)
|
||||
continue;
|
||||
}
|
||||
|
||||
tvhlog(LOG_DEBUG, "capmt",
|
||||
"New caid 0x%04X for service \"%s\"", c->caid, t->s_dvb_svcname);
|
||||
static void
|
||||
capmt_caid_change(th_descrambler_t *td)
|
||||
{
|
||||
capmt_service_t *ct = (capmt_service_t *)td;
|
||||
capmt_t *capmt = ct->ct_capmt;
|
||||
mpegts_service_t *t = (mpegts_service_t*)td->td_service;
|
||||
elementary_stream_t *st;
|
||||
capmt_caid_ecm_t *cce;
|
||||
caid_t *c;
|
||||
int change = 0;
|
||||
|
||||
/* ecmpid not already seen, add it to list */
|
||||
cce = calloc(1, sizeof(capmt_caid_ecm_t));
|
||||
cce->cce_caid = c->caid;
|
||||
cce->cce_ecmpid = st->es_pid;
|
||||
cce->cce_providerid = c->providerid;
|
||||
LIST_INSERT_HEAD(&ct->ct_caid_ecm, cce, cce_link);
|
||||
change = 1;
|
||||
}
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
LIST_FOREACH(c, &st->es_caids, link) {
|
||||
/* search ecmpid in list */
|
||||
LIST_FOREACH(cce, &ct->ct_caid_ecm, cce_link)
|
||||
if (cce->cce_caid == c->caid && cce->cce_providerid == c->providerid)
|
||||
break;
|
||||
if (cce)
|
||||
continue;
|
||||
tvhlog(LOG_DEBUG, "capmt",
|
||||
"New caid 0x%04X:0x%06X for service \"%s\"",
|
||||
c->caid, c->providerid, t->s_dvb_svcname);
|
||||
|
||||
if (capmt->capmt_oscam == CAPMT_OSCAM_SO_WRAPPER && capmt->capmt_sock[0] == 0) {
|
||||
/* New key, but we are not connected (anymore), can not descramble */
|
||||
ct->td_keystate = DS_UNKNOWN;
|
||||
return;
|
||||
/* ecmpid not already seen, add it to list */
|
||||
cce = calloc(1, sizeof(capmt_caid_ecm_t));
|
||||
cce->cce_caid = c->caid;
|
||||
cce->cce_ecmpid = st->es_pid;
|
||||
cce->cce_providerid = c->providerid;
|
||||
LIST_INSERT_HEAD(&ct->ct_caid_ecm, cce, cce_link);
|
||||
change = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (change)
|
||||
|
@ -1553,9 +1667,9 @@ capmt_service_start(service_t *s)
|
|||
|
||||
if (tuner < 0) {
|
||||
for (i = 0; i < MAX_CA; i++) {
|
||||
if (capmt->capmt_tuners[i] == NULL && tuner < 0)
|
||||
if (capmt->capmt_adapters[i].ca_tuner == NULL && tuner < 0)
|
||||
tuner = i;
|
||||
if (capmt->capmt_tuners[i] == t->s_dvb_active_input) {
|
||||
if (capmt->capmt_adapters[i].ca_tuner == t->s_dvb_active_input) {
|
||||
tuner = i;
|
||||
break;
|
||||
}
|
||||
|
@ -1572,7 +1686,7 @@ capmt_service_start(service_t *s)
|
|||
"Starting CAPMT server for service \"%s\" on adapter %d",
|
||||
t->s_dvb_svcname, tuner);
|
||||
|
||||
capmt->capmt_tuners[tuner] = t->s_dvb_active_input;
|
||||
capmt->capmt_adapters[tuner].ca_tuner = t->s_dvb_active_input;
|
||||
|
||||
/* create new capmt service */
|
||||
ct = calloc(1, sizeof(capmt_service_t));
|
||||
|
@ -1590,8 +1704,6 @@ capmt_service_start(service_t *s)
|
|||
tvhlog(LOG_DEBUG, "capmt",
|
||||
"New caid 0x%04X for service \"%s\"", c->caid, t->s_dvb_svcname);
|
||||
|
||||
mpegts_table_register_caid(((mpegts_service_t *)s)->s_dvb_mux, c->caid);
|
||||
|
||||
/* add it to list */
|
||||
cce = calloc(1, sizeof(capmt_caid_ecm_t));
|
||||
cce->cce_caid = c->caid;
|
||||
|
@ -1604,9 +1716,9 @@ capmt_service_start(service_t *s)
|
|||
|
||||
td = (th_descrambler_t *)ct;
|
||||
tvhcsa_init(td->td_csa = &ct->ct_csa);
|
||||
td->td_service = s;
|
||||
td->td_stop = capmt_service_destroy;
|
||||
td->td_table = capmt_table_input;
|
||||
td->td_service = s;
|
||||
td->td_stop = capmt_service_destroy;
|
||||
td->td_caid_change = capmt_caid_change;
|
||||
LIST_INSERT_HEAD(&t->s_descramblers, td, td_service_link);
|
||||
|
||||
LIST_INSERT_HEAD(&capmt->capmt_services, ct, ct_link);
|
||||
|
|
|
@ -120,6 +120,17 @@ typedef struct ecm_pid {
|
|||
} ecm_pid_t;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
struct cwc_service;
|
||||
typedef struct cwc_opaque {
|
||||
struct cwc_service *service;
|
||||
elementary_stream_t *estream;
|
||||
mpegts_mux_t *mux;
|
||||
} cwc_opaque_t;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -131,6 +142,8 @@ typedef struct cwc_service {
|
|||
LIST_ENTRY(cwc_service) cs_link;
|
||||
|
||||
int cs_channel;
|
||||
int cs_pid;
|
||||
cwc_opaque_t cs_opaque;
|
||||
|
||||
/**
|
||||
* ECM Status
|
||||
|
@ -1594,11 +1607,12 @@ cwc_emm_viaccess(cwc_t *cwc, struct cs_card_data *pcard, uint8_t *data, int mlen
|
|||
* t->s_streaming_mutex is held
|
||||
*/
|
||||
static void
|
||||
cwc_table_input(struct th_descrambler *td,
|
||||
struct elementary_stream *st, const uint8_t *data, int len)
|
||||
cwc_table_input(void *opaque, int pid, const uint8_t *data, int len)
|
||||
{
|
||||
cwc_service_t *ct = (cwc_service_t *)td;
|
||||
mpegts_service_t *t = (mpegts_service_t*)td->td_service;
|
||||
cwc_opaque_t *o = opaque;
|
||||
elementary_stream_t *st = o->estream;
|
||||
cwc_service_t *ct = o->service;
|
||||
mpegts_service_t *t = (mpegts_service_t*)ct->td_service;
|
||||
uint16_t sid = t->s_dvb_service_id;
|
||||
cwc_t *cwc = ct->cs_cwc;
|
||||
int channel;
|
||||
|
@ -1618,10 +1632,11 @@ cwc_table_input(struct th_descrambler *td,
|
|||
return;
|
||||
|
||||
LIST_FOREACH(ep, &ct->cs_pids, ep_link) {
|
||||
if(ep->ep_pid == st->es_pid)
|
||||
if(ep->ep_pid == pid)
|
||||
break;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&t->s_stream_mutex);
|
||||
if(ep == NULL) {
|
||||
if (ct->ecm_state == ECM_RESET) {
|
||||
ct->ecm_state = ECM_INIT;
|
||||
|
@ -1641,7 +1656,7 @@ cwc_table_input(struct th_descrambler *td,
|
|||
}
|
||||
}
|
||||
|
||||
if(t->s_dvb_prefcapid == st->es_pid) {
|
||||
if(t->s_dvb_prefcapid == pid) {
|
||||
ep = calloc(1, sizeof(ecm_pid_t));
|
||||
ep->ep_pid = t->s_dvb_prefcapid;
|
||||
LIST_INSERT_HEAD(&ct->cs_pids, ep, ep_link);
|
||||
|
@ -1649,12 +1664,13 @@ cwc_table_input(struct th_descrambler *td,
|
|||
}
|
||||
else if(t->s_dvb_prefcapid == 0) {
|
||||
ep = calloc(1, sizeof(ecm_pid_t));
|
||||
ep->ep_pid = st->es_pid;
|
||||
ep->ep_pid = pid;
|
||||
LIST_INSERT_HEAD(&ct->cs_pids, ep, ep_link);
|
||||
tvhlog(LOG_DEBUG, "cwc", "Insert new ECM (PID %d) for service \"%s\"", st->es_pid, t->s_dvb_svcname);
|
||||
tvhlog(LOG_DEBUG, "cwc", "Insert new ECM (PID %d) for service \"%s\"", pid, t->s_dvb_svcname);
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&t->s_stream_mutex);
|
||||
|
||||
if(ep == NULL)
|
||||
return;
|
||||
|
@ -1688,7 +1704,7 @@ cwc_table_input(struct th_descrambler *td,
|
|||
section = 0;
|
||||
}
|
||||
|
||||
channel = st->es_pid;
|
||||
channel = pid;
|
||||
snprintf(chaninfo, sizeof(chaninfo), " (PID %d)", channel);
|
||||
|
||||
if(ep->ep_sections[section] == NULL)
|
||||
|
@ -1901,6 +1917,8 @@ cwc_service_destroy(th_descrambler_t *td)
|
|||
ecm_pid_t *ep;
|
||||
int i;
|
||||
|
||||
descrambler_close_pid(ct->cs_opaque.mux, &ct->cs_opaque, ct->cs_pid);
|
||||
|
||||
while((ep = LIST_FIRST(&ct->cs_pids)) != NULL) {
|
||||
for(i = 0; i < 256; i++)
|
||||
free(ep->ep_sections[i]);
|
||||
|
@ -1916,25 +1934,6 @@ cwc_service_destroy(th_descrambler_t *td)
|
|||
free(ct);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static inline elementary_stream_t *
|
||||
cwc_find_stream_by_caid(service_t *t, const short caid)
|
||||
{
|
||||
elementary_stream_t *st;
|
||||
caid_t *c;
|
||||
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
LIST_FOREACH(c, &st->es_caids, link) {
|
||||
if(c->caid == caid)
|
||||
return st;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if our CAID's matches, and if so, link
|
||||
*
|
||||
|
@ -1946,6 +1945,8 @@ cwc_service_start(service_t *t)
|
|||
cwc_t *cwc;
|
||||
cwc_service_t *ct;
|
||||
th_descrambler_t *td;
|
||||
elementary_stream_t *st;
|
||||
caid_t *c;
|
||||
struct cs_card_data *pcard;
|
||||
|
||||
extern const idclass_t mpegts_service_class;
|
||||
|
@ -1958,9 +1959,16 @@ cwc_service_start(service_t *t)
|
|||
if (ct->td_service == t && ct->cs_cwc == cwc)
|
||||
break;
|
||||
}
|
||||
LIST_FOREACH(pcard,&cwc->cwc_cards, cs_card) {
|
||||
if((pcard->cwc_caid != 0) && cwc_find_stream_by_caid(t, pcard->cwc_caid))
|
||||
break;
|
||||
LIST_FOREACH(pcard, &cwc->cwc_cards, cs_card) {
|
||||
if (pcard->cwc_caid == 0) continue;
|
||||
TAILQ_FOREACH(st, &t->s_components, es_link) {
|
||||
LIST_FOREACH(c, &st->es_caids, link) {
|
||||
if (c->caid == pcard->cwc_caid)
|
||||
break;
|
||||
}
|
||||
if (c) break;
|
||||
}
|
||||
if (st) break;
|
||||
}
|
||||
if (!pcard) {
|
||||
if (ct) cwc_service_destroy((th_descrambler_t*)ct);
|
||||
|
@ -1969,22 +1977,26 @@ cwc_service_start(service_t *t)
|
|||
|
||||
if (ct) continue;
|
||||
|
||||
mpegts_table_register_caid(((mpegts_service_t *)t)->s_dvb_mux, pcard->cwc_caid);
|
||||
|
||||
ct = calloc(1, sizeof(cwc_service_t));
|
||||
ct->cs_cwc = cwc;
|
||||
ct->cs_channel = -1;
|
||||
ct->cs_pid = st->es_pid;
|
||||
ct->cs_opaque.service = ct;
|
||||
ct->cs_opaque.estream = st;
|
||||
ct->cs_opaque.mux = ((mpegts_service_t *)t)->s_dvb_mux;
|
||||
ct->ecm_state = ECM_INIT;
|
||||
|
||||
td = (th_descrambler_t *)ct;
|
||||
tvhcsa_init(td->td_csa = &ct->cs_csa);
|
||||
td->td_service = t;
|
||||
td->td_stop = cwc_service_destroy;
|
||||
td->td_table = cwc_table_input;
|
||||
LIST_INSERT_HEAD(&t->s_descramblers, td, td_service_link);
|
||||
|
||||
LIST_INSERT_HEAD(&cwc->cwc_services, ct, cs_link);
|
||||
|
||||
descrambler_open_pid(ct->cs_opaque.mux, &ct->cs_opaque,
|
||||
ct->cs_pid, cwc_table_input);
|
||||
|
||||
tvhlog(LOG_DEBUG, "cwc", "%s using CWC %s:%d",
|
||||
service_nicename(t), cwc->cwc_hostname, cwc->cwc_port);
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "cwc.h"
|
||||
#include "capmt.h"
|
||||
#include "ffdecsa/FFdecsa.h"
|
||||
#include "service.h"
|
||||
#include "input.h"
|
||||
#include "tvhcsa.h"
|
||||
|
||||
static struct strtab caidnametab[] = {
|
||||
|
@ -149,6 +149,17 @@ descrambler_service_stop ( service_t *t )
|
|||
td->td_stop(td);
|
||||
}
|
||||
|
||||
void
|
||||
descrambler_caid_changed ( service_t *t )
|
||||
{
|
||||
th_descrambler_t *td;
|
||||
|
||||
LIST_FOREACH(td, &t->s_descramblers, td_service_link) {
|
||||
if (td->td_caid_change)
|
||||
td->td_caid_change(td);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
descrambler_descramble ( service_t *t,
|
||||
elementary_stream_t *st,
|
||||
|
@ -173,14 +184,98 @@ descrambler_descramble ( service_t *t,
|
|||
return count == failed ? -1 : 0;
|
||||
}
|
||||
|
||||
void
|
||||
descrambler_ca_section( elementary_stream_t *st,
|
||||
const uint8_t *data, size_t len )
|
||||
static int
|
||||
descrambler_table_callback
|
||||
(mpegts_table_t *mt, const uint8_t *ptr, int len, int tableid)
|
||||
{
|
||||
th_descrambler_t *td;
|
||||
descrambler_table_t *dt = mt->mt_opaque;
|
||||
descrambler_section_t *ds;
|
||||
|
||||
LIST_FOREACH(td, &st->es_service->s_descramblers, td_service_link)
|
||||
td->td_table(td, st, data, len);
|
||||
pthread_mutex_lock(&mt->mt_mux->mm_descrambler_lock);
|
||||
TAILQ_FOREACH(ds, &dt->sections, link)
|
||||
ds->callback(ds->opaque, mt->mt_pid, ptr, len);
|
||||
pthread_mutex_unlock(&mt->mt_mux->mm_descrambler_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
descrambler_open_pid( mpegts_mux_t *mux, void *opaque, int pid,
|
||||
descrambler_section_callback_t callback )
|
||||
{
|
||||
descrambler_table_t *dt;
|
||||
descrambler_section_t *ds;
|
||||
|
||||
pthread_mutex_lock(&mux->mm_descrambler_lock);
|
||||
TAILQ_FOREACH(dt, &mux->mm_descrambler_tables, link) {
|
||||
if (dt->table->mt_pid == pid) {
|
||||
TAILQ_FOREACH(ds, &dt->sections, link) {
|
||||
if (ds->opaque == opaque) {
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!dt) {
|
||||
dt = calloc(1, sizeof(*dt));
|
||||
TAILQ_INIT(&dt->sections);
|
||||
dt->table = mpegts_table_add(mux, 0, 0, descrambler_table_callback,
|
||||
dt, "descrambler", MT_FULL, pid);
|
||||
TAILQ_INSERT_TAIL(&mux->mm_descrambler_tables, dt, link);
|
||||
}
|
||||
ds = calloc(1, sizeof(*ds));
|
||||
ds->callback = callback;
|
||||
ds->opaque = opaque;
|
||||
TAILQ_INSERT_TAIL(&dt->sections, ds, link);
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
descrambler_close_pid( mpegts_mux_t *mux, void *opaque, int pid )
|
||||
{
|
||||
descrambler_table_t *dt;
|
||||
descrambler_section_t *ds;
|
||||
|
||||
pthread_mutex_lock(&mux->mm_descrambler_lock);
|
||||
TAILQ_FOREACH(dt, &mux->mm_descrambler_tables, link) {
|
||||
if (dt->table->mt_pid == pid) {
|
||||
TAILQ_FOREACH(ds, &dt->sections, link) {
|
||||
if (ds->opaque == opaque) {
|
||||
TAILQ_REMOVE(&dt->sections, ds, link);
|
||||
free(ds);
|
||||
if (TAILQ_FIRST(&dt->sections) == NULL) {
|
||||
TAILQ_REMOVE(&mux->mm_descrambler_tables, dt, link);
|
||||
mpegts_table_destroy(dt->table);
|
||||
free(dt);
|
||||
}
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
descrambler_flush_tables( mpegts_mux_t *mux )
|
||||
{
|
||||
descrambler_table_t *dt;
|
||||
descrambler_section_t *ds;
|
||||
|
||||
pthread_mutex_lock(&mux->mm_descrambler_lock);
|
||||
while ((dt = TAILQ_FIRST(&mux->mm_descrambler_tables)) != NULL) {
|
||||
while ((ds = TAILQ_FIRST(&dt->sections)) != NULL) {
|
||||
TAILQ_REMOVE(&dt->sections, ds, link);
|
||||
free(ds);
|
||||
}
|
||||
TAILQ_REMOVE(&mux->mm_descrambler_tables, dt, link);
|
||||
mpegts_table_destroy(dt->table);
|
||||
free(dt);
|
||||
}
|
||||
pthread_mutex_unlock(&mux->mm_descrambler_lock);
|
||||
}
|
||||
|
||||
// TODO: might actually put const char* into caid_t
|
||||
|
|
|
@ -347,6 +347,9 @@ struct mpegts_mux
|
|||
LIST_HEAD(, mpegts_table) mm_tables;
|
||||
TAILQ_HEAD(, mpegts_table) mm_table_queue;
|
||||
|
||||
TAILQ_HEAD(, descrambler_table) mm_descrambler_tables;
|
||||
pthread_mutex_t mm_descrambler_lock;
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
|
@ -729,7 +732,6 @@ mpegts_table_t *mpegts_table_add
|
|||
void mpegts_table_flush_all
|
||||
(mpegts_mux_t *mm);
|
||||
void mpegts_table_destroy ( mpegts_table_t *mt );
|
||||
void mpegts_table_register_caid ( mpegts_mux_t *mm, uint16_t caid );
|
||||
|
||||
mpegts_service_t *mpegts_service_create0
|
||||
( mpegts_service_t *ms, const idclass_t *class, const char *uuid,
|
||||
|
|
|
@ -1561,6 +1561,10 @@ psi_parse_pmt
|
|||
if(t->s_status == SERVICE_RUNNING)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
// notify descrambler that we found another CAIDs
|
||||
if (update & PMT_UPDATE_NEW_CAID)
|
||||
descrambler_caid_changed((service_t *)t);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -314,8 +314,10 @@ mpegts_input_open_service ( mpegts_input_t *mi, mpegts_service_t *s, int init )
|
|||
pthread_mutex_lock(&s->s_stream_mutex);
|
||||
mi->mi_open_pid(mi, s->s_dvb_mux, s->s_pmt_pid, MPS_STREAM, s);
|
||||
mi->mi_open_pid(mi, s->s_dvb_mux, s->s_pcr_pid, MPS_STREAM, s);
|
||||
TAILQ_FOREACH(st, &s->s_components, es_link)
|
||||
mi->mi_open_pid(mi, s->s_dvb_mux, st->es_pid, MPS_STREAM, s);
|
||||
TAILQ_FOREACH(st, &s->s_components, es_link) {
|
||||
if (st->es_type != SCT_CA)
|
||||
mi->mi_open_pid(mi, s->s_dvb_mux, st->es_pid, MPS_STREAM, s);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&s->s_stream_mutex);
|
||||
pthread_mutex_unlock(&mi->mi_output_lock);
|
||||
|
|
|
@ -769,6 +769,8 @@ mpegts_mux_create0
|
|||
mm->mm_open_table = mpegts_mux_open_table;
|
||||
mm->mm_close_table = mpegts_mux_close_table;
|
||||
TAILQ_INIT(&mm->mm_table_queue);
|
||||
TAILQ_INIT(&mm->mm_descrambler_tables);
|
||||
pthread_mutex_init(&mm->mm_descrambler_lock, NULL);
|
||||
|
||||
mm->mm_last_pid = -1;
|
||||
|
||||
|
|
|
@ -200,20 +200,11 @@ void
|
|||
mpegts_table_flush_all ( mpegts_mux_t *mm )
|
||||
{
|
||||
mpegts_table_t *mt;
|
||||
descrambler_flush_tables(mm);
|
||||
while ((mt = LIST_FIRST(&mm->mm_tables)))
|
||||
mpegts_table_destroy(mt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register wanted CAID
|
||||
*/
|
||||
void
|
||||
mpegts_table_register_caid ( mpegts_mux_t *mm, uint16_t caid )
|
||||
{
|
||||
uintptr_t ca = caid;
|
||||
mpegts_table_add(mm, 0, 0, NULL, (void *)ca, "ca", MT_FULL, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Section assembly
|
||||
*/
|
||||
|
|
|
@ -44,17 +44,6 @@
|
|||
|
||||
static void ts_remux(mpegts_service_t *t, const uint8_t *tsb);
|
||||
|
||||
/**
|
||||
* Code for dealing with a complete section
|
||||
*/
|
||||
static void
|
||||
got_ca_section(const uint8_t *data, size_t len, void *opaque)
|
||||
{
|
||||
elementary_stream_t *st = opaque;
|
||||
assert(st->es_service->s_source_type == S_MPEG_TS);
|
||||
descrambler_ca_section(st, data, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Continue processing of transport stream packets
|
||||
*/
|
||||
|
@ -62,7 +51,7 @@ static void
|
|||
ts_recv_packet0
|
||||
(mpegts_service_t *t, elementary_stream_t *st, const uint8_t *tsb)
|
||||
{
|
||||
int off, pusi, cc, error, ccerr;
|
||||
int off, pusi, cc, error;
|
||||
|
||||
service_set_streaming_status_flags((service_t*)t, TSS_MUX_PACKETS);
|
||||
|
||||
|
@ -72,7 +61,6 @@ ts_recv_packet0
|
|||
if (!st)
|
||||
return;
|
||||
|
||||
ccerr = 0;
|
||||
error = !!(tsb[1] & 0x80);
|
||||
pusi = !!(tsb[1] & 0x40);
|
||||
|
||||
|
@ -81,7 +69,6 @@ ts_recv_packet0
|
|||
if(tsb[3] & 0x10) {
|
||||
cc = tsb[3] & 0xf;
|
||||
if(st->es_cc != -1 && cc != st->es_cc) {
|
||||
ccerr = 1;
|
||||
/* Incorrect CC */
|
||||
limitedlog(&st->es_loglimit_cc, "TS", service_component_nicename(st),
|
||||
"Continuity counter error");
|
||||
|
@ -100,10 +87,6 @@ ts_recv_packet0
|
|||
switch(st->es_type) {
|
||||
|
||||
case SCT_CA:
|
||||
if(st->es_section == NULL)
|
||||
st->es_section = calloc(1, sizeof(mpegts_psi_section_t));
|
||||
mpegts_psi_section_reassemble(st->es_section, tsb, 0, ccerr,
|
||||
got_ca_section, st);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
Loading…
Add table
Reference in a new issue