c++使用libvlc实现简单的播放器

VLC Media Player是一款非常强大的播放器,基本上支持绝大部分的解码器,但是源代码编译难度很大,所以还是使用编译好的库吧。

vlc sdk下载地址:http://download.videolan.org/pub/videolan/vlc/

vlc相关

  1. VLC-QT:
    用QT的小伙伴们可以使用开源的VLC-QT库哦,widget和qml都支持,由于 VLC-Qt 集成了整个 libVLC,因此具备 libVLC 的所有特性,例如:libVLC 实例和 player、单个文件和列表播放、音频和视频控制、元数据管理,如果想快速创建一个功能齐全的跨平台媒体播放器,这个库非常合适!详细的调用方法这里就不阐述了,直接百度吧。
    VLC-QT库官网地址:https://vlc-qt.tano.si/
    VLC_QT库github地址:https://github.com/vlc-qt
    VLC_QT库使用示例地址:https://github.com/vlc-qt/examples

  2. vlmc:
    vlmc(VideoLAN Movie Creator)是基于libVLC的非线性的视频编辑软件,可在Windows,Linux和Mac OS X上运行,但是vlmc仍在开发中,因此尚未准备好进行Beta测试或发布,因此感兴趣的小伙伴可以下载源码捣鼓一下还是非常有意思的。
    官网地址:https://www.videolan.org/vlmc/
    GitHub地址:https://code.videolan.org/videolan/vlmc.git

好,接下来进入正题

libvlc使用过程中遇到的问题:

  1. libvlc_new(0,NULL);总是失败
    解决办法:将下载的SDK目录下的plugins文件夹拷贝到exe目录。
  1. libvlc_media_t *vlc_mdia= libvlc_media_new_path(inst,“D:/box.mp4”);失败,返回空
    解决办法:libvlc_media_new_path(inst,“D:\box.mp4”);
  1. “libvlc_media_read_cb”: 未声明的标识符
    解决办法:在vlc.h 文件或其它文件中 添加 typedef __int64 ssize_t;
  1. libvlc_media_get_duration / libvlc_media_player_get_length / libvlc_media_player_get_time失败返回-1
    原因:没有解析元数据。
    解决办法:ibvlc_media_t 必须先解析视频或至少播放一次才能获取元数据。也就是调用libvlc_media_parse_with_options异步解析本地媒体(同步解析函数libvlc_media_parse已弃用),或调用libvlc_media_player_play播放一次。下面会讲到libvlc_media_parse_with_options调用方法。

解析媒体数据 + vlc事件订阅

  1. 创建事件管理器
libvlc_event_manager_t* vlc_media_event_mng = libvlc_media_event_manager(vlc_media);
  1. 订阅指定事件(这里订阅媒体解析和视频总时长事件)
libvlc_event_attach(vlc_media_event_mng, libvlc_MediaParsedChanged, event_callback, nullptr);
libvlc_event_attach(vlc_media_event_mng, libvlc_MediaDurationChanged, event_callback, nullptr);
  1. 开始异步解析本地媒体
libvlc_media_parse_with_options(vlc_media, libvlc_media_parse_local,-1);

event_callback:
说明:事件回调函数
参数event:事件类型
参数userData:自定义数据类型,可为Null

void event_callback(const libvlc_event_t *event, void *userData)
{
	switch (event->type)
	{
	case libvlc_MediaParsedChanged:
	{
	//在该事件中获取帧率fps
		libvlc_media_track_t **ppTracks = nullptr;
		int uiStreamCount = libvlc_media_tracks_get(g_vlcModel->m_media, &ppTracks);
		
		for (unsigned i = 0; i < uiStreamCount; i++)
		{
			libvlc_media_track_t* pTrack = ppTracks[i];
			if (pTrack && libvlc_track_video == pTrack->i_type)
			{
				libvlc_video_track_t* pVideoTrack = pTrack->video;
				int fps = pVideoTrack->i_frame_rate_num / (float)pVideoTrack->i_frame_rate_den;
				break;
			}
		}
		if(ppTracks)
			libvlc_media_tracks_release(ppTracks, uiStreamCount);
		break;
	}
	case libvlc_MediaDurationChanged:
	{
	//获取总时长
		int64_t duration = event->u.media_duration_changed.new_duration;
		break;
	}
	case libvlc_MediaPlayerPositionChanged:
	{
	//获取当前播放进度
		float pos = event->u.media_player_position_changed.new_position;
		break;
	}
	}	
}

libvlc_instance_t *vlc_inst= nullptr;
libvlc_media_t *vlc_media = nullptr;
libvlc_media_player_t *vlc_player = nullptr;
libvlc_event_manager_t *vlc_media_event_mng = nullptr;
libvlc_event_manager_t *vlc_player_event_mng = nullptr;

vlc_inst = libvlc_new(0, NULL);
if (vlc_inst)
{
	vlc_media = libvlc_media_new_path(vlc_inst ,"D:\\box.mp4");
	if (vlc_media)
	{
		//创建事件管理器
		vlc__media_event_mng = libvlc_media_event_manager(vlc_media);
		//订阅指定事件(视频解析,视频总时长,当前播放进度)
		libvlc_event_attach(vlc__media_event_mng, libvlc_MediaParsedChanged, event_callback, nullptr);
		libvlc_event_attach(vlc__media_event_mng, libvlc_MediaDurationChanged, event_callback, nullptr);
		libvlc_event_attach(vlc__media_event_mng, libvlc_MediaPlayerPositionChanged, event_callback, nullptr);
		//异步解析本地媒体
		libvlc_media_parse_with_options(vlc_media, libvlc_media_parse_local,-1);

		vlc_player = libvlc_media_player_new_from_media(vlc_media);
		if (vlc_player)
		{
			vlc__player_event_mng = libvlc_media_player_event_manager(vlc__player);
			libvlc_event_attach(vlc__player_event_mng, libvlc_MediaPlayerPositionChanged, event_callback, nullptr);

            auto imgBuffer = malloc(480 * 480* 4);
			libvlc_video_set_callbacks(vlc_player, [imgBuffer](void** pBuffer) -> void* {
		       std::cout << "Lock" << std::endl;
		       *pBuffer = imgBuffer;
		       return NULL;
	           }, [](void*, void*const*) {
		       std::cout << "unlock" << std::endl;
	           }, nullptr, param);
			libvlc_video_set_format(vlc_player, "RGBA", 450, 450, 450* 4);
		}
	}
}

你可能感兴趣的:(C++,QT,vlc)