Try to maintain a better synchronization with game framerate
This commit is contained in:
parent
88cbcd202c
commit
78dcabb143
@ -33,14 +33,17 @@ AVIWriter::AVIWriter()
|
|||||||
{
|
{
|
||||||
m_file = NULL;
|
m_file = NULL;
|
||||||
m_pbo_use = 0;
|
m_pbo_use = 0;
|
||||||
m_dt = 0.0f;
|
m_accumulated_time = 0.0f;
|
||||||
|
m_remaining_time = 0.0f;
|
||||||
|
m_img_quality = 0;
|
||||||
|
m_width = irr_driver->getActualScreenSize().Width;
|
||||||
|
m_height = irr_driver->getActualScreenSize().Height;
|
||||||
glGenBuffers(3, m_pbo);
|
glGenBuffers(3, m_pbo);
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo[i]);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo[i]);
|
||||||
glBufferData(GL_PIXEL_PACK_BUFFER,
|
glBufferData(GL_PIXEL_PACK_BUFFER, m_width * m_height * 4, NULL,
|
||||||
irr_driver->getActualScreenSize().getArea() * 4, NULL,
|
GL_STREAM_READ);
|
||||||
GL_STREAM_READ);
|
|
||||||
}
|
}
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
pthread_mutex_init(&m_fbi_mutex, NULL);
|
pthread_mutex_init(&m_fbi_mutex, NULL);
|
||||||
@ -63,15 +66,10 @@ void* AVIWriter::startRoutine(void *obj)
|
|||||||
&avi_writer->m_fbi_mutex);
|
&avi_writer->m_fbi_mutex);
|
||||||
waiting = avi_writer->m_fbi_queue.empty();
|
waiting = avi_writer->m_fbi_queue.empty();
|
||||||
}
|
}
|
||||||
uint8_t* fbi = avi_writer->m_fbi_queue.front();
|
auto& p = avi_writer->m_fbi_queue.front();
|
||||||
if (fbi == NULL)
|
uint8_t* fbi = p.first;
|
||||||
{
|
const float dt = p.second;
|
||||||
avi_writer->setCanBeDeleted();
|
if (dt < 0.0f)
|
||||||
avi_writer->m_fbi_queue.pop_front();
|
|
||||||
pthread_mutex_unlock(&avi_writer->m_fbi_mutex);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (fbi == (uint8_t*)0xAAAB1E5D)
|
|
||||||
{
|
{
|
||||||
avi_writer->closeFile();
|
avi_writer->closeFile();
|
||||||
avi_writer->m_file = NULL;
|
avi_writer->m_file = NULL;
|
||||||
@ -79,8 +77,21 @@ void* AVIWriter::startRoutine(void *obj)
|
|||||||
pthread_mutex_unlock(&avi_writer->m_fbi_mutex);
|
pthread_mutex_unlock(&avi_writer->m_fbi_mutex);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (fbi == NULL)
|
||||||
|
{
|
||||||
|
avi_writer->setCanBeDeleted();
|
||||||
|
avi_writer->m_fbi_queue.pop_front();
|
||||||
|
pthread_mutex_unlock(&avi_writer->m_fbi_mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
avi_writer->m_fbi_queue.pop_front();
|
avi_writer->m_fbi_queue.pop_front();
|
||||||
pthread_mutex_unlock(&avi_writer->m_fbi_mutex);
|
pthread_mutex_unlock(&avi_writer->m_fbi_mutex);
|
||||||
|
int frame_count = avi_writer->handleFrameBufferImage(fbi, dt);
|
||||||
|
if (frame_count == -1)
|
||||||
|
{
|
||||||
|
delete [] fbi;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
video::IImage* image = irr_driver->getVideoDriver()
|
video::IImage* image = irr_driver->getVideoDriver()
|
||||||
->createImageFromData(video::ECF_A8R8G8B8,
|
->createImageFromData(video::ECF_A8R8G8B8,
|
||||||
irr_driver->getActualScreenSize(), fbi,
|
irr_driver->getActualScreenSize(), fbi,
|
||||||
@ -94,12 +105,12 @@ void* AVIWriter::startRoutine(void *obj)
|
|||||||
rgb->unlock();
|
rgb->unlock();
|
||||||
rgb->drop();
|
rgb->drop();
|
||||||
uint8_t* orig_fbi = fbi;
|
uint8_t* orig_fbi = fbi;
|
||||||
const int pitch = irr_driver->getActualScreenSize().Width * 3;
|
const unsigned width = avi_writer->m_width;
|
||||||
uint8_t* p2 = fbi + (irr_driver->getActualScreenSize().Height - 1) *
|
const unsigned height = avi_writer->m_height;
|
||||||
pitch;
|
const int pitch = width * 3;
|
||||||
|
uint8_t* p2 = fbi + (height - 1) * pitch;
|
||||||
uint8_t* tmp_buf = new uint8_t[pitch];
|
uint8_t* tmp_buf = new uint8_t[pitch];
|
||||||
for (unsigned i = 0; i < irr_driver->getActualScreenSize().Height;
|
for (unsigned i = 0; i < height; i += 2)
|
||||||
i += 2)
|
|
||||||
{
|
{
|
||||||
memcpy(tmp_buf, fbi, pitch);
|
memcpy(tmp_buf, fbi, pitch);
|
||||||
memcpy(fbi, p2, pitch);
|
memcpy(fbi, p2, pitch);
|
||||||
@ -108,47 +119,67 @@ void* AVIWriter::startRoutine(void *obj)
|
|||||||
p2 -= pitch;
|
p2 -= pitch;
|
||||||
}
|
}
|
||||||
delete [] tmp_buf;
|
delete [] tmp_buf;
|
||||||
const unsigned size = irr_driver->getActualScreenSize().getArea() * 3;
|
const unsigned size = width * height * 3;
|
||||||
uint8_t* jpg = new uint8_t[size];
|
uint8_t* jpg = new uint8_t[size];
|
||||||
int new_len = bmpToJpg(orig_fbi, jpg, size,
|
int new_len = avi_writer->bmpToJpg(orig_fbi, jpg, size);
|
||||||
irr_driver->getActualScreenSize().Width,
|
delete [] orig_fbi;
|
||||||
irr_driver->getActualScreenSize().Height, 3, 70);
|
while (frame_count != 0)
|
||||||
delete[] orig_fbi;
|
{
|
||||||
avi_writer->addImage(jpg, new_len);
|
avi_writer->addImage(jpg, new_len);
|
||||||
delete[] jpg;
|
frame_count--;
|
||||||
|
}
|
||||||
|
delete [] jpg;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
} // startRoutine
|
} // startRoutine
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
int AVIWriter::handleFrameBufferImage(uint8_t* fbi, float dt)
|
||||||
|
{
|
||||||
|
const float frame_rate = 0.001f * m_msec_per_frame;
|
||||||
|
m_accumulated_time += dt;
|
||||||
|
if (m_accumulated_time < frame_rate && m_remaining_time < frame_rate)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int frame_count = 1;
|
||||||
|
m_remaining_time += m_accumulated_time - frame_rate;
|
||||||
|
m_accumulated_time = 0.0f;
|
||||||
|
while (m_remaining_time > frame_rate)
|
||||||
|
{
|
||||||
|
frame_count++;
|
||||||
|
m_remaining_time -= frame_rate;
|
||||||
|
}
|
||||||
|
return frame_count;
|
||||||
|
} // handleFrameBufferImage
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void AVIWriter::captureFrameBufferImage(float dt)
|
void AVIWriter::captureFrameBufferImage(float dt)
|
||||||
{
|
{
|
||||||
if (m_file == NULL)
|
if (m_file == NULL)
|
||||||
{
|
{
|
||||||
createFile(AVI_FORMAT_JPG, 24, 70);
|
createFile(AVI_FORMAT_JPG, 24/*fps*/, 24/*bits*/, 90/*quality*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dt += dt;
|
|
||||||
glReadBuffer(GL_BACK);
|
glReadBuffer(GL_BACK);
|
||||||
|
|
||||||
int pbo_read = -1;
|
int pbo_read = -1;
|
||||||
if (m_pbo_use > 2 && m_dt >= 0.0416666667f)
|
if (m_pbo_use > 3 && m_pbo_use % 3 == 0)
|
||||||
|
m_pbo_use = 3;
|
||||||
|
if (m_pbo_use >= 3)
|
||||||
{
|
{
|
||||||
m_dt = 0.0f;
|
|
||||||
pbo_read = m_pbo_use % 3;
|
pbo_read = m_pbo_use % 3;
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo[pbo_read]);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo[pbo_read]);
|
||||||
void* ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
void* ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
||||||
const unsigned size = irr_driver->getActualScreenSize().getArea() * 4;
|
const unsigned size = m_width * m_height * 4;
|
||||||
uint8_t* fbi = new uint8_t[size];
|
uint8_t* fbi = new uint8_t[size];
|
||||||
memcpy(fbi, ptr, size);
|
memcpy(fbi, ptr, size);
|
||||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||||
addFrameBufferImage(fbi);
|
addFrameBufferImage(fbi, dt);
|
||||||
}
|
}
|
||||||
int pbo_use = m_pbo_use++ % 3;
|
int pbo_use = m_pbo_use++ % 3;
|
||||||
assert(pbo_read == -1 || pbo_use == pbo_read);
|
assert(pbo_read == -1 || pbo_use == pbo_read);
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo[pbo_use]);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo[pbo_use]);
|
||||||
glReadPixels(0, 0, irr_driver->getActualScreenSize().Width,
|
glReadPixels(0, 0, m_width, m_height, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
|
||||||
irr_driver->getActualScreenSize().Height, GL_BGRA, GL_UNSIGNED_BYTE,
|
|
||||||
0);
|
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
} // captureFrameBufferImage
|
} // captureFrameBufferImage
|
||||||
|
|
||||||
@ -156,7 +187,7 @@ void AVIWriter::captureFrameBufferImage(float dt)
|
|||||||
void AVIWriter::stopRecording()
|
void AVIWriter::stopRecording()
|
||||||
{
|
{
|
||||||
assert(m_file != NULL);
|
assert(m_file != NULL);
|
||||||
addFrameBufferImage((uint8_t*)0xAAAB1E5D);
|
addFrameBufferImage(NULL, -1.0f);
|
||||||
} // stopRecording
|
} // stopRecording
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -348,14 +379,13 @@ error:
|
|||||||
} // closeFile
|
} // closeFile
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
bool AVIWriter::createFile(AVIFormat avi_format, int bits, int quality)
|
bool AVIWriter::createFile(AVIFormat avi_format, int fps, int bits,
|
||||||
|
int quality)
|
||||||
{
|
{
|
||||||
if (m_file != NULL)
|
if (m_file != NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int width = irr_driver->getActualScreenSize().Width;
|
m_img_quality = quality;
|
||||||
int height = irr_driver->getActualScreenSize().Height;
|
|
||||||
|
|
||||||
time_t rawtime;
|
time_t rawtime;
|
||||||
time(&rawtime);
|
time(&rawtime);
|
||||||
tm* timeInfo = localtime(&rawtime);
|
tm* timeInfo = localtime(&rawtime);
|
||||||
@ -372,19 +402,19 @@ bool AVIWriter::createFile(AVIFormat avi_format, int bits, int quality)
|
|||||||
+ time_buffer + ".avi";
|
+ time_buffer + ".avi";
|
||||||
m_stream_bytes = 0;
|
m_stream_bytes = 0;
|
||||||
m_total_frames = 0;
|
m_total_frames = 0;
|
||||||
m_msec_per_frame = 42;
|
m_msec_per_frame = unsigned(1000 / fps);
|
||||||
m_movi_start = 0;
|
m_movi_start = 0;
|
||||||
m_last_junk_chunk = 0;
|
m_last_junk_chunk = 0;
|
||||||
m_total_frames = 0;
|
m_total_frames = 0;
|
||||||
|
|
||||||
BitmapInfoHeader bitmap_hdr;
|
BitmapInfoHeader bitmap_hdr;
|
||||||
bitmap_hdr.biSize = sizeof(BitmapInfoHeader);
|
bitmap_hdr.biSize = sizeof(BitmapInfoHeader);
|
||||||
bitmap_hdr.biWidth = width;
|
bitmap_hdr.biWidth = m_width;
|
||||||
bitmap_hdr.biHeight = height;
|
bitmap_hdr.biHeight = m_height;
|
||||||
bitmap_hdr.biPlanes = 1;
|
bitmap_hdr.biPlanes = 1;
|
||||||
bitmap_hdr.biBitCount = bits;
|
bitmap_hdr.biBitCount = bits;
|
||||||
bitmap_hdr.biCompression = 0;
|
bitmap_hdr.biCompression = 0;
|
||||||
bitmap_hdr.biSizeImage = (width * height * 3 * bitmap_hdr.biPlanes);
|
bitmap_hdr.biSizeImage = (m_width * m_height * 3 * bitmap_hdr.biPlanes);
|
||||||
bitmap_hdr.biXPelsPerMeter = 0;
|
bitmap_hdr.biXPelsPerMeter = 0;
|
||||||
bitmap_hdr.biYPelsPerMeter = 0;
|
bitmap_hdr.biYPelsPerMeter = 0;
|
||||||
bitmap_hdr.biClrUsed = 0;
|
bitmap_hdr.biClrUsed = 0;
|
||||||
@ -407,8 +437,8 @@ bool AVIWriter::createFile(AVIFormat avi_format, int bits, int quality)
|
|||||||
m_avi_hdr.avih.dwInitialFrames = 0;
|
m_avi_hdr.avih.dwInitialFrames = 0;
|
||||||
m_avi_hdr.avih.dwStreams = 1; // 1 = video, 2 = video and audio
|
m_avi_hdr.avih.dwStreams = 1; // 1 = video, 2 = video and audio
|
||||||
m_avi_hdr.avih.dwSuggestedBufferSize = 0; // can be just 0
|
m_avi_hdr.avih.dwSuggestedBufferSize = 0; // can be just 0
|
||||||
m_avi_hdr.avih.dwWidth = width;
|
m_avi_hdr.avih.dwWidth = m_width;
|
||||||
m_avi_hdr.avih.dwHeight = height;
|
m_avi_hdr.avih.dwHeight = m_height;
|
||||||
|
|
||||||
m_format_hdr.list.fcc = FOURCC('L', 'I', 'S', 'T');
|
m_format_hdr.list.fcc = FOURCC('L', 'I', 'S', 'T');
|
||||||
m_format_hdr.list.cb = (sizeof(m_format_hdr) - 8) +
|
m_format_hdr.list.cb = (sizeof(m_format_hdr) - 8) +
|
||||||
@ -427,7 +457,7 @@ bool AVIWriter::createFile(AVIFormat avi_format, int bits, int quality)
|
|||||||
m_format_hdr.strh.dwStart = 0;
|
m_format_hdr.strh.dwStart = 0;
|
||||||
m_format_hdr.strh.dwLength = 0; // update when finished
|
m_format_hdr.strh.dwLength = 0; // update when finished
|
||||||
m_format_hdr.strh.dwSuggestedBufferSize = 0; // can be just 0
|
m_format_hdr.strh.dwSuggestedBufferSize = 0; // can be just 0
|
||||||
m_format_hdr.strh.dwQuality = quality * 100;
|
m_format_hdr.strh.dwQuality = m_img_quality * 100;
|
||||||
m_format_hdr.strh.dwSampleSize = 0;
|
m_format_hdr.strh.dwSampleSize = 0;
|
||||||
m_format_hdr.strh.Left = 0;
|
m_format_hdr.strh.Left = 0;
|
||||||
m_format_hdr.strh.Top = 0;
|
m_format_hdr.strh.Top = 0;
|
||||||
@ -445,7 +475,7 @@ bool AVIWriter::createFile(AVIFormat avi_format, int bits, int quality)
|
|||||||
}
|
}
|
||||||
else if (avi_format == AVI_FORMAT_BMP)
|
else if (avi_format == AVI_FORMAT_BMP)
|
||||||
{
|
{
|
||||||
bitmap_hdr.biHeight = -height;
|
bitmap_hdr.biHeight = -m_height;
|
||||||
bitmap_hdr.biCompression = 0;
|
bitmap_hdr.biCompression = 0;
|
||||||
m_chunk_fcc = FOURCC('0', '0', 'd', 'b');
|
m_chunk_fcc = FOURCC('0', '0', 'd', 'b');
|
||||||
}
|
}
|
||||||
@ -501,8 +531,7 @@ error:
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
int AVIWriter::bmpToJpg(unsigned char* image_data, unsigned char* image_output,
|
int AVIWriter::bmpToJpg(unsigned char* image_data, unsigned char* image_output,
|
||||||
unsigned long buf_length, unsigned int width,
|
unsigned long buf_length)
|
||||||
unsigned int height, int num_channels, int quality)
|
|
||||||
{
|
{
|
||||||
struct jpeg_compress_struct cinfo;
|
struct jpeg_compress_struct cinfo;
|
||||||
struct jpeg_error_mgr jerr;
|
struct jpeg_error_mgr jerr;
|
||||||
@ -510,13 +539,13 @@ int AVIWriter::bmpToJpg(unsigned char* image_data, unsigned char* image_output,
|
|||||||
|
|
||||||
jpeg_create_compress(&cinfo);
|
jpeg_create_compress(&cinfo);
|
||||||
|
|
||||||
cinfo.image_width = width;
|
cinfo.image_width = m_width;
|
||||||
cinfo.image_height = height;
|
cinfo.image_height = m_height;
|
||||||
cinfo.input_components = num_channels;
|
cinfo.input_components = 3;
|
||||||
cinfo.in_color_space = JCS_RGB;
|
cinfo.in_color_space = JCS_RGB;
|
||||||
|
|
||||||
jpeg_set_defaults(&cinfo);
|
jpeg_set_defaults(&cinfo);
|
||||||
jpeg_set_quality(&cinfo, quality, true);
|
jpeg_set_quality(&cinfo, m_img_quality, true);
|
||||||
|
|
||||||
jpeg_mem_dest(&cinfo, &image_output, &buf_length);
|
jpeg_mem_dest(&cinfo, &image_output, &buf_length);
|
||||||
|
|
||||||
@ -525,7 +554,7 @@ int AVIWriter::bmpToJpg(unsigned char* image_data, unsigned char* image_output,
|
|||||||
JSAMPROW jrow[1];
|
JSAMPROW jrow[1];
|
||||||
while (cinfo.next_scanline < cinfo.image_height)
|
while (cinfo.next_scanline < cinfo.image_height)
|
||||||
{
|
{
|
||||||
jrow[0] = &image_data[cinfo.next_scanline * width * num_channels];
|
jrow[0] = &image_data[cinfo.next_scanline * m_width * 3];
|
||||||
jpeg_write_scanlines(&cinfo, jrow, 1);
|
jpeg_write_scanlines(&cinfo, jrow, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,11 +169,12 @@ private:
|
|||||||
|
|
||||||
std::string m_filename;
|
std::string m_filename;
|
||||||
|
|
||||||
int m_last_junk_chunk, m_end_of_header, m_movi_start;
|
int m_last_junk_chunk, m_end_of_header, m_movi_start, m_img_quality;
|
||||||
|
|
||||||
unsigned int m_msec_per_frame, m_stream_bytes, m_total_frames, m_pbo_use;
|
unsigned int m_msec_per_frame, m_stream_bytes, m_total_frames, m_pbo_use,
|
||||||
|
m_width, m_height;
|
||||||
|
|
||||||
float m_dt;
|
float m_accumulated_time, m_remaining_time;
|
||||||
|
|
||||||
AVIHeader m_avi_hdr;
|
AVIHeader m_avi_hdr;
|
||||||
|
|
||||||
@ -185,7 +186,7 @@ private:
|
|||||||
|
|
||||||
uint32_t m_chunk_fcc;
|
uint32_t m_chunk_fcc;
|
||||||
|
|
||||||
std::list<uint8_t*> m_fbi_queue;
|
std::list<std::pair<uint8_t*, float> > m_fbi_queue;
|
||||||
|
|
||||||
pthread_t m_thread;
|
pthread_t m_thread;
|
||||||
|
|
||||||
@ -196,25 +197,26 @@ private:
|
|||||||
GLuint m_pbo[3];
|
GLuint m_pbo[3];
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
static int bmpToJpg(unsigned char* image_data, unsigned char* image_output,
|
int bmpToJpg(unsigned char* image_data, unsigned char* image_output,
|
||||||
unsigned long buf_length, unsigned int width,
|
unsigned long buf_length);
|
||||||
unsigned int height, int num_channels, int quality);
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
AVIErrCode addImage(unsigned char* buffer, int size);
|
AVIErrCode addImage(unsigned char* buffer, int size);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
bool closeFile(bool delete_file = false);
|
bool closeFile(bool delete_file = false);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
bool createFile(AVIFormat avi_format, int bits, int quality);
|
bool createFile(AVIFormat avi_format, int fps, int bits, int quality);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
bool addJUNKChunk(std::string str, unsigned int min_size);
|
bool addJUNKChunk(std::string str, unsigned int min_size);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void addFrameBufferImage(uint8_t* fbi)
|
void addFrameBufferImage(uint8_t* fbi, float dt)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&m_fbi_mutex);
|
pthread_mutex_lock(&m_fbi_mutex);
|
||||||
m_fbi_queue.push_back(fbi);
|
m_fbi_queue.emplace_back(fbi, dt);
|
||||||
pthread_cond_signal(&m_cond_request);
|
pthread_cond_signal(&m_cond_request);
|
||||||
pthread_mutex_unlock(&m_fbi_mutex);
|
pthread_mutex_unlock(&m_fbi_mutex);
|
||||||
}
|
}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
int handleFrameBufferImage(uint8_t* fbi, float dt);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -900,4 +900,4 @@ bool isOpen()
|
|||||||
return g_debug_menu_visible;
|
return g_debug_menu_visible;
|
||||||
} // isOpen
|
} // isOpen
|
||||||
|
|
||||||
} // namespace Debug
|
} // namespace Debug
|
||||||
|
Loading…
x
Reference in New Issue
Block a user