目标
亮度,对比度,色度和饱和度都是常见的视频调节参数,也是GStreamer里面设置色彩平衡的参数。本教程将展示:
如何发现可用的色彩平衡通道
如何改变它们
介绍
《GStreamer基础教程05——集成GUI工具》里面已经解释了GObject接口:应用通过它们来获得特定功能,而不用去管具体的element的实现。
playbin2实现了色彩平衡的接口(gstcolorbalance),这就可以设置色彩平衡了。如果playbin2里面的任何一个element支持了这个接口,playbin2就仅仅简单地把应用的设置传给element,否则就会在pipeline中增加一个色彩平衡的element。
这个接口允许查询可用的色彩平衡通道(gstcolorbalancechannel),包括它们的名字和值得有效区间,然后调整当前的值。
色彩平衡例子
- #include<string.h>
- #include<gst/gst.h>
- #include<gst/interfaces/colorbalance.h>
- typedefstruct_CustomData{
- GstElement*pipeline;
- GMainLoop*loop;
- }CustomData;
- /*Processacolorbalancecommand*/
- staticvoidupdate_color_channel(constgchar*channel_name,gbooleanincrease,GstColorBalance*cb){
- gdoublestep;
- gintvalue;
- GstColorBalanceChannel*channel=NULL;
- constGList*channels,*l;
- /*Retrievethelistofchannelsandlocatetherequestedone*/
- channels=gst_color_balance_list_channels(cb);
- for(l=channels;l!=NULL;l=l->next){
- GstColorBalanceChannel*tmp=(GstColorBalanceChannel*)l->data;
- if(g_strrstr(tmp->label,channel_name)){
- channel=tmp;
- break;
- }
- }
- if(!channel)
- return;
- /*Changethechannel'svalue*/
- step=0.1*(channel->max_value-channel->min_value);
- value=gst_color_balance_get_value(cb,channel);
- if(increase){
- value=(gint)(value+step);
- if(value>channel->max_value)
- value=channel->max_value;
- }else{
- value=(gint)(value-step);
- if(value<channel->min_value)
- value=channel->min_value;
- }
- gst_color_balance_set_value(cb,channel,value);
- }
- /*OutputthecurrentvaluesofallColorBalancechannels*/
- staticvoidprint_current_values(GstElement*pipeline){
- constGList*channels,*l;
- /*OutputColorBalancevalues*/
- channels=gst_color_balance_list_channels(GST_COLOR_BALANCE(pipeline));
- for(l=channels;l!=NULL;l=l->next){
- GstColorBalanceChannel*channel=(GstColorBalanceChannel*)l->data;
- gintvalue=gst_color_balance_get_value(GST_COLOR_BALANCE(pipeline),channel);
- g_print("%s:%3d%%",channel->label,
- 1100*(value-channel->min_value)/(channel->max_value-channel->min_value));
- }
- g_print(" ");
- }
- /*Processkeyboardinput*/
- staticgbooleanhandle_keyboard(GIOChannel*source,GIOConditioncond,CustomData*data){
- gchar*str=NULL;
- if(g_io_channel_read_line(source,&str,NULL,NULL,NULL)!=G_IO_STATUS_NORMAL){
- returnTRUE;
- }
- switch(g_ascii_tolower(str[0])){
- case'c':
- update_color_channel("CONTRAST",g_ascii_isupper(str[0]),GST_COLOR_BALANCE(data->pipeline));
- break;
- case'b':
- update_color_channel("BRIGHTNESS",g_ascii_isupper(str[0]),GST_COLOR_BALANCE(data->pipeline));
- break;
- case'h':
- update_color_channel("HUE",g_ascii_isupper(str[0]),GST_COLOR_BALANCE(data->pipeline));
- break;
- case's':
- update_color_channel("SATURATION",g_ascii_isupper(str[0]),GST_COLOR_BALANCE(data->pipeline));
- break;
- case'q':
- g_main_loop_quit(data->loop);
- break;
- default:
- break;
- }
- g_free(str);
- print_current_values(data->pipeline);
- returnTRUE;
- }
- intmain(intargc,charchar*argv[]){
- CustomDatadata;
- GstStateChangeReturnret;
- GIOChannel*io_stdin;
- /*InitializeGStreamer*/
- gst_init(&argc,&argv);
- /*Initializeourdatastructure*/
- memset(&data,0,sizeof(data));
- /*Printusagemap*/
- g_print(
- "USAGE:Chooseoneofthefollowingoptions,thenpressenter: "
- "'C'toincreasecontrast,'c'todecreasecontrast "
- "'B'toincreasebrightness,'b'todecreasebrightness "
- "'H'toincreasehue,'h'todecreasehue "
- "'S'toincreasesaturation,'s'todecreasesaturation "
- "'Q'toquit ");
- /*Buildthepipeline*/
- data.pipeline=gst_parse_launch("playbin2uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm",NULL);
- /*Addakeyboardwatchsowegetnotifiedofkeystrokes*/
- #ifdef_WIN32
- io_stdin=g_io_channel_win32_new_fd(fileno(stdin));
- #else
- io_stdin=g_io_channel_unix_new(fileno(stdin));
- #endif
- g_io_add_watch(io_stdin,G_IO_IN,(GIOFunc)handle_keyboard,&data);
- /*Startplaying*/
- ret=gst_element_set_state(data.pipeline,GST_STATE_PLAYING);
- if(ret==GST_STATE_CHANGE_FAILURE){
- g_printerr("Unabletosetthepipelinetotheplayingstate. ");
- gst_object_unref(data.pipeline);
- return-1;
- }
- print_current_values(data.pipeline);
- /*CreateaGLibMainLoopandsetittorun*/
- data.loop=g_main_loop_new(NULL,FALSE);
- g_main_loop_run(data.loop);
- /*Freeresources*/
- g_main_loop_unref(data.loop);
- g_io_channel_unref(io_stdin);
- gst_element_set_state(data.pipeline,GST_STATE_NULL);
- gst_object_unref(data.pipeline);
- return0;
- }
工作流程
main()函数非常的简单。用一个playbin2的建立pipeline,注册一个键盘处理函数来监控按键。
- /*OutputthecurrentvaluesofallColorBalancechannels*/
- staticvoidprint_current_values(GstElement*pipeline){
- constGList*channels,*l;
- /*OutputColorBalancevalues*/
- channels=gst_color_balance_list_channels(GST_COLOR_BALANCE(pipeline));
- for(l=channels;l!=NULL;l=l->next){
- GstColorBalanceChannel*channel=(GstColorBalanceChannel*)l->data;
- gintvalue=gst_color_balance_get_value(GST_COLOR_BALANCE(pipeline),channel);
- g_print("%s:%3d%%",channel->label,
- 1100*(value-channel->min_value)/(channel->max_value-channel->min_value));
- }
- g_print(" ");
- }
这个方法展示了如何获得通道的列表并打印所有通道当前的值。这是通过gst_color_balance_list_channels()方法来实现的,它会返回一个GList结构,我们遍历这个结构即可。
在这个列表里面的每一个element都是GstColorBalanceChannel结构,包括通道名,最小值和最大值。然后就可以在每个通道调用gst_color_balance_get_value()方法来获得当前值。
在这个例子中,当前值常常用占最大值的百分比来显示。
- /*Processacolorbalancecommand*/
- staticvoidupdate_color_channel(constgchar*channel_name,gbooleanincrease,GstColorBalance*cb){
- gdoublestep;
- gintvalue;
- GstColorBalanceChannel*channel=NULL;
- constGList*channels,*l;
- /*Retrievethelistofchannelsandlocatetherequestedone*/
- channels=gst_color_balance_list_channels(cb);
- for(l=channels;l!=NULL;l=l->next){
- GstColorBalanceChannel*tmp=(GstColorBalanceChannel*)l->data;
- if(g_strrstr(tmp->label,channel_name)){
- channel=tmp;
- break;
- }
- }
- if(!channel)
- return;
这个方法通过指定通道名来确定通道,然后根据操作增加或者减少值。另外,通道列表的获得后是根据指定的名字来解析获得通道的。很显然,这个列表只应该解析一次,指向通道的指针需要保持在比一个字符串更高效的数据结构中。
- /*Changethechannel'svalue*/
- step=0.1*(channel->max_value-channel->min_value);
- value=gst_color_balance_get_value(cb,channel);
- if(increase){
- value=(gint)(value+step);
- if(value>channel->max_value)
- value=channel->max_value;
- }else{
- value=(gint)(value-step);
- if(value<channel->min_value)
- value=channel->min_value;
- }
- gst_color_balance_set_value(cb,channel,value);
然后就获得当前通道的值,修改它但确保它的值有效,使用gst_color_balance_set_value()来设置。
其它没有什么了。运行一下这个程序实际看一下效果。