tsdebug: add possibility to save the whole input mux with decrambler keys
This commit is contained in:
parent
b87eb898c8
commit
2b2cb3236e
15 changed files with 401 additions and 5 deletions
4
Makefile
4
Makefile
|
@ -329,6 +329,10 @@ SRCS-${CONFIG_CAPMT} += \
|
|||
SRCS-${CONFIG_CONSTCW} += \
|
||||
src/descrambler/constcw.c
|
||||
|
||||
# TSDEBUGCW
|
||||
SRCS-${CONFIG_TSDEBUG} += \
|
||||
src/descrambler/tsdebugcw.c
|
||||
|
||||
# FFdecsa
|
||||
ifneq ($(CONFIG_DVBCSA),yes)
|
||||
FFDECSA-$(CONFIG_CAPMT) = yes
|
||||
|
|
8
configure
vendored
8
configure
vendored
|
@ -44,6 +44,7 @@ OPTIONS=(
|
|||
"kqueue:no"
|
||||
"dbus_1:auto"
|
||||
"android:no"
|
||||
"tsdebug:no"
|
||||
)
|
||||
|
||||
#
|
||||
|
@ -472,6 +473,13 @@ if enabled_or_auto dbus_1; then
|
|||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# TSDebug
|
||||
#
|
||||
if enabled_or_auto tsdebug; then
|
||||
enable mpegts_dvb
|
||||
fi
|
||||
|
||||
|
||||
# ###########################################################################
|
||||
# Write config
|
||||
|
|
|
@ -296,6 +296,9 @@ caclient_start ( struct service *t )
|
|||
if (cac->cac_enabled)
|
||||
cac->cac_start(cac, t);
|
||||
pthread_mutex_unlock(&caclients_mutex);
|
||||
#if ENABLE_TSDEBUG
|
||||
tsdebugcw_service_start(t);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -344,6 +347,9 @@ caclient_init(void)
|
|||
|
||||
pthread_mutex_init(&caclients_mutex, NULL);
|
||||
TAILQ_INIT(&caclients);
|
||||
#if ENABLE_TSDEBUG
|
||||
tsdebugcw_init();
|
||||
#endif
|
||||
|
||||
if (!(c = hts_settings_load("caclient")))
|
||||
return;
|
||||
|
|
|
@ -75,8 +75,14 @@ const char *caclient_get_status(caclient_t *cac);
|
|||
void caclient_init(void);
|
||||
void caclient_done(void);
|
||||
|
||||
void tsdebugcw_service_start(struct service *t);
|
||||
void tsdebugcw_new_keys(struct service *t, int type, uint8_t *odd, uint8_t *even);
|
||||
void tsdebugcw_go(void);
|
||||
void tsdebugcw_init(void);
|
||||
|
||||
caclient_t *cwc_create(void);
|
||||
caclient_t *capmt_create(void);
|
||||
caclient_t *constcw_create(void);
|
||||
caclient_t *tsdebugcw_create(void);
|
||||
|
||||
#endif /* __TVH_CACLIENT_H__ */
|
||||
|
|
|
@ -252,6 +252,40 @@ descrambler_keys ( th_descrambler_t *td, int type,
|
|||
|
||||
fin:
|
||||
pthread_mutex_unlock(&t->s_stream_mutex);
|
||||
#if ENABLE_TSDEBUG
|
||||
if (j) {
|
||||
tsdebug_packet_t *tp = malloc(sizeof(*tp));
|
||||
uint16_t keylen = dr->dr_csa.csa_keylen;
|
||||
uint16_t sid = ((mpegts_service_t *)td->td_service)->s_dvb_service_id;
|
||||
uint32_t pos = 0, crc;
|
||||
mpegts_mux_t *mm = ((mpegts_service_t *)td->td_service)->s_dvb_mux;
|
||||
if (!mm->mm_active)
|
||||
return;
|
||||
pthread_mutex_lock(&mm->mm_active->mmi_input->mi_output_lock);
|
||||
tp->pos = mm->mm_tsdebug_pos;
|
||||
memset(tp->pkt, 0xff, sizeof(tp->pkt));
|
||||
tp->pkt[pos++] = 0x47; /* sync byte */
|
||||
tp->pkt[pos++] = 0x1f; /* PID MSB */
|
||||
tp->pkt[pos++] = 0xff; /* PID LSB */
|
||||
tp->pkt[pos++] = 0x00; /* CC */
|
||||
memcpy(tp->pkt + pos, "TVHeadendDescramblerKeys", 24);
|
||||
pos += 24;
|
||||
tp->pkt[pos++] = type & 0xff;
|
||||
tp->pkt[pos++] = keylen & 0xff;
|
||||
tp->pkt[pos++] = (sid >> 8) & 0xff;
|
||||
tp->pkt[pos++] = sid & 0xff;
|
||||
memcpy(tp->pkt + pos, even, keylen);
|
||||
memcpy(tp->pkt + pos + keylen, odd, keylen);
|
||||
pos += 2 * keylen;
|
||||
crc = tvh_crc32(tp->pkt, pos, 0x859aa5ba);
|
||||
tp->pkt[pos++] = (crc >> 24) & 0xff;
|
||||
tp->pkt[pos++] = (crc >> 16) & 0xff;
|
||||
tp->pkt[pos++] = (crc >> 8) & 0xff;
|
||||
tp->pkt[pos++] = crc & 0xff;
|
||||
TAILQ_INSERT_HEAD(&mm->mm_tsdebug_packets, tp, link);
|
||||
pthread_mutex_unlock(&mm->mm_active->mmi_input->mi_output_lock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
169
src/descrambler/tsdebugcw.c
Normal file
169
src/descrambler/tsdebugcw.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* tvheadend, tsdebug code word interface
|
||||
* Copyright (C) 2014 Jaroslav Kysela
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "tvheadend.h"
|
||||
#include "caclient.h"
|
||||
#include "service.h"
|
||||
#include "input.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
typedef struct tsdebugcw_service {
|
||||
th_descrambler_t;
|
||||
|
||||
int tdcw_type;
|
||||
uint8_t tdcw_key_even[16]; /* DES or AES key */
|
||||
uint8_t tdcw_key_odd [16]; /* DES or AES key */
|
||||
|
||||
} tsdebugcw_service_t;
|
||||
|
||||
typedef struct tsdebugcw_request {
|
||||
TAILQ_ENTRY(tsdebugcw_request) link;
|
||||
tsdebugcw_service_t *ct;
|
||||
} tsdebugcw_request_t;
|
||||
|
||||
pthread_mutex_t tsdebugcw_mutex;
|
||||
TAILQ_HEAD(,tsdebugcw_request) tsdebugcw_requests;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static int
|
||||
tsdebugcw_ecm_reset(th_descrambler_t *th)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* s_stream_mutex is held
|
||||
*/
|
||||
static void
|
||||
tsdebugcw_service_destroy(th_descrambler_t *td)
|
||||
{
|
||||
tsdebugcw_service_t *ct = (tsdebugcw_service_t *)td;
|
||||
tsdebugcw_request_t *ctr, *ctrnext;
|
||||
|
||||
pthread_mutex_lock(&tsdebugcw_mutex);
|
||||
for (ctr = TAILQ_FIRST(&tsdebugcw_requests); ctr; ctr = ctrnext) {
|
||||
ctrnext = TAILQ_NEXT(ctr, link);
|
||||
if (ctr->ct == ct) {
|
||||
TAILQ_REMOVE(&tsdebugcw_requests, ctr, link);
|
||||
free(ctr);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&tsdebugcw_mutex);
|
||||
|
||||
LIST_REMOVE(td, td_service_link);
|
||||
free(ct->td_nicename);
|
||||
free(ct);
|
||||
}
|
||||
|
||||
/**
|
||||
* global_lock is held. Not that we care about that, but either way, it is.
|
||||
*/
|
||||
void
|
||||
tsdebugcw_service_start(service_t *t)
|
||||
{
|
||||
tsdebugcw_service_t *ct;
|
||||
th_descrambler_t *td;
|
||||
char buf[128];
|
||||
|
||||
extern const idclass_t mpegts_service_class;
|
||||
if (!idnode_is_instance(&t->s_id, &mpegts_service_class))
|
||||
return;
|
||||
|
||||
LIST_FOREACH(td, &t->s_descramblers, td_service_link)
|
||||
if (td->td_stop == tsdebugcw_service_destroy)
|
||||
break;
|
||||
if (td)
|
||||
return;
|
||||
|
||||
ct = calloc(1, sizeof(tsdebugcw_service_t));
|
||||
td = (th_descrambler_t *)ct;
|
||||
snprintf(buf, sizeof(buf), "tsdebugcw");
|
||||
td->td_nicename = strdup(buf);
|
||||
td->td_service = t;
|
||||
td->td_stop = tsdebugcw_service_destroy;
|
||||
td->td_ecm_reset = tsdebugcw_ecm_reset;
|
||||
LIST_INSERT_HEAD(&t->s_descramblers, td, td_service_link);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void
|
||||
tsdebugcw_new_keys(service_t *t, int type, uint8_t *odd, uint8_t *even)
|
||||
{
|
||||
static char empty[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
th_descrambler_t *td;
|
||||
tsdebugcw_service_t *ct;
|
||||
tsdebugcw_request_t *ctr;
|
||||
int keylen = type == DESCRAMBLER_AES ? 16 : 8;
|
||||
|
||||
LIST_FOREACH(td, &t->s_descramblers, td_service_link)
|
||||
if (td->td_stop == tsdebugcw_service_destroy)
|
||||
break;
|
||||
if (!td)
|
||||
return;
|
||||
ct = (tsdebugcw_service_t *)td;
|
||||
ct->tdcw_type = type;
|
||||
if (memcmp(empty, odd, keylen))
|
||||
memcpy(ct->tdcw_key_odd, odd, keylen);
|
||||
if (memcmp(empty, even, keylen))
|
||||
memcpy(ct->tdcw_key_even, even, keylen);
|
||||
ctr = malloc(sizeof(*ctr));
|
||||
ctr->ct = ct;
|
||||
pthread_mutex_lock(&tsdebugcw_mutex);
|
||||
TAILQ_INSERT_TAIL(&tsdebugcw_requests, ctr, link);
|
||||
pthread_mutex_unlock(&tsdebugcw_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void
|
||||
tsdebugcw_go(void)
|
||||
{
|
||||
tsdebugcw_request_t *ctr;
|
||||
tsdebugcw_service_t *ct;
|
||||
|
||||
while (1) {
|
||||
pthread_mutex_lock(&tsdebugcw_mutex);
|
||||
ctr = TAILQ_FIRST(&tsdebugcw_requests);
|
||||
if (ctr)
|
||||
TAILQ_REMOVE(&tsdebugcw_requests, ctr, link);
|
||||
pthread_mutex_unlock(&tsdebugcw_mutex);
|
||||
if (!ctr) break;
|
||||
ct = ctr->ct;
|
||||
descrambler_keys((th_descrambler_t *)ct, ct->tdcw_type,
|
||||
ct->tdcw_key_odd, ct->tdcw_key_even);
|
||||
free(ctr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
void
|
||||
tsdebugcw_init(void)
|
||||
{
|
||||
pthread_mutex_init(&tsdebugcw_mutex, NULL);
|
||||
TAILQ_INIT(&tsdebugcw_requests);
|
||||
}
|
|
@ -329,6 +329,12 @@ enum mpegts_mux_epg_flag
|
|||
};
|
||||
#define MM_EPG_LAST MM_EPG_ONLY_OPENTV_SKY_AUSAT
|
||||
|
||||
typedef struct tsdebug_packet {
|
||||
TAILQ_ENTRY(tsdebug_packet) link;
|
||||
uint8_t pkt[188];
|
||||
off_t pos;
|
||||
} tsdebug_packet_t;
|
||||
|
||||
/* Multiplex */
|
||||
struct mpegts_mux
|
||||
{
|
||||
|
@ -421,6 +427,16 @@ struct mpegts_mux
|
|||
int mm_epg;
|
||||
char *mm_charset;
|
||||
int mm_pmt_06_ac3;
|
||||
|
||||
/*
|
||||
* TSDEBUG
|
||||
*/
|
||||
#if ENABLE_TSDEBUG
|
||||
int mm_tsdebug_fd;
|
||||
int mm_tsdebug_fd2;
|
||||
off_t mm_tsdebug_pos;
|
||||
TAILQ_HEAD(, tsdebug_packet) mm_tsdebug_packets;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Service */
|
||||
|
@ -803,6 +819,28 @@ mpegts_pid_t * mpegts_input_open_pid
|
|||
void mpegts_input_close_pid
|
||||
( mpegts_input_t *mi, mpegts_mux_t *mm, int pid, int type, void *owner );
|
||||
|
||||
static inline void
|
||||
tsdebug_write(mpegts_mux_t *mm, uint8_t *buf, size_t len)
|
||||
{
|
||||
#if ENABLE_TSDEBUG
|
||||
ssize_t r = write(mm->mm_tsdebug_fd2, buf, len);
|
||||
if (r != len && mm->mm_tsdebug_fd2 >= 0)
|
||||
tvherror("tsdebug", "unable to write input data (%i)", errno);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline ssize_t
|
||||
sbuf_tsdebug_read(mpegts_mux_t *mm, sbuf_t *sb, int fd)
|
||||
{
|
||||
#if ENABLE_TSDEBUG
|
||||
ssize_t r = sbuf_read(sb, fd);
|
||||
tsdebug_write(mm, sb->sb_data + sb->sb_ptr - r, r);
|
||||
return r;
|
||||
#else
|
||||
return sbuf_read(sb, fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
void mpegts_table_dispatch
|
||||
(const uint8_t *sec, size_t r, void *mt);
|
||||
static inline void mpegts_table_grab
|
||||
|
|
|
@ -47,6 +47,7 @@ iptv_http_data
|
|||
|
||||
pthread_mutex_lock(&iptv_lock);
|
||||
|
||||
tsdebug_write((mpegts_mux_t *)im, buf, len);
|
||||
sbuf_append(&im->mm_iptv_buffer, buf, len);
|
||||
|
||||
if (len > 0)
|
||||
|
|
|
@ -137,6 +137,7 @@ iptv_rtp_read ( iptv_mux_t *im )
|
|||
|
||||
/* Move data */
|
||||
len -= hlen;
|
||||
tsdebug_write((mpegts_mux_t *)im, rtp + hlen, len);
|
||||
sbuf_append(&im->mm_iptv_buffer, rtp + hlen, len);
|
||||
res += len;
|
||||
}
|
||||
|
|
|
@ -856,7 +856,7 @@ linuxdvb_frontend_input_thread ( void *aux )
|
|||
if (ev[0].data.fd != dvr) break;
|
||||
|
||||
/* Read */
|
||||
if ((n = sbuf_read(&sb, dvr)) < 0) {
|
||||
if ((n = sbuf_tsdebug_read(mmi->mmi_mux, &sb, dvr)) < 0) {
|
||||
if (ERRNO_AGAIN(errno))
|
||||
continue;
|
||||
if (errno == EOVERFLOW) {
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
static void
|
||||
mpegts_input_del_network ( mpegts_network_link_t *mnl );
|
||||
|
@ -475,6 +478,34 @@ static void
|
|||
mpegts_input_started_mux
|
||||
( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
|
||||
{
|
||||
#if ENABLE_TSDEBUG
|
||||
extern char *tvheadend_tsdebug;
|
||||
static const char *tmpdir = "/tmp/tvheadend.tsdebug/";
|
||||
char buf[128];
|
||||
char path[PATH_MAX];
|
||||
struct stat st;
|
||||
if (!tvheadend_tsdebug && !stat(tmpdir, &st) && (st.st_mode & S_IFDIR) != 0)
|
||||
tvheadend_tsdebug = (char *)tmpdir;
|
||||
if (tvheadend_tsdebug && !strcmp(tvheadend_tsdebug, tmpdir) && stat(tmpdir, &st))
|
||||
tvheadend_tsdebug = NULL;
|
||||
if (tvheadend_tsdebug) {
|
||||
mpegts_mux_nice_name(mmi->mmi_mux, buf, sizeof(buf));
|
||||
snprintf(path, sizeof(path), "%s/%s-%li-%p-mux.ts", tvheadend_tsdebug,
|
||||
buf, (long)dispatch_clock, mi);
|
||||
mmi->mmi_mux->mm_tsdebug_fd = tvh_open(path, O_WRONLY | O_CREAT, 0600);
|
||||
if (mmi->mmi_mux->mm_tsdebug_fd < 0)
|
||||
tvherror("tsdebug", "unable to create file '%s' (%i)", path, errno);
|
||||
snprintf(path, sizeof(path), "%s/%s-%li-%p-input.ts", tvheadend_tsdebug,
|
||||
buf, (long)dispatch_clock, mi);
|
||||
mmi->mmi_mux->mm_tsdebug_fd2 = tvh_open(path, O_WRONLY | O_CREAT, 0600);
|
||||
if (mmi->mmi_mux->mm_tsdebug_fd2 < 0)
|
||||
tvherror("tsdebug", "unable to create file '%s' (%i)", path, errno);
|
||||
} else {
|
||||
mmi->mmi_mux->mm_tsdebug_fd = -1;
|
||||
mmi->mmi_mux->mm_tsdebug_fd2 = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Deliver first TS packets as fast as possible */
|
||||
mi->mi_last_dispatch = 0;
|
||||
/* Wait for first TS packet */
|
||||
|
@ -532,6 +563,19 @@ mpegts_input_stopped_mux
|
|||
}
|
||||
notify_reload("input_status");
|
||||
mpegts_input_dbus_notify(mi, 0);
|
||||
|
||||
#if ENABLE_TSDEBUG
|
||||
tsdebug_packet_t *tp;
|
||||
close(mmi->mmi_mux->mm_tsdebug_fd);
|
||||
close(mmi->mmi_mux->mm_tsdebug_fd2);
|
||||
mmi->mmi_mux->mm_tsdebug_fd = -1;
|
||||
mmi->mmi_mux->mm_tsdebug_fd2 = -1;
|
||||
mmi->mmi_mux->mm_tsdebug_pos = 0;
|
||||
while ((tp = TAILQ_FIRST(&mmi->mmi_mux->mm_tsdebug_packets)) != NULL) {
|
||||
TAILQ_REMOVE(&mmi->mmi_mux->mm_tsdebug_packets, tp, link);
|
||||
free(tp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -727,6 +771,37 @@ mpegts_input_table_waiting ( mpegts_input_t *mi, mpegts_mux_t *mm )
|
|||
pthread_mutex_unlock(&mm->mm_tables_lock);
|
||||
}
|
||||
|
||||
#if ENABLE_TSDEBUG
|
||||
static void
|
||||
tsdebug_check_tspkt( mpegts_mux_t *mm, uint8_t *pkt )
|
||||
{
|
||||
void tsdebugcw_new_keys(service_t *t, int type, uint8_t *odd, uint8_t *even);
|
||||
uint32_t pos, type, keylen, sid, crc;
|
||||
mpegts_service_t *t;
|
||||
|
||||
if (memcmp(pkt + 4, "TVHeadendDescramblerKeys", 24))
|
||||
return;
|
||||
pos = 4 + 24;
|
||||
type = pkt[pos + 0];
|
||||
keylen = pkt[pos + 1];
|
||||
sid = (pkt[pos + 2] << 8) | pkt[pos + 3];
|
||||
pos += 4 + 2 * keylen;
|
||||
if (pos > 184)
|
||||
return;
|
||||
crc = (pkt[pos + 0] << 24) | (pkt[pos + 1] << 16) |
|
||||
(pkt[pos + 2] << 8) | pkt[pos + 3];
|
||||
if (crc != tvh_crc32(pkt, pos, 0x859aa5ba))
|
||||
return;
|
||||
LIST_FOREACH(t, &mm->mm_services, s_dvb_mux_link)
|
||||
if (t->s_dvb_service_id == sid) break;
|
||||
if (!t)
|
||||
return;
|
||||
pos = 4 + 24 + 4;
|
||||
tvhdebug("descrambler", "Keys from MPEG-TS source (PID 0x1FFF)!");
|
||||
tsdebugcw_new_keys((service_t *)t, type, pkt + pos, pkt + pos + keylen);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
mpegts_input_process
|
||||
( mpegts_input_t *mi, mpegts_packet_t *mpkt )
|
||||
|
@ -744,6 +819,9 @@ mpegts_input_process
|
|||
mpegts_mux_t *mm = mpkt->mp_mux;
|
||||
mpegts_mux_instance_t *mmi;
|
||||
mpegts_pid_t *last_mp = NULL;
|
||||
#if ENABLE_TSDEBUG
|
||||
off_t tsdebug_pos = mm->mm_tsdebug_pos;
|
||||
#endif
|
||||
|
||||
if (mm == NULL || (mmi = mm->mm_active) == NULL)
|
||||
return;
|
||||
|
@ -767,7 +845,12 @@ mpegts_input_process
|
|||
pid &= 0x1FFF;
|
||||
|
||||
/* Ignore NUL packets */
|
||||
if (pid == 0x1FFF) goto done;
|
||||
if (pid == 0x1FFF) {
|
||||
#if ENABLE_TSDEBUG
|
||||
tsdebug_check_tspkt(mm, tsb);
|
||||
#endif
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Remove in future or move it outside this loop */
|
||||
lock_assert(&mi->mi_output_lock);
|
||||
|
@ -841,11 +924,15 @@ mpegts_input_process
|
|||
|
||||
done:
|
||||
tsb += 188;
|
||||
#if ENABLE_TSDEBUG
|
||||
mm->mm_tsdebug_pos += 188;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Raw stream */
|
||||
if (tsb != mpkt->mp_data &&
|
||||
LIST_FIRST(&mmi->mmi_streaming_pad.sp_targets) != NULL) {
|
||||
|
||||
streaming_message_t sm;
|
||||
pktbuf_t *pb = pktbuf_alloc(mpkt->mp_data, tsb - mpkt->mp_data);
|
||||
memset(&sm, 0, sizeof(sm));
|
||||
|
@ -854,6 +941,27 @@ done:
|
|||
streaming_pad_deliver(&mmi->mmi_streaming_pad, streaming_msg_clone(&sm));
|
||||
pktbuf_ref_dec(pb);
|
||||
}
|
||||
#if ENABLE_TSDEBUG
|
||||
{
|
||||
tsdebug_packet_t *tp, *tp_next;
|
||||
off_t pos = 0;
|
||||
size_t used = tsb - mpkt->mp_data;
|
||||
for (tp = TAILQ_FIRST(&mm->mm_tsdebug_packets); tp; tp = tp_next) {
|
||||
tp_next = TAILQ_NEXT(tp, link);
|
||||
assert((tp->pos % 188) == 0);
|
||||
assert(tp->pos >= tsdebug_pos && tp->pos < tsdebug_pos + used);
|
||||
if (mm->mm_tsdebug_fd >= 0) {
|
||||
tvh_write(mm->mm_tsdebug_fd, mpkt->mp_data + pos, tp->pos - tsdebug_pos - pos);
|
||||
tvh_write(mm->mm_tsdebug_fd, tp->pkt, 188);
|
||||
}
|
||||
pos = tp->pos - tsdebug_pos;
|
||||
TAILQ_REMOVE(&mm->mm_tsdebug_packets, tp, link);
|
||||
free(tp);
|
||||
}
|
||||
if (pos < used && mm->mm_tsdebug_fd >= 0)
|
||||
tvh_write(mm->mm_tsdebug_fd, mpkt->mp_data + pos, used - pos);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Wake table */
|
||||
if (table_wakeup)
|
||||
|
@ -888,6 +996,14 @@ mpegts_input_thread ( void * p )
|
|||
|
||||
/* Cleanup */
|
||||
free(mp);
|
||||
|
||||
#if ENABLE_TSDEBUG
|
||||
{
|
||||
extern void tsdebugcw_go(void);
|
||||
tsdebugcw_go();
|
||||
}
|
||||
#endif
|
||||
|
||||
pthread_mutex_lock(&mi->mi_input_lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -1228,6 +1228,7 @@ fast_exit:
|
|||
(uint32_t)((uint16_t)nseq-(uint16_t)(seq+1));
|
||||
seq = nseq;
|
||||
/* Process */
|
||||
tsdebug_write((mpegts_mux_t *)lm, p + pos, c - pos);
|
||||
sbuf_append(&sb, p + pos, c - pos);
|
||||
}
|
||||
mpegts_input_recv_packets((mpegts_input_t*)lfe, mmi,
|
||||
|
|
|
@ -214,8 +214,8 @@ tsfile_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *t )
|
|||
|
||||
/* Check file is accessible */
|
||||
if (lstat(mmi->mmi_tsfile_path, &st)) {
|
||||
tvhlog(LOG_ERR, "tsfile", "mmi %p could not stat %s",
|
||||
mmi, mmi->mmi_tsfile_path);
|
||||
tvhlog(LOG_ERR, "tsfile", "mmi %p could not stat '%s' (%i)",
|
||||
mmi, mmi->mmi_tsfile_path, errno);
|
||||
mmi->mmi_tune_failed = 1;
|
||||
return SM_CODE_TUNING_FAILED;
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ tvhdhomerun_frontend_input_thread ( void *aux )
|
|||
if (nfds < 1) continue;
|
||||
if (ev[0].data.fd != sockfd) break;
|
||||
|
||||
if((r = sbuf_read(&sb, sockfd)) < 0) {
|
||||
if((r = sbuf_tsdebug_read(mmi->mmi_mux, &sb, sockfd)) < 0) {
|
||||
/* whoopsy */
|
||||
if(ERRNO_AGAIN(errno))
|
||||
continue;
|
||||
|
|
12
src/main.c
12
src/main.c
|
@ -132,6 +132,7 @@ int tvheadend_webui_port;
|
|||
int tvheadend_webui_debug;
|
||||
int tvheadend_htsp_port;
|
||||
int tvheadend_htsp_port_extra;
|
||||
const char *tvheadend_tsdebug;
|
||||
const char *tvheadend_cwd;
|
||||
const char *tvheadend_webroot;
|
||||
const tvh_caps_t tvheadend_capabilities[] = {
|
||||
|
@ -469,7 +470,9 @@ main(int argc, char **argv)
|
|||
opt_fileline = 0,
|
||||
opt_threadid = 0,
|
||||
opt_ipv6 = 0,
|
||||
#if ENABLE_TSFILE
|
||||
opt_tsfile_tuner = 0,
|
||||
#endif
|
||||
opt_dump = 0,
|
||||
opt_xspf = 0,
|
||||
opt_dbus = 0,
|
||||
|
@ -560,9 +563,16 @@ main(int argc, char **argv)
|
|||
OPT_STR, &opt_subscribe },
|
||||
|
||||
|
||||
#if ENABLE_TSFILE || ENABLE_TSDEBUG
|
||||
{ 0, NULL, "TODO: testing", OPT_BOOL, NULL },
|
||||
#if ENABLE_TSFILE
|
||||
{ 0, "tsfile_tuners", "Number of tsfile tuners", OPT_INT, &opt_tsfile_tuner },
|
||||
{ 0, "tsfile", "tsfile input (mux file)", OPT_STR_LIST, &opt_tsfile },
|
||||
#endif
|
||||
#if ENABLE_TSDEBUG
|
||||
{ 0, "tsdebug", "Output directory for tsdebug", OPT_STR, &tvheadend_tsdebug },
|
||||
#endif
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
@ -957,7 +967,9 @@ main(int argc, char **argv)
|
|||
if(opt_fork)
|
||||
unlink(opt_pidpath);
|
||||
|
||||
#if ENABLE_TSFILE
|
||||
free(opt_tsfile.str);
|
||||
#endif
|
||||
free(opt_satip_xml.str);
|
||||
|
||||
/* OpenSSL - welcome to the "cleanup" hell */
|
||||
|
|
Loading…
Add table
Reference in a new issue