aboutsummaryrefslogtreecommitdiff
path: root/src/VideoPlayer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VideoPlayer.cpp')
-rw-r--r--src/VideoPlayer.cpp157
1 files changed, 77 insertions, 80 deletions
diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp
index 304ef2d..ecbca34 100644
--- a/src/VideoPlayer.cpp
+++ b/src/VideoPlayer.cpp
@@ -1,66 +1,31 @@
#include "../include/VideoPlayer.hpp"
+#include <SFML/Window/Mouse.hpp>
#include <mpv/client.h>
#include <mpv/opengl_cb.h>
+#include <SFML/OpenGL.hpp>
#include <clocale>
-#include <SFML/Config.hpp>
-
-#if defined(SFML_SYSTEM_WINDOWS)
- #ifdef _MSC_VER
- #include <windows.h>
- #endif
- #include <GL/gl.h>
- #include <GL/glx.h>
-#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
- #if defined(SFML_OPENGL_ES)
- #include <GLES/gl.h>
- #include <GLES/glext.h>
- #else
- #include <GL/gl.h>
- #endif
- #include <GL/glx.h>
- #define glGetProcAddress glXGetProcAddress
-#elif defined(SFML_SYSTEM_MACOS)
- #include <OpenGL/gl.h>
-#elif defined (SFML_SYSTEM_IOS)
- #include <OpenGLES/ES1/gl.h>
- #include <OpenGLES/ES1/glext.h>
-#elif defined (SFML_SYSTEM_ANDROID)
- #include <GLES/gl.h>
- #include <GLES/glext.h>
- // We're not using OpenGL ES 2+ yet, but we can use the sRGB extension
- #include <GLES2/gl2ext.h>
-#endif
-
-using namespace std;
-
namespace QuickMedia {
void* getProcAddressMpv(void *funcContext, const char *name) {
- return (void*)glGetProcAddress((const GLubyte*)name);
+ VideoPlayer *video_player = (VideoPlayer*)funcContext;
+ return (void*)video_player->context.getFunction(name);
}
void onMpvRedraw(void *rawVideo) {
- VideoPlayer *video = (VideoPlayer*)rawVideo;
- ++video->redrawCounter;
+ VideoPlayer *video_player = (VideoPlayer*)rawVideo;
+ ++video_player->redrawCounter;
}
VideoPlayer::VideoPlayer(unsigned int width, unsigned int height, const char *file, bool loop) :
redrawCounter(0),
context(sf::ContextSettings(), width, height),
+ onPlaybackEndedCallback(nullptr),
mpv(nullptr),
mpvGl(nullptr),
- textureBuffer((sf::Uint8*)malloc(width * height * 4)), // 4 = red, green, blue and alpha
- alive(true),
- video_size(width, height),
- desired_size(width, height)
+ textureBuffer(nullptr),
+ alive(true)
{
- if(!textureBuffer)
- throw VideoInitializationException("Failed to allocate memory for video");
-
context.setActive(true);
-
- if(!texture.create(width, height))
- throw VideoInitializationException("Failed to create texture for video");
texture.setSmooth(true);
// mpv_create requires LC_NUMERIC to be set to "C" for some reason, see mpv_create documentation
@@ -68,27 +33,29 @@ namespace QuickMedia {
mpv = mpv_create();
if(!mpv)
throw VideoInitializationException("Failed to create mpv handle");
-
- if(mpv_initialize(mpv) < 0)
- throw VideoInitializationException("Failed to initialize mpv");
mpv_set_option_string(mpv, "input-default-bindings", "yes");
- // Enable keyboard input on the X11 window
mpv_set_option_string(mpv, "input-vo-keyboard", "yes");
mpv_set_option_string(mpv, "vo", "opengl-cb");
mpv_set_option_string(mpv, "hwdec", "auto");
+
if(loop)
mpv_set_option_string(mpv, "loop", "inf");
+
+ if(mpv_initialize(mpv) < 0)
+ throw VideoInitializationException("Failed to initialize mpv");
+
mpvGl = (mpv_opengl_cb_context*)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB);
if(!mpvGl)
throw VideoInitializationException("Failed to initialize mpv opengl render context");
mpv_opengl_cb_set_update_callback(mpvGl, onMpvRedraw, this);
- if(mpv_opengl_cb_init_gl(mpvGl, nullptr, getProcAddressMpv, nullptr) < 0)
+ if(mpv_opengl_cb_init_gl(mpvGl, nullptr, getProcAddressMpv, this) < 0)
throw VideoInitializationException("Failed to initialize mpv gl callback func");
- renderThread = thread([this]() {
+ context.setActive(false);
+ renderThread = std::thread([this]() {
context.setActive(true);
while(alive) {
while(true) {
@@ -103,26 +70,32 @@ namespace QuickMedia {
mpv_get_property(mpv, "dheight", MPV_FORMAT_INT64, &h) >= 0 &&
w > 0 && h > 0 && (w != video_size.x || h != video_size.y))
{
- {
- lock_guard<mutex> lock(renderMutex);
- video_size.x = w;
- video_size.y = h;
- context.setActive(true);
- if(texture.create(w, h)) {
- void *newTextureBuf = realloc(textureBuffer, w * h * 4);
- if(newTextureBuf)
- textureBuffer = (sf::Uint8*)newTextureBuf;
- }
+ std::lock_guard<std::mutex> lock(renderMutex);
+ video_size.x = w;
+ video_size.y = h;
+ context.setActive(true);
+ // TODO: Verify if it's valid to re-create the texture like this,
+ // instead of using deconstructor
+ if(texture.create(w, h)) {
+ void *newTextureBuf = realloc(textureBuffer, w * h * 4);
+ if(newTextureBuf)
+ textureBuffer = (sf::Uint8*)newTextureBuf;
}
- resize(desired_size);
+ glViewport(0, 0, w, h);
}
+ resize(desired_size);
+ } else if(mpvEvent->event_id == MPV_EVENT_END_FILE) {
+ if(onPlaybackEndedCallback)
+ onPlaybackEndedCallback();
+ } else {
+ //printf("Mpv event: %s\n", mpv_event_name(mpvEvent->event_id));
}
}
- if(redrawCounter > 0) {
+ if(redrawCounter > 0 && textureBuffer) {
--redrawCounter;
context.setActive(true);
- lock_guard<mutex> lock(renderMutex);
+ std::lock_guard<std::mutex> lock(renderMutex);
auto textureSize = texture.getSize();
//mpv_render_context_render(mpvGl, params);
mpv_opengl_cb_draw(mpvGl, 0, textureSize.x, textureSize.y);
@@ -135,16 +108,16 @@ namespace QuickMedia {
}
});
- const char *cmd[] = { "loadfile", file, nullptr };
- mpv_command(mpv, cmd);
- context.setActive(false);
+ seekbar.setFillColor(sf::Color::White);
+ seekbar_background.setFillColor(sf::Color(0, 0, 0, 150));
+ load_file(file);
}
VideoPlayer::~VideoPlayer() {
alive = false;
renderThread.join();
- lock_guard<mutex> lock(renderMutex);
+ std::lock_guard<std::mutex> lock(renderMutex);
context.setActive(true);
if(mpvGl)
mpv_opengl_cb_set_update_callback(mpvGl, nullptr, nullptr);
@@ -159,7 +132,9 @@ namespace QuickMedia {
}
bool VideoPlayer::resize(const sf::Vector2i &size) {
- lock_guard<mutex> lock(renderMutex);
+ desired_size = size;
+ if(!textureBuffer)
+ return true;
float video_ratio = (double)video_size.x / (double)video_size.y;
float scale_x = 1.0f;
float scale_y = 1.0f;
@@ -175,21 +150,43 @@ namespace QuickMedia {
sprite.setPosition(size.x * 0.5f - video_size.x * scale_x * 0.5f, 0.0f);
}
sprite.setScale(scale_x, scale_y);
- desired_size = size;
- #if 0
- void *newTextureBuf = realloc(textureBuffer, size.x * size.y * 4);
- if(!newTextureBuf)
- return false;
- textureBuffer = (sf::Uint8*)newTextureBuf;
- if(!texture.create(size.x, size.y))
- return false;
- return true;
- #endif
return true;
}
void VideoPlayer::draw(sf::RenderWindow &window) {
- lock_guard<mutex> lock(renderMutex);
- window.draw(sprite);
+ {
+ std::lock_guard<std::mutex> lock(renderMutex);
+ window.draw(sprite);
+ }
+ double pos = 0.0;
+ mpv_get_property(mpv, "percent-pos", MPV_FORMAT_DOUBLE, &pos);
+ pos *= 0.01;
+
+ auto textureSize = sprite.getTextureRect();
+ auto scale = sprite.getScale();
+ auto video_size = sf::Vector2f(textureSize.width * scale.x, textureSize.height * scale.y);
+
+ const float seekbar_height = video_size.y * 0.025f;
+ seekbar.setPosition(sprite.getPosition() + sf::Vector2f(0.0f, video_size.y - seekbar_height));
+ seekbar.setSize(sf::Vector2f(video_size.x * pos, seekbar_height));
+ window.draw(seekbar);
+ seekbar_background.setPosition(seekbar.getPosition() + sf::Vector2f(video_size.x * pos, 0.0f));
+ seekbar_background.setSize(sf::Vector2f(video_size.x - video_size.x * pos, seekbar_height));
+ window.draw(seekbar_background);
+
+ if(sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
+ auto mouse_pos = sf::Mouse::getPosition(window);
+ auto seekbar_pos = seekbar.getPosition();
+ float diff_x = mouse_pos.x - seekbar_pos.x;
+ if(diff_x >= 0.0f && diff_x <= video_size.x && mouse_pos.y >= seekbar_pos.y && mouse_pos.y <= seekbar_pos.y + seekbar_height) {
+ double new_pos = ((double)diff_x / video_size.x) * 100.0;
+ mpv_set_property(mpv, "percent-pos", MPV_FORMAT_DOUBLE, &new_pos);
+ }
+ }
+ }
+
+ void VideoPlayer::load_file(const std::string &path) {
+ const char *cmd[] = { "loadfile", path.c_str(), nullptr };
+ mpv_command(mpv, cmd);
}
}