#include "VlcMediaPlayer.h" #if USE_VLC #include #ifdef _WIN32 #include typedef SSIZE_T ssize_t; #endif #include #include #include #include static libvlc_instance_t* vlcIns_ = nullptr; void* MediaCallbakLocak(void* opaque, void** planes) { VlcMediaPlayer* player = reinterpret_cast(opaque); player->mutx_.lock(); *planes = player->pixels_.data(); return nullptr; } void MediaCallbakUnLocak(void* opaque, void* picture, void* const* planes) { VlcMediaPlayer* player = reinterpret_cast(opaque); unsigned char* data = (unsigned char*)*planes; QImage image(data, player->videoWidth_, player->videoHeight_, QImage::Format_ARGB32); emit player->VideoDataOutput(std::move(image)); player->mutx_.unlock(); } void MediaCallbakDisplay(void* opaque, void* picture) { } void OnVLCEvent(const libvlc_event_t* event, void* data) { VlcMediaPlayer* player = reinterpret_cast(data); switch (event->type) { case libvlc_MediaListPlayerStopped: player->Stop(); break; case libvlc_MediaPlayerEndReached: emit player->Stopped(); break; case libvlc_MediaPlayerStopped: emit player->Stopped(); break; case libvlc_MediaPlayerPositionChanged: { float pos = event->u.media_player_position_changed.new_position; player->OnPostionChangedCallback(pos); } break; case libvlc_MediaPlayerTimeChanged: { qint64 pos = event->u.media_player_time_changed.new_time; player->OnTimeChangedCallback(pos); } break; default: break; } } VlcMediaPlayer::VlcMediaPlayer() { assert(nullptr != vlcIns_); } VlcMediaPlayer::~VlcMediaPlayer() { if (nullptr != vlcPlayer_) { libvlc_media_player_release(vlcPlayer_); vlcPlayer_ = nullptr; } } bool VlcMediaPlayer::Init() { const char* vlc_args[] = { "vlc –ffmpeg-hw", "-I", "dummy", "--ignore-config", "--extraintf=logger", "--verbose=2", "–no-audio", "–ffmpeg-hw-frames" }; vlcIns_ = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args); //vlcIns_ = libvlc_new(0, nullptr); return vlcIns_ != nullptr; } void VlcMediaPlayer::Uninit() { if (nullptr != vlcIns_) { libvlc_release(vlcIns_); vlcIns_ = nullptr; } } libvlc_instance_t* VlcMediaPlayer::GetVLCInstance() { assert(vlcIns_ != nullptr); return vlcIns_; } static unsigned setup(void** /*opaque*/, char* chroma, unsigned* width, unsigned* height, unsigned* pitches, unsigned* lines) { qDebug() << "chroma:" << QString(chroma) << "width:" << *width << ", height:" << *height; return 1; } bool VlcMediaPlayer::Play(const QString& path) { QFileInfo info(path); if (!info.isFile()) { qDebug() << __FUNCTION__ << "path is not file:" << path; return false; } Stop(); assert(nullptr != vlcIns_); assert(nullptr == vlcPlayer_); std::string stdPath = path.toStdString(); std::replace(stdPath.begin(), stdPath.end(), '/', '\\'); libvlc_media_t* media = libvlc_media_new_path(vlcIns_, stdPath.c_str()); if (nullptr == media) { qDebug() << __FUNCTION__ << "libvlc_media_new_path failed:" << path; return false;; } vlcPlayer_ = libvlc_media_player_new_from_media(media); if (nullptr == vlcPlayer_) { libvlc_media_release(media); qDebug() << __FUNCTION__ << "vlcPlayer_ is nullptr failed:" << path; return false; } libvlc_video_set_key_input(vlcPlayer_, false); libvlc_video_set_mouse_input(vlcPlayer_, false); libvlc_audio_set_volume(vlcPlayer_, int(200)); //QThread::msleep(1); libvlc_media_parse(media); libvlc_media_track_info_t* media_tracks = nullptr; libvlc_media_get_tracks_info(media, &media_tracks); if (nullptr == media_tracks) { libvlc_media_release(media); qDebug() << __FUNCTION__ << "vlcPlayer_ is nullptr failed:" << path; Stop(); return false; } if (media_tracks->u.video.i_width != videoWidth_ || media_tracks->u.video.i_height != videoHeight_) { videoWidth_ = media_tracks->u.video.i_width; videoHeight_ = media_tracks->u.video.i_height; pixels_.resize(videoWidth_ * videoHeight_ * 4, 0); } libvlc_video_set_callbacks(vlcPlayer_, MediaCallbakLocak, MediaCallbakUnLocak, MediaCallbakDisplay, this); libvlc_video_set_format(vlcPlayer_, "RV32", videoWidth_, videoHeight_, videoWidth_ * 4); int ret = libvlc_media_player_play(vlcPlayer_); if (0 != ret) { qDebug() << __FUNCTION__ << "libvlc_media_player_playr failed:" << " ret=" << ret << " path " << path; libvlc_media_release(media); Stop(); return false; } libvlc_event_manager_t* vlc_evt_man = libvlc_media_player_event_manager(vlcPlayer_); libvlc_event_attach(vlc_evt_man, libvlc_MediaPlayerPlaying, ::OnVLCEvent, this); libvlc_event_attach(vlc_evt_man, libvlc_MediaPlayerPositionChanged, ::OnVLCEvent, this); libvlc_event_attach(vlc_evt_man, libvlc_MediaPlayerTimeChanged, ::OnVLCEvent, this); libvlc_event_attach(vlc_evt_man, libvlc_MediaPlayerStopped, ::OnVLCEvent, this); libvlc_event_attach(vlc_evt_man, libvlc_MediaPlayerEndReached, ::OnVLCEvent, this); libvlc_event_attach(vlc_evt_man, libvlc_MediaListPlayerStopped, ::OnVLCEvent, this); moviePath_ = path; return true; } void VlcMediaPlayer::Stop() { if (nullptr != vlcPlayer_) { libvlc_media_player_stop(vlcPlayer_); libvlc_media_player_release(vlcPlayer_); vlcPlayer_ = nullptr; } } bool VlcMediaPlayer::IsPlaying() const { if (nullptr != vlcPlayer_) { return 1 == libvlc_media_player_is_playing(vlcPlayer_); } return false; } void VlcMediaPlayer::OnPostionChangedCallback(float pos) {} void VlcMediaPlayer::OnTimeChangedCallback(qint64 pos) { emit TimeChanged(pos); } #endif USE_VLC