static void int_range_rvalue2gvalue(VALUE value, GValue *result) { GValue *val; val = RVAL2GOBJ(value); gst_value_set_int_range(result, gst_value_get_int_range_min(val), gst_value_get_int_range_max(val)); }
static VALUE int_range_set_max(VALUE self, VALUE max) { GValue *value; value = RVAL2GOBJ(self); gst_value_set_int_range(value, gst_value_get_int_range_min(value), NUM2INT(max)); return Qnil; }
static void transform_value (GValue * dest, const GValue * src, GstPadDirection dir) { g_value_init (dest, G_VALUE_TYPE (src)); if (G_VALUE_HOLDS_INT (src)) { int x; x = g_value_get_int (src); if (dir == GST_PAD_SINK) { g_value_set_int (dest, x / 2); } else { g_value_set_int (dest, x * 2); } } else if (GST_VALUE_HOLDS_INT_RANGE (src)) { int min, max; min = gst_value_get_int_range_min (src); max = gst_value_get_int_range_max (src); if (dir == GST_PAD_SINK) { min = (min + 1) / 2; if (max == G_MAXINT) { max = G_MAXINT / 2; } else { max = (max + 1) / 2; } } else { if (max > G_MAXINT / 2) { max = G_MAXINT; } else { max = max * 2; } if (min > G_MAXINT / 2) { min = G_MAXINT; } else { min = min * 2; } } gst_value_set_int_range (dest, min, max); } else { /* FIXME */ g_warning ("case not handled"); g_value_set_int (dest, 100); } }
/* caps must be writable */ static void gst_opus_dec_caps_extend_channels_options (GstCaps * caps) { unsigned n; int channels; for (n = 0; n < gst_caps_get_size (caps); ++n) { GstStructure *s = gst_caps_get_structure (caps, n); if (gst_structure_get_int (s, "channels", &channels)) { if (channels == 1 || channels == 2) { GValue v = { 0 }; g_value_init (&v, GST_TYPE_INT_RANGE); gst_value_set_int_range (&v, 1, 2); gst_structure_set_value (s, "channels", &v); g_value_unset (&v); } } } }
static GstStructure *gst_avdtp_sink_parse_mpeg_caps( GstAvdtpSink *self, mpeg_capabilities_t *mpeg) { GstStructure *structure; GValue *value; GValue *list; gboolean valid_layer = FALSE; gboolean mono, stereo; if (!mpeg) return NULL; GST_LOG_OBJECT(self, "parsing mpeg caps"); structure = gst_structure_empty_new("audio/mpeg"); value = g_new0(GValue, 1); g_value_init(value, G_TYPE_INT); list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); g_value_set_int(value, 1); gst_value_list_prepend_value(list, value); g_value_set_int(value, 2); gst_value_list_prepend_value(list, value); gst_structure_set_value(structure, "mpegversion", list); g_free(list); /* layer */ GST_LOG_OBJECT(self, "setting mpeg layer"); list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); if (mpeg->layer & BT_MPEG_LAYER_1) { g_value_set_int(value, 1); gst_value_list_prepend_value(list, value); valid_layer = TRUE; } if (mpeg->layer & BT_MPEG_LAYER_2) { g_value_set_int(value, 2); gst_value_list_prepend_value(list, value); valid_layer = TRUE; } if (mpeg->layer & BT_MPEG_LAYER_3) { g_value_set_int(value, 3); gst_value_list_prepend_value(list, value); valid_layer = TRUE; } if (list) { gst_structure_set_value(structure, "layer", list); g_free(list); list = NULL; } if (!valid_layer) { gst_structure_free(structure); g_free(value); return NULL; } /* rate */ GST_LOG_OBJECT(self, "setting mpeg rate"); list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_48000) { g_value_set_int(value, 48000); gst_value_list_prepend_value(list, value); } if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_44100) { g_value_set_int(value, 44100); gst_value_list_prepend_value(list, value); } if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_32000) { g_value_set_int(value, 32000); gst_value_list_prepend_value(list, value); } if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_24000) { g_value_set_int(value, 24000); gst_value_list_prepend_value(list, value); } if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_22050) { g_value_set_int(value, 22050); gst_value_list_prepend_value(list, value); } if (mpeg->frequency & BT_MPEG_SAMPLING_FREQ_16000) { g_value_set_int(value, 16000); gst_value_list_prepend_value(list, value); } g_value_unset(value); if (list) { gst_structure_set_value(structure, "rate", list); g_free(list); list = NULL; } /* channels */ GST_LOG_OBJECT(self, "setting mpeg channels"); mono = FALSE; stereo = FALSE; if (mpeg->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) mono = TRUE; if ((mpeg->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) || (mpeg->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) || (mpeg->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)) stereo = TRUE; if (mono && stereo) { g_value_init(value, GST_TYPE_INT_RANGE); gst_value_set_int_range(value, 1, 2); } else { g_value_init(value, G_TYPE_INT); if (mono) g_value_set_int(value, 1); else if (stereo) g_value_set_int(value, 2); else { GST_ERROR_OBJECT(self, "Unexpected number of channels"); g_value_set_int(value, 0); } } gst_structure_set_value(structure, "channels", value); g_free(value); return structure; }
static GstStructure *gst_avdtp_sink_parse_sbc_caps( GstAvdtpSink *self, sbc_capabilities_t *sbc) { GstStructure *structure; GValue *value; GValue *list; gboolean mono, stereo; structure = gst_structure_empty_new("audio/x-sbc"); value = g_value_init(g_new0(GValue, 1), G_TYPE_STRING); /* mode */ list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) { g_value_set_static_string(value, "mono"); gst_value_list_prepend_value(list, value); } if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) { g_value_set_static_string(value, "stereo"); gst_value_list_prepend_value(list, value); } if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) { g_value_set_static_string(value, "dual"); gst_value_list_prepend_value(list, value); } if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) { g_value_set_static_string(value, "joint"); gst_value_list_prepend_value(list, value); } g_value_unset(value); if (list) { gst_structure_set_value(structure, "mode", list); g_free(list); list = NULL; } /* subbands */ list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); value = g_value_init(value, G_TYPE_INT); if (sbc->subbands & BT_A2DP_SUBBANDS_4) { g_value_set_int(value, 4); gst_value_list_prepend_value(list, value); } if (sbc->subbands & BT_A2DP_SUBBANDS_8) { g_value_set_int(value, 8); gst_value_list_prepend_value(list, value); } g_value_unset(value); if (list) { gst_structure_set_value(structure, "subbands", list); g_free(list); list = NULL; } /* blocks */ value = g_value_init(value, G_TYPE_INT); list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_16) { g_value_set_int(value, 16); gst_value_list_prepend_value(list, value); } if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_12) { g_value_set_int(value, 12); gst_value_list_prepend_value(list, value); } if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_8) { g_value_set_int(value, 8); gst_value_list_prepend_value(list, value); } if (sbc->block_length & BT_A2DP_BLOCK_LENGTH_4) { g_value_set_int(value, 4); gst_value_list_prepend_value(list, value); } g_value_unset(value); if (list) { gst_structure_set_value(structure, "blocks", list); g_free(list); list = NULL; } /* allocation */ g_value_init(value, G_TYPE_STRING); list = g_value_init(g_new0(GValue,1), GST_TYPE_LIST); if (sbc->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) { g_value_set_static_string(value, "loudness"); gst_value_list_prepend_value(list, value); } if (sbc->allocation_method & BT_A2DP_ALLOCATION_SNR) { g_value_set_static_string(value, "snr"); gst_value_list_prepend_value(list, value); } g_value_unset(value); if (list) { gst_structure_set_value(structure, "allocation", list); g_free(list); list = NULL; } /* rate */ g_value_init(value, G_TYPE_INT); list = g_value_init(g_new0(GValue, 1), GST_TYPE_LIST); if (sbc->frequency & BT_SBC_SAMPLING_FREQ_48000) { g_value_set_int(value, 48000); gst_value_list_prepend_value(list, value); } if (sbc->frequency & BT_SBC_SAMPLING_FREQ_44100) { g_value_set_int(value, 44100); gst_value_list_prepend_value(list, value); } if (sbc->frequency & BT_SBC_SAMPLING_FREQ_32000) { g_value_set_int(value, 32000); gst_value_list_prepend_value(list, value); } if (sbc->frequency & BT_SBC_SAMPLING_FREQ_16000) { g_value_set_int(value, 16000); gst_value_list_prepend_value(list, value); } g_value_unset(value); if (list) { gst_structure_set_value(structure, "rate", list); g_free(list); list = NULL; } /* bitpool */ value = g_value_init(value, GST_TYPE_INT_RANGE); gst_value_set_int_range(value, MIN(sbc->min_bitpool, TEMPLATE_MAX_BITPOOL), MIN(sbc->max_bitpool, TEMPLATE_MAX_BITPOOL)); gst_structure_set_value(structure, "bitpool", value); g_value_unset(value); /* channels */ mono = FALSE; stereo = FALSE; if (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) mono = TRUE; if ((sbc->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) || (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) || (sbc->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO)) stereo = TRUE; if (mono && stereo) { g_value_init(value, GST_TYPE_INT_RANGE); gst_value_set_int_range(value, 1, 2); } else { g_value_init(value, G_TYPE_INT); if (mono) g_value_set_int(value, 1); else if (stereo) g_value_set_int(value, 2); else { GST_ERROR_OBJECT(self, "Unexpected number of channels"); g_value_set_int(value, 0); } } gst_structure_set_value(structure, "channels", value); g_free(value); return structure; }
static GstCaps * gst_opus_enc_sink_getcaps (GstAudioEncoder * benc) { GstOpusEnc *enc; GstCaps *caps; GstCaps *peercaps = NULL; GstCaps *intersect = NULL; guint i; gboolean allow_multistream; enc = GST_OPUS_ENC (benc); GST_DEBUG_OBJECT (enc, "sink getcaps"); peercaps = gst_pad_peer_get_caps (GST_AUDIO_ENCODER_SRC_PAD (benc)); if (!peercaps) { GST_DEBUG_OBJECT (benc, "No peercaps, returning template sink caps"); return gst_caps_copy (gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SINK_PAD (benc))); } intersect = gst_caps_intersect (peercaps, gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (benc))); gst_caps_unref (peercaps); if (gst_caps_is_empty (intersect)) return intersect; allow_multistream = FALSE; for (i = 0; i < gst_caps_get_size (intersect); i++) { GstStructure *s = gst_caps_get_structure (intersect, i); gboolean multistream; if (gst_structure_get_boolean (s, "multistream", &multistream)) { if (multistream) { allow_multistream = TRUE; } } else { allow_multistream = TRUE; } } gst_caps_unref (intersect); caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SINK_PAD (benc))); if (!allow_multistream) { GValue range = { 0 }; g_value_init (&range, GST_TYPE_INT_RANGE); gst_value_set_int_range (&range, 1, 2); for (i = 0; i < gst_caps_get_size (caps); i++) { GstStructure *s = gst_caps_get_structure (caps, i); gst_structure_set_value (s, "channels", &range); } g_value_unset (&range); } GST_DEBUG_OBJECT (enc, "Returning caps: %" GST_PTR_FORMAT, caps); return caps; }
static VALUE int_range_set(VALUE self, VALUE min, VALUE max) { gst_value_set_int_range(RVAL2GOBJ(self), NUM2INT(min), NUM2INT(max)); return Qnil; }
static VALUE int_range_initialize(VALUE self, VALUE min, VALUE max) { gst_value_set_int_range(DATA_PTR(self), NUM2INT(min), NUM2INT(max)); return Qnil; }
GstCaps* convert_videoformatsdescription_to_caps (const std::vector<tcam::VideoFormatDescription>& descriptions) { GstCaps* caps = gst_caps_new_empty(); for (const auto& desc : descriptions) { if (desc.get_fourcc() == 0) { tcam_info("Format has empty fourcc. Ignoring"); continue; } const char* caps_string = tcam_fourcc_to_gst_1_0_caps_string(desc.get_fourcc()); if (caps_string == nullptr) { tcam_warning("Format has empty caps string. Ignoring %s", tcam::fourcc_to_description(desc.get_fourcc())); continue; } // tcam_error("Found '%s' pixel format string", caps_string); std::vector<struct tcam_resolution_description> res = desc.get_resolutions(); for (const auto& r : res) { int min_width = r.min_size.width; int min_height = r.min_size.height; int max_width = r.max_size.width; int max_height = r.max_size.height; if (r.type == TCAM_RESOLUTION_TYPE_RANGE) { std::vector<struct tcam_image_size> framesizes = tcam::get_standard_resolutions(r.min_size, r.max_size); // check if min/max are already in the vector. // some devices return std resolutions as max if (r.min_size != framesizes.front()) { framesizes.insert(framesizes.begin(), r.min_size); } if (r.max_size != framesizes.back()) { framesizes.push_back(r.max_size); } for (const auto& reso : framesizes) { GstStructure* structure = gst_structure_from_string (caps_string, NULL); std::vector<double> framerates = desc.get_framerates(reso); if (framerates.empty()) { // tcam_log(TCAM_LOG_WARNING, "No available framerates. Ignoring format."); continue; } GValue fps_list = G_VALUE_INIT; g_value_init(&fps_list, GST_TYPE_LIST); for (const auto& f : framerates) { int frame_rate_numerator; int frame_rate_denominator; gst_util_double_to_fraction(f, &frame_rate_numerator, &frame_rate_denominator); if ((frame_rate_denominator == 0) || (frame_rate_numerator == 0)) { continue; } GValue fraction = G_VALUE_INIT; g_value_init(&fraction, GST_TYPE_FRACTION); gst_value_set_fraction(&fraction, frame_rate_numerator, frame_rate_denominator); gst_value_list_append_value(&fps_list, &fraction); g_value_unset(&fraction); } gst_structure_set (structure, "width", G_TYPE_INT, reso.width, "height", G_TYPE_INT, reso.height, NULL); gst_structure_take_value(structure, "framerate", &fps_list); gst_caps_append_structure (caps, structure); } // finally also add the range to allow unusual settings like 1920x96@90fps GstStructure* structure = gst_structure_from_string (caps_string, NULL); GValue w = G_VALUE_INIT; g_value_init(&w, GST_TYPE_INT_RANGE); gst_value_set_int_range(&w, min_width, max_width); GValue h = G_VALUE_INIT; g_value_init(&h, GST_TYPE_INT_RANGE); gst_value_set_int_range(&h, min_height, max_height); std::vector<double> fps = desc.get_frame_rates(r); if (fps.empty()) { // GST_ERROR("Could not find any framerates for format"); continue; } int fps_min_num; int fps_min_den; int fps_max_num; int fps_max_den; gst_util_double_to_fraction(*std::min_element(fps.begin(), fps.end()), &fps_min_num, &fps_min_den); gst_util_double_to_fraction(*std::max_element(fps.begin(), fps.end()), &fps_max_num, &fps_max_den); GValue f = G_VALUE_INIT; g_value_init(&f, GST_TYPE_FRACTION_RANGE); gst_value_set_fraction_range_full(&f, fps_min_num, fps_min_den, fps_max_num, fps_max_den); gst_structure_set_value(structure, "width", &w); gst_structure_set_value(structure,"height", &h); gst_structure_set_value(structure,"framerate", &f); gst_caps_append_structure(caps, structure); } else { GstStructure* structure = gst_structure_from_string (caps_string, NULL); fill_structure_fixed_resolution(structure, desc, r); gst_caps_append_structure (caps, structure); } } } return caps; }
static gboolean gst_video_crop_transform_dimension_value (const GValue * src_val, gint delta, GValue * dest_val, GstPadDirection direction, gboolean dynamic) { gboolean ret = TRUE; if (G_VALUE_HOLDS_INT (src_val)) { gint ival = g_value_get_int (src_val); ival = gst_video_crop_transform_dimension (ival, delta); if (dynamic) { if (direction == GST_PAD_SRC) { if (ival == G_MAXINT) { g_value_init (dest_val, G_TYPE_INT); g_value_set_int (dest_val, ival); } else { g_value_init (dest_val, GST_TYPE_INT_RANGE); gst_value_set_int_range (dest_val, ival, G_MAXINT); } } else { if (ival == 1) { g_value_init (dest_val, G_TYPE_INT); g_value_set_int (dest_val, ival); } else { g_value_init (dest_val, GST_TYPE_INT_RANGE); gst_value_set_int_range (dest_val, 1, ival); } } } else { g_value_init (dest_val, G_TYPE_INT); g_value_set_int (dest_val, ival); } } else if (GST_VALUE_HOLDS_INT_RANGE (src_val)) { gint min = gst_value_get_int_range_min (src_val); gint max = gst_value_get_int_range_max (src_val); min = gst_video_crop_transform_dimension (min, delta); max = gst_video_crop_transform_dimension (max, delta); if (dynamic) { if (direction == GST_PAD_SRC) max = G_MAXINT; else min = 1; } if (min == max) { g_value_init (dest_val, G_TYPE_INT); g_value_set_int (dest_val, min); } else { g_value_init (dest_val, GST_TYPE_INT_RANGE); gst_value_set_int_range (dest_val, min, max); } } else if (GST_VALUE_HOLDS_LIST (src_val)) { gint i; g_value_init (dest_val, GST_TYPE_LIST); for (i = 0; i < gst_value_list_get_size (src_val); ++i) { const GValue *list_val; GValue newval = { 0, }; list_val = gst_value_list_get_value (src_val, i); if (gst_video_crop_transform_dimension_value (list_val, delta, &newval, direction, dynamic)) gst_value_list_append_value (dest_val, &newval); g_value_unset (&newval); } if (gst_value_list_get_size (dest_val) == 0) { g_value_unset (dest_val); ret = FALSE; } } else { ret = FALSE; } return ret; }