Skip to content

Instantly share code, notes, and snippets.

@mbabuskov
Created October 4, 2016 13:52
Show Gist options
  • Save mbabuskov/6f0a2b057c49fcc860e3d28d490fc7dd to your computer and use it in GitHub Desktop.
Save mbabuskov/6f0a2b057c49fcc860e3d28d490fc7dd to your computer and use it in GitHub Desktop.
#ifndef CORE_SCREENSHOT_H_
#define CORE_SCREENSHOT_H_
//------------------------------------------------------------------------------
class Screenshot
{
public:
int id; // thread ID (only used for loggin and debugging)
bool stopflag; // used to "tell" the thread to stop and clean up
std::string file;
SDL_Surface *surface;
Screenshot(int thread, const std::string& filename, SDL_Surface *surf, bool stop = false)
:id(thread),stopflag(stop),file(filename),surface(surf)
{
}
};
//------------------------------------------------------------------------------
static int ScreenshotThread(void *ptr)
{
SafeQueue<Screenshot> *q = (SafeQueue<Screenshot> *)ptr;
while (true)
{
Screenshot s = q->dequeue(); // waits until new screenshot is ready
if (s.stopflag)
{
// using printf because is sends the whole string at once (unlike std::cout)
// http://stackoverflow.com/questions/6374264/is-cout-synchronized-thread-safe
printf("Screenshot thread QUIT %d\n", s.id);
delete q; // free the queue memory
break;
}
IMG_SavePNG(s.surface, s.file.c_str());
SDL_FreeSurface(s.surface);
std::cout << "Screenshot thread " << s.id << " saved: " << s.file.c_str() << std::endl;
}
return 0;
}
//------------------------------------------------------------------------------
class ScreenshotManager
{
public:
bool recording;
int screenShotCounter;
int width;
int height;
SDL_Renderer *renderer;
std::vector<SafeQueue<Screenshot> *> screenshotQueues;
int roundrobin;
ScreenshotManager(SDL_Renderer *sdlrend, int w, int h)
:recording(false),screenShotCounter(1000000),roundrobin(0),
width(w),height(h),renderer(sdlrend)
{
for (int i = 0; i < 8; i++) // create 8 threads
{
std::stringstream ss;
ss << "ScreenshotThread" << i;
SafeQueue<Screenshot> *sq = new SafeQueue<Screenshot>;
if (!SDL_CreateThread(ScreenshotThread, ss.str().c_str(), (void *)sq))
{
std::cout << "ERROR: SDL_CreateThread failed: " << SDL_GetError() << std::endl;
break;
}
else
screenshotQueues.push_back(sq);
}
}
~ScreenshotManager()
{
for (int i = 0; i < screenshotQueues.size(); i++)
{
Screenshot shot(i, "", 0, true); // true = stop the thread
screenshotQueues[i]->enqueue(shot); // tell it to stop and delete the queue
}
}
void screenshot(std::string filename)
{
SDL_Surface *sshot = SDL_CreateRGBSurface(0, width, height,
32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
if (!sshot)
return;
SDL_RenderReadPixels(renderer, NULL, SDL_PIXELFORMAT_ARGB8888, sshot->pixels, sshot->pitch);
roundrobin++;
if (roundrobin >= screenshotQueues.size())
roundrobin = 0;
Screenshot shot(roundrobin, filename, sshot);
screenshotQueues[roundrobin]->enqueue(shot);
}
void update()
{
if (!recording || screenshotQueues.size() == 0)
return;
static bool skipper = true;
//skipper = !skipper; // uncomment this line for 30fps
if (skipper)
{
screenShotCounter++;
std::stringstream ss;
ss << "shot" << screenShotCounter << ".png";
screenshot(ss.str());
}
}
int getQueueSize()
{
int total = 0;
for (std::vector<SafeQueue<Screenshot> *>::iterator it = screenshotQueues.begin();
it != screenshotQueues.end(); ++it)
{
total += (*it)->count;
}
return total;
}
};
//------------------------------------------------------------------------------
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment