Call createFile only in AVIWriter thread
This commit is contained in:
parent
e2482e602c
commit
3ed52e26d0
@ -169,6 +169,9 @@ IrrDriver::~IrrDriver()
|
||||
#endif
|
||||
delete m_wind;
|
||||
delete m_renderer;
|
||||
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
|
||||
AVIWriter::kill();
|
||||
#endif
|
||||
} // ~IrrDriver
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -923,6 +926,9 @@ void IrrDriver::applyResolutionSettings()
|
||||
// (we're sure to update main.cpp at some point and forget this one...)
|
||||
VAOManager::getInstance()->kill();
|
||||
STKTexManager::getInstance()->kill();
|
||||
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
|
||||
AVIWriter::kill();
|
||||
#endif
|
||||
// initDevice will drop the current device.
|
||||
if (CVS->isGLSL())
|
||||
{
|
||||
@ -1899,11 +1905,20 @@ void IrrDriver::setRecording(bool val)
|
||||
#if !(defined(SERVER_ONLY) || defined(USE_GLES2))
|
||||
if (!CVS->isARBPixelBufferObjectUsable())
|
||||
return;
|
||||
if (val == false && m_recording == false)
|
||||
if (m_recording == val)
|
||||
return;
|
||||
m_recording = val;
|
||||
if (val == false)
|
||||
if (val == true)
|
||||
{
|
||||
std::string track_name = World::getWorld() != NULL ?
|
||||
race_manager->getTrackName() : "menu";
|
||||
AVIWriter::getInstance()->setRecordingTarget(file_manager
|
||||
->getScreenshotDir() + track_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
AVIWriter::getInstance()->stopRecording();
|
||||
}
|
||||
#endif
|
||||
} // setRecording
|
||||
|
||||
|
@ -20,10 +20,6 @@
|
||||
|
||||
#include "utils/avi_writer.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/vs.hpp"
|
||||
|
||||
#include <jpeglib.h>
|
||||
@ -33,10 +29,7 @@
|
||||
AVIWriter::AVIWriter()
|
||||
{
|
||||
m_file = NULL;
|
||||
m_pbo_use = 0;
|
||||
m_accumulated_time = 0.0f;
|
||||
m_remaining_time = 0.0f;
|
||||
m_img_quality = 0;
|
||||
reset();
|
||||
m_width = UserConfigParams::m_width;
|
||||
m_height = UserConfigParams::m_height;
|
||||
glGenBuffers(3, m_pbo);
|
||||
@ -47,11 +40,37 @@ AVIWriter::AVIWriter()
|
||||
GL_STREAM_READ);
|
||||
}
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
pthread_mutex_init(&m_fbi_mutex, NULL);
|
||||
pthread_cond_init(&m_cond_request, NULL);
|
||||
pthread_create(&m_thread, NULL, &startRoutine, this);
|
||||
} // AVIWriter
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
AVIWriter::~AVIWriter()
|
||||
{
|
||||
glDeleteBuffers(3, m_pbo);
|
||||
addFrameBufferImage(NULL, 0);
|
||||
if (!waitForReadyToDeleted(2.0f))
|
||||
Log::info("AVIWriter", "AVIWriter not stopping," "exiting anyway.");
|
||||
pthread_join(m_thread, NULL);
|
||||
pthread_cond_destroy(&m_cond_request);
|
||||
} // ~AVIWriter
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AVIWriter::reset()
|
||||
{
|
||||
m_last_junk_chunk = 0;
|
||||
m_end_of_header = 0;
|
||||
m_movi_start = 0;
|
||||
m_img_quality = UserConfigParams::m_record_compression;
|
||||
m_msec_per_frame = unsigned(1000 / UserConfigParams::m_record_fps);
|
||||
m_stream_bytes = 0;
|
||||
m_total_frames = 0;
|
||||
m_pbo_use = 0;
|
||||
m_accumulated_time = 0.0f;
|
||||
m_remaining_time = 0.0f;
|
||||
m_chunk_fcc = 0;
|
||||
} // reset
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void* AVIWriter::startRoutine(void *obj)
|
||||
{
|
||||
@ -59,34 +78,51 @@ void* AVIWriter::startRoutine(void *obj)
|
||||
AVIWriter* avi_writer = (AVIWriter*)obj;
|
||||
while (true)
|
||||
{
|
||||
pthread_mutex_lock(&avi_writer->m_fbi_mutex);
|
||||
bool waiting = avi_writer->m_fbi_queue.empty();
|
||||
avi_writer->m_fbi_queue.lock();
|
||||
bool waiting = avi_writer->m_fbi_queue.getData().empty();
|
||||
while (waiting)
|
||||
{
|
||||
pthread_cond_wait(&avi_writer->m_cond_request,
|
||||
&avi_writer->m_fbi_mutex);
|
||||
waiting = avi_writer->m_fbi_queue.empty();
|
||||
avi_writer->m_fbi_queue.getMutex());
|
||||
waiting = avi_writer->m_fbi_queue.getData().empty();
|
||||
}
|
||||
auto& p = avi_writer->m_fbi_queue.front();
|
||||
auto& p = avi_writer->m_fbi_queue.getData().front();
|
||||
uint8_t* fbi = p.first;
|
||||
int frame_count = p.second;
|
||||
if (frame_count == -1)
|
||||
{
|
||||
avi_writer->closeFile();
|
||||
avi_writer->m_file = NULL;
|
||||
avi_writer->m_fbi_queue.pop_front();
|
||||
pthread_mutex_unlock(&avi_writer->m_fbi_mutex);
|
||||
avi_writer->m_fbi_queue.getData().pop_front();
|
||||
avi_writer->m_fbi_queue.unlock();
|
||||
continue;
|
||||
}
|
||||
else if (fbi == NULL)
|
||||
{
|
||||
avi_writer->closeFile();
|
||||
avi_writer->setCanBeDeleted();
|
||||
avi_writer->m_fbi_queue.pop_front();
|
||||
pthread_mutex_unlock(&avi_writer->m_fbi_mutex);
|
||||
avi_writer->m_fbi_queue.getData().pop_front();
|
||||
avi_writer->m_fbi_queue.unlock();
|
||||
return NULL;
|
||||
}
|
||||
avi_writer->m_fbi_queue.pop_front();
|
||||
pthread_mutex_unlock(&avi_writer->m_fbi_mutex);
|
||||
const bool too_slow = avi_writer->m_fbi_queue.getData().size() > 50;
|
||||
avi_writer->m_fbi_queue.getData().pop_front();
|
||||
avi_writer->m_fbi_queue.unlock();
|
||||
if (too_slow)
|
||||
{
|
||||
delete [] fbi;
|
||||
avi_writer->cleanAllFrameBufferImages();
|
||||
continue;
|
||||
}
|
||||
if (avi_writer->m_file == NULL)
|
||||
{
|
||||
bool ret = avi_writer->createFile();
|
||||
if (!ret)
|
||||
{
|
||||
delete [] fbi;
|
||||
avi_writer->cleanAllFrameBufferImages();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
uint8_t* orig_fbi = fbi;
|
||||
const unsigned width = avi_writer->m_width;
|
||||
const unsigned height = avi_writer->m_height;
|
||||
@ -129,8 +165,16 @@ void* AVIWriter::startRoutine(void *obj)
|
||||
}
|
||||
while (frame_count != 0)
|
||||
{
|
||||
avi_writer->addImage(avi_writer->m_avi_format == AVI_FORMAT_JPG ?
|
||||
orig_fbi : orig_fbi + area, size);
|
||||
AVIErrCode code = avi_writer->addImage
|
||||
(avi_writer->m_avi_format == AVI_FORMAT_JPG ? orig_fbi :
|
||||
orig_fbi + area, size);
|
||||
if (code == AVI_SIZE_LIMIT_ERR)
|
||||
{
|
||||
avi_writer->createFile();
|
||||
continue;
|
||||
}
|
||||
else if (code == AVI_IO_ERR)
|
||||
break;
|
||||
frame_count--;
|
||||
}
|
||||
delete [] orig_fbi;
|
||||
@ -161,12 +205,7 @@ int AVIWriter::getFrameCount(float dt)
|
||||
// ----------------------------------------------------------------------------
|
||||
void AVIWriter::captureFrameBufferImage(float dt)
|
||||
{
|
||||
if (m_file == NULL)
|
||||
{
|
||||
createFile();
|
||||
}
|
||||
glReadBuffer(GL_BACK);
|
||||
|
||||
int pbo_read = -1;
|
||||
if (m_pbo_use > 3 && m_pbo_use % 3 == 0)
|
||||
m_pbo_use = 3;
|
||||
@ -194,13 +233,6 @@ void AVIWriter::captureFrameBufferImage(float dt)
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
} // captureFrameBufferImage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AVIWriter::stopRecording()
|
||||
{
|
||||
assert(m_file != NULL);
|
||||
addFrameBufferImage(NULL, -1);
|
||||
} // stopRecording
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool AVIWriter::addJUNKChunk(std::string str, unsigned int min_size)
|
||||
{
|
||||
@ -390,12 +422,8 @@ error:
|
||||
// ----------------------------------------------------------------------------
|
||||
bool AVIWriter::createFile()
|
||||
{
|
||||
if (m_file != NULL)
|
||||
return false;
|
||||
|
||||
m_avi_format =
|
||||
UserConfigParams::m_record_bmp ? AVI_FORMAT_BMP : AVI_FORMAT_JPG;
|
||||
m_img_quality = UserConfigParams::m_record_compression;
|
||||
time_t rawtime;
|
||||
time(&rawtime);
|
||||
tm* timeInfo = localtime(&rawtime);
|
||||
@ -405,14 +433,9 @@ bool AVIWriter::createFile()
|
||||
timeInfo->tm_mday, timeInfo->tm_hour,
|
||||
timeInfo->tm_min, timeInfo->tm_sec);
|
||||
|
||||
std::string track_name = World::getWorld() != NULL ?
|
||||
race_manager->getTrackName() : "menu";
|
||||
|
||||
m_filename = file_manager->getScreenshotDir() + track_name + "-"
|
||||
+ time_buffer + ".avi";
|
||||
m_filename = m_recording_target.getAtomic() + "-" + time_buffer + ".avi";
|
||||
m_stream_bytes = 0;
|
||||
m_total_frames = 0;
|
||||
m_msec_per_frame = unsigned(1000 / UserConfigParams::m_record_fps);
|
||||
m_movi_start = 0;
|
||||
m_last_junk_chunk = 0;
|
||||
m_total_frames = 0;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "utils/can_be_deleted.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/singleton.hpp"
|
||||
#include "utils/synchronised.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
@ -166,6 +167,8 @@ class AVIWriter : public CanBeDeleted, public NoCopy,
|
||||
private:
|
||||
FILE* m_file;
|
||||
|
||||
Synchronised<std::string> m_recording_target;
|
||||
|
||||
std::string m_filename;
|
||||
|
||||
int m_last_junk_chunk, m_end_of_header, m_movi_start, m_img_quality,
|
||||
@ -187,12 +190,10 @@ private:
|
||||
|
||||
uint32_t m_chunk_fcc;
|
||||
|
||||
std::list<std::pair<uint8_t*, int> > m_fbi_queue;
|
||||
Synchronised<std::list<std::pair<uint8_t*, int> > > m_fbi_queue;
|
||||
|
||||
pthread_t m_thread;
|
||||
|
||||
pthread_mutex_t m_fbi_mutex;
|
||||
|
||||
pthread_cond_t m_cond_request;
|
||||
|
||||
GLuint m_pbo[3];
|
||||
@ -211,23 +212,38 @@ private:
|
||||
// ------------------------------------------------------------------------
|
||||
void addFrameBufferImage(uint8_t* fbi, int frame_count)
|
||||
{
|
||||
pthread_mutex_lock(&m_fbi_mutex);
|
||||
m_fbi_queue.emplace_back(fbi, frame_count);
|
||||
m_fbi_queue.lock();
|
||||
m_fbi_queue.getData().emplace_back(fbi, frame_count);
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
pthread_mutex_unlock(&m_fbi_mutex);
|
||||
m_fbi_queue.unlock();
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
int getFrameCount(float dt);
|
||||
// ------------------------------------------------------------------------
|
||||
void cleanAllFrameBufferImages()
|
||||
{
|
||||
m_fbi_queue.lock();
|
||||
for (auto& p : m_fbi_queue.getData())
|
||||
delete p.first;
|
||||
m_fbi_queue.unlock();
|
||||
}
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
AVIWriter();
|
||||
// ------------------------------------------------------------------------
|
||||
~AVIWriter();
|
||||
// ------------------------------------------------------------------------
|
||||
static void* startRoutine(void *obj);
|
||||
// ------------------------------------------------------------------------
|
||||
void captureFrameBufferImage(float dt);
|
||||
// ------------------------------------------------------------------------
|
||||
void stopRecording();
|
||||
void reset();
|
||||
// ------------------------------------------------------------------------
|
||||
void stopRecording() { addFrameBufferImage(NULL, -1); }
|
||||
// ------------------------------------------------------------------------
|
||||
void setRecordingTarget(const std::string& name)
|
||||
{ m_recording_target.setAtomic(name); }
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user