-v参数
先看一个简单的例子:
gst-launch的pipeline,增加-v参数就可以输出caps的详细信息,包括我们想要的codec_data,那么,这个-v参数是怎么输出这些的,就需要深入跟踪下代码,因为这个输出不受GST_DEBUG的控制,是直接输出到terminal的。
$ gst-launch-1.0 filesrc location=~/h264.mp4 ! qtdemux ! fakesink -v
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
/GstPipeline:pipeline0/GstFakeSink:fakesink0.GstPad:sink: caps = video/x-h264, stream-format=(string)avc, alignment=(string)au, \
level=(string)3.1, profile=(string)high, codec_data=(buffer)0164001fffe100196764001facd9405005ba1000000300100000030320f183196001000568ebecb22c, \
width=(int)1280, height=(int)720, framerate=(fraction)25/1, pixel-aspect-ratio=(fraction)1/1
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
Redistribute latency...
New clock: GstSystemClock
Got EOS from element "pipeline0".
Execution ended after 0:00:00.001151180
Setting pipeline to NULL ...
Freeing pipeline ...
在gst-launch的代码中,-v参数的作用是输出状态信息和属性通知,如果有verbose参数,会先增加deep_notify处理函数:
{"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
N_("Output status information and property notifications"), NULL},
if (verbose) {
deep_notify_id =
gst_element_add_property_deep_notify_watch (pipeline, NULL, TRUE);
}
gst_element_property_deep_notify_cb
gst_element_property_deep_notify_cb
在这里是deep_notify
信号回调函数:
gulong
gst_element_add_property_deep_notify_watch (GstElement * element,
const gchar * property_name, gboolean include_value)
{
const gchar *sep;
gchar *signal_name;
gulong id;
g_return_val_if_fail (GST_IS_ELEMENT (element), 0);
sep = (property_name != NULL) ? "::" : NULL;
signal_name = g_strconcat ("deep-notify", sep, property_name, NULL);
id = g_signal_connect (element, signal_name,
G_CALLBACK (gst_element_property_deep_notify_cb),
GINT_TO_POINTER (include_value));
g_free (signal_name);
return id;
}
跟踪进入gst_element_property_deep_notify_cb函数,gst_message_new_property_notify会先创建新的property消息,然后post message。
gst_message_new_property_notify
gst_message_new_property_notify中构造MESSAGE_PROPERTY_NOTIFY
类型的message,message post之后,就会在gst-launch中接收处理。
GstMessage *
gst_message_new_property_notify (GstObject * src, const gchar * property_name,
GValue * val)
{
GstStructure *structure;
GValue name_val = G_VALUE_INIT;
g_return_val_if_fail (property_name != NULL, NULL);
structure = gst_structure_new_id_empty (GST_QUARK (MESSAGE_PROPERTY_NOTIFY));
g_value_init (&name_val, G_TYPE_STRING);
/* should already be interned, but let's make sure */
g_value_set_static_string (&name_val, g_intern_string (property_name));
gst_structure_id_take_value (structure, GST_QUARK (PROPERTY_NAME), &name_val);
if (val != NULL)
gst_structure_id_take_value (structure, GST_QUARK (PROPERTY_VALUE), val);
return gst_message_new_custom (GST_MESSAGE_PROPERTY_NOTIFY, src, structure);
}
gst-lauch之GST_MESSAGE_PROPERTY_NOTIFY
在gst-launch的中,GST_MESSAGE_PROPERTY_NOTIFY的处理分支,会先解析message的val,然后在最后通过gst_print打印出来,这就是为什么通过增加-v参数就能获取codec_data了。
case GST_MESSAGE_PROPERTY_NOTIFY:{
const GValue *val;
const gchar *name;
GstObject *obj;
gchar *val_str = NULL;
gchar **ex_prop, *obj_name;
if (quiet)
break;
gst_message_parse_property_notify (message, &obj, &name, &val);
/* Let's not print anything for excluded properties... */
ex_prop = exclude_args;
while (ex_prop != NULL && *ex_prop != NULL) {
if (strcmp (name, *ex_prop) == 0)
break;
ex_prop++;
}
if (ex_prop != NULL && *ex_prop != NULL)
break;
obj_name = gst_object_get_path_string (GST_OBJECT (obj));
if (val != NULL) {
if (G_VALUE_HOLDS_STRING (val))
val_str = g_value_dup_string (val);
else if (G_VALUE_TYPE (val) == GST_TYPE_CAPS)
val_str = gst_caps_to_string (g_value_get_boxed (val));
else if (G_VALUE_TYPE (val) == GST_TYPE_TAG_LIST)
val_str = gst_tag_list_to_string (g_value_get_boxed (val));
else if (G_VALUE_TYPE (val) == GST_TYPE_STRUCTURE)
val_str = gst_structure_to_string (g_value_get_boxed (val));
else
val_str = gst_value_serialize (val);
} else {
val_str = g_strdup ("(no value)");
}
gst_print ("%s: %s = %s\n", obj_name, name, val_str);
g_free (obj_name);
g_free (val_str);
break;
同样的,在codec-select的代码中,有deep_notify
信号回调函数gst_object_default_deep_notify:
gst-plugins-base/tests/examples/dynamic/codec-select.c
g_signal_connect (pipeline, "deep_notify",
G_CALLBACK (gst_object_default_deep_notify), NULL);
gst_object_default_deep_notify:
void
gst_object_default_deep_notify (GObject * object, GstObject * orig,
GParamSpec * pspec, gchar ** excluded_props)
{
GValue value = { 0, }; /* the important thing is that value.type = 0 */
gchar *str = NULL;
gchar *name = NULL;
if (pspec->flags & G_PARAM_READABLE) {
/* let's not print these out for excluded properties... */
while (excluded_props != NULL && *excluded_props != NULL) {
if (strcmp (pspec->name, *excluded_props) == 0)
return;
excluded_props++;
}
g_value_init (&value, pspec->value_type);
g_object_get_property (G_OBJECT (orig), pspec->name, &value);
if (G_VALUE_HOLDS_STRING (&value))
str = g_value_dup_string (&value);
else
str = gst_value_serialize (&value);
name = gst_object_get_path_string (orig);
// 打印-v参数
g_print ("%s: %s = %s\n", name, pspec->name, str);
g_free (name);
g_free (str);
g_value_unset (&value);
} else {
name = gst_object_get_path_string (orig);
g_warning ("Parameter %s not readable in %s.", pspec->name, name);
g_free (name);
}
}