Removed the deprecated VideoVlcComponent.

This commit is contained in:
Leon Styhre 2022-01-02 13:13:01 +01:00
parent 20dbaa01f2
commit 6431804ee7
12 changed files with 9 additions and 822 deletions

View file

@ -1,57 +0,0 @@
# - Try to find VLC library
# Once done this will define
#
# VLC_FOUND - system has VLC
# VLC_INCLUDE_DIR - The VLC include directory
# VLC_LIBRARIES - The libraries needed to use VLC
# VLC_DEFINITIONS - Compiler switches required for using VLC
#
# Copyright (C) 2008, Tanguy Krotoff <tkrotoff@gmail.com>
# Copyright (C) 2008, Lukas Durfina <lukas.durfina@gmail.com>
# Copyright (c) 2009, Fathi Boudra <fboudra@gmail.com>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if(VLC_INCLUDE_DIR AND VLC_LIBRARIES)
# In cache already
set(VLC_FIND_QUIETLY TRUE)
endif(VLC_INCLUDE_DIR AND VLC_LIBRARIES)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
if(NOT WIN32 AND NOT APPLE)
find_package(PkgConfig)
pkg_check_modules(VLC REQUIRED libvlc>=3.0.0)
set(VLC_DEFINITIONS ${VLC_CFLAGS})
set(VLC_LIBRARIES ${VLC_LDFLAGS})
endif(NOT WIN32 AND NOT APPLE)
if(WIN32)
# TODO add argument support to pass version on find_package
include(MacroEnsureVersion)
macro_ensure_version(3.0.0 ${VLC_VERSION} VLC_VERSION_OK)
if(VLC_VERSION_OK)
set(VLC_FOUND TRUE)
message(STATUS "VLC library found")
else(VLC_VERSION_OK)
set(VLC_FOUND FALSE)
message(FATAL_ERROR "VLC library not found")
endif(VLC_VERSION_OK)
find_path(VLC_INCLUDE_DIR
NAMES vlc.h
PATHS ${VLC_INCLUDE_DIRS}
PATH_SUFFIXES vlc)
find_library(VLC_LIBRARIES
NAMES vlc
PATHS ${VLC_LIBRARY_DIRS})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(VLC DEFAULT_MSG VLC_INCLUDE_DIR VLC_LIBRARIES)
# show the VLC_INCLUDE_DIR and VLC_LIBRARIES variables only in the advanced view
mark_as_advanced(VLC_INCLUDE_DIR VLC_LIBRARIES)
endif (WIN32)

View file

@ -35,7 +35,6 @@ option(RPI "Set to ON to enable Raspberry Pi specific build" ${RPI})
option(BUNDLED_CERTS "Set to ON to use bundled TLS/SSL certificates" ${BUNDLED_CERTS})
option(CEC "Set to ON to enable CEC" ${CEC})
option(VIDEO_HW_DECODING "Set to ON to enable FFmpeg HW decoding" ${VIDEO_HW_DECODING})
option(VLC_PLAYER "Set to ON to build the VLC-based video player" ${VLC_PLAYER})
option(CLANG_TIDY "Set to ON to build using the clang-tidy static analyzer" ${CLANG_TIDY})
option(ASAN "Set to ON to build with AddressSanitizer" ${ASAN})
option(TSAN "Set to ON to build with ThreadSanitizer" ${TSAN})
@ -113,9 +112,6 @@ elseif(NOT WIN32)
find_package(Freetype REQUIRED)
find_package(Pugixml REQUIRED)
find_package(SDL2 REQUIRED)
if(VLC_PLAYER)
find_package(VLC REQUIRED)
endif()
endif()
# Add libCEC support.
@ -278,10 +274,6 @@ if(VIDEO_HW_DECODING)
add_definitions(-DVIDEO_HW_DECODING)
endif()
if(VLC_PLAYER)
add_definitions(-DBUILD_VLC_PLAYER)
endif()
if(APPLE AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS 10.14)
add_definitions(-DLEGACY_MACOS)
endif()
@ -336,9 +328,6 @@ else()
${FREETYPE_INCLUDE_DIRS}
${PUGIXML_INCLUDE_DIRS}
${SDL2_INCLUDE_DIR})
if(VLC_PLAYER)
set(COMMON_INCLUDE_DIRS ${COMMON_INCLUDE_DIRS} ${VLC_INCLUDE_DIR})
endif()
endif()
# For Windows we need to add local include files for the dependency packages.
@ -349,11 +338,6 @@ if(WIN32)
endif()
endif()
# Temporary solution until the VLC find module has been updated to work properly on macOS.
if(APPLE AND VLC_PLAYER)
set(COMMON_INCLUDE_DIRS ${COMMON_INCLUDE_DIRS} "/Applications/VLC.app/Contents/MacOS/include")
endif()
if(WIN32)
set(COMMON_INCLUDE_DIRS ${COMMON_INCLUDE_DIRS} ${WIN32_INCLUDE_DIR})
endif()
@ -407,9 +391,6 @@ elseif(WIN32)
"${PROJECT_SOURCE_DIR}/SDL2main.lib"
"${PROJECT_SOURCE_DIR}/SDL2.lib"
"Winmm.dll")
if(VLC_PLAYER)
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} "${PROJECT_SOURCE_DIR}/libvlc.lib")
endif()
else()
set(COMMON_LIBRARIES "${PROJECT_SOURCE_DIR}/avcodec-58.dll"
"${PROJECT_SOURCE_DIR}/avfilter-7.dll"
@ -426,9 +407,6 @@ elseif(WIN32)
"${PROJECT_SOURCE_DIR}/SDL2.dll"
"mingw32"
"Winmm.dll")
if(VLC_PLAYER)
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} "${PROJECT_SOURCE_DIR}/libvlc.dll")
endif()
endif()
else()
set(COMMON_LIBRARIES ${CURL_LIBRARIES}
@ -437,9 +415,6 @@ else()
${FREETYPE_LIBRARIES}
${PUGIXML_LIBRARIES}
${SDL2_LIBRARY})
if(VLC_PLAYER)
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} ${VLC_LIBRARIES})
endif()
endif()
if(APPLE)
@ -447,11 +422,6 @@ if(APPLE)
# has been added to the install prefix.
set(CMAKE_INSTALL_PREFIX "/Applications/EmulationStation Desktop Edition.app/Contents/Resources")
if(VLC_PLAYER)
# Required as the VLC find module doesn't work properly on macOS.
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} "/Applications/VLC.app/Contents/MacOS/lib/libvlc.dylib")
endif()
# Set the same rpath links for the install executable as for the build executable.
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)

View file

@ -153,9 +153,6 @@ if(WIN32)
../VCRUNTIME140.dll
../VCRUNTIME140_1.dll
DESTINATION .)
if(VLC_PLAYER)
install(FILES ../libvlc.dll ../libvlccore.dll DESTINATION .)
endif()
else()
install(FILES ../avcodec-58.dll
../avfilter-7.dll
@ -174,13 +171,8 @@ if(WIN32)
../SDL2.dll
../vcomp140.dll
DESTINATION .)
if(VLC_PLAYER)
install(FILES ../libvlc.dll ../libvlccore.dll DESTINATION .)
endif()
endif()
if(VLC_PLAYER)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins DESTINATION .)
endif()
install(FILES ../LICENSE DESTINATION .)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/licenses DESTINATION .)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes DESTINATION .)
@ -225,15 +217,6 @@ elseif(APPLE)
install(FILES ${CMAKE_SOURCE_DIR}/libSDL2-2.0.dylib
PERMISSIONS ${APPLE_DYLIB_PERMISSIONS} DESTINATION ../MacOS)
if(VLC_PLAYER)
install(FILES ${CMAKE_SOURCE_DIR}/libvlc.dylib
PERMISSIONS ${APPLE_DYLIB_PERMISSIONS} DESTINATION ../MacOS)
install(FILES ${CMAKE_SOURCE_DIR}/libvlccore.dylib
PERMISSIONS ${APPLE_DYLIB_PERMISSIONS} DESTINATION ../MacOS)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/plugins
DESTINATION ../MacOS)
endif()
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE DESTINATION ../Resources)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/resources DESTINATION ../Resources)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes DESTINATION ../Resources)
@ -342,9 +325,6 @@ else()
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://es-de.org")
set(CPACK_DEBIAN_PACKAGE_SECTION "games")
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
if(VLC_PLAYER)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "vlc")
endif()
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
if(LINUX_CPACK_GENERATOR STREQUAL "RPM")
set(CPACK_GENERATOR "RPM")
@ -352,9 +332,6 @@ else()
set(CPACK_RPM_FILE_NAME "emulationstation-de-${CPACK_PACKAGE_VERSION}-${CPU_ARCHITECTURE}.rpm")
set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION})
set(CPACK_RPM_PACKAGE_LICENSE "MIT")
if(VLC_PLAYER)
set(CPACK_RPM_PACKAGE_REQUIRES "vlc")
endif()
list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CMAKE_INSTALL_PREFIX}")
list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CMAKE_INSTALL_PREFIX}/bin")
list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CMAKE_INSTALL_PREFIX}/share")

View file

@ -8,11 +8,8 @@
#include "MediaViewer.h"
#include "components/VideoFFmpegComponent.h"
#if defined(BUILD_VLC_PLAYER)
#include "components/VideoVlcComponent.h"
#endif
#include "Sound.h"
#include "components/VideoFFmpegComponent.h"
#include "views/ViewController.h"
MediaViewer::MediaViewer(Window* window)
@ -260,15 +257,7 @@ void MediaViewer::playVideo()
mDisplayingImage = false;
ViewController::get()->onStopVideo();
#if defined(BUILD_VLC_PLAYER)
if (Settings::getInstance()->getString("VideoPlayer") == "ffmpeg")
mVideo = new VideoFFmpegComponent(mWindow);
else
mVideo = new VideoVlcComponent(mWindow);
#else
mVideo = new VideoFFmpegComponent(mWindow);
#endif
mVideo->topWindow(true);
mVideo->setOrigin(0.5f, 0.5f);
mVideo->setPosition(Renderer::getScreenWidth() / 2.0f, Renderer::getScreenHeight() / 2.0f);

View file

@ -9,13 +9,10 @@
#include "SystemScreensaver.h"
#include "components/VideoFFmpegComponent.h"
#if defined(BUILD_VLC_PLAYER)
#include "components/VideoVlcComponent.h"
#endif
#include "FileData.h"
#include "Log.h"
#include "SystemData.h"
#include "components/VideoFFmpegComponent.h"
#include "resources/Font.h"
#include "utils/FileSystemUtil.h"
#include "utils/StringUtil.h"
@ -159,15 +156,7 @@ void SystemScreensaver::startScreensaver(bool generateMediaList)
if (Settings::getInstance()->getBool("ScreensaverVideoGameInfo"))
generateOverlayInfo();
#if defined(BUILD_VLC_PLAYER)
if (Settings::getInstance()->getString("VideoPlayer") == "vlc")
mVideoScreensaver = new VideoVlcComponent(mWindow);
else
mVideoScreensaver = new VideoFFmpegComponent(mWindow);
#else
mVideoScreensaver = new VideoFFmpegComponent(mWindow);
#endif
mVideoScreensaver->topWindow(true);
mVideoScreensaver->setOrigin(0.5f, 0.5f);
mVideoScreensaver->setPosition(Renderer::getScreenWidth() / 2.0f,

View file

@ -878,27 +878,6 @@ void GuiMenu::openOtherOptions()
}
});
#if defined(BUILD_VLC_PLAYER)
// Video player.
auto video_player = std::make_shared<OptionListComponent<std::string>>(
mWindow, getHelpStyle(), "FULLSCREEN MODE", false);
std::string selectedPlayer = Settings::getInstance()->getString("VideoPlayer");
video_player->add("FFmpeg", "ffmpeg", selectedPlayer == "ffmpeg");
video_player->add("VLC", "vlc", selectedPlayer == "vlc");
// If there are no objects returned, then there must be a manually modified entry in the
// configuration file. Simply set the video player to VLC in this case.
if (video_player->getSelectedObjects().size() == 0)
video_player->selectEntry(0);
s->addWithLabel("VIDEO PLAYER", video_player);
s->addSaveFunc([video_player, s] {
if (video_player->getSelected() != Settings::getInstance()->getString("VideoPlayer")) {
Settings::getInstance()->setString("VideoPlayer", video_player->getSelected());
s->setNeedsSaving();
s->setNeedsReloading();
}
});
#endif
// Exit button configuration.
auto exit_button_config = std::make_shared<OptionListComponent<std::string>>(
mWindow, getHelpStyle(), "EXIT BUTTON COMBO", false);
@ -977,11 +956,7 @@ void GuiMenu::openOtherOptions()
// Whether to enable hardware decoding for the FFmpeg video player.
auto video_hardware_decoding = std::make_shared<SwitchComponent>(mWindow);
video_hardware_decoding->setState(Settings::getInstance()->getBool("VideoHardwareDecoding"));
#if defined(BUILD_VLC_PLAYER)
s->addWithLabel("FFMPEG HARDWARE DECODING (EXPERIMENTAL)", video_hardware_decoding);
#else
s->addWithLabel("VIDEO HARDWARE DECODING (EXPERIMENTAL)", video_hardware_decoding);
#endif
s->addSaveFunc([video_hardware_decoding, s] {
if (video_hardware_decoding->getState() !=
Settings::getInstance()->getBool("VideoHardwareDecoding")) {
@ -995,11 +970,7 @@ void GuiMenu::openOtherOptions()
// Whether to upscale the video frame rate to 60 FPS.
auto video_upscale_frame_rate = std::make_shared<SwitchComponent>(mWindow);
video_upscale_frame_rate->setState(Settings::getInstance()->getBool("VideoUpscaleFrameRate"));
#if defined(BUILD_VLC_PLAYER)
s->addWithLabel("UPSCALE VIDEO FRAME RATE TO 60 FPS (FFMPEG)", video_upscale_frame_rate);
#else
s->addWithLabel("UPSCALE VIDEO FRAME RATE TO 60 FPS", video_upscale_frame_rate);
#endif
s->addSaveFunc([video_upscale_frame_rate, s] {
if (video_upscale_frame_rate->getState() !=
Settings::getInstance()->getBool("VideoUpscaleFrameRate")) {

View file

@ -8,13 +8,10 @@
#include "views/gamelist/VideoGameListView.h"
#include "animations/LambdaAnimation.h"
#include "components/VideoFFmpegComponent.h"
#if defined(BUILD_VLC_PLAYER)
#include "components/VideoVlcComponent.h"
#endif
#include "CollectionSystemsManager.h"
#include "SystemData.h"
#include "animations/LambdaAnimation.h"
#include "components/VideoFFmpegComponent.h"
#include "utils/FileSystemUtil.h"
#include "views/ViewController.h"
@ -53,16 +50,8 @@ VideoGameListView::VideoGameListView(Window* window, FileData* root)
{
const float padding = 0.01f;
// Create the correct type of video window.
#if defined(BUILD_VLC_PLAYER)
if (Settings::getInstance()->getString("VideoPlayer") == "vlc")
mVideo = new VideoVlcComponent(window);
else
mVideo = new VideoFFmpegComponent(window);
#else
// Create the video window.
mVideo = new VideoFFmpegComponent(window);
#endif
mList.setPosition(mSize.x * (0.50f + padding), mList.getPosition().y);
mList.setSize(mSize.x * (0.50f - padding), mList.getSize().y);

View file

@ -60,7 +60,6 @@ set(CORE_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextListComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoFFmpegComponent.h
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoVlcComponent.h
# GUIs
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiDetectDevice.h
@ -133,7 +132,6 @@ set(CORE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextEditComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoFFmpegComponent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoVlcComponent.cpp
# GUIs
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiDetectDevice.cpp

View file

@ -221,9 +221,6 @@ void Settings::setDefaults()
mIntMap["MaxVRAM"] = {256, 256};
#endif
mIntMap["DisplayIndex"] = {1, 1};
#if defined(BUILD_VLC_PLAYER)
mStringMap["VideoPlayer"] = {"ffmpeg", "ffmpeg"};
#endif
mStringMap["ExitButtonCombo"] = {"F4", "F4"};
mStringMap["SaveGamelistsMode"] = {"always", "always"};
#if defined(_WIN64)

View file

@ -9,15 +9,12 @@
#include "Window.h"
#include "components/HelpComponent.h"
#include "components/ImageComponent.h"
#include "guis/GuiInfoPopup.h"
#if defined(BUILD_VLC_PLAYER)
#include "components/VideoVlcComponent.h"
#endif
#include "InputManager.h"
#include "Log.h"
#include "Sound.h"
#include "components/HelpComponent.h"
#include "components/ImageComponent.h"
#include "guis/GuiInfoPopup.h"
#include "resources/Font.h"
#include <algorithm>
@ -152,9 +149,6 @@ void Window::deinit()
InputManager::getInstance()->deinit();
ResourceManager::getInstance()->unloadAll();
#if defined(BUILD_VLC_PLAYER)
VideoVlcComponent::deinit();
#endif
Renderer::deinit();
}

View file

@ -1,549 +0,0 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// VideoVlcComponent.cpp
//
// Video player based on libVLC.
//
#if defined(BUILD_VLC_PLAYER)
#include "components/VideoVlcComponent.h"
#include "AudioManager.h"
#include "Settings.h"
#include "Window.h"
#include "renderers/Renderer.h"
#include "resources/TextureResource.h"
#include "utils/StringUtil.h"
#if defined(__APPLE__)
#include "utils/FileSystemUtil.h"
#endif
#include <SDL2/SDL_mutex.h>
#include <SDL2/SDL_timer.h>
#include <vlc/vlc.h>
#if defined(_WIN64)
#include <codecvt>
#include <cstring>
#endif
libvlc_instance_t* VideoVlcComponent::mVLC = nullptr;
VideoVlcComponent::VideoVlcComponent(Window* window)
: VideoComponent(window)
, mMedia(nullptr)
, mMediaPlayer(nullptr)
, mContext({})
, mHasSetAudioVolume(false)
{
// Get an empty texture for rendering the video.
mTexture = TextureResource::get("");
// Make sure VLC has been initialized.
setupVLC();
}
VideoVlcComponent::~VideoVlcComponent()
{
stopVideo();
mTexture.reset();
}
void VideoVlcComponent::deinit()
{
if (mVLC) {
libvlc_release(mVLC);
mVLC = nullptr;
}
}
void VideoVlcComponent::setResize(float width, float height)
{
// This resize function is used when stretching videos to full screen in the video screensaver.
mTargetSize = glm::vec2{width, height};
mTargetIsMax = false;
mStaticImage.setResize(width, height);
resize();
}
void VideoVlcComponent::setMaxSize(float width, float height)
{
// This resize function is used in most instances, such as non-stretched video screensaver
// and the gamelist videos.
mTargetSize = glm::vec2{width, height};
mTargetIsMax = true;
mStaticImage.setMaxSize(width, height);
resize();
}
void VideoVlcComponent::setupVLC()
{
// If VLC hasn't been initialised yet then do it now.
if (!mVLC) {
const char* args[] = {"--quiet"};
#if defined(__APPLE__)
// It's required to set the VLC_PLUGIN_PATH variable on macOS, or the libVLC
// initialization will fail (with no error message).
std::string vlcPluginPath = Utils::FileSystem::getExePath() + "/plugins";
if (Utils::FileSystem::isDirectory(vlcPluginPath))
setenv("VLC_PLUGIN_PATH", vlcPluginPath.c_str(), 1);
else
setenv("VLC_PLUGIN_PATH", "/Applications/VLC.app/Contents/MacOS/plugins/", 1);
#endif
mVLC = libvlc_new(1, args);
}
}
void VideoVlcComponent::setupContext()
{
if (!mContext.valid) {
// Create an RGBA surface to render the video into.
mContext.surface = SDL_CreateRGBSurface(SDL_SWSURFACE, static_cast<int>(mVideoWidth),
static_cast<int>(mVideoHeight), 32, 0xff000000,
0x00ff0000, 0x0000ff00, 0x000000ff);
mContext.mutex = SDL_CreateMutex();
mContext.valid = true;
resize();
mHasSetAudioVolume = false;
}
}
void VideoVlcComponent::freeContext()
{
if (mContext.valid) {
SDL_FreeSurface(mContext.surface);
SDL_DestroyMutex(mContext.mutex);
mContext.valid = false;
}
}
void VideoVlcComponent::resize()
{
if (!mTexture)
return;
const glm::vec2 textureSize(static_cast<float>(mVideoWidth), static_cast<float>(mVideoHeight));
if (textureSize == glm::vec2{})
return;
if (mTargetIsMax) {
mSize = textureSize;
glm::vec2 resizeScale{(mTargetSize.x / mSize.x), (mTargetSize.y / mSize.y)};
if (resizeScale.x < resizeScale.y) {
mSize.x *= resizeScale.x;
mSize.y *= resizeScale.x;
}
else {
mSize.x *= resizeScale.y;
mSize.y *= resizeScale.y;
}
mSize.x = (mSize.y / textureSize.y) * textureSize.x;
mSize.y = std::round(mSize[1]);
}
else {
// If both components are set, we just stretch.
// If no components are set, we don't resize at all.
mSize = mTargetSize == glm::vec2{} ? textureSize : mTargetSize;
// If only one component is set, we resize in a way that maintains aspect ratio.
if (!mTargetSize.x && mTargetSize.y) {
mSize.y = std::round(mTargetSize.y);
mSize.x = (mSize.y / textureSize.y) * textureSize.x;
}
else if (mTargetSize.x && !mTargetSize.y) {
mSize.y = std::round((mTargetSize.x / textureSize.x) * textureSize.y);
mSize.x = (mSize.y / textureSize.y) * textureSize.x;
}
}
onSizeChanged();
}
void VideoVlcComponent::render(const glm::mat4& parentTrans)
{
// Set the audio volume. As libVLC is very unreliable we need to make an additional
// attempt here in the render loop in addition to the initialization in startVideo().
// This is required under some circumstances such as when running on a slow computer
// or sometimes even on a faster machine when changing to the video view style or
// when starting the application directly into a gamelist.
if (!mHasSetAudioVolume && mMediaPlayer)
setAudioVolume();
VideoComponent::render(parentTrans);
glm::mat4 trans{parentTrans * getTransform()};
GuiComponent::renderChildren(trans);
// Check the actual VLC state, i.e. if the video is really playing rather than
// still being opened.
if (mMediaPlayer && mIsPlaying && !mIsActuallyPlaying) {
libvlc_state_t state;
state = libvlc_media_player_get_state(mMediaPlayer);
if (state == libvlc_Playing)
mIsActuallyPlaying = true;
}
if (mIsPlaying && mContext.valid && mIsActuallyPlaying) {
unsigned int color;
if (mFadeIn < 1) {
const unsigned int fadeIn = static_cast<int>(mFadeIn * 255.0f);
color =
Renderer::convertRGBAToABGR((fadeIn << 24) | (fadeIn << 16) | (fadeIn << 8) | 255);
}
else {
color = 0xFFFFFFFF;
}
Renderer::Vertex vertices[4];
Renderer::setMatrix(parentTrans);
// Render the black rectangle behind the video.
if (mVideoRectangleCoords.size() == 4) {
Renderer::drawRect(mVideoRectangleCoords[0], mVideoRectangleCoords[1],
mVideoRectangleCoords[2], mVideoRectangleCoords[3], // Line break.
0x000000FF, 0x000000FF);
}
// clang-format off
vertices[0] = {{0.0f , 0.0f }, {0.0f, 0.0f}, color};
vertices[1] = {{0.0f , mSize.y}, {0.0f, 1.0f}, color};
vertices[2] = {{mSize.x, 0.0f }, {1.0f, 0.0f}, color};
vertices[3] = {{mSize.x, mSize.y}, {1.0f, 1.0f}, color};
// clang-format on
// Round vertices.
for (int i = 0; i < 4; ++i)
vertices[i].pos = glm::round(vertices[i].pos);
// Build a texture for the video frame.
mTexture->initFromPixels(reinterpret_cast<unsigned char*>(mContext.surface->pixels),
mContext.surface->w, mContext.surface->h);
mTexture->bind();
#if defined(USE_OPENGL_21)
// Render scanlines if this option is enabled. However, if this is the media viewer
// or the video screensaver, then skip this as the scanline rendering is then handled
// in those modules as a postprocessing step.
if ((!mScreensaverMode && !mMediaViewerMode) &&
Settings::getInstance()->getBool("GamelistVideoScanlines")) {
vertices[0].shaders = Renderer::SHADER_SCANLINES;
}
#endif
// Render it.
Renderer::setMatrix(trans);
Renderer::drawTriangleStrips(&vertices[0], 4, trans);
}
else {
VideoComponent::renderSnapshot(parentTrans);
}
}
void VideoVlcComponent::calculateBlackRectangle()
{
// Calculate the position and size for the black rectangle that will be rendered behind
// videos. If the option to display pillarboxes (and letterboxes) is enabled, then this
// would extend to the entire md_video area (if above the threshold as defined below) or
// otherwise it will exactly match the video size. The reason to add a black rectangle
// behind videos in this second instance is that the scanline rendering will make the
// video partially transparent so this may avoid some unforseen issues with some themes.
if (mVideoAreaPos != glm::vec2{} && mVideoAreaSize != glm::vec2{}) {
mVideoRectangleCoords.clear();
if (Settings::getInstance()->getBool("GamelistVideoPillarbox")) {
float rectHeight;
float rectWidth;
// Video is in landscape orientation.
if (mSize.x > mSize.y) {
// Checking the Y size should not normally be required as landscape format
// should mean the height can't be higher than the max size defined by the
// theme. But as the height in mSize is provided by libVLC in integer format
// and then scaled, there could be rounding errors that make the video height
// slightly higher than allowed. It's only a single pixel or a few pixels, but
// it's still visible for some videos.
if (mSize.y < mVideoAreaSize.y && mSize.y / mVideoAreaSize.y < 0.90f)
rectHeight = mVideoAreaSize.y;
else
rectHeight = mSize.y;
// Don't add a black border that is too narrow, that's what the 0.85 constant
// takes care of.
if (mSize.x < mVideoAreaSize.x && mSize.x / mVideoAreaSize.x < 0.85f)
rectWidth = mVideoAreaSize.x;
else
rectWidth = mSize.x;
}
// Video is in portrait orientation (or completely square).
else {
rectWidth = mVideoAreaSize.x;
rectHeight = mSize.y;
}
// Populate the rectangle coordinates to be used in render().
mVideoRectangleCoords.push_back(std::round(mVideoAreaPos.x - rectWidth * mOrigin.x));
mVideoRectangleCoords.push_back(std::round(mVideoAreaPos.y - rectHeight * mOrigin.y));
mVideoRectangleCoords.push_back(std::round(rectWidth));
mVideoRectangleCoords.push_back(std::round(rectHeight));
}
// If the option to display pillarboxes is disabled, then make the rectangle equivalent
// to the size of the video.
else {
mVideoRectangleCoords.push_back(std::round(mPosition.x - mSize.x * mOrigin.x));
mVideoRectangleCoords.push_back(std::round(mPosition.y - mSize.y * mOrigin.y));
mVideoRectangleCoords.push_back(std::round(mSize.x));
mVideoRectangleCoords.push_back(std::round(mSize.y));
}
}
}
void VideoVlcComponent::setAudioVolume()
{
if (mMediaPlayer && libvlc_media_player_get_state(mMediaPlayer) == libvlc_Playing) {
// This small delay may avoid a race condition in libVLC that could crash the application.
SDL_Delay(2);
bool outputSound = false;
if ((!mScreensaverMode && !mMediaViewerMode) &&
Settings::getInstance()->getBool("GamelistVideoAudio"))
outputSound = true;
else if (mScreensaverMode && Settings::getInstance()->getBool("ScreensaverVideoAudio"))
outputSound = true;
else if (mMediaViewerMode && Settings::getInstance()->getBool("MediaViewerVideoAudio"))
outputSound = true;
if (outputSound) {
if (libvlc_audio_get_mute(mMediaPlayer) == 1)
libvlc_audio_set_mute(mMediaPlayer, 0);
libvlc_audio_set_volume(mMediaPlayer,
Settings::getInstance()->getInt("SoundVolumeVideos"));
}
else {
libvlc_audio_set_volume(mMediaPlayer, 0);
}
mHasSetAudioVolume = true;
}
}
void VideoVlcComponent::startVideo()
{
if (!mIsPlaying && !mGameLaunched) {
mVideoWidth = 0;
mVideoHeight = 0;
#if defined(_WIN64)
std::string path(Utils::String::replace(mVideoPath, "/", "\\"));
#else
std::string path(mVideoPath);
#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;
int parseResult;
// Asynchronous media parsing.
libvlc_event_attach(libvlc_media_event_manager(mMedia), libvlc_MediaParsedChanged,
VlcMediaParseCallback, 0);
parseResult = libvlc_media_parse_with_options(mMedia, libvlc_media_parse_local, -1);
if (!parseResult) {
// Wait for a maximum of 1 second for the media parsing.
// This maximum time is quite excessive as this step should normally
// be completed in 15 - 30 ms or so.
for (int i = 0; i < 200; ++i) {
if (libvlc_media_get_parsed_status(mMedia))
break;
SDL_Delay(5);
};
}
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);
libvlc_media_parse_stop(mMedia);
libvlc_event_detach(libvlc_media_event_manager(mMedia), libvlc_MediaParsedChanged,
VlcMediaParseCallback, 0);
// 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);
// The code below enables the libVLC audio output to be processed inside ES-DE.
// Unfortunately this causes excessive stuttering for some reason that I still
// don't understand, so at the moment this code is disabled.
// auto audioFormatCallback = [](void **data, char *format,
// unsigned *rate, unsigned *channels) -> int {
// format = const_cast<char*>("F32L");
// *rate = 48000;
// *channels = 2;
// return 0;
// };
//
// libvlc_audio_set_format_callbacks(mMediaPlayer,
// audioFormatCallback, nullptr);
//
// auto audioPlayCallback = [](void* data, const void*
// samples,
// unsigned count, int64_t pts) {
// AudioManager::getInstance()->processStream(samples,
// count);
// };
//
// libvlc_audio_set_callbacks(mMediaPlayer,
// audioPlayCallback,
// nullptr, nullptr, nullptr, nullptr, this);
libvlc_video_set_format(mMediaPlayer, "RGBA", static_cast<int>(mVideoWidth),
static_cast<int>(mVideoHeight),
static_cast<int>(mVideoWidth * 4));
// Lock video memory as a preparation for rendering a frame.
auto videoLockCallback = [](void* data, void** p_pixels) -> void* {
struct VideoContext* videoContext =
reinterpret_cast<struct VideoContext*>(data);
SDL_LockMutex(videoContext->mutex);
SDL_LockSurface(videoContext->surface);
*p_pixels = videoContext->surface->pixels;
return nullptr; // Picture identifier, not needed here.
};
// Unlock the video memory after rendering a frame.
auto videoUnlockCallback = [](void* data, void*, void* const*) {
struct VideoContext* videoContext =
reinterpret_cast<struct VideoContext*>(data);
SDL_UnlockSurface(videoContext->surface);
SDL_UnlockMutex(videoContext->mutex);
};
libvlc_video_set_callbacks(mMediaPlayer, videoLockCallback, videoUnlockCallback,
nullptr, reinterpret_cast<void*>(&mContext));
libvlc_media_player_play(mMediaPlayer);
// Calculate pillarbox/letterbox sizes.
calculateBlackRectangle();
libvlc_state_t state;
state = libvlc_media_player_get_state(mMediaPlayer);
if (state != libvlc_Playing) {
// Wait for a maximum of 100 ms for the status of the video to change
// to libvlc_Playing as there would otherwise be a brief flicker before
// the video starts to play. This is also required to prevent the
// application from crashing under some circumstances as changing the
// video player audio volume is apparently not properly handled by libVLC.
// This maximum time is quite excessive as this step should normally
// be completed in 4 - 16 ms or so even on slower machines.
for (int i = 0; i < 50; ++i) {
state = libvlc_media_player_get_state(mMediaPlayer);
if (state == libvlc_Playing) {
// This additional delay is needed to prevent some kind of race
// condition in libVLC which would otherwise crash the application.
SDL_Delay(2);
break;
}
SDL_Delay(2);
};
}
// Attempt to set the audio volume. Under some circumstances it could fail
// as libVLC may not be correctly initialized. Therefore there is an
// additional call to this function in the render() loop.
setAudioVolume();
// Update the playing state.
mIsPlaying = true;
mFadeIn = 0.0f;
}
}
}
}
}
void VideoVlcComponent::stopVideo()
{
mIsPlaying = false;
mIsActuallyPlaying = false;
mStartDelayed = false;
mPause = 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 = nullptr;
mMedia = nullptr;
freeContext();
}
}
void VideoVlcComponent::pauseVideo()
{
// If a game has been launched and the flag to pause the video has been
// set, then rewind and pause.
if (!mPause || !mMediaPlayer)
return;
if (libvlc_media_player_get_state(mMediaPlayer) == libvlc_Playing) {
libvlc_media_player_set_position(mMediaPlayer, 0.0f);
libvlc_media_player_pause(mMediaPlayer);
}
}
void VideoVlcComponent::handleLooping()
{
if (mIsPlaying && mMediaPlayer) {
libvlc_state_t state = libvlc_media_player_get_state(mMediaPlayer);
if (state == libvlc_Ended) {
// If the screensaver video swap time is set to 0, it means we should
// skip to the next game when the video has finished playing.
if (mScreensaverMode &&
Settings::getInstance()->getInt("ScreensaverSwapVideoTimeout") == 0) {
mWindow->screensaverTriggerNextGame();
}
else {
libvlc_media_player_set_media(mMediaPlayer, mMedia);
libvlc_media_player_play(mMediaPlayer);
bool outputSound = false;
if ((!mScreensaverMode && !mMediaViewerMode) &&
Settings::getInstance()->getBool("GamelistVideoAudio"))
outputSound = true;
else if (mScreensaverMode &&
Settings::getInstance()->getBool("ScreensaverVideoAudio"))
outputSound = true;
else if (mMediaViewerMode &&
Settings::getInstance()->getBool("MediaViewerVideoAudio"))
outputSound = true;
if (!outputSound)
libvlc_audio_set_volume(mMediaPlayer, 0);
}
}
}
}
#endif

View file

@ -1,81 +0,0 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation Desktop Edition
// VideoVlcComponent.h
//
// Video player based on libVLC.
//
#ifndef ES_CORE_COMPONENTS_VIDEO_VLC_COMPONENT_H
#define ES_CORE_COMPONENTS_VIDEO_VLC_COMPONENT_H
#include "VideoComponent.h"
#include <vlc/vlc.h>
struct SDL_mutex;
struct SDL_Surface;
struct libvlc_instance_t;
struct libvlc_media_t;
struct libvlc_media_player_t;
struct VideoContext {
SDL_Surface* surface;
SDL_mutex* mutex;
bool valid;
};
class VideoVlcComponent : public VideoComponent
{
public:
VideoVlcComponent(Window* window);
virtual ~VideoVlcComponent();
static void deinit();
// 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. This can be set before or after a video is loaded.
// setMaxSize() and setResize() are mutually exclusive.
void setResize(float width, float height) override;
// Resize the video to be as large as possible but fit within a box of this size.
// This 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) override;
private:
static void setupVLC();
void setupContext();
void freeContext();
// Calculates the correct mSize from our resizing information (set by setResize/setMaxSize).
// Used internally whenever the resizing parameters or texture change.
void resize();
void render(const glm::mat4& parentTrans) override;
void calculateBlackRectangle();
void setAudioVolume();
// Start the video immediately.
virtual void startVideo() override;
// Stop the video.
virtual void stopVideo() override;
// Pause the video when a game has been launched.
virtual void pauseVideo() override;
// Handle looping the video. Must be called periodically.
virtual void handleLooping() override;
static void VlcMediaParseCallback(const libvlc_event_t* event, void* user_data) {}
static VideoVlcComponent* sInstance;
static libvlc_instance_t* mVLC;
libvlc_media_t* mMedia;
libvlc_media_player_t* mMediaPlayer;
VideoContext mContext;
bool mHasSetAudioVolume;
std::shared_ptr<TextureResource> mTexture;
std::vector<float> mVideoRectangleCoords;
};
#endif // ES_CORE_COMPONENTS_VIDEO_VLC_COMPONENT_H