C语言基于GTK+Libvlc实现的简易视频播放器

小编心语:现下,各种视频播放软件层出不穷,竞争也越演越烈,不知道大家有木有这个想法,小编有时在想能不能做一款属于自己的视频播放器呢~小编特意去实验楼,整理出了这篇关于如何实现简易视频播放器的博文。简易播放器,你值得拥有~

友情提示:这里只是前篇,只是一些简单的功能,其他功能将会在后篇为大家介绍——

C语言基于GTK+Libvlc实现的简易视频播放器

一、课程说明

如果你学习过之前上线的pygtk实现有道词典的项目课,那应该对gtk的使用有一些了解了,这个项目课学起来会相对轻松一些。 关于Gtk或者说是通常的图形应用开发的一些基础知识,我们会在以后的基础课程中体现,项目课适合有一定基础的用户学习。

二、Gtk简介

GTK+ 是一种图形用户界面(GUI)工具包。也就是说,它是一个库(或者,实际上是若干个密切相关的库的集合),它支持创建基于 GUI 的应用程序。可以把 GTK+ 想像成一个工具包,从这个工具包中可以找到用来创建 GUI 的许多已经准备好的构造块。

最初,GTK+ 是作为另一个著名的开放源码项目 —— GNU Image Manipulation Program (GIMP) —— 的副产品而创建的。在开发早期的 GIMP 版本时,Peter Mattis 和 Spencer Kimball 创建了 GTK(它代表 GIMP Toolkit),作为 Motif 工具包的替代,后者在那个时候不是免费的。(当这个工具包获得了面向对象特性和可扩展性之后,才在名称后面加上了一个加号。)

这差不多已经 10 年过去了。今天,在 GTK+ 的最新稳定版本 —— 2.8 版上(3.0测试中),仍然在进行许多活动,同时,GIMP 无疑仍然是使用 GTK+ 的最著名的程序之一,不过它已经不是惟一的使用 GTK+ 的程序了。已经为 GTK+ 编写了成百上千的应用程序,而且至少有两个主要的桌面环境(Xfce 和 GNOME)用 GTK+ 为用户提供完整的工作环境。

GTK+虽然是用C语言写的,但是您可以使用你熟悉的语言来使用GTK+,因为GTK+已经被绑定到几乎所有流行的语言上,如:C++,PHP, Guile,Perl, Python, TOM, Ada95, Objective C, Free Pascal, and Eiffel

使用GTK+的优秀应用程序:

· GIMP-GNU图像处理程序

· GNOME、XFCE等桌面环境和大部分窗口管理器都基于GTK+

· Inkscape-类似于Illustrator、CorelDraw的矢量图形绘制工具

· Pidgin-支持多种协议(IRC、Gtalk、Yahoo Talk、MSN、QQ等等)的聊天工具

· Firefox 、Chrome-两大流行浏览器

· ...

三、Vlc简介

1.简介:

VLC多媒体播放器(英语:VLC media player,最初为VideoLAN Client,是VideoLAN计划的开放源代码多媒体播放器。)支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影音光盘及各类流 协议。它也能作为单播或多播的流服务器在IPv4或IPv6的高速网络连接下使用。调用FFmpeg计划的解码器与libdvdcss程序库使其有播放多 媒体文件及加密DVD影碟的功能。

VLC自建的动态核心模块,使所有的接口(interfaces)、视频和音频输出(video and audio outputs)、控制(controls)、定标器(scalers)、解码器(codecs)、音频/视频滤波器(audio/video filters)包含于统一的模块之内,便于使用。在播放媒体文件时,无需用户干预,VLC会根据不同的情况自行调度输入协议(input protocol)、输入文件的格式(input file format)、输入转码器(input codec)、视频卡功能(video card capabilities)和其他参数。

VLC media player具有跨平台的特性,可用于Linux、Microsoft Windows、Mac OS X、BeOS、OS/2、BSD、安卓、iOS、及Solaris。

2.libvlc

libvlc是VLC media player使用的多媒体框架的核心引擎和扩展编程接口,它可以帮助开发者开发广泛的多媒体应用

libvlc多媒体框架结构如下:

libvlc API关系图表如下:

LibVlc官方API文档

四、gtk构建gtk界面

我们首先也只是布局和添加控件,之后再来实现业务逻辑,不多说,直接看图,这就是我们要先实现的播放器大致的界面布局,不过这个界面将不会是我们最 终要实现的样子,因为这是使用galde界面设计器创建的布局,大家初学时最好不要直接使用glade来进行布局,因为它会忽略很多细节。先从手写代码的 方式进行布局和添加控件,这样有助于你更好的掌握那些控件的使用方法。

1.先了解这个布局的层次关系

window
|---vbox|-------menubar|-------drawingarea|-------hbox
        |---hbuttonbox
        |   |---playbutton
        |   |---stopbutton
        |---scale
        |---fullscreenbutton

2.实现这个布局的代码如下:

//filename:gui.c#include <gtk/gtk.h>#include <gdk/gdkx.h>#include <glib.h>#define BORDER_WIDTH 6int main(int argc, char* argv[])
{
    GtkWidget   *window,
                *vbox,
                *hbox,
                *menubar,
                *filemenu,
                *fileitem,
                *filemenu_openitem,
                *hbuttonbox,
                *player_widget,
                *stop_button,
                *full_screen_button,
                *playpause_button,
                *process_scale,
                *play_icon_image,
                *pause_icon_image,
                *stop_icon_image;
    GtkAdjustment  *process_adjuest;    // 每个gtk程序都必须要有的,两个参数对应mian函数的两个参数,用于在命令行执行程序时传递并解析参数
    gtk_init(&argc, &argv);    // 创建一个window并完成初始化,如设置为顶层窗口,宽度和高度,标题等,并绑定destory信号,以便在关闭gtk窗口后程序能完全退出
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_container_set_border_width (GTK_CONTAINER (window), 0);
    gtk_window_set_title(GTK_WINDOW(window), "GTK+ libVLC Demo");    //创建一个方向垂直间距为0的box容器,并添加到前面创建的window中
    vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
    gtk_container_add(GTK_CONTAINER(window), vbox);    //创建一个menubar和两个menuitem分别为菜单中的“文件”和“打开”,由于它们为上下级菜单关系,
    //所以需要单独一个menu来放置"open_menu_item",也就是代码中的filemenu_openitem
    menubar = gtk_menu_bar_new();
    fileitem = gtk_menu_item_new_with_label ("File");
    filemenu_openitem = gtk_menu_item_new_with_label("Open");
    filemenu = gtk_menu_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), filemenu_openitem);    // 将filemenu设置为上一级fileitem的子菜单,然后将fileitem添加进menubar,最后将menubar放置进vbox
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileitem), filemenu);
    gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileitem);
    gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);    //创建一个draw_area控件,用做视频播放显示区域,并放置进vbox
    player_widget = gtk_drawing_area_new();
    gtk_box_pack_start(GTK_BOX(vbox), player_widget, TRUE, TRUE, 0);    //创建一个hbox作为vbox的子容器,一个hbuttonbox作为hbox的子容器,hbuttonbox用于放置两个button,
    // 再将一个scale(滚动条,用作视频播放进度条,原本的process控件不能拖动)添加进hbox,最后将hbox放置进最外面的vbox
    hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
    hbuttonbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
    gtk_container_set_border_width(GTK_CONTAINER(hbuttonbox), BORDER_WIDTH);
    gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox), GTK_BUTTONBOX_START);

    playpause_button = gtk_button_new_from_icon_name("media-playback-start", GTK_ICON_SIZE_BUTTON);
    stop_button = gtk_button_new_from_icon_name("media-playback-stop", GTK_ICON_SIZE_BUTTON);

    gtk_box_pack_start(GTK_BOX(hbuttonbox), playpause_button, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbuttonbox), stop_button, FALSE, FALSE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), hbuttonbox, FALSE, FALSE, 0);    //创建一个滚动条,使用一个自定义的adjust对象初始化
    process_adjuest = gtk_adjustment_new(0.00, 0.00, 100.00, 1.00, 0.00, 0.00);
    process_scale = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL,process_adjuest);
    gtk_box_pack_start(GTK_BOX(hbox), process_scale, TRUE, TRUE, 0);
    gtk_scale_set_draw_value (GTK_SCALE(process_scale), FALSE);
    gtk_scale_set_has_origin (GTK_SCALE(process_scale), TRUE);
    gtk_scale_set_value_pos(GTK_SCALE(process_scale), 0);
    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);    // 显示所有控件,并运行gtk程序
    gtk_widget_show_all(window);
    gtk_main ();    return 0;
}

如果你觉得有困难可以直接下载代码:(以下内容是在实验楼网站的虚拟平台上使用的,没有使用实验楼的不需要下面这个步骤)

$ wget https://raw.githubusercontent.com/shiyanlou/gtk-vlc-video-player/master/gui.c

3.代码说明:

上述代码,使用如下命令编译和运行:

# 注意pgk-config...那里不是单引号,是反单引号$ gcc gui.c -o gui `pkg-config --libs --cflags gtk+-3.0`$ ./gui

运行后,你将看到

代码的解释说明,已经尽可能在注释中说明,代码中一些gtk的API的使用和详细说明,请参看官方API文档,一些API的参数如果不太明确,你可以直接在代码中修改为不同的值,然后编译并运行代码,观察效果,帮助理解.

五、使用libvlc播放媒体文件通过gtk中显示

1.使用libvlc创建一个媒体播放器对象

在mian函数中添加如下代码:

  //setup vlc
    vlc_inst = libvlc_new(0, NULL);
    media_player = libvlc_media_player_new(vlc_inst);
    g_signal_connect(G_OBJECT(player_widget), "realize", G_CALLBACK(player_widget_on_realize), media_player);

2.使用filechooserdialog打开一个视频文件

首先给菜单栏中的open添加一个点击信号处理函数on_open,注意一般信号处 理函数的命令规则就是在函数名之前加上"on_",但这不是必需的,然后在on_open这个信号处理函数中,创建一个 filechoosedialog,并运行。打开文件,获取到uri(?)后,将其传递给open_media函数,使用vlc打开并播放视频文件。这里 注意,要想让vlc播放的视频显示在窗口中还需要给之前创建的draw_area控件绑定一个信号处理函数,这里面会将vlc的播放器窗口绘制在控件中。

具体实现代码如下:

添加信号处理

// 添加信号处理函数g_signal_connect(filemenu_openitem, "activate", G_CALLBACK(on_open), window);

处理函数实现

// 信号处理函数 void on_open(GtkWidget *widget, gpointer data) {
    GtkWidget *dialog;
    GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;

    dialog = gtk_file_chooser_dialog_new("open file", GTK_WINDOW(widget), action, _("Cancel"), GTK_RESPONSE_CANCEL, _("Open"), GTK_RESPONSE_ACCEPT, NULL);    if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {        char *uri;
        uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
        open_media(uri);
        g_free(uri);
    }
    gtk_widget_destroy(dialog);
}// 传入视频文件uri,使用libvlc播放视频文件void open_media(const char* uri) {
    media = libvlc_media_new_location(vlc_inst, uri);
    libvlc_media_player_set_media(media_player, media);

    current_play_time = 0.0f;
    gtk_scale_set_value_pos(GTK_SCALE(process_scale), current_play_time/video_length*100);

    play();
    libvlc_media_release(media);
}

因为我们使用了libvlc所以上面代码在编译时需要加上libvlc的编译和链接选项,可使用pkg-config工具获得

比如:

$ gcc -o videoplayer videoplayer.c `pkg-config --cflags --libs gtk+-3.0 libvlc`

一切正常的话,现在你的播放器应该已经可以播放出视频了,如果你需要一个视频文件来测试播放效果的话,你可以使用我提供的一个视频文件,这是一个相当有趣的视频,所以希望你一定要成功,然后你才能看到这个视频的内容。

$ wget http://anything-about-doc.qiniudn.com/gtk_libvlc_video_player/video_demo_01.flv

六、实现简单的播放控制,暂定/播放和停止

这个比较简单了,就是为播放和停止按钮分别绑定两个点击信号处理函数,并更具当前是否为播放状态设置按钮显示为播放还是暂定,及实现视频的暂定和继续播放

具体代码如下:

同样先添加信号处理

(略)

处理函数实现

// 使用libvlc传入当前的播放器对象,获取播放状态void on_playpause(GtkWidget *widget, gpointer data) {    if(libvlc_media_player_is_playing(media_player) == 1) {
        pause_player();
    }    else {
        play();
    }
}void on_stop(GtkWidget *widget, gpointer data) {
    pause_player();
    libvlc_media_player_stop(media_player);
}// play函数开始播放视频,并将播放按钮的图标换成表示暂定的图标void play(void) {
    libvlc_media_player_play(media_player);
    pause_icon_image = gtk_image_new_from_icon_name("media-playback-pause", GTK_ICON_SIZE_BUTTON);
    gtk_button_set_image(GTK_BUTTON(playpause_button), pause_icon_image);
}void pause_player(void) {
    libvlc_media_player_pause(media_player);
    play_icon_image = gtk_image_new_from_icon_name("media-playback-start", GTK_ICON_SIZE_BUTTON);
    gtk_button_set_image(GTK_BUTTON(playpause_button), play_icon_image);
}

七、实现播放进度显示和拖动进度条跳转

1.视频播放进度的显示

要显示播放进度,可以用两种方式,第一种呢,自定义一个信号每当vlc的播放进度发生变化时就发送这个信号,然后将滚动条绑定该信号,在该信号的信 号处理函数中获取vlc播放进度,并设置为滚动条的值;另一种是添加一个定时器,每隔一个时间比如0.5s去获取vlc的播放进度,使用之前创建滚动条是 自定义的一个GtkAdjuestment对象了设置滚动条的进度。前一种方法比较复杂,这里我们使用后一种

具体代码如下:

在open_media函数中添加定时器

// 表示每隔500ms会调用\_update\_scale函数,并将process\_scale作为数据对象传入g_timeout_add(500,_update_scale,process_scale);

_update_scale函数实现

// 该函数为一个`GSourceFunc`函数类型,要求必须要有返回值,返回类型为`gboolean`,// 如要下次继续执行该定时器,须返回`G\_SOURCE\_CONTINUE`,否则返回`G\_SOURCE\_REMOVE`
gboolean _update_scale(gpointer data){    // 获取当前打开视频的长度,时间单位为ms
    video_length = libvlc_media_player_get_length(media_player);    
    current_play_time = libvlc_media_player_get_time(media_player);
    gtk_adjustment_set_value(process_adjuest,current_play_time/video_length*100);    return G_SOURCE_CONTINUE;
}

2.实现拖动进度条跳转

这个功能可以给scale添加一个value\_changed信号处理函数就可以实现,只是这里有个小问题就是,如果直接这样实现的话,会跟上面的进度显示发生点小冲突,以为上面的进度更新也会触发这里的信号处理函数,导致视频一直在那来回卡动无法正常播放,这里我们可以在更新进度条是使用临时阻塞value\_changed信号的方式避免这个问题

具体代码如下:

添加信号处理(略)

处理函数实现

处理函数实现
// 通过adjuest对象获取拖动到的进度数值(根据之前的设定为1-100的范围),// 然后使用libvlc设定播放位置(根据百分百设定,故要除以100)void on_value_change(GtkWidget *widget, gpointer data){    float scale_value = gtk_adjustment_get_value(process_adjuest);
    libvlc_media_player_set_position(media_player, scale_value/100);
}

修改_update_scale函数如下:

// 在更新进度条数值前先阻塞信号处理函数的执行,之后在取消阻塞gboolean _update_scale(gpointer data){    // 获取当前打开视频的长度,时间单位为ms
    video_length = libvlc_media_player_get_length(media_player);    
    current_play_time = libvlc_media_player_get_time(media_player);
    g_signal_handlers_block_by_func(G_OBJECT(process_scale), on_value_change, NULL);
    gtk_adjustment_set_value(process_adjuest,current_play_time/video_length*100);
    g_signal_handlers_unblock_by_func(G_OBJECT(process_scale), on_value_change, NULL);    return G_SOURCE_CONTINUE;
}

七、总结

通过上面的一些说明,相信你可以独立构建一个实现基本功能的视频播放器了,不过总的说来,它是在是太基础了,简单来讲根本拿不出手啊,作为自己日常 使用都会有问题,比如不能全屏,不能添加字幕,不能调节音量(抱歉当前我们的实验环境可能也听不到声音,但对于一个播放器来说这一点我们还是要实现)等 等,这些就请你期待下一节项目课吧,我将带你一步一步添加功能,完善我们的视频播放器

本节完整代码下载(以下内容是在实验楼网站的虚拟平台上使用的,没有使用实验楼的不需要下面这个步骤)

$ git clone https://github.com/shiyanlou/gtk-vlc-video-player.git

更多详细步骤和代码请登录实验楼官方网站:http://www.shiyanlou.com/courses/69

有更多基础课、项目课欢迎大家登陆实验楼官方网站http://www.shiyanlou.com
现在登陆实验楼更有感恩好礼相送http://www.shiyanlou.com/huodong/thanks.html

时间: 2024-10-09 23:25:13

C语言基于GTK+Libvlc实现的简易视频播放器的相关文章

C语言基于GTK+Libvlc实现的简易视频播放器(二)

简易视频播放器-全屏播放 一.课程说明上一次我们使用gtk+libvlc实现了一个最简单的视频播放器,可以实现点击按钮暂定和停止播放视频,以及同步显 示视频播放进度,但即使作为一个视频播放器,只有这些功能也还是不够的,至少我们还应该有全屏播放的功能吧,所以这一次我们就来为上一次的视频播放器添加 上全屏播放功能.这个功能实现起来思路很简单,只是具体实现过程中有很多坑罢了,需要我们注意很多细节问题,还要解决一些bug等等.这次我们的代码出了 增加功能之外,也还会对上一次的基础代码做一些修改. 二.功

100行代码实现最简单的基于FFMPEG+SDL的视频播放器(SDL1.x)【转】

转自:http://blog.csdn.net/leixiaohua1020/article/details/8652605 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 简介 流程图 simplest_ffmpeg_player标准版代码 simplest_ffmpeg_player_suSU版代码 结果 FFMPEG相关学习资料 补充问题 ===================================================== 最简单的基于FFmp

最简单的基于DirectShow的示例:视频播放器图形界面版

本文记录一个最简单的基于DirectShow的图形界面的视频播放器.基于DirectShow的图形界面的播放器的例子还是比较多的,但是大部分都是"层层封装"的例子."层层封装"的例子相对来说更加稳定,但是却不是很容易理解.因为DirectShow本身的接口函数的数量就比较多,如果再加上封装DirectShow的函数,合起来的函数数量是非常大的,很容易让人搞不清哪些才是真正的DirectShow接口函数.本播放器剥去了DirectShow例子中的"层层封装&

转:最简单的基于 DirectShow 的视频播放器

50行代码实现的一个最简单的基于 DirectShow 的视频播放器 本文介绍一个最简单的基于 DirectShow 的视频播放器.该播放器对于初学者来说是十分有用的,它包含了使用 DirectShow 播放视频所有必备的函数. 直接贴上代码,具体代码的含义都写在注释中了: /* 雷霄骅 * 中国传媒大学/数字电视技术 * [email protected] * */ // aviplayer.cpp : 定义控制台应用程序的入口点. #include "stdafx.h" #incl

基于C/S模式的简易聊天室

一.任务简要描述 移动互联网技术的广泛应用为人们提供了非常便捷的沟通方式.QQ.微信和微博等是便携式聊天系统的典型代表,它们的功能非常强大. 本系统利用TCP/IP协议的Socket和ServerSocket类,实现基于C/S模式的简易聊天室.该聊天室包括服务端和客户端两部分,服务端是客户端发送消息的中转站:客户端之间可以直接通信,也可以与服务器通信.聊天结束后客户端断开与服务端的连接,服务器也可以停止信息中转服务. 二.系统需求分析 本系统采用C/S软件架构,服务器端负责监听客户端发来的消息,

最简单的基于libVLC的例子:最简单的基于libVLC的视频播放器

本文记录使用libVLC的开发的最简单的视频播放器示例.VLC Media Player是一款优秀的播放器,但是由于它的源代码编译的难度比较大,一直没有深入研究过它的开发方面的技术.此前触到了一些VLC开发方面的东西,因此总结了一下libVLC的开发示例程序. 如何获取VLC的SDK VLC开发所需的库文件可以有2种获取方法: 1. 自行编译2. 直接从安装目录里面拷贝出来 第一种方法难度要大一些.尤其是在Windows下编译VLC是个比较麻烦的事情.一般情况下可以选择第二种方法获取VLC开发所

Ubuntu 12.04下在Eclipse IDE for C/C++ Developers中运行C语言的GTK程序

哈哈哈--终于搞定了GTK程序的编译与运行,纠结了近一个月的问题终于得以解决,痛快!近一个月来,不断百度.发博文.百度知道提问.csdn提问--经常发私信.评论博文麻烦大牛,比如sunny2038.轻飘风扬.Sun1956--在此对所有帮助我的人表示感谢! 特别感谢csdn的sunny2038,他的博文<Windows和Ubuntu11.10在Eclipse中配置C和GTK>和热心回复给了我很大的帮助! Neo E. Cai的博文<Ubuntu下GTK的安装.编译和测试>对我具有非

R语言基于S4的面向对象编程

前言 本文接上一篇文章 R语言基于S3的面向对象编程,本文继续介绍R语言基于S4的面向对象编程. S4对象系统具有明显的结构化特征,更适合面向对象的程序设计.Bioconductor社区,以S4对象系统做为基础架构,只接受符合S4定义的R包. 目录 S4对象介绍 创建S4对象 访问对象的属性 S4的泛型函数 查看S4对象的函数 S4对象的使用 1 S4对象介绍 S4对象系统是一种标准的R语言面向对象实现方式,S4对象有明确的类定义,参数定义,参数检查,继承关系,实例化等的面向对象系统的特征. 2

R语言简介,环境配置与简易使用

R语言简介,环境配置与简易使用 首先,R是一种语言,同时也是一个开发环境. R是用于统计分析.绘图的语言和操作环境.R是属于GNU系统的一个自由.免费.源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具. 使用R,首先需要安装环境,http://cran.r-project.org有各个版本的安装包. 如图,是windows下64位的安装包: 安装完成后,打开界面 简易使用–命令行 R是一种区分大小写的解释型语言.在命令提示符(>)后,每次输入并执行一条命令 ,或者一次性执行写在脚本中文