VLC Media Player是一款非常强大的播放器,基本上支持绝大部分的解码器,但是源代码编译难度很大,所以还是使用编译好的库吧。
vlc sdk下载地址:http://download.videolan.org/pub/videolan/vlc/
vlc相关
-
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 -
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使用过程中遇到的问题:
- libvlc_new(0,NULL);总是失败
解决办法:将下载的SDK目录下的plugins文件夹拷贝到exe目录。
- libvlc_media_t *vlc_mdia= libvlc_media_new_path(inst,“D:/box.mp4”);失败,返回空
解决办法:libvlc_media_new_path(inst,“D:\box.mp4”);
- “libvlc_media_read_cb”: 未声明的标识符
解决办法:在vlc.h 文件或其它文件中 添加 typedef __int64 ssize_t;
- 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事件订阅
- 创建事件管理器
libvlc_event_manager_t* 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_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);
}
}
}