From 837c23a370f9ff62ce1a33a3b4a390d985c1c9e5 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 9 Aug 2016 14:35:44 +0200 Subject: [PATCH] format: implement more gstreamer -> pinos format --- pinos/gst/gstpinosformat.c | 380 +++++++++++++++++++++++++++++---- pinos/server/daemon.c | 2 - pinos/server/node.c | 4 +- spa/include/spa/audio/format.h | 3 + spa/include/spa/props.h | 3 - spa/lib/audio-raw.c | 20 ++ spa/lib/control.c | 8 +- spa/lib/props.c | 7 +- 8 files changed, 367 insertions(+), 60 deletions(-) diff --git a/pinos/gst/gstpinosformat.c b/pinos/gst/gstpinosformat.c index 296534cbc..3306b9dc9 100644 --- a/pinos/gst/gstpinosformat.c +++ b/pinos/gst/gstpinosformat.c @@ -17,6 +17,8 @@ * Boston, MA 02110-1301, USA. */ +#include + #include #include #include @@ -27,67 +29,355 @@ #include "gstpinosformat.h" +static guint +calc_range_size (const GValue *val) +{ + guint res = 0; + + if (G_VALUE_TYPE (val) == GST_TYPE_LIST) + res += gst_value_list_get_size (val); + else if (G_VALUE_TYPE (val) == GST_TYPE_ARRAY) + res += gst_value_array_get_size (val); + else if (G_VALUE_TYPE (val) == GST_TYPE_INT_RANGE) + res += 2; + else if (G_VALUE_TYPE (val) == GST_TYPE_INT64_RANGE) + res += 2; + else if (G_VALUE_TYPE (val) == GST_TYPE_DOUBLE_RANGE) + res += 2; + else if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION_RANGE) + res += 2; + + return res; +} + +static void +calc_size (GstCapsFeatures *cf, GstStructure *cs, guint *n_infos, guint *n_ranges, guint *n_datas) +{ + guint c; + const GValue *val; + + if (gst_structure_has_name (cs, "video/x-raw")) { + if ((val = gst_structure_get_value (cs, "format"))) { + c = calc_range_size (val); + n_infos[0] += 1; + n_ranges[0] += c; + n_datas[0] += (1 + c) * sizeof (SpaVideoFormat); + } + if ((val = gst_structure_get_value (cs, "width")) || + (val = gst_structure_get_value (cs, "height"))) { + c = calc_range_size (val); + n_infos[0]++; + n_ranges[0] += c; + n_datas[0] += (1 + c) * sizeof (SpaRectangle); + } + if ((val = gst_structure_get_value (cs, "framerate"))) { + c = calc_range_size (val); + n_infos[0]++; + n_ranges[0] += c; + n_datas[0] += (1 + c) * sizeof (SpaFraction); + } + } else if (gst_structure_has_name (cs, "audio/x-raw")) { + if ((val = gst_structure_get_value (cs, "format"))) { + c = calc_range_size (val); + n_infos[0]++; + n_ranges[0] += c; + n_datas[0] += (1 + c) * sizeof (SpaAudioFormat); + } + if ((val = gst_structure_get_value (cs, "layout"))) { + c = calc_range_size (val); + n_infos[0]++; + n_ranges[0] += c; + n_datas[0] += (1 + c) * sizeof (SpaAudioLayout); + } + if ((val = gst_structure_get_value (cs, "rate"))) { + c = calc_range_size (val); + n_infos[0]++; + n_ranges[0] += c; + n_datas[0] += (1 + c) * sizeof (uint32_t); + } + if ((val = gst_structure_get_value (cs, "channels"))) { + c = calc_range_size (val); + n_infos[0]++; + n_ranges[0] += c; + n_datas[0] += (1 + c) * sizeof (uint32_t); + } + } +} + static SpaFormat * convert_1 (GstCapsFeatures *cf, GstStructure *cs) { SpaMemory *mem; - SpaFormat *res = NULL; - const gchar *s; - int i; + SpaFormat *f; + guint size, n_infos = 0, n_ranges = 0, n_datas = 0; + SpaPropInfo *bpi; + SpaPropRangeInfo *bri; + int pi, ri; + void *p; + const GValue *val, *val2; + + calc_size (cf, cs, &n_infos, &n_ranges, &n_datas); + + size = sizeof (SpaFormat); + size += n_infos * sizeof (SpaPropInfo); + size += n_ranges * sizeof (SpaPropRangeInfo); + size += n_datas; + + mem = spa_memory_alloc_size (SPA_MEMORY_POOL_LOCAL, NULL, size); + f = spa_memory_ensure_ptr (mem); + f->mem.mem = mem->mem; + f->mem.offset = 0; + f->mem.size = mem->size; + + bpi = SPA_MEMBER (f, sizeof (SpaFormat), SpaPropInfo); + bri = SPA_MEMBER (bpi, n_infos * sizeof (SpaPropInfo), SpaPropRangeInfo); + p = SPA_MEMBER (bri, n_ranges * sizeof (SpaPropRangeInfo), void); + + pi = ri = 0; + + f->props.n_prop_info = n_infos; + f->props.prop_info = bpi; + f->props.unset_mask = 0; if (gst_structure_has_name (cs, "video/x-raw")) { - SpaVideoRawFormat *f; + f->media_type = SPA_MEDIA_TYPE_VIDEO; + f->media_subtype = SPA_MEDIA_SUBTYPE_RAW; - mem = spa_memory_alloc_size (SPA_MEMORY_POOL_LOCAL, NULL, sizeof (SpaVideoRawFormat)); - f = spa_memory_ensure_ptr (mem); - f->format.mem.mem = mem->mem; - f->format.mem.offset = 0; - f->format.mem.size = mem->size; + val = gst_structure_get_value (cs, "format"); + if (val) { + SpaVideoFormat *sv = p; - spa_video_raw_format_init (f); + spa_video_raw_fill_prop_info (&bpi[pi], + SPA_PROP_ID_VIDEO_FORMAT, + SPA_PTRDIFF (p, f)); - if (!(s = gst_structure_get_string (cs, "format"))) - goto done; - f->info.format = gst_video_format_from_string (s); - if (!gst_structure_get_int (cs, "width", &i)) - goto done; - f->info.size.width = i; - if (!gst_structure_get_int (cs, "height", &i)) - goto done; - f->info.size.height = i; - f->format.props.unset_mask = 0; + if (G_VALUE_TYPE (val) == G_TYPE_STRING) { + *sv = gst_video_format_from_string (g_value_get_string (val)); + p = ++sv; + } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else if (G_VALUE_TYPE (val) == GST_TYPE_ARRAY) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } + pi++; + } + val = gst_structure_get_value (cs, "width"); + val2 = gst_structure_get_value (cs, "height"); + if (val || val2) { + SpaRectangle *sv = p; - res = &f->format; + spa_video_raw_fill_prop_info (&bpi[pi], + SPA_PROP_ID_VIDEO_SIZE, + SPA_PTRDIFF (p, f)); + + if (val && val2 && G_VALUE_TYPE (val) == G_VALUE_TYPE (val2)) { + if (G_VALUE_TYPE (val) == G_TYPE_INT) { + sv->width = g_value_get_int (val); + sv->height = g_value_get_int (val2); + p = ++sv; + bpi[pi].range_type = SPA_PROP_RANGE_TYPE_NONE; + bpi[pi].n_range_values = 0; + bpi[pi].range_values = NULL; + } else if (G_VALUE_TYPE (val) == GST_TYPE_INT_RANGE) { + bpi[pi].range_type = SPA_PROP_RANGE_TYPE_MIN_MAX; + bpi[pi].n_range_values = 2; + bpi[pi].range_values = &bri[ri]; + + bri[ri].name = NULL; + bri[ri].description = NULL; + bri[ri].size = sizeof (SpaRectangle); + bri[ri].value = p; + sv->width = gst_value_get_int_range_min (val); + sv->height = gst_value_get_int_range_min (val2); + p = ++sv; + ri++; + + bri[ri].name = NULL; + bri[ri].description = NULL; + bri[ri].size = sizeof (SpaRectangle); + bri[ri].value = p; + sv->width = gst_value_get_int_range_max (val); + sv->height = gst_value_get_int_range_max (val2); + p = ++sv; + ri++; + + f->props.unset_mask |= (1u << pi); + } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else if (G_VALUE_TYPE (val) == GST_TYPE_ARRAY) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } + } + pi++; + } + val = gst_structure_get_value (cs, "framerate"); + if (val) { + SpaFraction *sv = p; + + spa_video_raw_fill_prop_info (&bpi[pi], + SPA_PROP_ID_VIDEO_FRAMERATE, + SPA_PTRDIFF (p, f)); + + if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION) { + sv->num = gst_value_get_fraction_numerator (val); + sv->denom = gst_value_get_fraction_denominator (val); + p = ++sv; + bpi[pi].range_type = SPA_PROP_RANGE_TYPE_NONE; + bpi[pi].n_range_values = 0; + bpi[pi].range_values = NULL; + } else if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION_RANGE) { + const GValue *min, *max; + + min = gst_value_get_fraction_range_min (val); + max = gst_value_get_fraction_range_max (val); + + bpi[pi].range_type = SPA_PROP_RANGE_TYPE_MIN_MAX; + bpi[pi].n_range_values = 2; + bpi[pi].range_values = &bri[ri]; + + bri[ri].name = NULL; + bri[ri].description = NULL; + bri[ri].size = sizeof (SpaFraction); + bri[ri].value = p; + sv->num = gst_value_get_fraction_numerator (min); + sv->denom = gst_value_get_fraction_denominator (min); + p = ++sv; + ri++; + + bri[ri].name = NULL; + bri[ri].description = NULL; + bri[ri].size = sizeof (SpaFraction); + bri[ri].value = p; + sv->num = gst_value_get_fraction_numerator (max); + sv->denom = gst_value_get_fraction_denominator (max); + p = ++sv; + ri++; + + f->props.unset_mask |= (1u << pi); + } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else if (G_VALUE_TYPE (val) == GST_TYPE_ARRAY) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } + pi++; + } } else if (gst_structure_has_name (cs, "audio/x-raw")) { - SpaAudioRawFormat *f; + f->media_type = SPA_MEDIA_TYPE_AUDIO; + f->media_subtype = SPA_MEDIA_SUBTYPE_RAW; - mem = spa_memory_alloc_size (SPA_MEMORY_POOL_LOCAL, NULL, sizeof (SpaAudioRawFormat)); - f = spa_memory_ensure_ptr (mem); - f->format.mem.mem = mem->mem; - f->format.mem.offset = 0; - f->format.mem.size = mem->size; + val = gst_structure_get_value (cs, "format"); + if (val) { + SpaAudioFormat *sv = p; - spa_audio_raw_format_init (f); + spa_audio_raw_fill_prop_info (&bpi[pi], + SPA_PROP_ID_AUDIO_FORMAT, + SPA_PTRDIFF (p, f)); - if (!(s = gst_structure_get_string (cs, "format"))) - goto done; - f->info.format = gst_audio_format_from_string (s); - if (!(s = gst_structure_get_string (cs, "layout"))) - goto done; - f->info.layout = 0; - if (!gst_structure_get_int (cs, "rate", &i)) - goto done; - f->info.rate = i; - if (!gst_structure_get_int (cs, "channels", &i)) - goto done; - f->info.channels = i; - f->format.props.unset_mask = 0; + if (G_VALUE_TYPE (val) == G_TYPE_STRING) { + *sv = gst_audio_format_from_string (g_value_get_string (val)); + p = ++sv; + } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else if (G_VALUE_TYPE (val) == GST_TYPE_ARRAY) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } + pi++; + } + val = gst_structure_get_value (cs, "layout"); + if (val) { + SpaAudioLayout *sv = p; - res = &f->format; + spa_audio_raw_fill_prop_info (&bpi[pi], + SPA_PROP_ID_AUDIO_LAYOUT, + SPA_PTRDIFF (p, f)); + + if (G_VALUE_TYPE (val) == G_TYPE_STRING) { + const gchar *s = g_value_get_string (val); + if (!strcmp (s, "interleaved")) + *sv = SPA_AUDIO_LAYOUT_INTERLEAVED; + else if (!strcmp (s, "non-interleaved")) + *sv = SPA_AUDIO_LAYOUT_NON_INTERLEAVED; + p = ++sv; + } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else if (G_VALUE_TYPE (val) == GST_TYPE_ARRAY) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } + pi++; + } + val = gst_structure_get_value (cs, "rate"); + if (val) { + uint32_t *sv = p; + + spa_audio_raw_fill_prop_info (&bpi[pi], + SPA_PROP_ID_AUDIO_RATE, + SPA_PTRDIFF (p, f)); + + if (G_VALUE_TYPE (val) == G_TYPE_INT) { + *sv = g_value_get_int (val); + p = ++sv; + } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else if (G_VALUE_TYPE (val) == GST_TYPE_ARRAY) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } + pi++; + } + val = gst_structure_get_value (cs, "channels"); + if (val) { + uint32_t *sv = p; + + spa_audio_raw_fill_prop_info (&bpi[pi], + SPA_PROP_ID_AUDIO_CHANNELS, + SPA_PTRDIFF (p, f)); + + if (G_VALUE_TYPE (val) == G_TYPE_INT) { + *sv = g_value_get_int (val); + p = ++sv; + } else if (G_VALUE_TYPE (val) == GST_TYPE_LIST) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else if (G_VALUE_TYPE (val) == GST_TYPE_ARRAY) { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } else { + fprintf (stderr, "implement me\n"); + f->props.unset_mask |= (1u << pi); + } + pi++; + } } - -done: - return res; + return f; } SpaFormat * diff --git a/pinos/server/daemon.c b/pinos/server/daemon.c index 5e9ffb326..858404177 100644 --- a/pinos/server/daemon.c +++ b/pinos/server/daemon.c @@ -185,13 +185,11 @@ no_node: static void on_port_added (PinosNode *node, PinosPort *port, PinosClient *client) { - pinos_client_add_object (client, G_OBJECT (port)); } static void on_port_removed (PinosNode *node, PinosPort *port, PinosClient *client) { - pinos_client_remove_object (client, G_OBJECT (port)); } static gboolean diff --git a/pinos/server/node.c b/pinos/server/node.c index 5de503131..d33393d85 100644 --- a/pinos/server/node.c +++ b/pinos/server/node.c @@ -514,7 +514,7 @@ pinos_node_class_init (PinosNodeClass * klass) NULL, g_cclosure_marshal_generic, G_TYPE_NONE, - 0, + 1, PINOS_TYPE_PORT); signals[SIGNAL_PORT_REMOVED] = g_signal_new ("port-removed", G_TYPE_FROM_CLASS (klass), @@ -524,7 +524,7 @@ pinos_node_class_init (PinosNodeClass * klass) NULL, g_cclosure_marshal_generic, G_TYPE_NONE, - 0, + 1, PINOS_TYPE_PORT); node_class->set_state = node_set_state; diff --git a/spa/include/spa/audio/format.h b/spa/include/spa/audio/format.h index 8463f89dc..f4198c4f7 100644 --- a/spa/include/spa/audio/format.h +++ b/spa/include/spa/audio/format.h @@ -48,6 +48,9 @@ SpaResult spa_audio_raw_format_init (SpaAudioRawFormat *format); SpaResult spa_audio_raw_format_parse (const SpaFormat *format, SpaAudioRawFormat *rawformat); +SpaResult spa_audio_raw_fill_prop_info (SpaPropInfo *info, + SpaPropIdAudio id, + size_t offset); #ifdef __cplusplus } /* extern "C" */ diff --git a/spa/include/spa/props.h b/spa/include/spa/props.h index 616adc760..87429e87c 100644 --- a/spa/include/spa/props.h +++ b/spa/include/spa/props.h @@ -126,9 +126,6 @@ typedef struct { * @range_values: array of possible values * @tags: extra tags, NULL terminated * @offset: offset in structure with data - * @mask_offset: offset in structure for the mask - * @unset_mask: mask to clear when value is set - * @priv: extra private data */ typedef struct { uint32_t id; diff --git a/spa/lib/audio-raw.c b/spa/lib/audio-raw.c index 7a3418860..d1828b750 100644 --- a/spa/lib/audio-raw.c +++ b/spa/lib/audio-raw.c @@ -234,3 +234,23 @@ fallback: return res; } + +SpaResult +spa_audio_raw_fill_prop_info (SpaPropInfo *info, + SpaPropIdAudio id, + size_t offset) +{ + unsigned int i; + + if (info == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + for (i = 0; i < SPA_N_ELEMENTS (raw_format_prop_info); i++) { + if (raw_format_prop_info[i].id == id) { + memcpy (info, &raw_format_prop_info[i], sizeof (SpaPropInfo)); + info->offset = offset; + return SPA_RESULT_OK; + } + } + return SPA_RESULT_INVALID_PROPERTY_INDEX; +} diff --git a/spa/lib/control.c b/spa/lib/control.c index 2da965bf6..386ceda0a 100644 --- a/spa/lib/control.c +++ b/spa/lib/control.c @@ -72,10 +72,10 @@ typedef struct { */ SpaResult spa_control_init_data (SpaControl *control, - void *data, - size_t size, - int *fds, - unsigned int n_fds) + void *data, + size_t size, + int *fds, + unsigned int n_fds) { SpaStackControl *sc = SSC (control); diff --git a/spa/lib/props.c b/spa/lib/props.c index 9613aba10..856eeb6fe 100644 --- a/spa/lib/props.c +++ b/spa/lib/props.c @@ -47,7 +47,7 @@ spa_props_set_prop (SpaProps *props, if (info->offset != 0) memcpy ((uint8_t*)props + info->offset, value->value, value->size); - props->unset_mask &= ~(1 << index); + props->unset_mask &= ~(1u << index); return SPA_RESULT_OK; } @@ -68,8 +68,7 @@ spa_props_get_prop (const SpaProps *props, info = &props->prop_info[index]; if ((info->flags & SPA_PROP_FLAG_READABLE) == 0) return SPA_RESULT_INVALID_PROPERTY_ACCESS; - - if (props->unset_mask & (1 << index)) + if (props->unset_mask & (1u << index)) return SPA_RESULT_PROPERTY_UNSET; value->type = info->type; @@ -106,7 +105,7 @@ spa_props_copy (const SpaProps *src, if (info->offset) memcpy ((uint8_t*)dest + info->offset, value.value, value.size); - dest->unset_mask &= ~(1 << i); + dest->unset_mask &= ~(1u << i); } return SPA_RESULT_OK; }