mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 14:15:38 +00:00
Adding experimental OMX video player component. Squashed from fieldofcows' work (by pjft).
This commit is contained in:
parent
e27e7cfd19
commit
34ea9caa89
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
|||
[submodule "external/pugixml"]
|
||||
path = external/pugixml
|
||||
url = https://github.com/zeux/pugixml.git
|
|
@ -4,13 +4,18 @@
|
|||
#include "animations/LambdaAnimation.h"
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef _RPI_
|
||||
#include "components/VideoPlayerComponent.h"
|
||||
#include "Settings.h"
|
||||
#endif
|
||||
#include "components/VideoVlcComponent.h"
|
||||
|
||||
VideoGameListView::VideoGameListView(Window* window, FileData* root) :
|
||||
BasicGameListView(window, root),
|
||||
mDescContainer(window), mDescription(window),
|
||||
mMarquee(window),
|
||||
mImage(window),
|
||||
mVideo(window),
|
||||
mVideo(nullptr),
|
||||
mVideoPlaying(false),
|
||||
|
||||
mLblRating(window), mLblReleaseDate(window), mLblDeveloper(window), mLblPublisher(window),
|
||||
|
@ -21,6 +26,16 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) :
|
|||
{
|
||||
const float padding = 0.01f;
|
||||
|
||||
// Create the correct type of video window
|
||||
#ifdef _RPI_
|
||||
if (Settings::getInstance()->getBool("VideoOmxPlayer"))
|
||||
mVideo = new VideoPlayerComponent(window);
|
||||
else
|
||||
mVideo = new VideoVlcComponent(window);
|
||||
#else
|
||||
mVideo = new VideoVlcComponent(window);
|
||||
#endif
|
||||
|
||||
mList.setPosition(mSize.x() * (0.50f + padding), mList.getPosition().y());
|
||||
mList.setSize(mSize.x() * (0.50f - padding), mList.getSize().y());
|
||||
mList.setAlignment(TextListComponent<FileData*>::ALIGN_LEFT);
|
||||
|
@ -42,10 +57,10 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) :
|
|||
addChild(&mImage);
|
||||
|
||||
// video
|
||||
mVideo.setOrigin(0.5f, 0.5f);
|
||||
mVideo.setPosition(mSize.x() * 0.25f, mSize.y() * 0.4f);
|
||||
mVideo.setSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.4f);
|
||||
mVideo.setDefaultZIndex(30);
|
||||
mVideo->setOrigin(0.5f, 0.5f);
|
||||
mVideo->setPosition(mSize.x() * 0.25f, mSize.y() * 0.4f);
|
||||
mVideo->setSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.4f);
|
||||
mVideo->setDefaultZIndex(30);
|
||||
addChild(&mVideo);
|
||||
|
||||
// metadata labels + values
|
||||
|
@ -91,6 +106,7 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) :
|
|||
|
||||
VideoGameListView::~VideoGameListView()
|
||||
{
|
||||
delete mVideo;
|
||||
}
|
||||
|
||||
void VideoGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||
|
@ -100,7 +116,7 @@ void VideoGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
|||
using namespace ThemeFlags;
|
||||
mMarquee.applyTheme(theme, getName(), "md_marquee", POSITION | ThemeFlags::SIZE | Z_INDEX);
|
||||
mImage.applyTheme(theme, getName(), "md_image", POSITION | ThemeFlags::SIZE | Z_INDEX);
|
||||
mVideo.applyTheme(theme, getName(), "md_video", POSITION | ThemeFlags::SIZE | ThemeFlags::DELAY | Z_INDEX);
|
||||
mVideo->applyTheme(theme, getName(), "md_video", POSITION | ThemeFlags::SIZE | ThemeFlags::DELAY | Z_INDEX);
|
||||
|
||||
initMDLabels();
|
||||
std::vector<TextComponent*> labels = getMDLabels();
|
||||
|
@ -214,8 +230,8 @@ void VideoGameListView::updateInfoPanel()
|
|||
bool fadingOut;
|
||||
if(file == NULL)
|
||||
{
|
||||
mVideo.setVideo("");
|
||||
mVideo.setImage("");
|
||||
mVideo->setVideo("");
|
||||
mVideo->setImage("");
|
||||
mVideoPlaying = false;
|
||||
//mMarquee.setImage("");
|
||||
//mDescription.setText("");
|
||||
|
@ -244,13 +260,13 @@ void VideoGameListView::updateInfoPanel()
|
|||
thumbnail_path.erase(0, 1);
|
||||
thumbnail_path.insert(0, getHomePath());
|
||||
}
|
||||
if (!mVideo.setVideo(video_path))
|
||||
if (!mVideo->setVideo(video_path))
|
||||
{
|
||||
mVideo.setDefaultVideo();
|
||||
mVideo->setDefaultVideo();
|
||||
}
|
||||
mVideoPlaying = true;
|
||||
|
||||
mVideo.setImage(thumbnail_path);
|
||||
mVideo->setImage(thumbnail_path);
|
||||
mMarquee.setImage(marquee_path);
|
||||
mImage.setImage(thumbnail_path);
|
||||
|
||||
|
@ -275,7 +291,7 @@ void VideoGameListView::updateInfoPanel()
|
|||
|
||||
std::vector<GuiComponent*> comps = getMDValues();
|
||||
comps.push_back(&mMarquee);
|
||||
comps.push_back(&mVideo);
|
||||
comps.push_back(mVideo);
|
||||
comps.push_back(&mDescription);
|
||||
comps.push_back(&mImage);
|
||||
std::vector<TextComponent*> labels = getMDLabels();
|
||||
|
@ -304,7 +320,7 @@ void VideoGameListView::launch(FileData* game)
|
|||
{
|
||||
Eigen::Vector3f target(Renderer::getScreenWidth() / 2.0f, Renderer::getScreenHeight() / 2.0f, 0);
|
||||
if(mMarquee.hasImage())
|
||||
target << mVideo.getCenter().x(), mVideo.getCenter().y(), 0;
|
||||
target << mVideo->getCenter().x(), mVideo->getCenter().y(), 0;
|
||||
|
||||
ViewController::get()->launch(game, target);
|
||||
}
|
||||
|
@ -340,7 +356,7 @@ std::vector<GuiComponent*> VideoGameListView::getMDValues()
|
|||
void VideoGameListView::update(int deltaTime)
|
||||
{
|
||||
BasicGameListView::update(deltaTime);
|
||||
mVideo.update(deltaTime);
|
||||
mVideo->update(deltaTime);
|
||||
}
|
||||
|
||||
void VideoGameListView::onShow()
|
||||
|
|
|
@ -30,7 +30,7 @@ private:
|
|||
void initMDValues();
|
||||
|
||||
ImageComponent mMarquee;
|
||||
VideoComponent mVideo;
|
||||
VideoComponent* mVideo;
|
||||
ImageComponent mImage;
|
||||
|
||||
TextComponent mLblRating, mLblReleaseDate, mLblDeveloper, mLblPublisher, mLblGenre, mLblPlayers, mLblLastPlayed, mLblPlayCount;
|
||||
|
|
|
@ -43,6 +43,8 @@ set(CORE_HEADERS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextComponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextEditComponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoComponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoPlayerComponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoVlcComponent.h
|
||||
|
||||
# Guis
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiDetectDevice.h
|
||||
|
@ -99,6 +101,8 @@ set(CORE_SOURCES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextComponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextEditComponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoComponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoPlayerComponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoVlcComponent.cpp
|
||||
|
||||
# Guis
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiDetectDevice.cpp
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "animations/AnimationController.h"
|
||||
#include "ThemeData.h"
|
||||
|
||||
GuiComponent::GuiComponent(Window* window) : mWindow(window), mParent(NULL), mOpacity(255),
|
||||
GuiComponent::GuiComponent(Window* window) : mWindow(window), mParent(NULL), mOpacity(255),
|
||||
mPosition(Eigen::Vector3f::Zero()), mSize(Eigen::Vector2f::Zero()), mTransform(Eigen::Affine3f::Identity()),
|
||||
mIsProcessing(false)
|
||||
{
|
||||
|
@ -390,4 +390,20 @@ void GuiComponent::onHide()
|
|||
getChild(i)->onHide();
|
||||
}
|
||||
|
||||
void GuiComponent::onScreenSaverActivate()
|
||||
{
|
||||
for(unsigned int i = 0; i < getChildCount(); i++)
|
||||
getChild(i)->onScreenSaverActivate();
|
||||
}
|
||||
|
||||
void GuiComponent::onScreenSaverDeactivate()
|
||||
{
|
||||
for(unsigned int i = 0; i < getChildCount(); i++)
|
||||
getChild(i)->onScreenSaverDeactivate();
|
||||
}
|
||||
|
||||
void GuiComponent::topWindow(bool isTop)
|
||||
{
|
||||
for(unsigned int i = 0; i < getChildCount(); i++)
|
||||
getChild(i)->topWindow(isTop);
|
||||
}
|
|
@ -45,7 +45,7 @@ public:
|
|||
void setSize(const Eigen::Vector2f& size);
|
||||
void setSize(float w, float h);
|
||||
virtual void onSizeChanged() {};
|
||||
|
||||
|
||||
float getZIndex() const;
|
||||
void setZIndex(float zIndex);
|
||||
|
||||
|
@ -84,9 +84,12 @@ public:
|
|||
|
||||
virtual void onFocusGained() {};
|
||||
virtual void onFocusLost() {};
|
||||
|
||||
|
||||
virtual void onShow();
|
||||
virtual void onHide();
|
||||
virtual void onScreenSaverActivate();
|
||||
virtual void onScreenSaverDeactivate();
|
||||
virtual void topWindow(bool isTop);
|
||||
|
||||
// Default implementation just handles <pos> and <size> tags as normalized float pairs.
|
||||
// You probably want to keep this behavior for any derived classes as well as add your own.
|
||||
|
@ -97,7 +100,7 @@ public:
|
|||
|
||||
// Called whenever help prompts change.
|
||||
void updateHelpPrompts();
|
||||
|
||||
|
||||
virtual HelpStyle getHelpStyle();
|
||||
|
||||
// Returns true if the component is busy doing background processing (e.g. HTTP downloads)
|
||||
|
|
|
@ -47,7 +47,7 @@ void Settings::setDefaults()
|
|||
mBoolMap["SplashScreen"] = true;
|
||||
|
||||
#ifdef _RPI_
|
||||
// don't enable VSync by default on the Pi, since it already
|
||||
// don't enable VSync by default on the Pi, since it already
|
||||
// has trouble trying to render things at 60fps in certain menus
|
||||
mBoolMap["VSync"] = false;
|
||||
#else
|
||||
|
@ -76,6 +76,14 @@ void Settings::setDefaults()
|
|||
mStringMap["ScreenSaverBehavior"] = "dim";
|
||||
mStringMap["Scraper"] = "TheGamesDB";
|
||||
mStringMap["GamelistViewStyle"] = "automatic";
|
||||
|
||||
// This setting only applies to raspberry pi but set it for all platforms so
|
||||
// we don't get a warning if we encounter it on a different platform
|
||||
#ifdef _RPI_
|
||||
mBoolMap["VideoOmxPlayer"] = true;
|
||||
#else
|
||||
mBoolMap["VideoOmxPlayer"] = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename K, typename V>
|
||||
|
|
|
@ -29,6 +29,11 @@ Window::~Window()
|
|||
|
||||
void Window::pushGui(GuiComponent* gui)
|
||||
{
|
||||
if (mGuiStack.size() > 0)
|
||||
{
|
||||
auto& top = mGuiStack.back();
|
||||
top->topWindow(false);
|
||||
}
|
||||
mGuiStack.push_back(gui);
|
||||
gui->updateHelpPrompts();
|
||||
}
|
||||
|
@ -42,7 +47,10 @@ void Window::removeGui(GuiComponent* gui)
|
|||
i = mGuiStack.erase(i);
|
||||
|
||||
if(i == mGuiStack.end() && mGuiStack.size()) // we just popped the stack and the stack is not empty
|
||||
{
|
||||
mGuiStack.back()->updateHelpPrompts();
|
||||
mGuiStack.back()->topWindow(true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -8,54 +8,24 @@
|
|||
|
||||
#define FADE_TIME_MS 200
|
||||
|
||||
libvlc_instance_t* VideoComponent::mVLC = NULL;
|
||||
|
||||
// VLC prepares to render a video frame.
|
||||
static void *lock(void *data, void **p_pixels) {
|
||||
struct VideoContext *c = (struct VideoContext *)data;
|
||||
SDL_LockMutex(c->mutex);
|
||||
SDL_LockSurface(c->surface);
|
||||
*p_pixels = c->surface->pixels;
|
||||
return NULL; // Picture identifier, not needed here.
|
||||
}
|
||||
|
||||
// VLC just rendered a video frame.
|
||||
static void unlock(void *data, void *id, void *const *p_pixels) {
|
||||
struct VideoContext *c = (struct VideoContext *)data;
|
||||
SDL_UnlockSurface(c->surface);
|
||||
SDL_UnlockMutex(c->mutex);
|
||||
}
|
||||
|
||||
// VLC wants to display a video frame.
|
||||
static void display(void *data, void *id) {
|
||||
//Data to be displayed
|
||||
}
|
||||
|
||||
VideoComponent::VideoComponent(Window* window) :
|
||||
GuiComponent(window),
|
||||
mStaticImage(window),
|
||||
mMediaPlayer(nullptr),
|
||||
mVideoHeight(0),
|
||||
mVideoWidth(0),
|
||||
mStartDelayed(false),
|
||||
mIsPlaying(false),
|
||||
mShowing(false),
|
||||
mScreensaverActive(false),
|
||||
mDisable(false),
|
||||
mTargetIsMax(false),
|
||||
mOrigin(0, 0),
|
||||
mTargetSize(0, 0)
|
||||
{
|
||||
memset(&mContext, 0, sizeof(mContext));
|
||||
|
||||
// Setup the default configuration
|
||||
mConfig.showSnapshotDelay = false;
|
||||
mConfig.showSnapshotNoVideo = false;
|
||||
mConfig.startDelay = 0;
|
||||
|
||||
// Get an empty texture for rendering the video
|
||||
mTexture = TextureResource::get("");
|
||||
|
||||
// Make sure VLC has been initialised
|
||||
setupVLC();
|
||||
}
|
||||
|
||||
VideoComponent::~VideoComponent()
|
||||
|
@ -163,7 +133,7 @@ void VideoComponent::onSizeChanged()
|
|||
|
||||
bool VideoComponent::setVideo(std::string path)
|
||||
{
|
||||
// Convert the path into a format VLC can understand
|
||||
// Convert the path into a generic format
|
||||
boost::filesystem::path fullPath = getCanonicalPath(path);
|
||||
fullPath.make_preferred().native();
|
||||
|
||||
|
@ -189,7 +159,7 @@ void VideoComponent::setImage(std::string path)
|
|||
// Check that the image has changed
|
||||
if (path == mStaticImagePath)
|
||||
return;
|
||||
|
||||
|
||||
mStaticImage.setImage(path);
|
||||
mFadeIn = 0.0f;
|
||||
mStaticImagePath = path;
|
||||
|
@ -215,83 +185,14 @@ void VideoComponent::render(const Eigen::Affine3f& parentTrans)
|
|||
GuiComponent::renderChildren(trans);
|
||||
|
||||
Renderer::setMatrix(trans);
|
||||
|
||||
|
||||
// Handle the case where the video is delayed
|
||||
handleStartDelay();
|
||||
|
||||
// Handle looping of the video
|
||||
handleLooping();
|
||||
|
||||
if (mIsPlaying && mContext.valid)
|
||||
{
|
||||
float tex_offs_x = 0.0f;
|
||||
float tex_offs_y = 0.0f;
|
||||
float x2;
|
||||
float y2;
|
||||
|
||||
x = -(float)mSize.x() * mOrigin.x();
|
||||
y = -(float)mSize.y() * mOrigin.y();
|
||||
x2 = x+mSize.x();
|
||||
y2 = y+mSize.y();
|
||||
|
||||
// Define a structure to contain the data for each vertex
|
||||
struct Vertex
|
||||
{
|
||||
Eigen::Vector2f pos;
|
||||
Eigen::Vector2f tex;
|
||||
Eigen::Vector4f colour;
|
||||
} vertices[6];
|
||||
|
||||
// We need two triangles to cover the rectangular area
|
||||
vertices[0].pos[0] = x; vertices[0].pos[1] = y;
|
||||
vertices[1].pos[0] = x; vertices[1].pos[1] = y2;
|
||||
vertices[2].pos[0] = x2; vertices[2].pos[1] = y;
|
||||
|
||||
vertices[3].pos[0] = x2; vertices[3].pos[1] = y;
|
||||
vertices[4].pos[0] = x; vertices[4].pos[1] = y2;
|
||||
vertices[5].pos[0] = x2; vertices[5].pos[1] = y2;
|
||||
|
||||
// Texture coordinates
|
||||
vertices[0].tex[0] = -tex_offs_x; vertices[0].tex[1] = -tex_offs_y;
|
||||
vertices[1].tex[0] = -tex_offs_x; vertices[1].tex[1] = 1.0f + tex_offs_y;
|
||||
vertices[2].tex[0] = 1.0f + tex_offs_x; vertices[2].tex[1] = -tex_offs_y;
|
||||
|
||||
vertices[3].tex[0] = 1.0f + tex_offs_x; vertices[3].tex[1] = -tex_offs_y;
|
||||
vertices[4].tex[0] = -tex_offs_x; vertices[4].tex[1] = 1.0f + tex_offs_y;
|
||||
vertices[5].tex[0] = 1.0f + tex_offs_x; vertices[5].tex[1] = 1.0f + tex_offs_y;
|
||||
|
||||
// Colours - use this to fade the video in and out
|
||||
for (int i = 0; i < (4 * 6); ++i) {
|
||||
if ((i%4) < 3)
|
||||
vertices[i / 4].colour[i % 4] = mFadeIn;
|
||||
else
|
||||
vertices[i / 4].colour[i % 4] = 1.0f;
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
// Build a texture for the video frame
|
||||
mTexture->initFromPixels((unsigned char*)mContext.surface->pixels, mContext.surface->w, mContext.surface->h);
|
||||
mTexture->bind();
|
||||
|
||||
// Render it
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glColorPointer(4, GL_FLOAT, sizeof(Vertex), &vertices[0].colour);
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].pos);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].tex);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
else
|
||||
if (!mIsPlaying)
|
||||
{
|
||||
// This is the case where the video is not currently being displayed. Work out
|
||||
// if we need to display a static image
|
||||
|
@ -361,38 +262,6 @@ std::vector<HelpPrompt> VideoComponent::getHelpPrompts()
|
|||
return ret;
|
||||
}
|
||||
|
||||
void VideoComponent::setupContext()
|
||||
{
|
||||
if (!mContext.valid)
|
||||
{
|
||||
// Create an RGBA surface to render the video into
|
||||
mContext.surface = SDL_CreateRGBSurface(SDL_SWSURFACE, (int)mVideoWidth, (int)mVideoHeight, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
|
||||
mContext.mutex = SDL_CreateMutex();
|
||||
mContext.valid = true;
|
||||
resize();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoComponent::freeContext()
|
||||
{
|
||||
if (mContext.valid)
|
||||
{
|
||||
SDL_FreeSurface(mContext.surface);
|
||||
SDL_DestroyMutex(mContext.mutex);
|
||||
mContext.valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
void VideoComponent::setupVLC()
|
||||
{
|
||||
// If VLC hasn't been initialised yet then do it now
|
||||
if (!mVLC)
|
||||
{
|
||||
const char* args[] = { "--quiet" };
|
||||
mVLC = libvlc_new(sizeof(args) / sizeof(args[0]), args);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoComponent::handleStartDelay()
|
||||
{
|
||||
// Only play if any delay has timed out
|
||||
|
@ -413,74 +282,6 @@ void VideoComponent::handleStartDelay()
|
|||
|
||||
void VideoComponent::handleLooping()
|
||||
{
|
||||
if (mIsPlaying && mMediaPlayer)
|
||||
{
|
||||
libvlc_state_t state = libvlc_media_player_get_state(mMediaPlayer);
|
||||
if (state == libvlc_Ended)
|
||||
{
|
||||
//libvlc_media_player_set_position(mMediaPlayer, 0.0f);
|
||||
libvlc_media_player_set_media(mMediaPlayer, mMedia);
|
||||
libvlc_media_player_play(mMediaPlayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VideoComponent::startVideo()
|
||||
{
|
||||
if (!mIsPlaying) {
|
||||
mVideoWidth = 0;
|
||||
mVideoHeight = 0;
|
||||
|
||||
#ifdef WIN32
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wton;
|
||||
std::string path = wton.to_bytes(mVideoPath.c_str());
|
||||
#else
|
||||
std::string path(mVideoPath.c_str());
|
||||
#endif
|
||||
// Make sure we have a video path
|
||||
if (mVLC && (path.size() > 0))
|
||||
{
|
||||
// Set the video that we are going to be playing so we don't attempt to restart it
|
||||
mPlayingVideoPath = mVideoPath;
|
||||
|
||||
// Open the media
|
||||
mMedia = libvlc_media_new_path(mVLC, path.c_str());
|
||||
if (mMedia)
|
||||
{
|
||||
unsigned track_count;
|
||||
// Get the media metadata so we can find the aspect ratio
|
||||
libvlc_media_parse(mMedia);
|
||||
libvlc_media_track_t** tracks;
|
||||
track_count = libvlc_media_tracks_get(mMedia, &tracks);
|
||||
for (unsigned track = 0; track < track_count; ++track)
|
||||
{
|
||||
if (tracks[track]->i_type == libvlc_track_video)
|
||||
{
|
||||
mVideoWidth = tracks[track]->video->i_width;
|
||||
mVideoHeight = tracks[track]->video->i_height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
libvlc_media_tracks_release(tracks, track_count);
|
||||
|
||||
// Make sure we found a valid video track
|
||||
if ((mVideoWidth > 0) && (mVideoHeight > 0))
|
||||
{
|
||||
setupContext();
|
||||
|
||||
// Setup the media player
|
||||
mMediaPlayer = libvlc_media_player_new_from_media(mMedia);
|
||||
libvlc_media_player_play(mMediaPlayer);
|
||||
libvlc_video_set_callbacks(mMediaPlayer, lock, unlock, display, (void*)&mContext);
|
||||
libvlc_video_set_format(mMediaPlayer, "RGBA", (int)mVideoWidth, (int)mVideoHeight, (int)mVideoWidth * 4);
|
||||
|
||||
// Update the playing state
|
||||
mIsPlaying = true;
|
||||
mFadeIn = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VideoComponent::startVideoWithDelay()
|
||||
|
@ -508,21 +309,6 @@ void VideoComponent::startVideoWithDelay()
|
|||
}
|
||||
}
|
||||
|
||||
void VideoComponent::stopVideo()
|
||||
{
|
||||
mIsPlaying = false;
|
||||
mStartDelayed = false;
|
||||
// Release the media player so it stops calling back to us
|
||||
if (mMediaPlayer)
|
||||
{
|
||||
libvlc_media_player_stop(mMediaPlayer);
|
||||
libvlc_media_player_release(mMediaPlayer);
|
||||
libvlc_media_release(mMedia);
|
||||
mMediaPlayer = NULL;
|
||||
freeContext();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoComponent::update(int deltaTime)
|
||||
{
|
||||
manageState();
|
||||
|
@ -532,10 +318,10 @@ void VideoComponent::update(int deltaTime)
|
|||
if (mStartDelayed)
|
||||
{
|
||||
Uint32 ticks = SDL_GetTicks();
|
||||
if (mStartTime > ticks)
|
||||
if (mStartTime > ticks)
|
||||
{
|
||||
Uint32 diff = mStartTime - ticks;
|
||||
if (diff < FADE_TIME_MS)
|
||||
if (diff < FADE_TIME_MS)
|
||||
{
|
||||
mFadeIn = (float)diff / (float)FADE_TIME_MS;
|
||||
return;
|
||||
|
@ -554,8 +340,9 @@ void VideoComponent::update(int deltaTime)
|
|||
|
||||
void VideoComponent::manageState()
|
||||
{
|
||||
// We will only show if the component is on display
|
||||
bool show = mShowing;
|
||||
// We will only show if the component is on display and the screensaver
|
||||
// is not active
|
||||
bool show = mShowing && !mScreensaverActive && !mDisable;
|
||||
|
||||
// See if we're already playing
|
||||
if (mIsPlaying)
|
||||
|
@ -598,4 +385,20 @@ void VideoComponent::onHide()
|
|||
manageState();
|
||||
}
|
||||
|
||||
void VideoComponent::onScreenSaverActivate()
|
||||
{
|
||||
mScreensaverActive = true;
|
||||
manageState();
|
||||
}
|
||||
|
||||
void VideoComponent::onScreenSaverDeactivate()
|
||||
{
|
||||
mScreensaverActive = false;
|
||||
manageState();
|
||||
}
|
||||
|
||||
void VideoComponent::topWindow(bool isTop)
|
||||
{
|
||||
mDisable = !isTop;
|
||||
manageState();
|
||||
}
|
||||
|
|
|
@ -8,18 +8,10 @@
|
|||
#include "ImageComponent.h"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "resources/TextureResource.h"
|
||||
#include <vlc/vlc.h>
|
||||
#include <SDL.h>
|
||||
#include <SDL_mutex.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
struct VideoContext {
|
||||
SDL_Surface* surface;
|
||||
SDL_mutex* mutex;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
class VideoComponent : public GuiComponent
|
||||
{
|
||||
// Structure that groups together the configuration of the video component
|
||||
|
@ -32,8 +24,6 @@ class VideoComponent : public GuiComponent
|
|||
};
|
||||
|
||||
public:
|
||||
static void setupVLC();
|
||||
|
||||
VideoComponent(Window* window);
|
||||
virtual ~VideoComponent();
|
||||
|
||||
|
@ -44,9 +34,12 @@ public:
|
|||
|
||||
// Configures the component to show the default video
|
||||
void setDefaultVideo();
|
||||
|
||||
|
||||
virtual void onShow() override;
|
||||
virtual void onHide() override;
|
||||
virtual void onScreenSaverActivate() override;
|
||||
virtual void onScreenSaverDeactivate() override;
|
||||
virtual void topWindow(bool isTop) override;
|
||||
|
||||
//Sets the origin as a percentage of this image (e.g. (0, 0) is top left, (0.5, 0.5) is the center)
|
||||
void setOrigin(float originX, float originY);
|
||||
|
@ -80,34 +73,23 @@ public:
|
|||
virtual void update(int deltaTime);
|
||||
|
||||
private:
|
||||
// Calculates the correct mSize from our resizing information (set by setResize/setMaxSize).
|
||||
// Used internally whenever the resizing parameters or texture change.
|
||||
void resize();
|
||||
|
||||
// Start the video Immediately
|
||||
void startVideo();
|
||||
virtual void startVideo() = 0;
|
||||
// Stop the video
|
||||
virtual void stopVideo() { };
|
||||
// Handle looping the video. Must be called periodically
|
||||
virtual void handleLooping();
|
||||
|
||||
// Start the video after any configured delay
|
||||
void startVideoWithDelay();
|
||||
// Stop the video
|
||||
void stopVideo();
|
||||
|
||||
void setupContext();
|
||||
void freeContext();
|
||||
|
||||
// Handle any delay to the start of playing the video clip. Must be called periodically
|
||||
void handleStartDelay();
|
||||
|
||||
// Handle looping the video. Must be called periodically
|
||||
void handleLooping();
|
||||
|
||||
// Manage the playing state of the component
|
||||
void manageState();
|
||||
|
||||
private:
|
||||
static libvlc_instance_t* mVLC;
|
||||
libvlc_media_t* mMedia;
|
||||
libvlc_media_player_t* mMediaPlayer;
|
||||
VideoContext mContext;
|
||||
protected:
|
||||
unsigned mVideoWidth;
|
||||
unsigned mVideoHeight;
|
||||
Eigen::Vector2f mOrigin;
|
||||
|
@ -123,6 +105,8 @@ private:
|
|||
unsigned mStartTime;
|
||||
bool mIsPlaying;
|
||||
bool mShowing;
|
||||
bool mDisable;
|
||||
bool mScreensaverActive;
|
||||
bool mTargetIsMax;
|
||||
|
||||
Configuration mConfig;
|
||||
|
|
98
es-core/src/components/VideoPlayerComponent.cpp
Normal file
98
es-core/src/components/VideoPlayerComponent.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#ifdef _RPI_
|
||||
#include "components/VideoPlayerComponent.h"
|
||||
#include "Renderer.h"
|
||||
#include "ThemeData.h"
|
||||
#include "Util.h"
|
||||
#include <signal.h>
|
||||
#include <wait.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
VideoPlayerComponent::VideoPlayerComponent(Window* window) :
|
||||
VideoComponent(window),
|
||||
mPlayerPid(-1)
|
||||
{
|
||||
}
|
||||
|
||||
VideoPlayerComponent::~VideoPlayerComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void VideoPlayerComponent::render(const Eigen::Affine3f& parentTrans)
|
||||
{
|
||||
VideoComponent::render(parentTrans);
|
||||
}
|
||||
|
||||
void VideoPlayerComponent::startVideo()
|
||||
{
|
||||
if (!mIsPlaying) {
|
||||
mVideoWidth = 0;
|
||||
mVideoHeight = 0;
|
||||
|
||||
std::string path(mVideoPath.c_str());
|
||||
|
||||
// Make sure we have a video path
|
||||
if ((path.size() > 0) && (mPlayerPid == -1))
|
||||
{
|
||||
// Set the video that we are going to be playing so we don't attempt to restart it
|
||||
mPlayingVideoPath = mVideoPath;
|
||||
|
||||
// Start the player process
|
||||
pid_t pid = fork();
|
||||
if (pid == -1)
|
||||
{
|
||||
// Failed
|
||||
mPlayingVideoPath = "";
|
||||
}
|
||||
else if (pid > 0)
|
||||
{
|
||||
mPlayerPid = pid;
|
||||
// Update the playing state
|
||||
mIsPlaying = true;
|
||||
mFadeIn = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find out the pixel position of the video view and build a command line for
|
||||
// omxplayer to position it in the right place
|
||||
char buf[32];
|
||||
float x = mPosition.x() - (mOrigin.x() * mSize.x());
|
||||
float y = mPosition.y() - (mOrigin.y() * mSize.y());
|
||||
sprintf(buf, "%d,%d,%d,%d", (int)x, (int)y, (int)(x + mSize.x()), (int)(y + mSize.y()));
|
||||
// We need to specify the layer of 10000 or above to ensure the video is displayed on top
|
||||
// of our SDL display
|
||||
const char* argv[] = { "", "--win", buf, "--layer", "10000", "--loop", "--no-osd", "", NULL };
|
||||
const char* env[] = { "LD_LIBRARY_PATH=/opt/vc/libs:/usr/lib/omxplayer", NULL };
|
||||
// Fill in the empty argument with the video path
|
||||
argv[7] = mPlayingVideoPath.c_str();
|
||||
// Redirect stdout
|
||||
int fdin = open("/dev/null", O_RDONLY);
|
||||
int fdout = open("/dev/null", O_WRONLY);
|
||||
dup2(fdin, 0);
|
||||
dup2(fdout, 1);
|
||||
// Run the omxplayer binary
|
||||
execve("/usr/bin/omxplayer.bin", (char**)argv, (char**)env);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VideoPlayerComponent::stopVideo()
|
||||
{
|
||||
mIsPlaying = false;
|
||||
mStartDelayed = false;
|
||||
|
||||
// Stop the player process
|
||||
if (mPlayerPid != -1)
|
||||
{
|
||||
int status;
|
||||
kill(mPlayerPid, SIGKILL);
|
||||
waitpid(mPlayerPid, &status, WNOHANG);
|
||||
mPlayerPid = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
30
es-core/src/components/VideoPlayerComponent.h
Normal file
30
es-core/src/components/VideoPlayerComponent.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifdef _RPI_
|
||||
#ifndef _VIDEOPLAYERCOMPONENT_H_
|
||||
#define _VIDEOPLAYERCOMPONENT_H_
|
||||
|
||||
#include "platform.h"
|
||||
#include GLHEADER
|
||||
|
||||
#include "components/VideoComponent.h"
|
||||
|
||||
class VideoPlayerComponent : public VideoComponent
|
||||
{
|
||||
public:
|
||||
VideoPlayerComponent(Window* window);
|
||||
virtual ~VideoPlayerComponent();
|
||||
|
||||
void render(const Eigen::Affine3f& parentTrans) override;
|
||||
|
||||
private:
|
||||
// Start the video Immediately
|
||||
virtual void startVideo();
|
||||
// Stop the video
|
||||
virtual void stopVideo();
|
||||
|
||||
private:
|
||||
pid_t mPlayerPid;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
247
es-core/src/components/VideoVlcComponent.cpp
Normal file
247
es-core/src/components/VideoVlcComponent.cpp
Normal file
|
@ -0,0 +1,247 @@
|
|||
#include "components/VideoVlcComponent.h"
|
||||
#include "Renderer.h"
|
||||
#include "ThemeData.h"
|
||||
#include "Util.h"
|
||||
#ifdef WIN32
|
||||
#include <codecvt>
|
||||
#endif
|
||||
|
||||
libvlc_instance_t* VideoVlcComponent::mVLC = NULL;
|
||||
|
||||
// VLC prepares to render a video frame.
|
||||
static void *lock(void *data, void **p_pixels) {
|
||||
struct VideoContext *c = (struct VideoContext *)data;
|
||||
SDL_LockMutex(c->mutex);
|
||||
SDL_LockSurface(c->surface);
|
||||
*p_pixels = c->surface->pixels;
|
||||
return NULL; // Picture identifier, not needed here.
|
||||
}
|
||||
|
||||
// VLC just rendered a video frame.
|
||||
static void unlock(void *data, void *id, void *const *p_pixels) {
|
||||
struct VideoContext *c = (struct VideoContext *)data;
|
||||
SDL_UnlockSurface(c->surface);
|
||||
SDL_UnlockMutex(c->mutex);
|
||||
}
|
||||
|
||||
// VLC wants to display a video frame.
|
||||
static void display(void *data, void *id) {
|
||||
//Data to be displayed
|
||||
}
|
||||
|
||||
VideoVlcComponent::VideoVlcComponent(Window* window) :
|
||||
VideoComponent(window),
|
||||
mMediaPlayer(nullptr)
|
||||
{
|
||||
memset(&mContext, 0, sizeof(mContext));
|
||||
|
||||
// Get an empty texture for rendering the video
|
||||
mTexture = TextureResource::get("");
|
||||
|
||||
// Make sure VLC has been initialised
|
||||
setupVLC();
|
||||
}
|
||||
|
||||
VideoVlcComponent::~VideoVlcComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void VideoVlcComponent::render(const Eigen::Affine3f& parentTrans)
|
||||
{
|
||||
VideoComponent::render(parentTrans);
|
||||
float x, y;
|
||||
|
||||
Eigen::Affine3f trans = parentTrans * getTransform();
|
||||
GuiComponent::renderChildren(trans);
|
||||
|
||||
Renderer::setMatrix(trans);
|
||||
|
||||
if (mIsPlaying && mContext.valid)
|
||||
{
|
||||
float tex_offs_x = 0.0f;
|
||||
float tex_offs_y = 0.0f;
|
||||
float x2;
|
||||
float y2;
|
||||
|
||||
x = -(float)mSize.x() * mOrigin.x();
|
||||
y = -(float)mSize.y() * mOrigin.y();
|
||||
x2 = x+mSize.x();
|
||||
y2 = y+mSize.y();
|
||||
|
||||
// Define a structure to contain the data for each vertex
|
||||
struct Vertex
|
||||
{
|
||||
Eigen::Vector2f pos;
|
||||
Eigen::Vector2f tex;
|
||||
Eigen::Vector4f colour;
|
||||
} vertices[6];
|
||||
|
||||
// We need two triangles to cover the rectangular area
|
||||
vertices[0].pos[0] = x; vertices[0].pos[1] = y;
|
||||
vertices[1].pos[0] = x; vertices[1].pos[1] = y2;
|
||||
vertices[2].pos[0] = x2; vertices[2].pos[1] = y;
|
||||
|
||||
vertices[3].pos[0] = x2; vertices[3].pos[1] = y;
|
||||
vertices[4].pos[0] = x; vertices[4].pos[1] = y2;
|
||||
vertices[5].pos[0] = x2; vertices[5].pos[1] = y2;
|
||||
|
||||
// Texture coordinates
|
||||
vertices[0].tex[0] = -tex_offs_x; vertices[0].tex[1] = -tex_offs_y;
|
||||
vertices[1].tex[0] = -tex_offs_x; vertices[1].tex[1] = 1.0f + tex_offs_y;
|
||||
vertices[2].tex[0] = 1.0f + tex_offs_x; vertices[2].tex[1] = -tex_offs_y;
|
||||
|
||||
vertices[3].tex[0] = 1.0f + tex_offs_x; vertices[3].tex[1] = -tex_offs_y;
|
||||
vertices[4].tex[0] = -tex_offs_x; vertices[4].tex[1] = 1.0f + tex_offs_y;
|
||||
vertices[5].tex[0] = 1.0f + tex_offs_x; vertices[5].tex[1] = 1.0f + tex_offs_y;
|
||||
|
||||
// Colours - use this to fade the video in and out
|
||||
for (int i = 0; i < (4 * 6); ++i) {
|
||||
if ((i%4) < 3)
|
||||
vertices[i / 4].colour[i % 4] = mFadeIn;
|
||||
else
|
||||
vertices[i / 4].colour[i % 4] = 1.0f;
|
||||
}
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
// Build a texture for the video frame
|
||||
mTexture->initFromPixels((unsigned char*)mContext.surface->pixels, mContext.surface->w, mContext.surface->h);
|
||||
mTexture->bind();
|
||||
|
||||
// Render it
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glColorPointer(4, GL_FLOAT, sizeof(Vertex), &vertices[0].colour);
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].pos);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].tex);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoVlcComponent::setupContext()
|
||||
{
|
||||
if (!mContext.valid)
|
||||
{
|
||||
// Create an RGBA surface to render the video into
|
||||
mContext.surface = SDL_CreateRGBSurface(SDL_SWSURFACE, (int)mVideoWidth, (int)mVideoHeight, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
|
||||
mContext.mutex = SDL_CreateMutex();
|
||||
mContext.valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
void VideoVlcComponent::freeContext()
|
||||
{
|
||||
if (mContext.valid)
|
||||
{
|
||||
SDL_FreeSurface(mContext.surface);
|
||||
SDL_DestroyMutex(mContext.mutex);
|
||||
mContext.valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
void VideoVlcComponent::setupVLC()
|
||||
{
|
||||
// If VLC hasn't been initialised yet then do it now
|
||||
if (!mVLC)
|
||||
{
|
||||
const char* args[] = { "--quiet" };
|
||||
mVLC = libvlc_new(sizeof(args) / sizeof(args[0]), args);
|
||||
}
|
||||
}
|
||||
|
||||
void VideoVlcComponent::handleLooping()
|
||||
{
|
||||
if (mIsPlaying && mMediaPlayer)
|
||||
{
|
||||
libvlc_state_t state = libvlc_media_player_get_state(mMediaPlayer);
|
||||
if (state == libvlc_Ended)
|
||||
{
|
||||
//libvlc_media_player_set_position(mMediaPlayer, 0.0f);
|
||||
libvlc_media_player_set_media(mMediaPlayer, mMedia);
|
||||
libvlc_media_player_play(mMediaPlayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VideoVlcComponent::startVideo()
|
||||
{
|
||||
if (!mIsPlaying) {
|
||||
mVideoWidth = 0;
|
||||
mVideoHeight = 0;
|
||||
|
||||
#ifdef WIN32
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wton;
|
||||
std::string path = wton.to_bytes(mVideoPath.c_str());
|
||||
#else
|
||||
std::string path(mVideoPath.c_str());
|
||||
#endif
|
||||
// Make sure we have a video path
|
||||
if (mVLC && (path.size() > 0))
|
||||
{
|
||||
// Set the video that we are going to be playing so we don't attempt to restart it
|
||||
mPlayingVideoPath = mVideoPath;
|
||||
|
||||
// Open the media
|
||||
mMedia = libvlc_media_new_path(mVLC, path.c_str());
|
||||
if (mMedia)
|
||||
{
|
||||
unsigned track_count;
|
||||
// Get the media metadata so we can find the aspect ratio
|
||||
libvlc_media_parse(mMedia);
|
||||
libvlc_media_track_t** tracks;
|
||||
track_count = libvlc_media_tracks_get(mMedia, &tracks);
|
||||
for (unsigned track = 0; track < track_count; ++track)
|
||||
{
|
||||
if (tracks[track]->i_type == libvlc_track_video)
|
||||
{
|
||||
mVideoWidth = tracks[track]->video->i_width;
|
||||
mVideoHeight = tracks[track]->video->i_height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
libvlc_media_tracks_release(tracks, track_count);
|
||||
|
||||
// Make sure we found a valid video track
|
||||
if ((mVideoWidth > 0) && (mVideoHeight > 0))
|
||||
{
|
||||
setupContext();
|
||||
|
||||
// Setup the media player
|
||||
mMediaPlayer = libvlc_media_player_new_from_media(mMedia);
|
||||
libvlc_media_player_play(mMediaPlayer);
|
||||
libvlc_video_set_callbacks(mMediaPlayer, lock, unlock, display, (void*)&mContext);
|
||||
libvlc_video_set_format(mMediaPlayer, "RGBA", (int)mVideoWidth, (int)mVideoHeight, (int)mVideoWidth * 4);
|
||||
|
||||
// Update the playing state
|
||||
mIsPlaying = true;
|
||||
mFadeIn = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VideoVlcComponent::stopVideo()
|
||||
{
|
||||
mIsPlaying = false;
|
||||
mStartDelayed = false;
|
||||
// Release the media player so it stops calling back to us
|
||||
if (mMediaPlayer)
|
||||
{
|
||||
libvlc_media_player_stop(mMediaPlayer);
|
||||
libvlc_media_player_release(mMediaPlayer);
|
||||
libvlc_media_release(mMedia);
|
||||
mMediaPlayer = NULL;
|
||||
freeContext();
|
||||
}
|
||||
}
|
||||
|
55
es-core/src/components/VideoVlcComponent.h
Normal file
55
es-core/src/components/VideoVlcComponent.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
#ifndef _VIDEOVLCCOMPONENT_H_
|
||||
#define _VIDEOVLCCOMPONENT_H_
|
||||
|
||||
#include "platform.h"
|
||||
#include GLHEADER
|
||||
|
||||
#include "VideoComponent.h"
|
||||
#include <vlc/vlc.h>
|
||||
#include "resources/TextureResource.h"
|
||||
|
||||
struct VideoContext {
|
||||
SDL_Surface* surface;
|
||||
SDL_mutex* mutex;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
class VideoVlcComponent : public VideoComponent
|
||||
{
|
||||
// Structure that groups together the configuration of the video component
|
||||
struct Configuration
|
||||
{
|
||||
unsigned startDelay;
|
||||
bool showSnapshotNoVideo;
|
||||
bool showSnapshotDelay;
|
||||
std::string defaultVideoPath;
|
||||
};
|
||||
|
||||
public:
|
||||
static void setupVLC();
|
||||
|
||||
VideoVlcComponent(Window* window);
|
||||
virtual ~VideoVlcComponent();
|
||||
|
||||
void render(const Eigen::Affine3f& parentTrans) override;
|
||||
|
||||
private:
|
||||
// Start the video Immediately
|
||||
virtual void startVideo();
|
||||
// Stop the video
|
||||
virtual void stopVideo();
|
||||
// Handle looping the video. Must be called periodically
|
||||
virtual void handleLooping();
|
||||
|
||||
void setupContext();
|
||||
void freeContext();
|
||||
|
||||
private:
|
||||
static libvlc_instance_t* mVLC;
|
||||
libvlc_media_t* mMedia;
|
||||
libvlc_media_player_t* mMediaPlayer;
|
||||
VideoContext mContext;
|
||||
std::shared_ptr<TextureResource> mTexture;
|
||||
};
|
||||
|
||||
#endif
|
1
external/pugixml
vendored
1
external/pugixml
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit d2deb420bc70369faa12785df2b5dd4d390e523d
|
Loading…
Reference in a new issue