diff --git a/screenshot.cpp b/screenshot.cpp index 03cdc823..8abc71c6 100644 --- a/screenshot.cpp +++ b/screenshot.cpp @@ -617,9 +617,11 @@ EX namespace shot { purehookset hooks_hqshot; #if HDR -enum screenshot_format { png, svg, wrl }; +enum screenshot_format { png, svg, wrl, rawfile }; #endif +EX int rawfile_handle; + EX int shotx = 2000; EX int shoty = 2000; EX screenshot_format format; @@ -667,9 +669,19 @@ EX SDL_Surface *empty_surface(int x, int y, bool alpha) { } #if CAP_PNG + +void output(SDL_Surface* s, const string& fname) { + if(format == screenshot_format::rawfile) { + for(int y=0; y& what IS(default_screenshot_co return; case screenshot_format::png: + case screenshot_format::rawfile: #if CAP_PNG render_png(fname, what); #endif @@ -913,6 +926,7 @@ EX void menu() { break; } + case screenshot_format::rawfile: case screenshot_format::png: { #if CAP_PNG dialog::addSelItem(XLAT("supersampling"), its(shot_aa), 's'); @@ -1266,11 +1280,13 @@ EX void rollback() { #if CAP_FILES && CAP_SHOT EX string animfile = "animation-%04d.png"; +EX string videofile = "animation.mp4"; + int min_frame = 0, max_frame = 999999; int numturns = 0; -bool record_animation() { +EX bool record_animation() { lastticks = 0; ticks = 0; int oldturn = -1; @@ -1307,6 +1323,41 @@ bool record_animation() { } #endif +#if CAP_VIDEO +EX bool record_video(string fname IS(videofile), bool_reaction_t rec IS(record_animation)) { + + array tab; + if(pipe(&tab[0])) { + addMessage(format("Error: %s", strerror(errno))); + return false; + } + println(hlog, "tab = ", tab); + + int pid = fork(); + if(pid == 0) { + close(0); + dup(tab[0]); + close(tab[1]); + close(tab[0]); + string fformat = "ffmpeg -y -f rawvideo -pix_fmt bgra -s " + its(shot::shotx) + "x" + its(shot::shoty) + " -r 60 -i - -pix_fmt yuv420p -codec:v libx264 \"" + fname + "\""; + system(fformat.c_str()); + exit(0); + } + + close(tab[0]); + shot::rawfile_handle = tab[1]; + dynamicval sf(shot::format, shot::screenshot_format::rawfile); + rec(); + close(tab[1]); + wait(nullptr); + return true; + } + +EX bool record_video_std() { + return record_video(videofile, record_animation); + } +#endif + void display_animation() { if(ma == maCircle && (circle_display_color & 0xFF)) { for(int s=0; s<10; s++) { @@ -1552,12 +1603,19 @@ EX void show() { dialog::addBreak(100); dialog::addSelItem(XLAT("frames to record"), its(noframes), 'n'); dialog::add_action([] () { dialog::editNumber(noframes, 0, 300, 30, 5, XLAT("frames to record"), ""); }); - dialog::addSelItem(XLAT("record to a file"), animfile, 'R'); - dialog::add_action([] () { - dialog::openFileDialog(animfile, XLAT("record to a file"), + dialog::addSelItem(XLAT("record to sequence of image files"), animfile, 'R'); + dialog::add_action([] () { + dialog::openFileDialog(animfile, XLAT("record to sequence of image files"), shot::format_extension(), record_animation); }); #endif + #if CAP_VIDEO + dialog::addSelItem(XLAT("record to video file"), videofile, 'M'); + dialog::add_action([] () { + dialog::openFileDialog(videofile, XLAT("record to video file"), + ".mp4", record_video_std); + }); + #endif dialog::addBack(); dialog::display(); } @@ -1583,6 +1641,10 @@ int readArgs() { PHASE(3); shift(); noframes = argi(); shift(); animfile = args(); record_animation(); } + else if(argis("-animvideo")) { + PHASE(3); shift(); noframes = argi(); + shift(); videofile = args(); record_video(); + } else if(argis("-record-only")) { PHASEFROM(2); shift(); min_frame = argi(); diff --git a/sysconfig.h b/sysconfig.h index ce4f70b3..fce85bc0 100644 --- a/sysconfig.h +++ b/sysconfig.h @@ -173,6 +173,10 @@ #define CAP_ODS 0 #endif +#ifndef CAP_VIDEO +#define CAP_VIDEO (CAP_SHOT && ISLINUX && CAP_SDL) +#endif + #ifndef MAXMDIM #define MAXMDIM 4 #endif @@ -440,6 +444,10 @@ extern "C" { #include #include +#if CAP_VIDEO +#include +#endif + #if CAP_ZLIB #include #endif