216 lines
6.0 KiB
C++
216 lines
6.0 KiB
C++
#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
|