Skip to content

Commit

Permalink
Fix video recording with SDL_Image
Browse files Browse the repository at this point in the history
  • Loading branch information
kongaskristjan committed Dec 24, 2019
1 parent d889418 commit 98c64ac
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 25 deletions.
9 changes: 7 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ if(NOT EMSCRIPTEN)
find_package(SDL2TTF REQUIRED)
endif()

find_package(SDL2Image)
if(SDLIMAGE_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D SDL2_IMAGE_ENABLED")
endif()

FILE(GLOB LibSources Lib/*.cpp Lib/*.h)
add_library(library ${LibSources})

Expand All @@ -27,9 +32,9 @@ if(EMSCRIPTEN)

configure_file(Tests/PhaseTransition.html PhaseTransition.html COPY_ONLY)
else()
include_directories(${SDL2_INCLUDE_DIRS} ${SDL2TTF_INCLUDE_DIR} .)
include_directories(${SDL2_INCLUDE_DIRS} ${SDL2TTF_INCLUDE_DIR} ${SDL2_IMAGE_INCLUDE_DIR} .)

target_link_libraries(PhaseTransition library ${SDL2_LIBRARIES} ${SDL2TTF_LIBRARY} Threads::Threads)
target_link_libraries(PhaseTransition library ${SDL2_LIBRARIES} ${SDL2TTF_LIBRARY} ${SDL2_IMAGE_LIBRARY} Threads::Threads)
endif()

# Testing
Expand Down
43 changes: 24 additions & 19 deletions Lib/Display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#include "Display.h"
#include "Globals.h"

#if __cplusplus >= 201703L
#include <filesystem>
#ifdef SDL2_IMAGE_ENABLED
#include <SDL_image.h>
#endif

CallbackHandler::CallbackHandler(int _totalParticleTypes):
Expand Down Expand Up @@ -143,9 +143,9 @@ void UniverseModifier::addNew(Universe &universe, const CallbackHandler &handler


Display::Display(Universe &_universe, const std::string &_windowCaption, const std::string &_displayedCaption,
const std::string &_directoryPath, const std::string &recordingPath):
const std::string &_directoryPath, const std::string &_recordingPath):
universe(_universe), displayedCaption(_displayedCaption), directoryPath(_directoryPath),
handler(_universe.getParticleTypes().size()) {
handler(_universe.getParticleTypes().size()), recordingPath(_recordingPath) {
windowCaption = _windowCaption + " - " + _displayedCaption;

if(SDL_Init(SDL_INIT_VIDEO) < 0) {
Expand All @@ -167,12 +167,14 @@ Display::Display(Universe &_universe, const std::string &_windowCaption, const s
TTF_Init();
font = TTF_OpenFont((directoryPath + "Fonts/DroidSans.ttf").c_str(), 24);

isRecording = false;
if(! recordingPath.empty()) {
#if __cplusplus >= 201703L
auto path = std::filesystem::path(recordingPath);
std::filesystem::create_directories(path.parent_path());
#if SDL2_IMAGE_ENABLED
isRecording = true;
system((std::string("mkdir -p ") + recordingPath).c_str());
#else
std::cerr << "Warning: trying to record, but this build does not support recording" << std::endl;
#endif
//recorder.open(recordingPath, CV_FOURCC('M','J','P','G'), 60, cv::Size(universe.getConfig().sizeX, universe.getConfig().sizeY));
}
}

Expand All @@ -187,22 +189,12 @@ Display::~Display() {
}

const CallbackHandler & Display::update() {
/*
if(recorder.isOpened()) {
recorder.write(img);
auto now = std::chrono::system_clock::now();
auto millisFromEpoch = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
if(millisFromEpoch % 1000 < 500)
drawText(img, "Recording...", cv::Point(30, 30));
}
*/

SDL_FillRect(surface, nullptr, 0x000000);
drawParticles();
drawDisplayedCaption();
drawStats();
drawPointer();
if(isRecording) recordAndDrawRecordingText();
SDL_UpdateWindowSurface(window);
SDL_Event event;
while(SDL_PollEvent(& event)) {
Expand Down Expand Up @@ -310,6 +302,19 @@ void Display::drawParticles() {
}
}

void Display::recordAndDrawRecordingText() {
if(! isRecording) return;

#ifdef SDL2_IMAGE_ENABLED
IMG_SaveJPG(surface, (recordingPath + std::to_string(timestamp++) + ".jpg").c_str(), 95);
#endif

auto now = std::chrono::system_clock::now();
auto millisFromEpoch = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
if (millisFromEpoch % 1000 < 500)
drawText("Recording...", 30, 30);
}

void Display::drawSpriteFromCenter(SDL_Surface *sprite, int x, int y) {
assert(sprite != nullptr);
SDL_Rect inputRect{0, 0, sprite->w, sprite->h};
Expand Down
7 changes: 6 additions & 1 deletion Lib/Display.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,22 @@ class Display {
void drawStats();
void drawText(const std::string &text, int x, int y);
void drawSpriteFromCenter(SDL_Surface *sprite, int x, int y);
void recordAndDrawRecordingText();
std::tuple<int, double, double> computeStats() const;

Universe &universe;
std::string windowCaption, displayedCaption;
std::string directoryPath;
CallbackHandler handler;
//cv::VideoWriter recorder;
SDL_Window *window = nullptr;
SDL_Surface *surface = nullptr;
SDL_Surface *defaultPointer = nullptr, *increasePointer = nullptr, *decreasePointer = nullptr;
TTF_Font *font;

std::string recordingPath;
bool isRecording;

int timestamp = 0;
};

std::string to_string(double x, int precision);
Expand Down
2 changes: 1 addition & 1 deletion PhaseTransition/PhaseTransition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ int main(int argc, char **argv) {
#endif

std::string recordingPath;
if(! globalSetup->recordingPrefix.empty()) recordingPath = globalSetup->recordingPrefix + currentDateTime() + ".avi";
if(! globalSetup->recordingPrefix.empty()) recordingPath = globalSetup->recordingPrefix + currentDateTime() + "/";
globalUniverse.reset(new Universe({ globalSetup->sizeX, globalSetup->sizeY, globalSetup->forceFactor, globalSetup->gravity },
globalSetup->particleTypes));
globalSetup->addParticlesToUniverse(*globalUniverse);
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ Requirements:
* cmake 3.10+
* pthreads
* SDL 2 and SDL_ttf 2
* gtest (optional)
* emscripten (optional)
* SDL_image 2 (optional - recording video)
* gtest (optional - running tests)
* emscripten (optional - building for web)

Building:

Expand Down
100 changes: 100 additions & 0 deletions cmake/FindSDL2Image.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Locate SDL_image library
#
# This module defines:
#
# ::
#
# SDL2_IMAGE_LIBRARIES, the name of the library to link against
# SDL2_IMAGE_INCLUDE_DIRS, where to find the headers
# SDL2_IMAGE_FOUND, if false, do not try to link against
# SDL2_IMAGE_VERSION_STRING - human-readable string containing the version of SDL_image
#
#
#
# For backward compatibility the following variables are also set:
#
# ::
#
# SDLIMAGE_LIBRARY (same value as SDL2_IMAGE_LIBRARIES)
# SDLIMAGE_INCLUDE_DIR (same value as SDL2_IMAGE_INCLUDE_DIRS)
# SDLIMAGE_FOUND (same value as SDL2_IMAGE_FOUND)
#
#
#
# $SDLDIR is an environment variable that would correspond to the
# ./configure --prefix=$SDLDIR used in building SDL.
#
# Created by Eric Wing. This was influenced by the FindSDL.cmake
# module, but with modifications to recognize OS X frameworks and
# additional Unix paths (FreeBSD, etc).

#=============================================================================
# Copyright 2005-2009 Kitware, Inc.
# Copyright 2012 Benjamin Eikel
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)

find_path(SDL2_IMAGE_INCLUDE_DIR SDL_image.h
HINTS
ENV SDL2IMAGEDIR
ENV SDL2DIR
PATH_SUFFIXES SDL2
# path suffixes to search inside ENV{SDLDIR}
include/SDL2 include
PATHS ${SDL2_IMAGE_PATH}
)

if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(VC_LIB_PATH_SUFFIX lib/x64)
else()
set(VC_LIB_PATH_SUFFIX lib/x86)
endif()

find_library(SDL2_IMAGE_LIBRARY
NAMES SDL2_image
HINTS
ENV SDL2IMAGEDIR
ENV SDL2DIR
PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX}
PATHS ${SDL2_IMAGE_PATH}
)

if(SDL2_IMAGE_INCLUDE_DIR AND EXISTS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h")
file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+[0-9]+$")
file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+[0-9]+$")
file(STRINGS "${SDL2_IMAGE_INCLUDE_DIR}/SDL_image.h" SDL2_IMAGE_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+[0-9]+$")
string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MAJOR "${SDL2_IMAGE_VERSION_MAJOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_MINOR "${SDL2_IMAGE_VERSION_MINOR_LINE}")
string(REGEX REPLACE "^#define[ \t]+SDL_IMAGE_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_IMAGE_VERSION_PATCH "${SDL2_IMAGE_VERSION_PATCH_LINE}")
set(SDL2_IMAGE_VERSION_STRING ${SDL2_IMAGE_VERSION_MAJOR}.${SDL2_IMAGE_VERSION_MINOR}.${SDL2_IMAGE_VERSION_PATCH})
unset(SDL2_IMAGE_VERSION_MAJOR_LINE)
unset(SDL2_IMAGE_VERSION_MINOR_LINE)
unset(SDL2_IMAGE_VERSION_PATCH_LINE)
unset(SDL2_IMAGE_VERSION_MAJOR)
unset(SDL2_IMAGE_VERSION_MINOR)
unset(SDL2_IMAGE_VERSION_PATCH)
endif()

set(SDL2_IMAGE_LIBRARIES ${SDL2_IMAGE_LIBRARY})
set(SDL2_IMAGE_INCLUDE_DIRS ${SDL2_IMAGE_INCLUDE_DIR})

include(FindPackageHandleStandardArgs)

FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_image
REQUIRED_VARS SDL2_IMAGE_LIBRARIES SDL2_IMAGE_INCLUDE_DIRS
VERSION_VAR SDL2_IMAGE_VERSION_STRING)

# for backward compatibility
set(SDLIMAGE_LIBRARY ${SDL2_IMAGE_LIBRARIES})
set(SDLIMAGE_INCLUDE_DIR ${SDL2_IMAGE_INCLUDE_DIRS})
set(SDLIMAGE_FOUND ${SDL2_IMAGE_FOUND})

mark_as_advanced(SDL2_IMAGE_LIBRARY SDL2_IMAGE_INCLUDE_DIR)

0 comments on commit 98c64ac

Please sign in to comment.