mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-23 07:38:16 +00:00
dvbbasebin: also accept DVBv5 channels.conf format
Confirmed working with ISDB-T & ATSC conf files. https://bugzilla.gnome.org/show_bug.cgi?id=764957
This commit is contained in:
parent
f6eeb314d3
commit
dc93c448ca
1 changed files with 353 additions and 14 deletions
|
@ -45,6 +45,319 @@ GST_DEBUG_CATEGORY_EXTERN (dvb_base_bin_debug);
|
|||
* Detect when the file changed on disk
|
||||
*/
|
||||
|
||||
typedef gboolean (*GstDvbV5ChannelsConfPropSetFunction) (GstElement *
|
||||
dvbbasebin, const gchar * property, GKeyFile * kf,
|
||||
const gchar * channel_name, const gchar * key);
|
||||
|
||||
static gint
|
||||
gst_dvb_base_bin_find_string_in_array (const gchar ** array, const gchar * str)
|
||||
{
|
||||
gint i = 0;
|
||||
const gchar *cur;
|
||||
while ((cur = array[i])) {
|
||||
if (strcmp (cur, str) == 0)
|
||||
return i;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dvb_base_bin_conf_set_property_from_string_array (GstElement * dvbbasebin,
|
||||
const gchar * property, GKeyFile * kf, const gchar * channel_name,
|
||||
const gchar * key, const gchar ** strings, gint default_value)
|
||||
{
|
||||
gchar *str;
|
||||
gint v;
|
||||
|
||||
str = g_key_file_get_string (kf, channel_name, key, NULL);
|
||||
v = gst_dvb_base_bin_find_string_in_array (strings, str);
|
||||
if (v == -1) {
|
||||
GST_WARNING_OBJECT (dvbbasebin, "Unexpected value '%s' for property "
|
||||
"'%s', using default: %d", str, property, default_value);
|
||||
v = default_value;
|
||||
}
|
||||
|
||||
g_free (str);
|
||||
g_object_set (dvbbasebin, property, v, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* TODO handle errors when getting keyfile data on all these functions */
|
||||
static gboolean
|
||||
gst_dvb_base_bin_conf_set_string (GstElement * dvbbasebin,
|
||||
const gchar * property, GKeyFile * kf, const gchar * channel_name,
|
||||
const gchar * key)
|
||||
{
|
||||
gchar *str;
|
||||
|
||||
str = g_key_file_get_string (kf, channel_name, key, NULL);
|
||||
g_object_set (dvbbasebin, property, str, NULL);
|
||||
g_free (str);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dvb_base_bin_conf_set_uint (GstElement * dvbbasebin, const gchar * property,
|
||||
GKeyFile * kf, const gchar * channel_name, const gchar * key)
|
||||
{
|
||||
guint64 v;
|
||||
|
||||
v = g_key_file_get_uint64 (kf, channel_name, key, NULL);
|
||||
g_object_set (dvbbasebin, property, (guint) v, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dvb_base_bin_conf_set_int (GstElement * dvbbasebin, const gchar * property,
|
||||
GKeyFile * kf, const gchar * channel_name, const gchar * key)
|
||||
{
|
||||
gint v;
|
||||
|
||||
v = g_key_file_get_integer (kf, channel_name, key, NULL);
|
||||
g_object_set (dvbbasebin, property, v, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dvb_base_bin_conf_set_inversion (GstElement * dvbbasebin,
|
||||
const gchar * property, GKeyFile * kf, const gchar * channel_name,
|
||||
const gchar * key)
|
||||
{
|
||||
gchar *str;
|
||||
gint v;
|
||||
|
||||
str = g_key_file_get_string (kf, channel_name, key, NULL);
|
||||
if (strcmp (str, "AUTO") == 0)
|
||||
v = 2;
|
||||
else if (strcmp (str, "ON") == 0)
|
||||
v = 1;
|
||||
else
|
||||
v = 0; /* OFF */
|
||||
|
||||
g_free (str);
|
||||
g_object_set (dvbbasebin, property, v, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dvb_base_bin_conf_set_guard (GstElement * dvbbasebin,
|
||||
const gchar * property, GKeyFile * kf, const gchar * channel_name,
|
||||
const gchar * key)
|
||||
{
|
||||
const gchar *guards[] = {
|
||||
"32", "16", "8", "4", "auto",
|
||||
"128", "19/128", "19/256",
|
||||
"PN420", "PN595", "PN945", NULL
|
||||
};
|
||||
return gst_dvb_base_bin_conf_set_property_from_string_array (dvbbasebin,
|
||||
property, kf, channel_name, key, guards, 4);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dvb_base_bin_conf_set_trans_mode (GstElement * dvbbasebin,
|
||||
const gchar * property, GKeyFile * kf, const gchar * channel_name,
|
||||
const gchar * key)
|
||||
{
|
||||
const gchar *trans_modes[] = {
|
||||
"2K", "8K", "AUTO", "4K", "1K",
|
||||
"16K", "32K", "C1", "C3780", NULL
|
||||
};
|
||||
return gst_dvb_base_bin_conf_set_property_from_string_array (dvbbasebin,
|
||||
property, kf, channel_name, key, trans_modes, 2);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dvb_base_bin_conf_set_code_rate (GstElement * dvbbasebin,
|
||||
const gchar * property, GKeyFile * kf, const gchar * channel_name,
|
||||
const gchar * key)
|
||||
{
|
||||
const gchar *code_rates[] = {
|
||||
"NONE", "1/2", "2/3", "3/4", "4/5",
|
||||
"5/6", "6/7", "7/8", "8/9", "AUTO",
|
||||
"3/5", "9/10", "2/5", NULL
|
||||
};
|
||||
return gst_dvb_base_bin_conf_set_property_from_string_array (dvbbasebin,
|
||||
property, kf, channel_name, key, code_rates, 9);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dvb_base_bin_conf_set_delsys (GstElement * dvbbasebin,
|
||||
const gchar * property, GKeyFile * kf, const gchar * channel_name,
|
||||
const gchar * key)
|
||||
{
|
||||
const gchar *delsys[] = {
|
||||
"UNDEFINED", "DVBCA", "DVBCB", "DVBT", "DSS",
|
||||
"DVBS", "DVBS2", "DVBH", "ISDBT", "ISDBS",
|
||||
"ISDBC", "ATSC", "ATSCMH", "DTMB", "CMMB",
|
||||
"DAB", "DVBT2", "TURBO", "DVBCC", NULL
|
||||
};
|
||||
return gst_dvb_base_bin_conf_set_property_from_string_array (dvbbasebin,
|
||||
property, kf, channel_name, key, delsys, 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dvb_base_bin_conf_set_modulation (GstElement * dvbbasebin,
|
||||
const gchar * property, GKeyFile * kf, const gchar * channel_name,
|
||||
const gchar * key)
|
||||
{
|
||||
const gchar *modulations[] = {
|
||||
"QPSK", "QAM/16", "QAM/32", "QAM/64",
|
||||
"QAM/128", "QAM/256", "AUTO", "8VSB",
|
||||
"16VSB", "8PSK", "16APSK", "32APSK",
|
||||
"DQPSK", "QAM4NR", NULL
|
||||
};
|
||||
return gst_dvb_base_bin_conf_set_property_from_string_array (dvbbasebin,
|
||||
property, kf, channel_name, key, modulations, 6);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const gchar *conf_property;
|
||||
const gchar *elem_property;
|
||||
GstDvbV5ChannelsConfPropSetFunction set_func;
|
||||
} GstDvbV5ChannelsConfToPropertyMap;
|
||||
|
||||
GstDvbV5ChannelsConfToPropertyMap dvbv5_prop_map[] = {
|
||||
{"SERVICE_ID", "program-numbers", gst_dvb_base_bin_conf_set_string},
|
||||
{"FREQUENCY", "frequency", gst_dvb_base_bin_conf_set_uint},
|
||||
{"BANDWIDTH_HZ", "bandwidth-hz", gst_dvb_base_bin_conf_set_uint},
|
||||
{"INVERSION", "inversion", gst_dvb_base_bin_conf_set_inversion},
|
||||
{"GUARD_INTERVAL", "guard", gst_dvb_base_bin_conf_set_guard},
|
||||
{"TRANSMISSION_MODE", "trans-mode", gst_dvb_base_bin_conf_set_trans_mode},
|
||||
{"ISDBT_LAYER_ENABLED", "isdbt-layer-enabled",
|
||||
gst_dvb_base_bin_conf_set_uint},
|
||||
{"ISDBT_PARTIAL_RECEPTION", "isdbt-partial-reception",
|
||||
gst_dvb_base_bin_conf_set_int},
|
||||
{"ISDBT_SOUND_BROADCASTING", "isdbt-sound-broadcasting",
|
||||
gst_dvb_base_bin_conf_set_int},
|
||||
{"ISDBT_SB_SUBCHANNEL_ID", "isdbt-sb-subchannel-id",
|
||||
gst_dvb_base_bin_conf_set_int},
|
||||
{"ISDBT_SB_SEGMENT_IDX", "isdbt-sb-segment-idx",
|
||||
gst_dvb_base_bin_conf_set_int},
|
||||
{"ISDBT_SB_SEGMENT_COUNT", "isdbt-sb-segment-count", gst_dvb_base_bin_conf_set_int}, /* Range in files start from 0, property starts from 1 */
|
||||
{"ISDBT_LAYERA_FEC", "isdbt-layera-fec", gst_dvb_base_bin_conf_set_code_rate},
|
||||
{"ISDBT_LAYERA_MODULATION", "isdbt-layera-modulation",
|
||||
gst_dvb_base_bin_conf_set_modulation},
|
||||
{"ISDBT_LAYERA_SEGMENT_COUNT", "isdbt-layera-segment-count",
|
||||
gst_dvb_base_bin_conf_set_int},
|
||||
{"ISDBT_LAYERA_TIME_INTERLEAVING", "isdbt-layera-time-interleaving",
|
||||
gst_dvb_base_bin_conf_set_int},
|
||||
{"ISDBT_LAYERB_FEC", "isdbt-layerb-fec", gst_dvb_base_bin_conf_set_code_rate},
|
||||
{"ISDBT_LAYERB_MODULATION", "isdbt-layerb-modulation",
|
||||
gst_dvb_base_bin_conf_set_modulation},
|
||||
{"ISDBT_LAYERB_SEGMENT_COUNT", "isdbt-layerb-segment-count",
|
||||
gst_dvb_base_bin_conf_set_int},
|
||||
{"ISDBT_LAYERB_TIME_INTERLEAVING", "isdbt-layerb-time-interleaving",
|
||||
gst_dvb_base_bin_conf_set_int},
|
||||
{"ISDBT_LAYERC_FEC", "isdbt-layerc-fec", gst_dvb_base_bin_conf_set_code_rate},
|
||||
{"ISDBT_LAYERC_MODULATION", "isdbt-layerc-modulation",
|
||||
gst_dvb_base_bin_conf_set_modulation},
|
||||
{"ISDBT_LAYERC_SEGMENT_COUNT", "isdbt-layerc-segment-count",
|
||||
gst_dvb_base_bin_conf_set_int},
|
||||
{"ISDBT_LAYERC_TIME_INTERLEAVING", "isdbt-layerc-time-interleaving",
|
||||
gst_dvb_base_bin_conf_set_int},
|
||||
{"DELIVERY_SYSTEM", "delsys", gst_dvb_base_bin_conf_set_delsys},
|
||||
{NULL,}
|
||||
};
|
||||
|
||||
static gboolean
|
||||
parse_and_configure_from_v5_channels_conf_file (GstElement * dvbbasebin,
|
||||
const gchar * filename, const gchar * channel_name, GError ** error)
|
||||
{
|
||||
GKeyFile *keyfile;
|
||||
gchar **keys, **keys_p;
|
||||
GError *err = NULL;
|
||||
|
||||
keyfile = g_key_file_new ();
|
||||
if (!g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, &err))
|
||||
goto load_error;
|
||||
|
||||
if (!g_key_file_has_group (keyfile, channel_name))
|
||||
goto unknown_channel;
|
||||
|
||||
keys = g_key_file_get_keys (keyfile, channel_name, NULL, &err);
|
||||
if (!keys)
|
||||
goto no_properties;
|
||||
|
||||
keys_p = keys;
|
||||
while (*keys_p) {
|
||||
const gchar *k = *keys_p;
|
||||
const GstDvbV5ChannelsConfToPropertyMap *map_entry = dvbv5_prop_map;
|
||||
gboolean property_found = FALSE;
|
||||
|
||||
GST_LOG_OBJECT (dvbbasebin, "Setting property %s", k);
|
||||
|
||||
while (map_entry->conf_property) {
|
||||
if (strcmp (map_entry->conf_property, k) == 0) {
|
||||
if (!map_entry->set_func (dvbbasebin, map_entry->elem_property, keyfile,
|
||||
channel_name, k))
|
||||
goto property_error;
|
||||
property_found = TRUE;
|
||||
break;
|
||||
}
|
||||
map_entry++;
|
||||
}
|
||||
|
||||
if (!property_found) {
|
||||
GST_DEBUG_OBJECT (dvbbasebin, "Failed to map channels.conf property "
|
||||
"'%s'", k);
|
||||
}
|
||||
|
||||
keys_p++;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (dvbbasebin, "Succesfully parsed channels file");
|
||||
g_strfreev (keys);
|
||||
g_key_file_unref (keyfile);
|
||||
return TRUE;
|
||||
|
||||
load_error:
|
||||
if ((err->domain == G_FILE_ERROR && err->code == G_FILE_ERROR_NOENT) ||
|
||||
(err->domain == G_KEY_FILE_ERROR
|
||||
&& err->code == G_KEY_FILE_ERROR_NOT_FOUND)) {
|
||||
g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_NOT_FOUND,
|
||||
_("Couldn't find DVB channel configuration file"));
|
||||
} else {
|
||||
g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_READ,
|
||||
_("Couldn't load DVB channel configuration file: %s"), err->message);
|
||||
}
|
||||
g_clear_error (&err);
|
||||
return FALSE;
|
||||
|
||||
unknown_channel:
|
||||
{
|
||||
/* FIXME: is channel name guaranteed to be ASCII or UTF-8? */
|
||||
g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_NOT_FOUND,
|
||||
_("Couldn't find details for DVB channel %s"), channel_name);
|
||||
g_key_file_unref (keyfile);
|
||||
g_clear_error (&err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
no_properties:
|
||||
{
|
||||
/* FIXME: is channel name guaranteed to be ASCII or UTF-8? */
|
||||
g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_NOT_FOUND,
|
||||
_("No properties for the DVB channel %s"), channel_name);
|
||||
g_key_file_unref (keyfile);
|
||||
g_clear_error (&err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
property_error:
|
||||
{
|
||||
/* FIXME: is channel name guaranteed to be ASCII or UTF-8? */
|
||||
g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
|
||||
_("Failed to set properties for the DVB channel %s"), channel_name);
|
||||
g_key_file_unref (keyfile);
|
||||
g_clear_error (&err);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* this will do zap style channels.conf only for the moment */
|
||||
static GHashTable *
|
||||
parse_channels_conf_from_file (GstElement * dvbbasebin, const gchar * filename,
|
||||
|
@ -192,15 +505,13 @@ destroy_channels_hash (GHashTable * channels)
|
|||
g_hash_table_foreach_remove (channels, remove_channel_from_hash, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
set_properties_for_channel (GstElement * dvbbasebin,
|
||||
const gchar * channel_name, GError ** error)
|
||||
static gboolean
|
||||
parse_and_configure_from_channels_conf_file (GstElement * dvbbasebin,
|
||||
const gchar * filename, const gchar * channel_name, GError ** error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GHashTable *channels, *params;
|
||||
gchar *filename;
|
||||
gchar *type;
|
||||
const gchar *adapter;
|
||||
|
||||
/**
|
||||
* Assumptions are made here about a format that is loosely
|
||||
|
@ -213,13 +524,7 @@ set_properties_for_channel (GstElement * dvbbasebin,
|
|||
* g_object_set line and let dvbsrc work his magic out.
|
||||
*/
|
||||
|
||||
filename = g_strdup (g_getenv ("GST_DVB_CHANNELS_CONF"));
|
||||
if (filename == NULL) {
|
||||
filename = g_build_filename (g_get_user_config_dir (),
|
||||
"gstreamer-" GST_API_VERSION, "dvb-channels.conf", NULL);
|
||||
}
|
||||
channels = parse_channels_conf_from_file (dvbbasebin, filename, error);
|
||||
g_free (filename);
|
||||
|
||||
if (!channels)
|
||||
goto beach;
|
||||
|
@ -232,9 +537,6 @@ set_properties_for_channel (GstElement * dvbbasebin,
|
|||
g_object_set (dvbbasebin, "program-numbers",
|
||||
g_hash_table_lookup (params, "sid"), NULL);
|
||||
/* check if it is terrestrial or satellite */
|
||||
adapter = g_getenv ("GST_DVB_ADAPTER");
|
||||
if (adapter)
|
||||
g_object_set (dvbbasebin, "adapter", atoi (adapter), NULL);
|
||||
g_object_set (dvbbasebin, "frequency",
|
||||
atoi (g_hash_table_lookup (params, "frequency")), NULL);
|
||||
type = g_hash_table_lookup (params, "type");
|
||||
|
@ -466,3 +768,40 @@ unknown_channel:
|
|||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
set_properties_for_channel (GstElement * dvbbasebin,
|
||||
const gchar * channel_name, GError ** error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
gchar *filename;
|
||||
const gchar *adapter;
|
||||
|
||||
filename = g_strdup (g_getenv ("GST_DVB_CHANNELS_CONF"));
|
||||
if (filename == NULL) {
|
||||
filename = g_build_filename (g_get_user_config_dir (),
|
||||
"gstreamer-" GST_API_VERSION, "dvb-channels.conf", NULL);
|
||||
}
|
||||
|
||||
/* TODO detect channels.conf file format */
|
||||
|
||||
adapter = g_getenv ("GST_DVB_ADAPTER");
|
||||
if (adapter)
|
||||
g_object_set (dvbbasebin, "adapter", atoi (adapter), NULL);
|
||||
|
||||
if (!(ret =
|
||||
parse_and_configure_from_v5_channels_conf_file (dvbbasebin, filename,
|
||||
channel_name, error))) {
|
||||
/* TODO only fallback if it was a parsing error */
|
||||
|
||||
g_clear_error (error);
|
||||
GST_DEBUG_OBJECT (dvbbasebin, "Resorting to old ZAP format file parsing");
|
||||
|
||||
/* fallback to old format */
|
||||
ret =
|
||||
parse_and_configure_from_channels_conf_file (dvbbasebin, filename,
|
||||
channel_name, error);
|
||||
}
|
||||
g_free (filename);
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue