【GStreamer开发】GStreamer播放教程05——色彩平衡

目标

      亮度,对比度,色度和饱和度都是常见的视频调节参数,也是GStreamer里面设置色彩平衡的参数。本教程将展示:

      如何发现可用的色彩平衡通道

      如何改变它们


介绍

      《GStreamer基础教程05——集成GUI工具》里面已经解释了GObject接口:应用通过它们来获得特定功能,而不用去管具体的element的实现。

      playbin2实现了色彩平衡的接口(gstcolorbalance),这就可以设置色彩平衡了。如果playbin2里面的任何一个element支持了这个接口,playbin2就仅仅简单地把应用的设置传给element,否则就会在pipeline中增加一个色彩平衡的element。

      这个接口允许查询可用的色彩平衡通道(gstcolorbalancechannel),包括它们的名字和值得有效区间,然后调整当前的值。


色彩平衡例子

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #include <string.h>  
  2. #include <gst/gst.h>  
  3. #include <gst/interfaces/colorbalance.h>  
  4.     
  5. typedef struct _CustomData {  
  6.   GstElement *pipeline;  
  7.   GMainLoop *loop;  
  8. } CustomData;  
  9.     
  10. /* Process a color balance command */  
  11. static void update_color_channel (const gchar *channel_name, gboolean increase, GstColorBalance *cb) {  
  12.   gdouble step;  
  13.   gint value;  
  14.   GstColorBalanceChannel *channel = NULL;  
  15.   const GList *channels, *l;  
  16.     
  17.   /* Retrieve the list of channels and locate the requested one */  
  18.   channels = gst_color_balance_list_channels (cb);  
  19.   for (l = channels; l != NULL; l = l->next) {  
  20.     GstColorBalanceChannel *tmp = (GstColorBalanceChannel *)l->data;  
  21.       
  22.     if (g_strrstr (tmp->label, channel_name)) {  
  23.       channel = tmp;  
  24.       break;  
  25.     }  
  26.   }  
  27.   if (!channel)  
  28.     return;  
  29.     
  30.   /* Change the channel's value */  
  31.   step = 0.1 * (channel->max_value - channel->min_value);  
  32.   value = gst_color_balance_get_value (cb, channel);  
  33.   if (increase) {  
  34.     value = (gint)(value + step);  
  35.     if (value > channel->max_value)  
  36.       value = channel->max_value;  
  37.   } else {  
  38.     value = (gint)(value - step);  
  39.     if (value < channel->min_value)  
  40.       value = channel->min_value;  
  41.   }  
  42.   gst_color_balance_set_value (cb, channel, value);  
  43. }  
  44.     
  45. /* Output the current values of all Color Balance channels */  
  46. static void print_current_values (GstElement *pipeline) {  
  47.   const GList *channels, *l;  
  48.     
  49.   /* Output Color Balance values */  
  50.   channels = gst_color_balance_list_channels (GST_COLOR_BALANCE (pipeline));  
  51.   for (l = channels; l != NULL; l = l->next) {  
  52.     GstColorBalanceChannel *channel = (GstColorBalanceChannel *)l->data;  
  53.     gint value = gst_color_balance_get_value (GST_COLOR_BALANCE (pipeline), channel);  
  54.     g_print ("%s: %3d%% ", channel->label,  
  55.         1100 * (value - channel->min_value) / (channel->max_value - channel->min_value));  
  56.   }  
  57.   g_print (" ");  
  58. }  
  59.     
  60. /* Process keyboard input */  
  61. static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) {  
  62.   gchar *str = NULL;  
  63.     
  64.   if (g_io_channel_read_line (source, &str, NULLNULLNULL) != G_IO_STATUS_NORMAL) {  
  65.     return TRUE;  
  66.   }  
  67.     
  68.   switch (g_ascii_tolower (str[0])) {  
  69.   case 'c':  
  70.     update_color_channel ("CONTRAST", g_ascii_isupper (str[0]), GST_COLOR_BALANCE (data->pipeline));  
  71.     break;  
  72.   case 'b':  
  73.     update_color_channel ("BRIGHTNESS", g_ascii_isupper (str[0]), GST_COLOR_BALANCE (data->pipeline));  
  74.     break;  
  75.   case 'h':  
  76.     update_color_channel ("HUE", g_ascii_isupper (str[0]), GST_COLOR_BALANCE (data->pipeline));  
  77.     break;  
  78.   case 's':  
  79.     update_color_channel ("SATURATION", g_ascii_isupper (str[0]), GST_COLOR_BALANCE (data->pipeline));  
  80.     break;  
  81.   case 'q':  
  82.     g_main_loop_quit (data->loop);  
  83.     break;  
  84.   default:  
  85.     break;  
  86.   }  
  87.     
  88.   g_free (str);  
  89.     
  90.   print_current_values (data->pipeline);  
  91.     
  92.   return TRUE;  
  93. }  
  94.     
  95. int main(int argc, charchar *argv[]) {  
  96.   CustomData data;  
  97.   GstStateChangeReturn ret;  
  98.   GIOChannel *io_stdin;  
  99.      
  100.   /* Initialize GStreamer */  
  101.   gst_init (&argc, &argv);  
  102.     
  103.   /* Initialize our data structure */  
  104.   memset (&data, 0sizeof (data));  
  105.     
  106.   /* Print usage map */  
  107.   g_print (  
  108.     "USAGE: Choose one of the following options, then press enter: "  
  109.     " 'C' to increase contrast, 'c' to decrease contrast "  
  110.     " 'B' to increase brightness, 'b' to decrease brightness "  
  111.     " 'H' to increase hue, 'h' to decrease hue "  
  112.     " 'S' to increase saturation, 's' to decrease saturation "  
  113.     " 'Q' to quit ");  
  114.     
  115.   /* Build the pipeline */  
  116.   data.pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm"NULL);  
  117.     
  118.   /* Add a keyboard watch so we get notified of keystrokes */  
  119. #ifdef _WIN32  
  120.   io_stdin = g_io_channel_win32_new_fd (fileno (stdin));  
  121. #else  
  122.   io_stdin = g_io_channel_unix_new (fileno (stdin));  
  123. #endif  
  124.   g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data);  
  125.     
  126.   /* Start playing */  
  127.   ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);  
  128.   if (ret == GST_STATE_CHANGE_FAILURE) {  
  129.     g_printerr ("Unable to set the pipeline to the playing state. ");  
  130.     gst_object_unref (data.pipeline);  
  131.     return -1;  
  132.   }  
  133.   print_current_values (data.pipeline);  
  134.      
  135.   /* Create a GLib Main Loop and set it to run */  
  136.   data.loop = g_main_loop_new (NULL, FALSE);  
  137.   g_main_loop_run (data.loop);  
  138.     
  139.   /* Free resources */  
  140.   g_main_loop_unref (data.loop);  
  141.   g_io_channel_unref (io_stdin);  
  142.   gst_element_set_state (data.pipeline, GST_STATE_NULL);  
  143.   gst_object_unref (data.pipeline);  
  144.   return 0;  
  145. }  

工作流程

      main()函数非常的简单。用一个playbin2的建立pipeline,注册一个键盘处理函数来监控按键。

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /* Output the current values of all Color Balance channels */  
  2. static void print_current_values (GstElement *pipeline) {  
  3.   const GList *channels, *l;  
  4.     
  5.   /* Output Color Balance values */  
  6.   channels = gst_color_balance_list_channels (GST_COLOR_BALANCE (pipeline));  
  7.   for (l = channels; l != NULL; l = l->next) {  
  8.     GstColorBalanceChannel *channel = (GstColorBalanceChannel *)l->data;  
  9.     gint value = gst_color_balance_get_value (GST_COLOR_BALANCE (pipeline), channel);  
  10.     g_print ("%s: %3d%% ", channel->label,  
  11.         1100 * (value - channel->min_value) / (channel->max_value - channel->min_value));  
  12.   }  
  13.   g_print (" ");  
  14. }  

      这个方法展示了如何获得通道的列表并打印所有通道当前的值。这是通过gst_color_balance_list_channels()方法来实现的,它会返回一个GList结构,我们遍历这个结构即可。

      在这个列表里面的每一个element都是GstColorBalanceChannel结构,包括通道名,最小值和最大值。然后就可以在每个通道调用gst_color_balance_get_value()方法来获得当前值。

      在这个例子中,当前值常常用占最大值的百分比来显示。

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /* Process a color balance command */  
  2. static void update_color_channel (const gchar *channel_name, gboolean increase, GstColorBalance *cb) {  
  3.   gdouble step;  
  4.   gint value;  
  5.   GstColorBalanceChannel *channel = NULL;  
  6.   const GList *channels, *l;  
  7.     
  8.   /* Retrieve the list of channels and locate the requested one */  
  9.   channels = gst_color_balance_list_channels (cb);  
  10.   for (l = channels; l != NULL; l = l->next) {  
  11.     GstColorBalanceChannel *tmp = (GstColorBalanceChannel *)l->data;  
  12.       
  13.     if (g_strrstr (tmp->label, channel_name)) {  
  14.       channel = tmp;  
  15.       break;  
  16.     }  
  17.   }  
  18.   if (!channel)  
  19.     return;  

      这个方法通过指定通道名来确定通道,然后根据操作增加或者减少值。另外,通道列表的获得后是根据指定的名字来解析获得通道的。很显然,这个列表只应该解析一次,指向通道的指针需要保持在比一个字符串更高效的数据结构中。

[objc] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. /* Change the channel's value */  
  2. step = 0.1 * (channel->max_value - channel->min_value);  
  3. value = gst_color_balance_get_value (cb, channel);  
  4. if (increase) {  
  5.   value = (gint)(value + step);  
  6.   if (value > channel->max_value)  
  7.     value = channel->max_value;  
  8. else {  
  9.   value = (gint)(value - step);  
  10.   if (value < channel->min_value)  
  11.     value = channel->min_value;  
  12. }  
  13. gst_color_balance_set_value (cb, channel, value);  

      然后就获得当前通道的值,修改它但确保它的值有效,使用gst_color_balance_set_value()来设置。

      其它没有什么了。运行一下这个程序实际看一下效果。

原文地址:https://www.cnblogs.com/huty/p/8517340.html