culturered_client/Common/VlcMediaPlayer.cpp

216 lines
6.0 KiB
C++
Raw Normal View History

2024-09-07 03:34:44 +00:00
#include "VlcMediaPlayer.h"
#if USE_VLC
#include <assert.h>
#ifdef _WIN32
#include <basetsd.h>
typedef SSIZE_T ssize_t;
#endif
#include <vlc/vlc.h>
#include <QDebug>
#include <QFileInfo>
#include <QImage>
static libvlc_instance_t* vlcIns_ = nullptr;
void* MediaCallbakLocak(void* opaque, void** planes) {
VlcMediaPlayer* player = reinterpret_cast<VlcMediaPlayer*>(opaque);
player->mutx_.lock();
*planes = player->pixels_.data();
return nullptr;
}
void MediaCallbakUnLocak(void* opaque, void* picture, void* const* planes) {
VlcMediaPlayer* player = reinterpret_cast<VlcMediaPlayer*>(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<VlcMediaPlayer*>(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