culturered_client/Common/VlcMediaPlayer.cpp
2024-09-07 11:34:44 +08:00

216 lines
6.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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