zoukankan      html  css  js  c++  java
  • 【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()来设置。

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

  • 相关阅读:
    音乐播放器
    对象的单体模式和面向对象
    箭头函数详解及this指向
    ES6的基础语法
    房贷灵活计算器
    [译文] SQL JOIN,你想知道的应该都有
    [Perl] 删除数组中重复元素
    [Qt] 自定义 滚动条 样式
    nodejs之异步思想
    导致人生失败的31种原因(转自csdn博客)
  • 原文地址:https://www.cnblogs.com/huty/p/8517341.html
Copyright © 2011-2022 走看看