From d8a0392275d912729a8e8faf5257e71cf5fc3941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Tue, 2 Mar 2010 22:10:21 +0000 Subject: [PATCH] * Add a new DVB adapter option that allows the entire DVB Mux to be written to disk as Tvheadend tunes to it. This should aid a lot when it comes to debugging --- debian/changelog | 4 ++ src/dvb/dvb.h | 7 +++ src/dvb/dvb_adapter.c | 41 +++++++++++++++++- src/dvb/dvb_fe.c | 86 +++++++++++++++++++++++++++++++++++++ src/webui/extjs_dvb.c | 4 ++ src/webui/static/app/dvb.js | 9 +++- 6 files changed, 148 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 69f82843..d74ef384 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,10 @@ hts-tvheadend (2.11-WIP) hts; urgency=low * Add circular 10.75 GHz LNB + * Add a new DVB adapter option that allows the entire DVB Mux to be + written to disk as Tvheadend tunes to it. This should aid a lot when + it comes to debugging + hts-tvheadend (2.10) hts; urgency=high * Fix a crash in HTSP server. diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 99ddf263..5d7636de 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -195,6 +195,11 @@ typedef struct th_dvb_adapter { struct th_dvb_mux_instance_list tda_mux_hash[TDA_MUX_HASH_WIDTH]; + uint32_t tda_dump_muxes; + + int tda_allpids_dmx_fd; + int tda_dump_fd; + } th_dvb_adapter_t; @@ -219,6 +224,8 @@ void dvb_adapter_set_idlescan(th_dvb_adapter_t *tda, int on); void dvb_adapter_set_qmon(th_dvb_adapter_t *tda, int on); +void dvb_adapter_set_dump_muxes(th_dvb_adapter_t *tda, int on); + void dvb_adapter_set_nitoid(th_dvb_adapter_t *tda, int nitoid); void dvb_adapter_set_diseqc_version(th_dvb_adapter_t *tda, unsigned int v); diff --git a/src/dvb/dvb_adapter.c b/src/dvb/dvb_adapter.c index b894d637..858c2b95 100644 --- a/src/dvb/dvb_adapter.c +++ b/src/dvb/dvb_adapter.c @@ -60,6 +60,10 @@ tda_alloc(void) TAILQ_INIT(&tda->tda_scan_queues[1]); TAILQ_INIT(&tda->tda_initial_scan_queue); TAILQ_INIT(&tda->tda_satconfs); + + tda->tda_allpids_dmx_fd = -1; + tda->tda_dump_fd = -1; + return tda; } @@ -79,6 +83,7 @@ tda_save(th_dvb_adapter_t *tda) htsmsg_add_u32(m, "autodiscovery", tda->tda_autodiscovery); htsmsg_add_u32(m, "idlescan", tda->tda_idlescan); htsmsg_add_u32(m, "qmon", tda->tda_qmon); + htsmsg_add_u32(m, "dump_muxes", tda->tda_dump_muxes); htsmsg_add_u32(m, "nitoid", tda->tda_nitoid); htsmsg_add_u32(m, "diseqc_version", tda->tda_diseqc_version); hts_settings_save(m, "dvbadapters/%s", tda->tda_identifier); @@ -166,6 +171,25 @@ dvb_adapter_set_qmon(th_dvb_adapter_t *tda, int on) } +/** + * + */ +void +dvb_adapter_set_dump_muxes(th_dvb_adapter_t *tda, int on) +{ + if(tda->tda_dump_muxes == on) + return; + + lock_assert(&global_lock); + + tvhlog(LOG_NOTICE, "dvb", "Adapter \"%s\" dump of DVB mux input set to: %s", + tda->tda_displayname, on ? "On" : "Off"); + + tda->tda_dump_muxes = on; + tda_save(tda); +} + + /** * */ @@ -356,6 +380,7 @@ dvb_adapter_init(uint32_t adapter_mask) htsmsg_get_u32(c, "autodiscovery", &tda->tda_autodiscovery); htsmsg_get_u32(c, "idlescan", &tda->tda_idlescan); htsmsg_get_u32(c, "qmon", &tda->tda_qmon); + htsmsg_get_u32(c, "dump_muxes", &tda->tda_dump_muxes); htsmsg_get_u32(c, "nitoid", &tda->tda_nitoid); htsmsg_get_u32(c, "diseqc_version", &tda->tda_diseqc_version); } @@ -484,6 +509,7 @@ dvb_adapter_clean(th_dvb_adapter_t *tda) + /** * */ @@ -501,15 +527,28 @@ dvb_adapter_input_dvr(void *aux) return NULL; } + while(1) { r = read(fd, tsb, sizeof(tsb)); pthread_mutex_lock(&tda->tda_delivery_mutex); - for(i = 0; i < r; i += 188) + for(i = 0; i < r; i += 188) { LIST_FOREACH(t, &tda->tda_transports, tht_active_link) if(t->tht_dvb_mux_instance == tda->tda_mux_current) ts_recv_packet1(t, tsb + i, NULL); + } + + if(tda->tda_dump_fd != -1) { + if(write(tda->tda_dump_fd, tsb, r) != r) { + tvhlog(LOG_ERR, "dvb", + "\"%s\" unable to write to mux dump file -- %s", + tda->tda_identifier, strerror(errno)); + + close(tda->tda_dump_fd); + tda->tda_dump_fd = -1; + } + } pthread_mutex_unlock(&tda->tda_delivery_mutex); } diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index 769a5559..4f7329a0 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -159,6 +160,16 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi) assert(tdmi == tda->tda_mux_current); tda->tda_mux_current = NULL; + if(tda->tda_allpids_dmx_fd != -1) { + close(tda->tda_allpids_dmx_fd); + tda->tda_allpids_dmx_fd = -1; + } + + if(tda->tda_dump_fd != -1) { + close(tda->tda_dump_fd); + tda->tda_dump_fd = -1; + } + if(tdmi->tdmi_table_initial) { tdmi->tdmi_table_initial = 0; tda->tda_initial_num_mux--; @@ -177,6 +188,78 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi) } +/** + * Open a dump file which we write the entire mux output to + */ +static void +dvb_adapter_open_dump_file(th_dvb_adapter_t *tda) +{ + struct dmx_pes_filter_params dmx_param; + char fullname[1000]; + char path[500]; + extern char *dvr_storage; + const char *fname = tda->tda_mux_current->tdmi_identifier; + + int fd = tvh_open(tda->tda_demux_path, O_RDWR, 0); + if(fd == -1) + return; + + memset(&dmx_param, 0, sizeof(dmx_param)); + dmx_param.pid = 0x2000; + dmx_param.input = DMX_IN_FRONTEND; + dmx_param.output = DMX_OUT_TS_TAP; + dmx_param.pes_type = DMX_PES_OTHER; + dmx_param.flags = DMX_IMMEDIATE_START; + + if(ioctl(fd, DMX_SET_PES_FILTER, &dmx_param)) { + tvhlog(LOG_ERR, "dvb", + "\"%s\" unable to configure demuxer \"%s\" for all PIDs -- %s", + fname, tda->tda_demux_path, + strerror(errno)); + close(fd); + return; + } + + snprintf(path, sizeof(path), "%s/muxdumps", dvr_storage); + + if(mkdir(path, 0777) && errno != EEXIST) { + tvhlog(LOG_ERR, "dvb", "\"%s\" unable to create mux dump dir %s -- %s", + fname, path, strerror(errno)); + close(fd); + return; + } + + int attempt = 1; + + while(1) { + struct stat st; + snprintf(fullname, sizeof(fullname), "%s/%s.dump%d.ts", + path, fname, attempt); + + if(stat(fullname, &st) == -1) + break; + + attempt++; + } + + int f = open(fullname, O_CREAT | O_TRUNC | O_WRONLY, 0777); + + if(f == -1) { + tvhlog(LOG_ERR, "dvb", "\"%s\" unable to create mux dump file %s -- %s", + fname, fullname, strerror(errno)); + close(fd); + return; + } + + tvhlog(LOG_WARNING, "dvb", "\"%s\" writing to mux dump file %s", + fname, fullname); + + tda->tda_allpids_dmx_fd = fd; + tda->tda_dump_fd = f; +} + + + #if DVB_API_VERSION >= 5 static int check_frontend (int fe_fd, int dvr, int human_readable) { @@ -374,6 +457,9 @@ dvb_fe_tune(th_dvb_mux_instance_t *tdmi, const char *reason) tda->tda_mux_current = tdmi; + if(tda->tda_dump_muxes) + dvb_adapter_open_dump_file(tda); + gtimer_arm(&tda->tda_fe_monitor_timer, dvb_fe_monitor, tda, 1); dvb_table_add_default(tdmi); diff --git a/src/webui/extjs_dvb.c b/src/webui/extjs_dvb.c index 83623c70..f17b4876 100644 --- a/src/webui/extjs_dvb.c +++ b/src/webui/extjs_dvb.c @@ -152,6 +152,7 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) htsmsg_add_u32(r, "automux", tda->tda_autodiscovery); htsmsg_add_u32(r, "idlescan", tda->tda_idlescan); htsmsg_add_u32(r, "qmon", tda->tda_qmon); + htsmsg_add_u32(r, "dumpmux", tda->tda_dump_muxes); htsmsg_add_u32(r, "nitoid", tda->tda_nitoid); htsmsg_add_str(r, "diseqcversion", ((const char *[]){"DiSEqC 1.0 / 2.0", @@ -173,6 +174,9 @@ extjs_dvbadapter(http_connection_t *hc, const char *remain, void *opaque) s = http_arg_get(&hc->hc_req_args, "qmon"); dvb_adapter_set_qmon(tda, !!s); + s = http_arg_get(&hc->hc_req_args, "dumpmux"); + dvb_adapter_set_dump_muxes(tda, !!s); + if((s = http_arg_get(&hc->hc_req_args, "nitoid")) != NULL) dvb_adapter_set_nitoid(tda, atoi(s)); diff --git a/src/webui/static/app/dvb.js b/src/webui/static/app/dvb.js index 2420a5b4..6b0d8433 100644 --- a/src/webui/static/app/dvb.js +++ b/src/webui/static/app/dvb.js @@ -1008,7 +1008,8 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) { var confreader = new Ext.data.JsonReader({ root: 'dvbadapters' - }, ['name', 'automux', 'idlescan', 'diseqcversion', 'qmon', 'nitoid']); + }, ['name', 'automux', 'idlescan', 'diseqcversion', 'qmon', + 'dumpmux', 'nitoid']); function saveConfForm () { @@ -1037,6 +1038,10 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) { fieldLabel: 'Monitor signal quality', name: 'qmon' }), + new Ext.form.Checkbox({ + fieldLabel: 'Write full DVB MUX to disk', + name: 'dumpmux' + }), { fieldLabel: 'NIT-o Network ID', name: 'nitoid', @@ -1066,7 +1071,7 @@ tvheadend.dvb_adapter_general = function(adapterData, satConfStore) { style:'margin:10px', bodyStyle:'padding:5px', labelAlign: 'right', - labelWidth: 130, + labelWidth: 160, waitMsgTarget: true, reader: confreader, defaultType: 'textfield',