存档

文章标签 ‘libvlc’

libvlc-gtk使用手记

十二月 5th, {2010 2 条评论 7,768 人阅读过  

前几天实验室这个破项目非要加上什么流媒体的功能,简单起见使用了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的命名风格,即便没有注释也可以很简单地了解它们的用法,就不多说了。

分类: C/C++ 标签: ,