aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <m.chehab@samsung.com>2014-09-13 12:25:36 -0300
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-09-13 12:49:20 -0300
commit67a718b3f1c8edb47f052cfa1e34c2234bb3dad5 (patch)
tree505150964a20fd2cc905073bddcc084d8eac7ab2
parent538ff283e735e7593d9e450a89f74ffcbdd7bedd (diff)
Add support for VDR format (only for output)
VDR has its own special format, that doesn't fit into the normal oneline parsers. So, it requires its own code to parse. Add support for it, as used on vdr 2.1.6. Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r--lib/include/libdvbv5/dvb-file.h27
-rw-r--r--lib/libdvbv5/Makefile.am1
-rw-r--r--lib/libdvbv5/dvb-file.c9
-rw-r--r--lib/libdvbv5/dvb-vdr-format.c411
4 files changed, 443 insertions, 5 deletions
diff --git a/lib/include/libdvbv5/dvb-file.h b/lib/include/libdvbv5/dvb-file.h
index 09cc6c0d..0ae1fbc7 100644
--- a/lib/include/libdvbv5/dvb-file.h
+++ b/lib/include/libdvbv5/dvb-file.h
@@ -219,13 +219,16 @@ struct dvb_parse_file {
* @brief File is at the dvb-apps output format for dvb-zap
* @var FILE_DVBV5
* @brief File is at libdvbv5 format
- *
+ * @var FILE_VDR
+ * @brief File is at DVR format (as supported on version 2.1.6).
+ * Note: this is only supported as an output format.
*/
enum dvb_file_formats {
FILE_UNKNOWN,
FILE_ZAP,
FILE_CHANNEL,
FILE_DVBV5,
+ FILE_VDR,
};
struct dvb_v5_descriptors;
@@ -443,11 +446,11 @@ int dvb_parse_delsys(const char *name);
* @ingroup file
*
* @param name string containing the name of the format
- * Current valid names are: ZAP, CHANNEL and DVBV5. The name is
- * case-insensitive.
+ * Current valid names are: ZAP, CHANNEL, VDR and DVBV5.
+ * The name is case-insensitive.
*
- * It returns FILE_ZAP, FILE_CHANNEL, FILE_DVBV5 if the name was translated,
- * or FILE_UNKNOWN otherwise.
+ * @return It returns FILE_ZAP, FILE_CHANNEL, FILE_VDR or FILE_DVBV5
+ * if the name was translated. FILE_UNKNOWN otherwise.
*/
enum dvb_file_formats dvb_parse_format(const char *name);
@@ -490,6 +493,20 @@ int dvb_write_format_oneline(const char *fname,
uint32_t delsys,
const struct dvb_parse_file *parse_file);
+/**
+ * @brief Writes a file into vdr format (compatible up to version 2.1)
+ * @ingroup file
+ *
+ * @param fname file name
+ * @param dvb_file contents of the file to be written
+ *
+ * @return It returns zero if success, or a positive error number if it fails.
+ *
+ * This function is called internally by dvb_write_file_format.
+ */
+int dvb_write_format_vdr(const char *fname,
+ struct dvb_file *dvb_file);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libdvbv5/Makefile.am b/lib/libdvbv5/Makefile.am
index ad0c6bbb..fd212363 100644
--- a/lib/libdvbv5/Makefile.am
+++ b/lib/libdvbv5/Makefile.am
@@ -59,6 +59,7 @@ libdvbv5_la_SOURCES = \
crc32.c \
dvb-legacy-channel-format.c \
dvb-zap-format.c \
+ dvb-vdr-format.c \
dvb-v5.c \
dvb-v5.h \
parse_string.c \
diff --git a/lib/libdvbv5/dvb-file.c b/lib/libdvbv5/dvb-file.c
index a570596f..27d9a63d 100644
--- a/lib/libdvbv5/dvb-file.c
+++ b/lib/libdvbv5/dvb-file.c
@@ -1282,6 +1282,8 @@ enum dvb_file_formats dvb_parse_format(const char *name)
return FILE_CHANNEL;
if (!strcasecmp(name, "DVBV5"))
return FILE_DVBV5;
+ if (!strcasecmp(name, "VDR"))
+ return FILE_VDR;
fprintf(stderr, "File format %s is unknown\n", name);
return FILE_UNKNOWN;
@@ -1369,6 +1371,10 @@ struct dvb_file *dvb_read_file_format(const char *fname,
case FILE_DVBV5:
dvb_file = dvb_read_file(fname);
break;
+ case FILE_VDR:
+ /* FIXME: add support for VDR input */
+ fprintf(stderr, "Currently, VDR format is supported only for output\n");
+ return NULL;
default:
fprintf(stderr, "Format is not supported\n");
return NULL;
@@ -1400,6 +1406,9 @@ int dvb_write_file_format(const char *fname,
case FILE_DVBV5:
ret = dvb_write_file(fname, dvb_file);
break;
+ case FILE_VDR:
+ ret = dvb_write_format_vdr(fname, dvb_file);
+ break;
default:
return -1;
}
diff --git a/lib/libdvbv5/dvb-vdr-format.c b/lib/libdvbv5/dvb-vdr-format.c
new file mode 100644
index 00000000..1700518f
--- /dev/null
+++ b/lib/libdvbv5/dvb-vdr-format.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2011-2012 - Mauro Carvalho Chehab
+ *
+ * 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 version 2
+ * of the License.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ * Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libdvbv5/dvb-file.h>
+#include <libdvbv5/dvb-v5-std.h>
+
+#define PTABLE(a) .table = a, .size=ARRAY_SIZE(a)
+
+/*
+ * Standard channel.conf format for DVB-T, DVB-C, DVB-S, DVB-S2 and ATSC
+ */
+static const char *vdr_parse_bandwidth[] = {
+ [BANDWIDTH_1_712_MHZ] = "B1712",
+ [BANDWIDTH_5_MHZ] = "B5",
+ [BANDWIDTH_6_MHZ] = "B6",
+ [BANDWIDTH_7_MHZ] = "B7",
+ [BANDWIDTH_8_MHZ] = "B8",
+ [BANDWIDTH_10_MHZ] = "B10",
+ [BANDWIDTH_AUTO] = "B999",
+};
+
+static const char *vdr_parse_code_rate_hp[12] = {
+ [FEC_NONE] = "C0",
+ [FEC_1_2] = "C12",
+ [FEC_2_3] = "C23",
+ [FEC_3_4] = "C34",
+ [FEC_3_5] = "C35",
+ [FEC_4_5] = "C45",
+ [FEC_5_6] = "C56",
+ [FEC_6_7] = "C67",
+ [FEC_7_8] = "C78",
+ [FEC_8_9] = "C89",
+ [FEC_9_10] = "C910",
+ [FEC_AUTO] = "C999",
+};
+
+static const char *vdr_parse_code_rate_lp[12] = {
+ [FEC_NONE] = "D0",
+ [FEC_1_2] = "D12",
+ [FEC_2_3] = "D23",
+ [FEC_3_4] = "D34",
+ [FEC_3_5] = "D35",
+ [FEC_4_5] = "D45",
+ [FEC_5_6] = "D56",
+ [FEC_6_7] = "D67",
+ [FEC_7_8] = "D78",
+ [FEC_8_9] = "D89",
+ [FEC_9_10] = "D910",
+ [FEC_AUTO] = "D999",
+};
+static const char *vdr_parse_guard_interval[] = {
+ [GUARD_INTERVAL_1_4] = "G4",
+ [GUARD_INTERVAL_1_8] = "G8",
+ [GUARD_INTERVAL_1_16] = "G16",
+ [GUARD_INTERVAL_1_32] = "G32",
+ [GUARD_INTERVAL_1_128] = "G128",
+ [GUARD_INTERVAL_19_128] = "G19128",
+ [GUARD_INTERVAL_19_256] = "G19256",
+ [GUARD_INTERVAL_AUTO] = "G999",
+};
+
+static const char *vdr_parse_polarization[] = {
+ [POLARIZATION_OFF] = "",
+ [POLARIZATION_H] = "H",
+ [POLARIZATION_V] = "V",
+ [POLARIZATION_L] = "L",
+ [POLARIZATION_R] = "R",
+};
+
+static const char *vdr_parse_inversion[] = {
+ [INVERSION_OFF] = "I0",
+ [INVERSION_ON] = "I1",
+ [INVERSION_AUTO] = "I999",
+};
+
+static const char *vdr_parse_modulation[] = {
+ [QAM_16] = "M16",
+ [QAM_32] = "M32",
+ [QAM_64] = "M64",
+ [QAM_128] = "M128",
+ [QAM_256] = "M256",
+ [QPSK] = "M2",
+ [PSK_8] = "M5",
+ [APSK_16] = "M6",
+ [APSK_32] = "M7",
+ [VSB_8] = "M10",
+ [VSB_16] = "M11",
+ [DQPSK] = "M12",
+ [QAM_AUTO] = "M999",
+};
+
+static const char *vdr_parse_pilot[] = {
+ [PILOT_OFF] = "N0",
+ [PILOT_ON] = "N1",
+ [PILOT_AUTO] = "N999",
+};
+
+static const char *vdr_parse_rolloff[] = {
+ [ROLLOFF_AUTO] = "O0",
+ [ROLLOFF_20] = "O20",
+ [ROLLOFF_25] = "O25",
+ [ROLLOFF_35] = "O35",
+};
+
+static const char *vdr_parse_trans_mode[] = {
+ [TRANSMISSION_MODE_1K] = "T1",
+ [TRANSMISSION_MODE_2K] = "T2",
+ [TRANSMISSION_MODE_4K] = "T4",
+ [TRANSMISSION_MODE_8K] = "T8",
+ [TRANSMISSION_MODE_16K] = "T16",
+ [TRANSMISSION_MODE_32K] = "T32",
+ [TRANSMISSION_MODE_AUTO] = "T999",
+};
+
+static const char *vdr_parse_hierarchy[] = {
+ [HIERARCHY_1] = "Y1",
+ [HIERARCHY_2] = "Y2",
+ [HIERARCHY_4] = "Y4",
+ [HIERARCHY_AUTO] = "Y999",
+ [HIERARCHY_NONE] = "Y0",
+};
+
+static const char *vdr_parse_delivery_system[] = {
+ [SYS_DVBS] = "S0",
+ [SYS_DVBS2] = "S1",
+ [SYS_DVBT] = "S0",
+ [SYS_DVBT2] = "S1",
+};
+
+/*
+ * The tables below deal only with the "Parameters" part of the VDR
+ * format.
+ */
+static const struct dvb_parse_table sys_atsc_table[] = {
+ { DTV_MODULATION, PTABLE(vdr_parse_modulation) },
+ { DTV_INVERSION, PTABLE(vdr_parse_inversion) },
+};
+
+static const struct dvb_parse_table sys_dvbc_table[] = {
+ { DTV_SYMBOL_RATE, NULL, 0 },
+ { DTV_INNER_FEC, PTABLE(vdr_parse_code_rate_hp) },
+ { DTV_MODULATION, PTABLE(vdr_parse_modulation) },
+ { DTV_INVERSION, PTABLE(vdr_parse_inversion) },
+};
+
+static const struct dvb_parse_table sys_dvbs_table[] = {
+ { DTV_DELIVERY_SYSTEM, PTABLE(vdr_parse_delivery_system) },
+ { DTV_POLARIZATION, PTABLE(vdr_parse_polarization) },
+ { DTV_SYMBOL_RATE, NULL, 0 },
+ { DTV_INNER_FEC, PTABLE(vdr_parse_code_rate_hp) },
+ { DTV_INVERSION, PTABLE(vdr_parse_inversion) },
+};
+
+static const struct dvb_parse_table sys_dvbs2_table[] = {
+ { DTV_DELIVERY_SYSTEM, PTABLE(vdr_parse_delivery_system) },
+ { DTV_POLARIZATION, PTABLE(vdr_parse_polarization) },
+ { DTV_SYMBOL_RATE, NULL, 0 },
+ { DTV_INNER_FEC, PTABLE(vdr_parse_code_rate_hp) },
+ { DTV_INVERSION, PTABLE(vdr_parse_inversion) },
+ /* DVB-S2 specifics */
+ { DTV_MODULATION, PTABLE(vdr_parse_modulation) },
+ { DTV_PILOT, PTABLE(vdr_parse_pilot) },
+ { DTV_ROLLOFF, PTABLE(vdr_parse_rolloff) },
+ { DTV_STREAM_ID, NULL, },
+};
+
+static const struct dvb_parse_table sys_dvbt_table[] = {
+ { DTV_DELIVERY_SYSTEM, PTABLE(vdr_parse_delivery_system) },
+ { DTV_BANDWIDTH_HZ, PTABLE(vdr_parse_bandwidth) },
+ { DTV_CODE_RATE_HP, PTABLE(vdr_parse_code_rate_hp) },
+ { DTV_CODE_RATE_LP, PTABLE(vdr_parse_code_rate_lp) },
+ { DTV_INVERSION, PTABLE(vdr_parse_inversion) },
+ { DTV_MODULATION, PTABLE(vdr_parse_modulation) },
+ { DTV_TRANSMISSION_MODE, PTABLE(vdr_parse_trans_mode) },
+ { DTV_GUARD_INTERVAL, PTABLE(vdr_parse_guard_interval) },
+ { DTV_HIERARCHY, PTABLE(vdr_parse_hierarchy) },
+};
+
+static const struct dvb_parse_table sys_dvbt2_table[] = {
+ { DTV_DELIVERY_SYSTEM, PTABLE(vdr_parse_delivery_system) },
+ { DTV_BANDWIDTH_HZ, PTABLE(vdr_parse_bandwidth) },
+ { DTV_CODE_RATE_HP, PTABLE(vdr_parse_code_rate_hp) },
+ { DTV_CODE_RATE_LP, PTABLE(vdr_parse_code_rate_lp) },
+ { DTV_INVERSION, PTABLE(vdr_parse_inversion) },
+ { DTV_MODULATION, PTABLE(vdr_parse_modulation) },
+ { DTV_TRANSMISSION_MODE, PTABLE(vdr_parse_trans_mode) },
+ { DTV_GUARD_INTERVAL, PTABLE(vdr_parse_guard_interval) },
+ { DTV_HIERARCHY, PTABLE(vdr_parse_hierarchy) },
+ /* DVB-T2 specifics */
+ { DTV_STREAM_ID, NULL, },
+};
+
+static const struct dvb_parse_file vdr_file_format = {
+ .formats = {
+ {
+ .id = "A",
+ .delsys = SYS_ATSC,
+ PTABLE(sys_atsc_table),
+ }, {
+ .id = "C",
+ .delsys = SYS_DVBC_ANNEX_A,
+ PTABLE(sys_dvbc_table),
+ }, {
+ .id = "S",
+ .delsys = SYS_DVBS,
+ PTABLE(sys_dvbs_table),
+ }, {
+ .id = "S",
+ .delsys = SYS_DVBS2,
+ PTABLE(sys_dvbs2_table),
+ }, {
+ .id = "T",
+ .delsys = SYS_DVBT,
+ PTABLE(sys_dvbt_table),
+ }, {
+ .id = "T",
+ .delsys = SYS_DVBT2,
+ PTABLE(sys_dvbt2_table),
+ }, {
+ NULL, 0, NULL, 0,
+ }
+ }
+};
+
+int dvb_write_format_vdr(const char *fname,
+ struct dvb_file *dvb_file)
+{
+ const struct dvb_parse_file *parse_file = &vdr_file_format;
+ const struct dvb_parse_struct *formats = parse_file->formats;
+ int i, j, line = 0;
+ FILE *fp;
+ const struct dvb_parse_struct *fmt;
+ struct dvb_entry *entry;
+ const struct dvb_parse_table *table;
+ const char *id;
+ uint32_t delsys, freq, data, srate;
+ char err_msg[80];
+
+ fp = fopen(fname, "w");
+ if (!fp) {
+ perror(fname);
+ return -errno;
+ }
+
+ for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) {
+ if (dvb_retrieve_entry_prop(entry, DTV_DELIVERY_SYSTEM, &delsys) < 0)
+ continue;
+
+ for (i = 0; formats[i].delsys != 0; i++) {
+ if (formats[i].delsys == delsys)
+ break;
+ }
+ if (formats[i].delsys == 0) {
+ fprintf(stderr,
+ "WARNING: entry %d: delivery system %d not supported on this format. skipping entry\n",
+ line, delsys);
+ continue;
+ }
+ id = formats[i].id;
+
+ if (!entry->channel) {
+ fprintf(stderr,
+ "WARNING: entry %d: channel name not found. skipping entry\n",
+ line);
+ continue;
+ }
+
+ if (dvb_retrieve_entry_prop(entry, DTV_FREQUENCY, &freq) < 0) {
+ fprintf(stderr,
+ "WARNING: entry %d: frequency not found. skipping entry\n",
+ line);
+ continue;
+ }
+
+ /* Output channel name */
+ fprintf(fp, "%s", entry->channel);
+ if (entry->vchannel)
+ fprintf(fp, ",%s", entry->vchannel);
+
+ /*
+ * Output frequency:
+ * in kHz for terrestrial/cable
+ * in MHz for satellite
+ */
+ fprintf(fp, ":%i:", freq / 1000);
+
+ /* Output modulation parameters */
+ fmt = &formats[i];
+ for (i = 0; i < fmt->size; i++) {
+ table = &fmt->table[i];
+
+ for (j = 0; j < entry->n_props; j++)
+ if (entry->props[j].cmd == table->prop)
+ break;
+
+ if (!table->size || j >= entry->n_props)
+ continue;
+
+ data = entry->props[j].u.data;
+
+ if (table->prop == DTV_BANDWIDTH_HZ) {
+ for (j = 0; j < ARRAY_SIZE(fe_bandwidth_name); j++) {
+ if (fe_bandwidth_name[j] == data) {
+ data = j;
+ break;
+ }
+ }
+ if (j == ARRAY_SIZE(fe_bandwidth_name))
+ data = BANDWIDTH_AUTO;
+ }
+ if (data >= table->size) {
+ sprintf(err_msg,
+ "value not supported");
+ goto error;
+ }
+
+ fprintf(fp, "%s", table->table[data]);
+ }
+
+ /* Output format type */
+ fprintf(fp, ":%s:", id);
+
+ /*
+ * Output satellite location
+ * FIXME: probably require some adjustments to match the
+ * format expected by VDR.
+ */
+ switch(delsys) {
+ case SYS_DVBS:
+ case SYS_DVBS2:
+ fprintf(fp, "%s:", entry->location);
+ }
+
+ /* Output symbol rate */
+ srate = 27500000;
+ switch(delsys) {
+ case SYS_DVBS:
+ case SYS_DVBS2:
+ case SYS_DVBC_ANNEX_A:
+ if (dvb_retrieve_entry_prop(entry, DTV_SYMBOL_RATE, &srate) < 0) {
+ sprintf(err_msg,
+ "symbol rate not found");
+ goto error;
+ }
+ }
+ fprintf(fp, "%d:", srate / 1000);
+
+ /* Output video PID(s) */
+ for (i = 0; i < entry->video_pid_len; i++) {
+ if (i)
+ fprintf(fp,",");
+ fprintf(fp, "%d", entry->video_pid[i]);
+ }
+ if (!i)
+ fprintf(fp, "0");
+ fprintf(fp, ":");
+
+ /* Output audio PID(s) */
+ for (i = 0; i < entry->audio_pid_len; i++) {
+ if (i)
+ fprintf(fp,",");
+ fprintf(fp, "%d", entry->audio_pid[i]);
+ }
+ if (!i)
+ fprintf(fp, "0");
+ fprintf(fp, ":");
+
+ /* FIXME: Output teletex PID(s) */
+ fprintf(fp, "0:");
+
+ /* Output Conditional Access - let VDR discover it */
+ fprintf(fp, "0:");
+
+ /* Output Service ID */
+ fprintf(fp, "%d:", entry->service_id);
+
+ /* Output SID, NID, TID and RID */
+ fprintf(fp, "0:0:0:");
+
+ fprintf(fp, "\n");
+ line++;
+ };
+ fclose (fp);
+ return 0;
+
+error:
+ fprintf(stderr, "ERROR: %s while parsing entry %d of %s\n",
+ err_msg, line, fname);
+ fclose(fp);
+ return -1;
+}

Privacy Policy