libvlc-gtk使用手记
前几天实验室这个破项目非要加上什么流媒体的功能,简单起见使用了VLC来实现,客户端这边就得需要把相关的播放界面整合到现有的界面里面来,之前的客户端UI我都是用GTK实现的,没办法,GTK用得比较多,相对熟练一些就用GTK来做了,没想到要把VLC整到GTK里面来那么麻烦,原生的libvlc是不支持GTK的,需要加一层libvlc-gtk,从网上好不容易下载到了libvlc-gtk的源码,从哪里下的也记不清了,反正就是零散地几个文件,没有README甚至连Makefile都没有,没办法首先得先写个Makefile把它编译一下,libvlc-gtk一共有八个文件,Makefile如下:
libvlc_objs=gtk-libvlc-media.o gtk-libvlc-instance.o gtk-libvlc-media-player.o libvlc_cflags=`pkg-config --cflags gtk+-2.0 libvlc` -I../ -fPIC -shared libvlc_ldflag=-fPIC -shared `pkg-config --libs gtk+-2.0 libvlc` libvlc_so=libvlcgtk.so %.o:%.c gcc -o $@ -c $< -g $(libvlc_cflags) $(libvlc_so):$(libvlc_objs) gcc $(libvlc_ldflag) -o $(libvlc_so) $(libvlc_objs) install: install libvlcgtk.so /usr/local/lib/libvlcgtk.so ldconfig clean: rm -f *.o *.so
当然这样在编译的时候还会有些问题,libvlc-gtk理所当然需要libvlc的支持,而libvlc各个版本之间的函数有一点点不一样,所以就需要进行条件编译,而libvlc-gtk把条件编译选项都写好了,用了自定义的几个版本号的宏来检测相关的版本,如果这几个宏没有定义便会在编译时报错,相关代码如下:
// Set default value for LIBVLC_VERSION_MAJOR #ifndef LIBVLC_VERSION_MAJOR #error "LIBVLC_VERSION_MAJOR must be defined." #endif // Set default value for LIBVLC_VERSION_MINOR #ifndef LIBVLC_VERSION_MINOR #error "LIBVLC_VERSION_MINOR must be defined." #endif // Set default value for LIBVLC_VERSION_REVISION #ifndef LIBVLC_VERSION_REVISION #error "LIBVLC_VERSION_REVISION must be defined." #endif
检查了一下相关的函数后我自己在gtk-libvlc-include.h里面定义了这几个宏:
#define LIBVLC_VERSION_MAJOR 0 #define LIBVLC_VERSION_MINOR 9 #define LIBVLC_VERSION_REVISION 0
当然也可以通过其它的方式定义,如在Makefile里面,我这里图省事就直接在这里写死了。
libvlc-gtk的API使用起来也很简单,下面的一段代码是用来播放在5004端口接收到的UDP媒体流:
#define MRL rtp://:5004 int player_init() { GtkLibvlcInstance *inst; GtkLibvlcMedia *vlc_media; GtkWidget *player; GError *error = NULL; GtkWindow *window; /* load the vlc instance */ inst = gtk_libvlc_instance_new(NULL, NULL, &error); return_if_fail(error); /* creat a new media item */ vlc_media = gtk_libvlc_media_new(MRL); /* creat a media player */ player = gtk_libvlc_media_player_new(inst, &error); gtk_widget_set_usize(media->player, 600, 500); return_if_fail(error); gtk_container_add(GTK_CONTAINER(window), player); g_signal_connect(G_OBJECT(GTK_WIDGET(media->player)), "expose_event", G_CALLBACK(draw_able_expose), NULL); /* the player widget must be realized before playing */ gtk_widget_realize(media->player); /* add a media to the player */ gtk_libvlc_media_player_add_media( GTK_LIBVLC_MEDIA_PLAYER(media->player), vlc_media); gtk_libvlc_media_player_play( GTK_LIBVLC_MEDIA_PLAYER(media->player), NULL, &error); g_object_unref(inst); g_object_unref(vlc_media); return 0; }
不同版本的libvlc这之间MRL的格式也有所不同,0.23版本的MRL格式如:rtp://:5004,0.22版本的则如:rtp://@:5004
既然player被封装成一个widget,那么我们就可以用gdk的一些方法很容易地在它上面绘图,如我在播放前加上了一个logo:
g_signal_connect(G_OBJECT(GTK_WIDGET(media->player)), "expose_event", G_CALLBACK(draw_able_expose), NULL); static gboolean draw_able_expose(GtkWidget *widget, GdkEventExpose *e, gpointer data) { GdkGC *gc; GdkColormap *colormap; GdkPixbuf *pixbuf; GdkColor color; GdkDrawable *drawing; gint width; gint height; drawing = widget->window; pixbuf = gdk_pixbuf_new_from_file_at_size( "skin/mplayer.svg", 96, 96,NULL); gc=gdk_gc_new(drawing); colormap=gtk_widget_get_colormap(widget); gdk_color_parse("white",&color); gdk_color_alloc(colormap,&color); gdk_gc_set_foreground(gc,&color); gdk_drawable_get_size(drawing, &width, &height); gdk_draw_pixbuf(drawing, gc, pixbuf, 0, 0, (width - 96) / 2, (height - 96) / 2, 96, 96, GDK_RGB_DITHER_NORMAL, 0, 0); g_object_unref(pixbuf); }
最基本的呈现一个视频流的用法就这些了,像其它的一些API也很简单的,都是采用GTK的命名风格,即便没有注释也可以很简单地了解它们的用法,就不多说了。
Recent Comments