Fixes and tweaks to OMXPlayer work, by pjft

- Correct handling of zombie processes left in memory
- Add options to mute video
- Fix resizing to work with theme refactorings introduced by jdrassa and zigurana
This commit is contained in:
pjft 2017-03-25 17:02:28 +00:00
parent 34ea9caa89
commit 029e8bd040
13 changed files with 266 additions and 128 deletions

3
.gitmodules vendored
View file

@ -0,0 +1,3 @@
[submodule "external/pugixml"]
path = external/pugixml
url = https://github.com/zeux/pugixml.git

View file

@ -78,7 +78,7 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
// disable sounds // disable sounds
auto sounds_enabled = std::make_shared<SwitchComponent>(mWindow); auto sounds_enabled = std::make_shared<SwitchComponent>(mWindow);
sounds_enabled->setState(Settings::getInstance()->getBool("EnableSounds")); sounds_enabled->setState(Settings::getInstance()->getBool("EnableSounds"));
s->addWithLabel("ENABLE SOUNDS", sounds_enabled); s->addWithLabel("ENABLE NAVIGATION SOUNDS", sounds_enabled);
s->addSaveFunc([sounds_enabled] { Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState()); }); s->addSaveFunc([sounds_enabled] { Settings::getInstance()->setBool("EnableSounds", sounds_enabled->getState()); });
mWindow->pushGui(s); mWindow->pushGui(s);
@ -181,6 +181,36 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mMenu(window, "MAIN MEN
mWindow->pushGui(s); mWindow->pushGui(s);
}); });
addEntry("VIDEO PLAYER SETTINGS", 0x777777FF, true,
[this] {
auto s = new GuiSettings(mWindow, "VIDEO PLAYER SETTINGS");
#ifdef _RPI_
// Video Player - VideoOmxPlayer
auto omx_player = std::make_shared<SwitchComponent>(mWindow);
omx_player->setState(Settings::getInstance()->getBool("VideoOmxPlayer"));
s->addWithLabel("USE OMX VIDEO PLAYER (HW ACCELERATED)", omx_player);
s->addSaveFunc([omx_player]
{
// need to reload all views to re-create the right video components
bool needReload = false;
if(Settings::getInstance()->getBool("VideoOmxPlayer") != omx_player->getState())
needReload = true;
Settings::getInstance()->setBool("VideoOmxPlayer", omx_player->getState());
if(needReload)
ViewController::get()->reloadAll();
});
#endif
auto video_audio = std::make_shared<SwitchComponent>(mWindow);
video_audio->setState(Settings::getInstance()->getBool("VideoAudio"));
s->addWithLabel("ENABLE VIDEO AUDIO", video_audio);
s->addSaveFunc([video_audio] { Settings::getInstance()->setBool("VideoAudio", video_audio->getState()); });
mWindow->pushGui(s);
});
addEntry("OTHER SETTINGS", 0x777777FF, true, addEntry("OTHER SETTINGS", 0x777777FF, true,
[this] { [this] {
auto s = new GuiSettings(mWindow, "OTHER SETTINGS"); auto s = new GuiSettings(mWindow, "OTHER SETTINGS");

View file

@ -61,7 +61,7 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root) :
mVideo->setPosition(mSize.x() * 0.25f, mSize.y() * 0.4f); mVideo->setPosition(mSize.x() * 0.25f, mSize.y() * 0.4f);
mVideo->setSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.4f); mVideo->setSize(mSize.x() * (0.5f - 2*padding), mSize.y() * 0.4f);
mVideo->setDefaultZIndex(30); mVideo->setDefaultZIndex(30);
addChild(&mVideo); addChild(mVideo);
// metadata labels + values // metadata labels + values
mLblRating.setText("Rating: "); mLblRating.setText("Rating: ");

View file

@ -79,11 +79,9 @@ void Settings::setDefaults()
// This setting only applies to raspberry pi but set it for all platforms so // 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 // we don't get a warning if we encounter it on a different platform
#ifdef _RPI_
mBoolMap["VideoOmxPlayer"] = true;
#else
mBoolMap["VideoOmxPlayer"] = false; mBoolMap["VideoOmxPlayer"] = false;
#endif mBoolMap["VideoAudio"] = true;
} }
template <typename K, typename V> template <typename K, typename V>

View file

@ -115,10 +115,20 @@ void Window::textInput(const char* text)
void Window::input(InputConfig* config, Input input) void Window::input(InputConfig* config, Input input)
{ {
if (mRenderScreenSaver)
{
mRenderScreenSaver = false;
// Tell the GUI components the screensaver has stopped
for(auto i = mGuiStack.begin(); i != mGuiStack.end(); i++)
(*i)->onScreenSaverDeactivate();
}
if(mSleeping) if(mSleeping)
{ {
// wake up // wake up
mTimeSinceLastInput = 0; mTimeSinceLastInput = 0;
mSleeping = false; mSleeping = false;
onWake(); onWake();
return; return;
@ -218,6 +228,13 @@ void Window::render()
unsigned int screensaverTime = (unsigned int)Settings::getInstance()->getInt("ScreenSaverTime"); unsigned int screensaverTime = (unsigned int)Settings::getInstance()->getInt("ScreenSaverTime");
if(mTimeSinceLastInput >= screensaverTime && screensaverTime != 0) if(mTimeSinceLastInput >= screensaverTime && screensaverTime != 0)
{ {
if (!mRenderScreenSaver)
{
for(auto i = mGuiStack.begin(); i != mGuiStack.end(); i++)
(*i)->onScreenSaverActivate();
mRenderScreenSaver = true;
}
renderScreenSaver(); renderScreenSaver();
if (!isProcessing() && mAllowSleep) if (!isProcessing() && mAllowSleep)

View file

@ -17,6 +17,7 @@ public:
void pushGui(GuiComponent* gui); void pushGui(GuiComponent* gui);
void removeGui(GuiComponent* gui); void removeGui(GuiComponent* gui);
GuiComponent* peekGui(); GuiComponent* peekGui();
inline int getGuiStackSize() { return mGuiStack.size(); }
void textInput(const char* text); void textInput(const char* text);
void input(InputConfig* config, Input input); void input(InputConfig* config, Input input);
@ -55,6 +56,7 @@ private:
int mFrameTimeElapsed; int mFrameTimeElapsed;
int mFrameCountElapsed; int mFrameCountElapsed;
int mAverageDeltaTime; int mAverageDeltaTime;
bool mRenderScreenSaver;
std::unique_ptr<TextCache> mFrameDataText; std::unique_ptr<TextCache> mFrameDataText;

View file

@ -2,6 +2,7 @@
#include "Renderer.h" #include "Renderer.h"
#include "ThemeData.h" #include "ThemeData.h"
#include "Util.h" #include "Util.h"
#include "Window.h"
#ifdef WIN32 #ifdef WIN32
#include <codecvt> #include <codecvt>
#endif #endif
@ -26,6 +27,10 @@ VideoComponent::VideoComponent(Window* window) :
mConfig.showSnapshotDelay = false; mConfig.showSnapshotDelay = false;
mConfig.showSnapshotNoVideo = false; mConfig.showSnapshotNoVideo = false;
mConfig.startDelay = 0; mConfig.startDelay = 0;
if (mWindow->getGuiStackSize() > 1) {
topWindow(false);
}
} }
VideoComponent::~VideoComponent() VideoComponent::~VideoComponent()
@ -42,89 +47,12 @@ void VideoComponent::setOrigin(float originX, float originY)
mStaticImage.setOrigin(originX, originY); mStaticImage.setOrigin(originX, originY);
} }
void VideoComponent::setResize(float width, float height)
{
mTargetSize << width, height;
mTargetIsMax = false;
mStaticImage.setResize(width, height);
resize();
}
void VideoComponent::setMaxSize(float width, float height)
{
mTargetSize << width, height;
mTargetIsMax = true;
mStaticImage.setMaxSize(width, height);
resize();
}
Eigen::Vector2f VideoComponent::getCenter() const Eigen::Vector2f VideoComponent::getCenter() const
{ {
return Eigen::Vector2f(mPosition.x() - (getSize().x() * mOrigin.x()) + getSize().x() / 2, return Eigen::Vector2f(mPosition.x() - (getSize().x() * mOrigin.x()) + getSize().x() / 2,
mPosition.y() - (getSize().y() * mOrigin.y()) + getSize().y() / 2); mPosition.y() - (getSize().y() * mOrigin.y()) + getSize().y() / 2);
} }
void VideoComponent::resize()
{
if(!mTexture)
return;
const Eigen::Vector2f textureSize(mVideoWidth, mVideoHeight);
if(textureSize.isZero())
return;
// SVG rasterization is determined by height (see SVGResource.cpp), and rasterization is done in terms of pixels
// if rounding is off enough in the rasterization step (for images with extreme aspect ratios), it can cause cutoff when the aspect ratio breaks
// so, we always make sure the resultant height is an integer to make sure cutoff doesn't happen, and scale width from that
// (you'll see this scattered throughout the function)
// this is probably not the best way, so if you're familiar with this problem and have a better solution, please make a pull request!
if(mTargetIsMax)
{
mSize = textureSize;
Eigen::Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y()));
if(resizeScale.x() < resizeScale.y())
{
mSize[0] *= resizeScale.x();
mSize[1] *= resizeScale.x();
}else{
mSize[0] *= resizeScale.y();
mSize[1] *= resizeScale.y();
}
// for SVG rasterization, always calculate width from rounded height (see comment above)
mSize[1] = round(mSize[1]);
mSize[0] = (mSize[1] / textureSize.y()) * textureSize.x();
}else{
// if both components are set, we just stretch
// if no components are set, we don't resize at all
mSize = mTargetSize.isZero() ? textureSize : mTargetSize;
// if only one component is set, we resize in a way that maintains aspect ratio
// for SVG rasterization, we always calculate width from rounded height (see comment above)
if(!mTargetSize.x() && mTargetSize.y())
{
mSize[1] = round(mTargetSize.y());
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
}else if(mTargetSize.x() && !mTargetSize.y())
{
mSize[1] = round((mTargetSize.x() / textureSize.x()) * textureSize.y());
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
}
}
// mSize.y() should already be rounded
mTexture->rasterizeAt((int)round(mSize.x()), (int)round(mSize.y()));
onSizeChanged();
}
void VideoComponent::onSizeChanged() void VideoComponent::onSizeChanged()
{ {
// Update the embeded static image // Update the embeded static image
@ -161,6 +89,8 @@ void VideoComponent::setImage(std::string path)
return; return;
mStaticImage.setImage(path); mStaticImage.setImage(path);
// Make the image stretch to fill the video region
mStaticImage.setSize(getSize());
mFadeIn = 0.0f; mFadeIn = 0.0f;
mStaticImagePath = path; mStaticImagePath = path;
} }

View file

@ -48,19 +48,6 @@ public:
void onSizeChanged() override; void onSizeChanged() override;
void setOpacity(unsigned char opacity) override; void setOpacity(unsigned char opacity) override;
// Resize the video to fit this size. If one axis is zero, scale that axis to maintain aspect ratio.
// If both are non-zero, potentially break the aspect ratio. If both are zero, no resizing.
// Can be set before or after a video is loaded.
// setMaxSize() and setResize() are mutually exclusive.
void setResize(float width, float height);
inline void setResize(const Eigen::Vector2f& size) { setResize(size.x(), size.y()); }
// Resize the video to be as large as possible but fit within a box of this size.
// Can be set before or after a video is loaded.
// Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive.
void setMaxSize(float width, float height);
inline void setMaxSize(const Eigen::Vector2f& size) { setMaxSize(size.x(), size.y()); }
void render(const Eigen::Affine3f& parentTrans) override; void render(const Eigen::Affine3f& parentTrans) override;
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override; virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override;
@ -72,6 +59,19 @@ public:
virtual void update(int deltaTime); virtual void update(int deltaTime);
// Resize the video to fit this size. If one axis is zero, scale that axis to maintain aspect ratio.
// If both are non-zero, potentially break the aspect ratio. If both are zero, no resizing.
// Can be set before or after a video is loaded.
// setMaxSize() and setResize() are mutually exclusive.
virtual void setResize(float width, float height) = 0;
inline void setResize(const Eigen::Vector2f& size) { setResize(size.x(), size.y()); }
// Resize the video to be as large as possible but fit within a box of this size.
// Can be set before or after a video is loaded.
// Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive.
virtual void setMaxSize(float width, float height) = 0;
inline void setMaxSize(const Eigen::Vector2f& size) { setMaxSize(size.x(), size.y()); }
private: private:
// Start the video Immediately // Start the video Immediately
virtual void startVideo() = 0; virtual void startVideo() = 0;

View file

@ -2,6 +2,7 @@
#include "components/VideoPlayerComponent.h" #include "components/VideoPlayerComponent.h"
#include "Renderer.h" #include "Renderer.h"
#include "ThemeData.h" #include "ThemeData.h"
#include "Settings.h"
#include "Util.h" #include "Util.h"
#include <signal.h> #include <signal.h>
#include <wait.h> #include <wait.h>
@ -24,6 +25,24 @@ void VideoPlayerComponent::render(const Eigen::Affine3f& parentTrans)
VideoComponent::render(parentTrans); VideoComponent::render(parentTrans);
} }
void VideoPlayerComponent::setResize(float width, float height)
{
setSize(width, height);
mTargetSize << width, height;
mTargetIsMax = false;
mStaticImage.setSize(width, height);
onSizeChanged();
}
void VideoPlayerComponent::setMaxSize(float width, float height)
{
setSize(width, height);
mTargetSize << width, height;
mTargetIsMax = true;
mStaticImage.setMaxSize(width, height);
onSizeChanged();
}
void VideoPlayerComponent::startVideo() void VideoPlayerComponent::startVideo()
{ {
if (!mIsPlaying) { if (!mIsPlaying) {
@ -49,11 +68,13 @@ void VideoPlayerComponent::startVideo()
{ {
mPlayerPid = pid; mPlayerPid = pid;
// Update the playing state // Update the playing state
signal(SIGCHLD, catch_child);
mIsPlaying = true; mIsPlaying = true;
mFadeIn = 0.0f; mFadeIn = 0.0f;
} }
else else
{ {
// Find out the pixel position of the video view and build a command line for // Find out the pixel position of the video view and build a command line for
// omxplayer to position it in the right place // omxplayer to position it in the right place
char buf[32]; char buf[32];
@ -62,10 +83,25 @@ void VideoPlayerComponent::startVideo()
sprintf(buf, "%d,%d,%d,%d", (int)x, (int)y, (int)(x + mSize.x()), (int)(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 // We need to specify the layer of 10000 or above to ensure the video is displayed on top
// of our SDL display // of our SDL display
const char* argv[] = { "", "--win", buf, "--layer", "10000", "--loop", "--no-osd", "", NULL };
const char* argv[] = { "", "--layer", "10010", "--loop", "--no-osd", "--aspect-mode", "letterbox", "--vol", "0", "--win", buf, "-b", "", "", "", "", NULL };
// check if we want to mute the audio
if (!Settings::getInstance()->getBool("VideoAudio"))
{
argv[8] = "-1000000";
}
// if we are rendering a video gamelist
if (!mTargetIsMax)
{
argv[6] = "stretch";
}
argv[11] = mPlayingVideoPath.c_str();
const char* env[] = { "LD_LIBRARY_PATH=/opt/vc/libs:/usr/lib/omxplayer", 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 // Redirect stdout
int fdin = open("/dev/null", O_RDONLY); int fdin = open("/dev/null", O_RDONLY);
int fdout = open("/dev/null", O_WRONLY); int fdout = open("/dev/null", O_WRONLY);
@ -73,12 +109,20 @@ void VideoPlayerComponent::startVideo()
dup2(fdout, 1); dup2(fdout, 1);
// Run the omxplayer binary // Run the omxplayer binary
execve("/usr/bin/omxplayer.bin", (char**)argv, (char**)env); execve("/usr/bin/omxplayer.bin", (char**)argv, (char**)env);
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
} }
} }
} }
void catch_child(int sig_num)
{
/* when we get here, we know there's a zombie child waiting */
int child_status;
wait(&child_status);
}
void VideoPlayerComponent::stopVideo() void VideoPlayerComponent::stopVideo()
{ {
mIsPlaying = false; mIsPlaying = false;

View file

@ -7,6 +7,8 @@
#include "components/VideoComponent.h" #include "components/VideoComponent.h"
void catch_child(int sig_num);
class VideoPlayerComponent : public VideoComponent class VideoPlayerComponent : public VideoComponent
{ {
public: public:
@ -15,6 +17,17 @@ public:
void render(const Eigen::Affine3f& parentTrans) override; void render(const Eigen::Affine3f& parentTrans) override;
// Resize the video to fit this size. If one axis is zero, scale that axis to maintain aspect ratio.
// If both are non-zero, potentially break the aspect ratio. If both are zero, no resizing.
// Can be set before or after a video is loaded.
// setMaxSize() and setResize() are mutually exclusive.
void setResize(float width, float height);
// Resize the video to be as large as possible but fit within a box of this size.
// Can be set before or after a video is loaded.
// Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive.
void setMaxSize(float width, float height);
private: private:
// Start the video Immediately // Start the video Immediately
virtual void startVideo(); virtual void startVideo();

View file

@ -2,6 +2,7 @@
#include "Renderer.h" #include "Renderer.h"
#include "ThemeData.h" #include "ThemeData.h"
#include "Util.h" #include "Util.h"
#include "Settings.h"
#ifdef WIN32 #ifdef WIN32
#include <codecvt> #include <codecvt>
#endif #endif
@ -46,6 +47,82 @@ VideoVlcComponent::~VideoVlcComponent()
{ {
} }
void VideoVlcComponent::setResize(float width, float height)
{
mTargetSize << width, height;
mTargetIsMax = false;
mStaticImage.setResize(width, height);
resize();
}
void VideoVlcComponent::setMaxSize(float width, float height)
{
mTargetSize << width, height;
mTargetIsMax = true;
mStaticImage.setMaxSize(width, height);
resize();
}
void VideoVlcComponent::resize()
{
if(!mTexture)
return;
const Eigen::Vector2f textureSize(mVideoWidth, mVideoHeight);
if(textureSize.isZero())
return;
// SVG rasterization is determined by height (see SVGResource.cpp), and rasterization is done in terms of pixels
// if rounding is off enough in the rasterization step (for images with extreme aspect ratios), it can cause cutoff when the aspect ratio breaks
// so, we always make sure the resultant height is an integer to make sure cutoff doesn't happen, and scale width from that
// (you'll see this scattered throughout the function)
// this is probably not the best way, so if you're familiar with this problem and have a better solution, please make a pull request!
if(mTargetIsMax)
{
mSize = textureSize;
Eigen::Vector2f resizeScale((mTargetSize.x() / mSize.x()), (mTargetSize.y() / mSize.y()));
if(resizeScale.x() < resizeScale.y())
{
mSize[0] *= resizeScale.x();
mSize[1] *= resizeScale.x();
}else{
mSize[0] *= resizeScale.y();
mSize[1] *= resizeScale.y();
}
// for SVG rasterization, always calculate width from rounded height (see comment above)
mSize[1] = round(mSize[1]);
mSize[0] = (mSize[1] / textureSize.y()) * textureSize.x();
}else{
// if both components are set, we just stretch
// if no components are set, we don't resize at all
mSize = mTargetSize.isZero() ? textureSize : mTargetSize;
// if only one component is set, we resize in a way that maintains aspect ratio
// for SVG rasterization, we always calculate width from rounded height (see comment above)
if(!mTargetSize.x() && mTargetSize.y())
{
mSize[1] = round(mTargetSize.y());
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
}else if(mTargetSize.x() && !mTargetSize.y())
{
mSize[1] = round((mTargetSize.x() / textureSize.x()) * textureSize.y());
mSize[0] = (mSize.y() / textureSize.y()) * textureSize.x();
}
}
// mSize.y() should already be rounded
mTexture->rasterizeAt((int)round(mSize.x()), (int)round(mSize.y()));
onSizeChanged();
}
void VideoVlcComponent::render(const Eigen::Affine3f& parentTrans) void VideoVlcComponent::render(const Eigen::Affine3f& parentTrans)
{ {
VideoComponent::render(parentTrans); VideoComponent::render(parentTrans);
@ -135,6 +212,7 @@ void VideoVlcComponent::setupContext()
mContext.surface = SDL_CreateRGBSurface(SDL_SWSURFACE, (int)mVideoWidth, (int)mVideoHeight, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); mContext.surface = SDL_CreateRGBSurface(SDL_SWSURFACE, (int)mVideoWidth, (int)mVideoHeight, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
mContext.mutex = SDL_CreateMutex(); mContext.mutex = SDL_CreateMutex();
mContext.valid = true; mContext.valid = true;
resize();
} }
} }
@ -153,7 +231,9 @@ void VideoVlcComponent::setupVLC()
// If VLC hasn't been initialised yet then do it now // If VLC hasn't been initialised yet then do it now
if (!mVLC) if (!mVLC)
{ {
const char* args[] = { "--quiet" }; const char* args[] = { "--quiet", "", "", "" };
// check if we want to mute the audio
mVLC = libvlc_new(sizeof(args) / sizeof(args[0]), args); mVLC = libvlc_new(sizeof(args) / sizeof(args[0]), args);
} }
} }
@ -217,6 +297,11 @@ void VideoVlcComponent::startVideo()
// Setup the media player // Setup the media player
mMediaPlayer = libvlc_media_player_new_from_media(mMedia); mMediaPlayer = libvlc_media_player_new_from_media(mMedia);
if (!Settings::getInstance()->getBool("VideoAudio"))
{
libvlc_audio_set_mute(mMediaPlayer, 1);
}
libvlc_media_player_play(mMediaPlayer); libvlc_media_player_play(mMediaPlayer);
libvlc_video_set_callbacks(mMediaPlayer, lock, unlock, display, (void*)&mContext); libvlc_video_set_callbacks(mMediaPlayer, lock, unlock, display, (void*)&mContext);
libvlc_video_set_format(mMediaPlayer, "RGBA", (int)mVideoWidth, (int)mVideoHeight, (int)mVideoWidth * 4); libvlc_video_set_format(mMediaPlayer, "RGBA", (int)mVideoWidth, (int)mVideoHeight, (int)mVideoWidth * 4);

View file

@ -33,7 +33,22 @@ public:
void render(const Eigen::Affine3f& parentTrans) override; void render(const Eigen::Affine3f& parentTrans) override;
// Resize the video to fit this size. If one axis is zero, scale that axis to maintain aspect ratio.
// If both are non-zero, potentially break the aspect ratio. If both are zero, no resizing.
// Can be set before or after a video is loaded.
// setMaxSize() and setResize() are mutually exclusive.
void setResize(float width, float height);
// Resize the video to be as large as possible but fit within a box of this size.
// Can be set before or after a video is loaded.
// Never breaks the aspect ratio. setMaxSize() and setResize() are mutually exclusive.
void setMaxSize(float width, float height);
private: 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 // Start the video Immediately
virtual void startVideo(); virtual void startVideo();
// Stop the video // Stop the video

1
external/pugixml vendored Submodule

@ -0,0 +1 @@
Subproject commit d2deb420bc70369faa12785df2b5dd4d390e523d