diff options
Diffstat (limited to 'stream/stream_dvb.c')
-rw-r--r-- | stream/stream_dvb.c | 784 |
1 files changed, 333 insertions, 451 deletions
diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index c6edaa03e9..96590d28f3 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -41,9 +41,6 @@ #include <unistd.h> #include <fcntl.h> #include <errno.h> -#include <pthread.h> - -#include <libavutil/avstring.h> #include "osdep/io.h" #include "misc/ctype.h" @@ -55,6 +52,7 @@ #include "options/m_option.h" #include "options/options.h" #include "options/path.h" +#include "osdep/threads.h" #include "dvbin.h" #include "dvb_tune.h" @@ -64,130 +62,125 @@ #endif #define CHANNEL_LINE_LEN 256 -#define min(a, b) ((a) <= (b) ? (a) : (b)) #define OPT_BASE_STRUCT dvb_opts_t static dvb_state_t *global_dvb_state = NULL; -static pthread_mutex_t global_dvb_state_lock = PTHREAD_MUTEX_INITIALIZER; +static mp_static_mutex global_dvb_state_lock = MP_STATIC_MUTEX_INITIALIZER; const struct m_sub_options stream_dvb_conf = { .opts = (const m_option_t[]) { - OPT_STRING("prog", cfg_prog, UPDATE_DVB_PROG), - OPT_INTRANGE("card", cfg_devno, 0, 0, MAX_ADAPTERS-1), - OPT_INTRANGE("timeout", cfg_timeout, 0, 1, 30), - OPT_STRING("file", cfg_file, M_OPT_FILE), - OPT_FLAG("full-transponder", cfg_full_transponder, 0), - OPT_INT("channel-switch-offset", cfg_channel_switch_offset, - UPDATE_DVB_PROG), + {"prog", OPT_STRING(cfg_prog), .flags = UPDATE_DVB_PROG}, + {"card", OPT_INT(cfg_devno), M_RANGE(0, MAX_ADAPTERS-1)}, + {"timeout", OPT_INT(cfg_timeout), M_RANGE(1, 30)}, + {"file", OPT_STRING(cfg_file), .flags = M_OPT_FILE}, + {"full-transponder", OPT_BOOL(cfg_full_transponder)}, + {"channel-switch-offset", OPT_INT(cfg_channel_switch_offset), + .flags = UPDATE_DVB_PROG}, {0} }, .size = sizeof(dvb_opts_t), .defaults = &(const dvb_opts_t){ .cfg_prog = NULL, - .cfg_devno = 0, .cfg_timeout = 30, }, }; void dvbin_close(stream_t *stream); -static fe_modulation_t parse_vdr_modulation(const char** modstring) { - if (!strncmp(*modstring, "16", 2)) { - (*modstring)+=2; - return QAM_16; - } else if (!strncmp(*modstring, "32", 2)) { - (*modstring)+=2; - return QAM_32; - } else if (!strncmp(*modstring, "64", 2)) { - (*modstring)+=2; - return QAM_64; - } else if (!strncmp(*modstring, "128", 3)) { - (*modstring)+=3; - return QAM_128; - } else if (!strncmp(*modstring, "256", 3)) { - (*modstring)+=3; - return QAM_256; - } else if (!strncmp(*modstring, "998", 3)) { - (*modstring)+=3; - return QAM_AUTO; - } else if (!strncmp(*modstring, "2", 1)) { - (*modstring)++; - return QPSK; - } else if (!strncmp(*modstring, "5", 1)) { - (*modstring)++; - return PSK_8; - } else if (!strncmp(*modstring, "6", 1)) { - (*modstring)++; - return APSK_16; - } else if (!strncmp(*modstring, "7", 1)) { - (*modstring)++; - return APSK_32; - } else if (!strncmp(*modstring, "10", 2)) { - (*modstring)+=2; - return VSB_8; - } else if (!strncmp(*modstring, "11", 2)) { - (*modstring)+=2; - return VSB_16; - } else if (!strncmp(*modstring, "12", 2)) { - (*modstring)+=2; - return DQPSK; - } else { - return QAM_AUTO; +static fe_code_rate_t parse_fec(const char *cr) +{ + if (!strcmp(cr, "FEC_1_2")) { + return FEC_1_2; + } else if (!strcmp(cr, "FEC_2_3")) { + return FEC_2_3; + } else if (!strcmp(cr, "FEC_3_4")) { + return FEC_3_4; + } else if (!strcmp(cr, "FEC_4_5")) { + return FEC_4_5; + } else if (!strcmp(cr, "FEC_5_6")) { + return FEC_5_6; + } else if (!strcmp(cr, "FEC_6_7")) { + return FEC_6_7; + } else if (!strcmp(cr, "FEC_7_8")) { + return FEC_7_8; + } else if (!strcmp(cr, "FEC_8_9")) { + return FEC_8_9; + } else if (!strcmp(cr, "FEC_NONE")) { + return FEC_NONE; + } + return FEC_NONE; +} + +static fe_modulation_t parse_vdr_modulation(const char** modstring) +{ + static const struct { const char *s; fe_modulation_t v; } table[] = { + { "16", QAM_16 }, + { "32", QAM_32 }, + { "64", QAM_64 }, + { "128", QAM_128 }, + { "256", QAM_256 }, + { "998", QAM_AUTO }, + { "2", QPSK }, + { "5", PSK_8 }, + { "6", APSK_16 }, + { "7", APSK_32 }, + { "10", VSB_8 }, + { "11", VSB_16 }, + { "12", DQPSK }, + }; + for (int i = 0; i < MP_ARRAY_SIZE(table); i++) { + if (!strncmp(*modstring, table[i].s, strlen(table[i].s))) { + *modstring += strlen(table[i].s); + return table[i].v; + } } + return QAM_AUTO; } static void parse_vdr_par_string(const char *vdr_par_str, dvb_channel_t *ptr) { //FIXME: There is more information in this parameter string, especially related // to non-DVB-S reception. - if (vdr_par_str[0]) { - const char *vdr_par = &vdr_par_str[0]; - while (vdr_par && *vdr_par) { - switch (mp_toupper(*vdr_par)) { - case 'H': - ptr->pol = 'H'; - vdr_par++; - break; - case 'V': - ptr->pol = 'V'; - vdr_par++; - break; - case 'S': - vdr_par++; - if (*vdr_par == '1') { - ptr->is_dvb_x2 = true; - } else { - ptr->is_dvb_x2 = false; - } - vdr_par++; - break; - case 'P': - vdr_par++; - char *endptr = NULL; - errno = 0; - int n = strtol(vdr_par, &endptr, 10); - if (!errno && endptr != vdr_par) { - ptr->stream_id = n; - vdr_par = endptr; - } - break; - case 'I': - vdr_par++; - if (*vdr_par == '1') { - ptr->inv = INVERSION_ON; - } else { - ptr->inv = INVERSION_OFF; - } - vdr_par++; - break; - case 'M': - vdr_par++; - ptr->mod = parse_vdr_modulation(&vdr_par); - break; - default: - vdr_par++; + if (!vdr_par_str[0]) + return; + const char *vdr_par = &vdr_par_str[0]; + while (vdr_par && *vdr_par) { + switch (mp_toupper(*vdr_par)) { + case 'H': + ptr->pol = 'H'; + vdr_par++; + break; + case 'V': + ptr->pol = 'V'; + vdr_par++; + break; + case 'S': + vdr_par++; + ptr->is_dvb_x2 = *vdr_par == '1'; + vdr_par++; + break; + case 'P': + vdr_par++; + char *endptr = NULL; + errno = 0; + int n = strtol(vdr_par, &endptr, 10); + if (!errno && endptr != vdr_par) { + ptr->stream_id = n; + vdr_par = endptr; } + break; + case 'I': + vdr_par++; + ptr->inv = (*vdr_par == '1') ? INVERSION_ON : INVERSION_OFF; + vdr_par++; + break; + case 'M': + vdr_par++; + ptr->mod = parse_vdr_modulation(&vdr_par); + break; + default: + vdr_par++; } } } @@ -217,38 +210,36 @@ static char *dvb_strtok_r(char *s, const char *sep, char **p) static bool parse_pid_string(struct mp_log *log, char *pid_string, dvb_channel_t *ptr) { - if (pid_string[0]) { - int pcnt = 0; - /* These tokens also catch vdr-style PID lists. - * They can contain 123=deu@3,124=eng+jap@4;125 - * 3 and 4 are codes for codec type, =langLeft+langRight is allowed, - * and ; may separate a dolby channel. - * With the numChars-test and the full token-list, all is handled - * gracefully. - */ - const char *tokens = "+,;"; - char *pidPart; - char *savePtr = NULL; - pidPart = dvb_strtok_r(pid_string, tokens, &savePtr); - while (pidPart != NULL) { - if (ptr->pids_cnt >= DMX_FILTER_SIZE - 1) { - mp_verbose(log, "Maximum number of PIDs for one channel " - "reached, ignoring further ones!\n"); - return pcnt > 0; - } - int numChars = 0; - int pid = 0; - pcnt += sscanf(pidPart, "%d%n", &pid, &numChars); - if (numChars > 0) { - ptr->pids[ptr->pids_cnt] = pid; - ptr->pids_cnt++; - } - pidPart = dvb_strtok_r(NULL, tokens, &savePtr); + if (!pid_string[0]) + return false; + int pcnt = 0; + /* These tokens also catch vdr-style PID lists. + * They can contain 123=deu@3,124=eng+jap@4;125 + * 3 and 4 are codes for codec type, =langLeft+langRight is allowed, + * and ; may separate a dolby channel. + * With the numChars-test and the full token-list, all is handled + * gracefully. + */ + const char *tokens = "+,;"; + char *pidPart; + char *savePtr = NULL; + pidPart = dvb_strtok_r(pid_string, tokens, &savePtr); + while (pidPart != NULL) { + if (ptr->pids_cnt >= DMX_FILTER_SIZE - 1) { + mp_verbose(log, "Maximum number of PIDs for one channel " + "reached, ignoring further ones!\n"); + break; } - if (pcnt > 0) - return true; + int numChars = 0; + int pid = 0; + pcnt += sscanf(pidPart, "%d%n", &pid, &numChars); + if (numChars > 0) { + ptr->pids[ptr->pids_cnt] = pid; + ptr->pids_cnt++; + } + pidPart = dvb_strtok_r(NULL, tokens, &savePtr); } - return false; + return pcnt > 0; } static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, @@ -259,77 +250,66 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, int delsys, unsigned int delsys_mask) { dvb_channels_list_t *list = list_add; - FILE *f; - char line[CHANNEL_LINE_LEN], *colon; if (!filename) - return NULL; + return list; - int fields, cnt, k; - int has8192, has0; - dvb_channel_t *ptr, *tmp, chn; - char tmp_lcr[256], tmp_hier[256], inv[256], bw[256], cr[256], mod[256], - transm[256], gi[256], vpid_str[256], apid_str[256], tpid_str[256], - vdr_par_str[256], vdr_loc_str[256]; const char *cbl_conf = "%d:%255[^:]:%d:%255[^:]:%255[^:]:%255[^:]:%255[^:]\n"; const char *sat_conf = "%d:%c:%d:%d:%255[^:]:%255[^:]\n"; const char *ter_conf = "%d:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]:%255[^:]\n"; -#ifdef DVB_ATSC const char *atsc_conf = "%d:%255[^:]:%255[^:]:%255[^:]\n"; -#endif const char *vdr_conf = "%d:%255[^:]:%255[^:]:%d:%255[^:]:%255[^:]:%255[^:]:%*255[^:]:%d:%*d:%*d:%*d\n%n"; - mp_verbose(log, "CONFIG_READ FILE: %s, type: %s\n", + mp_verbose(log, "Reading config file %s for type %s\n", filename, get_dvb_delsys(delsys)); - if ((f = fopen(filename, "r")) == NULL) { - mp_fatal(log, "CAN'T READ CONFIG FILE %s\n", filename); - return NULL; + FILE *f = fopen(filename, "r"); + if (!f) { + mp_fatal(log, "Can't open file %s\n", filename); + return list; } - if (list == NULL) { - list = malloc(sizeof(dvb_channels_list_t)); - if (list == NULL) { - fclose(f); - mp_verbose(log, "DVB_GET_CHANNELS: couldn't malloc enough memory\n"); - return NULL; - } - memset(list, 0x00, sizeof(dvb_channels_list_t)); - } + if (!list) + list = talloc_zero(NULL, dvb_channels_list_t); - ptr = &chn; while (!feof(f)) { - if (fgets(line, CHANNEL_LINE_LEN, f) == NULL) + char line[CHANNEL_LINE_LEN]; + if (!fgets(line, CHANNEL_LINE_LEN, f)) continue; - if ((line[0] == '#') || (strlen(line) == 0)) + if (line[0] == '#' || strlen(line) == 0) continue; - memset(ptr, 0x00, sizeof(dvb_channel_t)); + dvb_channel_t chn = {0}; + dvb_channel_t *ptr = &chn; + + char tmp_lcr[256], tmp_hier[256], inv[256], bw[256], cr[256], mod[256], + transm[256], gi[256], vpid_str[256], apid_str[256], tpid_str[256], + vdr_par_str[256], vdr_loc_str[256]; + vpid_str[0] = apid_str[0] = tpid_str[0] = 0; vdr_loc_str[0] = vdr_par_str[0] = 0; - colon = strchr(line, ':'); - if (colon) { - k = colon - line; - if (!k) - continue; - // In some modern VDR-style configs, channel name also has bouquet after ;. - // Parse that off, we ignore it. - char *bouquet_sep = strchr(line, ';'); - int channel_name_length = k; - if (bouquet_sep && bouquet_sep < colon) - channel_name_length = (bouquet_sep - line); - ptr->name = malloc((channel_name_length + 1)); - if (!ptr->name) - continue; - av_strlcpy(ptr->name, line, (channel_name_length + 1)); - } else { + char *colon = strchr(line, ':'); + if (!colon) continue; + int k = colon - line; + if (!k) + continue; + // In some modern VDR-style configs, channel name also has bouquet after ;. + // Parse that off, we ignore it. + char *bouquet_sep = strchr(line, ';'); + { + int namelen = k; + if (bouquet_sep && bouquet_sep < colon) + namelen = bouquet_sep - line; + ptr->name = talloc_strndup(list, line, namelen); } + k++; + ptr->pids_cnt = 0; ptr->freq = 0; ptr->service_id = -1; @@ -348,13 +328,22 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, ptr->trans = TRANSMISSION_MODE_AUTO; // Check if VDR-type channels.conf-line - then full line is consumed by the scan. - int num_chars = 0; + int fields, num_chars = 0; fields = sscanf(&line[k], vdr_conf, &ptr->freq, vdr_par_str, vdr_loc_str, &ptr->srate, vpid_str, apid_str, tpid_str, &ptr->service_id, &num_chars); - if (num_chars == strlen(&line[k])) { + bool is_vdr_conf = (num_chars == strlen(&line[k])); + + // Special case: DVB-T style ZAP config also has 13 columns. + // Most columns should have non-numeric content, but some channel list generators insert 0 + // if a value is not used. However, INVERSION_* should always set after frequency. + if (is_vdr_conf && !strncmp(vdr_par_str, "INVERSION_", 10)) { + is_vdr_conf = false; + } + + if (is_vdr_conf) { // Modulation parsed here, not via old xine-parsing path. mod[0] = '\0'; // It's a VDR-style config line. @@ -362,11 +351,11 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, // Frequency in VDR-style config files is in MHz for DVB-S, // and may be in MHz, kHz or Hz for DVB-C and DVB-T. // General rule to get useful units is to multiply by 1000 until value is larger than 1000000. - while (ptr->freq < 1000000UL) { - ptr->freq *= 1000UL; + while (ptr->freq < 1000000U) { + ptr->freq *= 1000U; } // Symbol rate in VDR-style config files is divided by 1000. - ptr->srate *= 1000UL; + ptr->srate *= 1000U; switch (delsys) { case SYS_DVBT: case SYS_DVBT2: @@ -379,7 +368,7 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, if (!DELSYS_IS_SET(delsys_mask, delsys)) continue; /* Skip channel. */ mp_verbose(log, "VDR, %s, NUM: %d, NUM_FIELDS: %d, NAME: %s, " - "FREQ: %d, SRATE: %d, T2: %s", + "FREQ: %d, SRATE: %d, T2: %s\n", get_dvb_delsys(delsys), list->NUM_CHANNELS, fields, ptr->name, ptr->freq, ptr->srate, @@ -389,8 +378,9 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, case SYS_DVBC_ANNEX_C: case SYS_ATSC: case SYS_DVBC_ANNEX_B: + case SYS_ISDBT: mp_verbose(log, "VDR, %s, NUM: %d, NUM_FIELDS: %d, NAME: %s, " - "FREQ: %d, SRATE: %d", + "FREQ: %d, SRATE: %d\n", get_dvb_delsys(delsys), list->NUM_CHANNELS, fields, ptr->name, ptr->freq, ptr->srate); @@ -426,7 +416,7 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, mp_verbose(log, "VDR, %s, NUM: %d, NUM_FIELDS: %d, NAME: %s, " "FREQ: %d, SRATE: %d, POL: %c, DISEQC: %d, S2: %s, " - "StreamID: %d, SID: %d", + "StreamID: %d, SID: %d\n", get_dvb_delsys(delsys), list->NUM_CHANNELS, fields, ptr->name, ptr->freq, ptr->srate, ptr->pol, @@ -437,13 +427,15 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, break; } } else { + // ZAP style channel config file. switch (delsys) { case SYS_DVBT: case SYS_DVBT2: + case SYS_ISDBT: fields = sscanf(&line[k], ter_conf, &ptr->freq, inv, bw, cr, tmp_lcr, mod, transm, gi, tmp_hier, vpid_str, apid_str); - mp_verbose(log, "%s, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d", + mp_verbose(log, "%s, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d\n", get_dvb_delsys(delsys), list->NUM_CHANNELS, fields, ptr->name, ptr->freq); break; @@ -453,12 +445,11 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, &ptr->freq, inv, &ptr->srate, cr, mod, vpid_str, apid_str); mp_verbose(log, "%s, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d, " - "SRATE: %d", + "SRATE: %d\n", get_dvb_delsys(delsys), list->NUM_CHANNELS, fields, ptr->name, ptr->freq, ptr->srate); break; -#ifdef DVB_ATSC case SYS_ATSC: case SYS_DVBC_ANNEX_B: fields = sscanf(&line[k], atsc_conf, @@ -467,7 +458,6 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, get_dvb_delsys(delsys), list->NUM_CHANNELS, fields, ptr->name, ptr->freq); break; -#endif case SYS_DVBS: case SYS_DVBS2: fields = sscanf(&line[k], sat_conf, @@ -475,14 +465,14 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, vpid_str, apid_str); ptr->pol = mp_toupper(ptr->pol); - ptr->freq *= 1000UL; - ptr->srate *= 1000UL; + ptr->freq *= 1000U; + ptr->srate *= 1000U; if (ptr->diseqc > 4) continue; if (ptr->diseqc > 0) ptr->diseqc--; mp_verbose(log, "%s, NUM: %d, NUM_FIELDS: %d, NAME: %s, FREQ: %d, " - "SRATE: %d, POL: %c, DISEQC: %d", + "SRATE: %d, POL: %c, DISEQC: %d\n", get_dvb_delsys(delsys), list->NUM_CHANNELS, fields, ptr->name, ptr->freq, ptr->srate, ptr->pol, ptr->diseqc); @@ -530,12 +520,12 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, ptr->pids_cnt++; } - has8192 = has0 = 0; - for (cnt = 0; cnt < ptr->pids_cnt; cnt++) { + bool has8192 = false, has0 = false; + for (int cnt = 0; cnt < ptr->pids_cnt; cnt++) { if (ptr->pids[cnt] == 8192) - has8192 = 1; + has8192 = true; if (ptr->pids[cnt] == 0) - has0 = 1; + has0 = true; } /* 8192 is the pseudo-PID for full TP dump, @@ -551,13 +541,14 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, } mp_verbose(log, " PIDS: "); - for (cnt = 0; cnt < ptr->pids_cnt; cnt++) + for (int cnt = 0; cnt < ptr->pids_cnt; cnt++) mp_verbose(log, " %d ", ptr->pids[cnt]); mp_verbose(log, "\n"); switch (delsys) { case SYS_DVBT: case SYS_DVBT2: + case SYS_ISDBT: case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_C: if (!strcmp(inv, "INVERSION_ON")) { @@ -566,31 +557,13 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, ptr->inv = INVERSION_OFF; } - - if (!strcmp(cr, "FEC_1_2")) { - ptr->cr = FEC_1_2; - } else if (!strcmp(cr, "FEC_2_3")) { - ptr->cr = FEC_2_3; - } else if (!strcmp(cr, "FEC_3_4")) { - ptr->cr = FEC_3_4; - } else if (!strcmp(cr, "FEC_4_5")) { - ptr->cr = FEC_4_5; - } else if (!strcmp(cr, "FEC_6_7")) { - ptr->cr = FEC_6_7; - } else if (!strcmp(cr, "FEC_8_9")) { - ptr->cr = FEC_8_9; - } else if (!strcmp(cr, "FEC_5_6")) { - ptr->cr = FEC_5_6; - } else if (!strcmp(cr, "FEC_7_8")) { - ptr->cr = FEC_7_8; - } else if (!strcmp(cr, "FEC_NONE")) { - ptr->cr = FEC_NONE; - } + ptr->cr = parse_fec(cr); } switch (delsys) { case SYS_DVBT: case SYS_DVBT2: + case SYS_ISDBT: case SYS_DVBC_ANNEX_A: case SYS_DVBC_ANNEX_C: case SYS_ATSC: @@ -605,15 +578,13 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, ptr->mod = QAM_32; } else if (!strcmp(mod, "QAM_16")) { ptr->mod = QAM_16; -#ifdef DVB_ATSC } else if (!strcmp(mod, "VSB_8") || !strcmp(mod, "8VSB")) { ptr->mod = VSB_8; } else if (!strcmp(mod, "VSB_16") || !strcmp(mod, "16VSB")) { ptr->mod = VSB_16; -#endif } } -#ifdef DVB_ATSC + /* Modulation defines real delsys for ATSC: Terrestrial (VSB) is SYS_ATSC, Cable (QAM) is SYS_DVBC_ANNEX_B. */ if (delsys == SYS_ATSC || delsys == SYS_DVBC_ANNEX_B) { @@ -624,14 +595,14 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, } if (!DELSYS_IS_SET(delsys_mask, delsys)) continue; /* Skip channel. */ - mp_verbose(log, "Switched to delivery system for ATSC: %s (guessed from modulation).\n", + mp_verbose(log, "Switched to delivery system for ATSC: %s (guessed from modulation)\n", get_dvb_delsys(delsys)); } -#endif switch (delsys) { case SYS_DVBT: case SYS_DVBT2: + case SYS_ISDBT: if (!strcmp(bw, "BANDWIDTH_5_MHZ")) { ptr->bw = BANDWIDTH_5_MHZ; } else if (!strcmp(bw, "BANDWIDTH_6_MHZ")) { @@ -663,26 +634,7 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, ptr->gi = GUARD_INTERVAL_1_4; } - if (!strcmp(tmp_lcr, "FEC_1_2")) { - ptr->cr_lp = FEC_1_2; - } else if (!strcmp(tmp_lcr, "FEC_2_3")) { - ptr->cr_lp = FEC_2_3; - } else if (!strcmp(tmp_lcr, "FEC_3_4")) { - ptr->cr_lp = FEC_3_4; - } else if (!strcmp(tmp_lcr, "FEC_4_5")) { - ptr->cr_lp = FEC_4_5; - } else if (!strcmp(tmp_lcr, "FEC_6_7")) { - ptr->cr_lp = FEC_6_7; - } else if (!strcmp(tmp_lcr, "FEC_8_9")) { - ptr->cr_lp = FEC_8_9; - } else if (!strcmp(tmp_lcr, "FEC_5_6")) { - ptr->cr_lp = FEC_5_6; - } else if (!strcmp(tmp_lcr, "FEC_7_8")) { - ptr->cr_lp = FEC_7_8; - } else if (!strcmp(tmp_lcr, "FEC_NONE")) { - ptr->cr_lp = FEC_NONE; - } - + ptr->cr_lp = parse_fec(tmp_lcr); if (!strcmp(tmp_hier, "HIERARCHY_1")) { ptr->hier = HIERARCHY_1; @@ -695,69 +647,38 @@ static dvb_channels_list_t *dvb_get_channels(struct mp_log *log, } } - tmp = realloc(list->channels, sizeof(dvb_channel_t) * - (list->NUM_CHANNELS + 1)); - if (tmp == NULL) - break; - - list->channels = tmp; - memcpy(&(list->channels[list->NUM_CHANNELS]), ptr, sizeof(dvb_channel_t)); - list->NUM_CHANNELS++; - if (sizeof(dvb_channel_t) * list->NUM_CHANNELS >= 1024 * 1024) { - mp_verbose(log, "dvbin.c, > 1MB allocated for channels struct, " - "dropping the rest of the file\n"); - break; - } + MP_TARRAY_APPEND(list, list->channels, list->NUM_CHANNELS, *ptr); } fclose(f); - if (list->NUM_CHANNELS == 0) { - free(list->channels); - free(list); - return NULL; - } + if (list->NUM_CHANNELS == 0) + TA_FREEP(&list); return list; } -void dvb_free_state(dvb_state_t *state) -{ - int i, j; - - for (i = 0; i < state->adapters_count; i++) { - if (!state->adapters[i].list) - continue; - if (state->adapters[i].list->channels) { - for (j = 0; j < state->adapters[i].list->NUM_CHANNELS; j++) - free(state->adapters[i].list->channels[j].name); - free(state->adapters[i].list->channels); - } - free(state->adapters[i].list); - } - free(state); -} - static int dvb_streaming_read(stream_t *stream, void *buffer, int size) { - struct pollfd pfds[1]; - int pos = 0, tries, rk, fd; - dvb_priv_t *priv = (dvb_priv_t *) stream->priv; + dvb_priv_t *priv = stream->priv; dvb_state_t *state = priv->state; + int pos = 0; + int tries = state->retry; + const int fd = state->dvr_fd; MP_TRACE(stream, "dvb_streaming_read(%d)\n", size); - tries = state->retry; - fd = state->dvr_fd; + struct pollfd pfds[1]; + pfds[0].fd = fd; + pfds[0].events = POLLIN | POLLPRI; + while (pos < size) { - rk = read(fd, (char *)buffer + pos, (size - pos)); + int rk = read(fd, (char *)buffer + pos, (size - pos)); if (rk <= 0) { if (pos || tries == 0) break; - tries --; - pfds[0].fd = fd; - pfds[0].events = POLLIN | POLLPRI; + tries--; if (poll(pfds, 1, 2000) <= 0) { - MP_ERR(stream, "dvb_streaming_read, failed with " + MP_ERR(stream, "dvb_streaming_read: failed with " "errno %d when reading %d bytes\n", errno, size - pos); errno = 0; break; @@ -765,11 +686,11 @@ static int dvb_streaming_read(stream_t *stream, void *buffer, int size) continue; } pos += rk; - MP_TRACE(stream, "ret (%d) bytes\n", pos); + MP_TRACE(stream, "got %d bytes\n", pos); } if (!pos) - MP_ERR(stream, "dvb_streaming_read, return 0 bytes\n"); + MP_ERR(stream, "dvb_streaming_read: returning 0 bytes\n"); // Check if config parameters have been updated. dvb_update_config(stream); @@ -779,42 +700,30 @@ static int dvb_streaming_read(stream_t *stream, void *buffer, int size) int dvb_set_channel(stream_t *stream, unsigned int adapter, unsigned int n) { - dvb_channels_list_t *new_list; - dvb_channel_t *channel; dvb_priv_t *priv = stream->priv; - char buf[4096]; - dvb_state_t *state = (dvb_state_t *) priv->state; - int devno; - int i; - - if (adapter >= state->adapters_count) { - MP_ERR(stream, "dvb_set_channel: INVALID internal ADAPTER NUMBER: %d vs %d, abort\n", - adapter, state->adapters_count); - return 0; - } + dvb_state_t *state = priv->state; - devno = state->adapters[adapter].devno; - new_list = state->adapters[adapter].list; - if (n > new_list->NUM_CHANNELS) { - MP_ERR(stream, "dvb_set_channel: INVALID CHANNEL NUMBER: %d, for " - "adapter %d, abort\n", n, devno); - return 0; - } - channel = &(new_list->channels[n]); + assert(adapter < state->adapters_count); + int devno = state->adapters[adapter].devno; + dvb_channels_list_t *new_list = state->adapters[adapter].list; + assert(n < new_list->NUM_CHANNELS); + dvb_channel_t *channel = &(new_list->channels[n]); if (state->is_on) { //the fds are already open and we have to stop the demuxers /* Remove all demuxes. */ dvb_fix_demuxes(priv, 0); state->retry = 0; - //empty both the stream's and driver's buffer + // empty both the stream's and driver's buffer + char buf[4096]; while (dvb_streaming_read(stream, buf, sizeof(buf)) > 0) {} + if (state->cur_adapter != adapter || state->cur_frontend != channel->frontend) { dvbin_close(stream); if (!dvb_open_devices(priv, devno, channel->frontend, channel->pids_cnt)) { - MP_ERR(stream, "DVB_SET_CHANNEL, COULDN'T OPEN DEVICES OF " - "ADAPTER: %d, EXIT\n", devno); + MP_ERR(stream, "dvb_set_channel: couldn't open devices of adapter " + "%d\n", devno); return 0; } } else { @@ -825,18 +734,16 @@ int dvb_set_channel(stream_t *stream, unsigned int adapter, unsigned int n) } } else { if (!dvb_open_devices(priv, devno, channel->frontend, channel->pids_cnt)) { - MP_ERR(stream, "DVB_SET_CHANNEL2, COULDN'T OPEN DEVICES OF " - "ADAPTER: %d, EXIT\n", devno); + MP_ERR(stream, "dvb_set_channel: couldn't open devices of adapter " + "%d\n", devno); return 0; } } state->retry = 5; new_list->current = n; - MP_VERBOSE(stream, "DVB_SET_CHANNEL: new channel name=%s, adapter: %d, " - "channel %d\n", channel->name, devno, n); - - stream_drop_buffers(stream); + MP_VERBOSE(stream, "dvb_set_channel: new channel name=\"%s\", adapter: %d, " + "channel: %d\n", channel->name, devno, n); if (channel->freq != state->last_freq) { if (!dvb_tune(priv, channel->delsys, channel->freq, @@ -848,7 +755,7 @@ int dvb_set_channel(stream_t *stream, unsigned int adapter, unsigned int n) return 0; } - state->is_on = 1; + state->is_on = true; state->last_freq = channel->freq; state->cur_adapter = adapter; state->cur_frontend = channel->frontend; @@ -856,30 +763,30 @@ int dvb_set_channel(stream_t *stream, unsigned int adapter, unsigned int n) if (channel->service_id != -1) { /* We need the PMT-PID in addition. If it has not yet beem resolved, do it now. */ - for (i = 0; i < channel->pids_cnt; i++) { + for (int i = 0; i < channel->pids_cnt; i++) { if (channel->pids[i] == -1) { - MP_VERBOSE(stream, "DVB_SET_CHANNEL: PMT-PID for service %d " + MP_VERBOSE(stream, "dvb_set_channel: PMT-PID for service %d " "not resolved yet, parsing PAT...\n", channel->service_id); int pmt_pid = dvb_get_pmt_pid(priv, adapter, channel->service_id); - MP_VERBOSE(stream, "DVB_SET_CHANNEL: Found PMT-PID: %d\n", - pmt_pid); + MP_VERBOSE(stream, "found PMT-PID: %d\n", pmt_pid); channel->pids[i] = pmt_pid; + break; } } } // sets demux filters and restart the stream - for (i = 0; i < channel->pids_cnt; i++) { + for (int i = 0; i < channel->pids_cnt; i++) { if (channel->pids[i] == -1) { // In case PMT was not resolved, skip it here. - MP_ERR(stream, "DVB_SET_CHANNEL: PMT-PID not found, " - "teletext-decoding may fail.\n"); - } else { - if (!dvb_set_ts_filt(priv, state->demux_fds[i], channel->pids[i], - DMX_PES_OTHER)) - return 0; + MP_ERR(stream, "dvb_set_channel: PMT-PID not found, " + "teletext decoding may fail.\n"); + continue; } + if (!dvb_set_ts_filt(priv, state->demux_fds[i], channel->pids[i], + DMX_PES_OTHER)) + return 0; } return 1; @@ -887,13 +794,12 @@ int dvb_set_channel(stream_t *stream, unsigned int adapter, unsigned int n) static int dvbin_stream_control(struct stream *s, int cmd, void *arg) { - dvb_priv_t *priv = (dvb_priv_t *) s->priv; + dvb_priv_t *priv = s->priv; dvb_state_t *state = priv->state; - dvb_channels_list_t *list = NULL; if (state->cur_adapter >= state->adapters_count) return STREAM_ERROR; - list = state->adapters[state->cur_adapter].list; + dvb_channels_list_t *list = state->adapters[state->cur_adapter].list; switch (cmd) { case STREAM_CTRL_GET_METADATA: { @@ -909,52 +815,46 @@ static int dvbin_stream_control(struct stream *s, int cmd, void *arg) void dvbin_close(stream_t *stream) { - dvb_priv_t *priv = (dvb_priv_t *) stream->priv; + dvb_priv_t *priv = stream->priv; dvb_state_t *state = priv->state; if (state->switching_channel && state->is_on) { - // Prevent state destruction, reset channel-switch. - state->switching_channel = false; - pthread_mutex_lock(&global_dvb_state_lock); - global_dvb_state->stream_used = false; - pthread_mutex_unlock(&global_dvb_state_lock); - return; + // Prevent state destruction, reset channel-switch. + state->switching_channel = false; + mp_mutex_lock(&global_dvb_state_lock); + global_dvb_state->stream_used = false; + mp_mutex_unlock(&global_dvb_state_lock); + return; } for (int i = state->demux_fds_cnt - 1; i >= 0; i--) { state->demux_fds_cnt--; - MP_VERBOSE(stream, "DVBIN_CLOSE, close(%d), fd=%d, COUNT=%d\n", i, - state->demux_fds[i], state->demux_fds_cnt); close(state->demux_fds[i]); } close(state->dvr_fd); close(state->fe_fd); state->fe_fd = state->dvr_fd = -1; - state->is_on = 0; + state->is_on = false; state->cur_adapter = -1; state->cur_frontend = -1; - pthread_mutex_lock(&global_dvb_state_lock); - dvb_free_state(state); - global_dvb_state = NULL; - pthread_mutex_unlock(&global_dvb_state_lock); + mp_mutex_lock(&global_dvb_state_lock); + TA_FREEP(&global_dvb_state); + mp_mutex_unlock(&global_dvb_state_lock); } |