Restructured Qt AVI writer to run is its own thread.

This commit is contained in:
mjbudd77 2021-04-29 21:50:45 -04:00
parent e9dbe9428a
commit b9f6bf281f
6 changed files with 193 additions and 10 deletions

View File

@ -4,13 +4,23 @@
#include <string.h> #include <string.h>
#include "driver.h" #include "driver.h"
#include "common/os_utils.h"
#include "Qt/AviRecord.h" #include "Qt/AviRecord.h"
#include "Qt/avi/gwavi.h" #include "Qt/avi/gwavi.h"
#include "Qt/nes_shm.h" #include "Qt/nes_shm.h"
#include "Qt/ConsoleUtilities.h"
static gwavi_t *gwavi = NULL; static gwavi_t *gwavi = NULL;
static bool recordEnable = false; static bool recordEnable = false;
static int vbufHead = 0;
static int vbufTail = 0;
static int vbufSize = 0;
static int abufHead = 0;
static int abufTail = 0;
static int abufSize = 0;
static uint32_t *rawVideoBuf = NULL;
static int16_t *rawAudioBuf = NULL;
//************************************************************************************** //**************************************************************************************
static void convertRgb_32_to_24( const unsigned char *src, unsigned char *dest, int w, int h, int nPix ) static void convertRgb_32_to_24( const unsigned char *src, unsigned char *dest, int w, int h, int nPix )
@ -64,6 +74,12 @@ int aviRecordOpenFile( const char *filepath, int format, int width, int height )
return -1; return -1;
} }
vbufSize = 1024 * 1024 * 60;
rawVideoBuf = (uint32_t*)malloc( vbufSize * sizeof(uint32_t) );
abufSize = 48000;
rawAudioBuf = (int16_t*)malloc( abufSize * sizeof(uint16_t) );
recordEnable = true; recordEnable = true;
return 0; return 0;
} }
@ -79,18 +95,38 @@ int aviRecordAddFrame( void )
{ {
return -1; return -1;
} }
int numPixels, bufferSize; int i, head, numPixels, availSize;
numPixels = nes_shm->video.ncol * nes_shm->video.nrow; numPixels = nes_shm->video.ncol * nes_shm->video.nrow;
bufferSize = numPixels * sizeof(uint32_t);
availSize = (vbufTail - vbufHead);
if ( availSize <= 0 )
{ {
unsigned char rgb24[bufferSize]; availSize += vbufSize;
convertRgb_32_to_24( (const unsigned char*)nes_shm->pixbuf, rgb24,
nes_shm->video.ncol, nes_shm->video.nrow, numPixels );
gwavi->add_frame( rgb24, numPixels*3 );
} }
while ( numPixels > availSize )
{
//printf("Video Unavail %i \n", availSize );
msleep(1);
availSize = (vbufTail - vbufHead);
if ( availSize <= 0 )
{
availSize += vbufSize;
}
}
i = 0; head = vbufHead;
while ( i < numPixels )
{
rawVideoBuf[ head ] = nes_shm->pixbuf[i]; i++;
head = (head + 1) % vbufSize;
}
vbufHead = head;
return 0; return 0;
} }
//************************************************************************************** //**************************************************************************************
@ -105,13 +141,15 @@ int aviRecordAddAudioFrame( int32_t *buf, int numSamples )
{ {
return -1; return -1;
} }
int16_t lclBuf[numSamples];
for (int i=0; i<numSamples; i++) for (int i=0; i<numSamples; i++)
{ {
lclBuf[i] = buf[i]; rawAudioBuf[ abufHead ] = buf[i];
abufHead = (abufHead + 1) % abufSize;
} }
gwavi->add_audio( (unsigned char *)lclBuf, numSamples*2);
return 0;
} }
//************************************************************************************** //**************************************************************************************
int aviRecordClose(void) int aviRecordClose(void)
@ -125,6 +163,17 @@ int aviRecordClose(void)
delete gwavi; gwavi = NULL; delete gwavi; gwavi = NULL;
} }
if ( rawVideoBuf != NULL )
{
free(rawVideoBuf); rawVideoBuf = NULL;
}
if ( rawAudioBuf != NULL )
{
free(rawAudioBuf); rawAudioBuf = NULL;
}
vbufTail = abufTail = 0;
vbufSize = abufSize = 0;
return 0; return 0;
} }
//************************************************************************************** //**************************************************************************************
@ -133,3 +182,91 @@ bool aviRecordRunning(void)
return recordEnable; return recordEnable;
} }
//************************************************************************************** //**************************************************************************************
// AVI Recorder Disk Thread
//**************************************************************************************
//----------------------------------------------------
AviRecordDiskThread_t::AviRecordDiskThread_t( QObject *parent )
: QThread(parent)
{
}
//----------------------------------------------------
AviRecordDiskThread_t::~AviRecordDiskThread_t(void)
{
}
//----------------------------------------------------
void AviRecordDiskThread_t::run(void)
{
int numPixels, width, height, numPixelsReady = 0;
int numSamples = 0;
unsigned char *rgb24;
int16_t audioOut[48000];
uint32_t videoOut[1048576];
printf("AVI Record Disk Start\n");
setPriority( QThread::HighestPriority );
//avgAudioPerFrame = 48000 / 60;
width = nes_shm->video.ncol;
height = nes_shm->video.nrow;
numPixels = width * height;
rgb24 = (unsigned char *)malloc( numPixels * sizeof(uint32_t) );
while ( !isInterruptionRequested() )
{
while ( (numPixelsReady < numPixels) && (vbufTail != vbufHead) )
{
videoOut[ numPixelsReady ] = rawVideoBuf[ vbufTail ]; numPixelsReady++;
vbufTail = (vbufTail + 1) % vbufSize;
}
if ( numPixelsReady >= numPixels )
{
convertRgb_32_to_24( (const unsigned char*)videoOut, rgb24,
width, height, numPixels );
gwavi->add_frame( rgb24, numPixels*3 );
numPixelsReady = 0;
numSamples = 0;
while ( abufHead != abufTail )
{
audioOut[ numSamples ] = rawAudioBuf[ abufTail ]; numSamples++;
abufTail = (abufTail + 1) % abufSize;
//if ( numSamples > avgAudioPerFrame )
//{
// break;
//}
}
if ( numSamples > 0 )
{
//printf("NUM Audio Samples: %i \n", numSamples );
gwavi->add_audio( (unsigned char *)audioOut, numSamples*2);
numSamples = 0;
}
}
else
{
msleep(1);
}
}
free(rgb24);
aviRecordClose();
printf("AVI Record Disk Exit\n");
emit finished();
}
//----------------------------------------------------
//**************************************************************************************

View File

@ -1,6 +1,11 @@
// AviRecord.h // AviRecord.h
// //
#ifndef __AVI_RECORD_H__
#define __AVI_RECORD_H__
#include <stdint.h> #include <stdint.h>
#include <QThread>
int aviRecordOpenFile( const char *filepath, int format, int width, int height ); int aviRecordOpenFile( const char *filepath, int format, int width, int height );
@ -11,3 +16,21 @@ int aviRecordAddAudioFrame( int32_t *buf, int numSamples );
int aviRecordClose(void); int aviRecordClose(void);
bool aviRecordRunning(void); bool aviRecordRunning(void);
class AviRecordDiskThread_t : public QThread
{
Q_OBJECT
protected:
void run( void ) override;
public:
AviRecordDiskThread_t( QObject *parent = 0 );
~AviRecordDiskThread_t(void);
private:
signals:
void finished(void);
};
#endif

View File

@ -209,6 +209,10 @@ consoleWin_t::consoleWin_t(QWidget *parent)
// Viewport Cursor Type and Visibility // Viewport Cursor Type and Visibility
loadCursor(); loadCursor();
// Create AVI Recording Disk Thread
aviDiskThread = new AviRecordDiskThread_t(this);
} }
consoleWin_t::~consoleWin_t(void) consoleWin_t::~consoleWin_t(void)
@ -244,6 +248,10 @@ consoleWin_t::~consoleWin_t(void)
emulatorThread->quit(); emulatorThread->quit();
emulatorThread->wait( 1000 ); emulatorThread->wait( 1000 );
aviDiskThread->requestInterruption();
aviDiskThread->quit();
aviDiskThread->wait( 10000 );
fceuWrapperLock(); fceuWrapperLock();
fceuWrapperClose(); fceuWrapperClose();
fceuWrapperUnLock(); fceuWrapperUnLock();
@ -3100,13 +3108,16 @@ void consoleWin_t::aviOpen(void)
if ( aviRecordRunning() ) if ( aviRecordRunning() )
{ {
fceuWrapperLock(); fceuWrapperLock();
aviRecordClose(); aviDiskThread->requestInterruption();
aviDiskThread->quit();
aviDiskThread->wait(10000);
fceuWrapperUnLock(); fceuWrapperUnLock();
} }
else else
{ {
fceuWrapperLock(); fceuWrapperLock();
aviRecordOpenFile( NULL, 0, 256, 240 ); aviRecordOpenFile( NULL, 0, 256, 240 );
aviDiskThread->start();
fceuWrapperUnLock(); fceuWrapperUnLock();
} }
} }

View File

@ -27,6 +27,7 @@
#include "Qt/ConsoleViewerGL.h" #include "Qt/ConsoleViewerGL.h"
#include "Qt/ConsoleViewerSDL.h" #include "Qt/ConsoleViewerSDL.h"
#include "Qt/GamePadConf.h" #include "Qt/GamePadConf.h"
#include "Qt/AviRecord.h"
class emulatorThread_t : public QThread class emulatorThread_t : public QThread
{ {
@ -123,6 +124,7 @@ class consoleWin_t : public QMainWindow
int loadVideoDriver( int driverId ); int loadVideoDriver( int driverId );
emulatorThread_t *emulatorThread; emulatorThread_t *emulatorThread;
AviRecordDiskThread_t *aviDiskThread;
void addRecentRom( const char *rom ); void addRecentRom( const char *rom );

View File

@ -81,6 +81,11 @@ gwavi_t::gwavi_t(void)
offset_count = 0; offset_count = 0;
} }
gwavi_t::~gwavi_t(void)
{
}
int int
gwavi_t::open(const char *filename, unsigned int width, unsigned int height, gwavi_t::open(const char *filename, unsigned int width, unsigned int height,
@ -105,9 +110,13 @@ gwavi_t::open(const char *filename, unsigned int width, unsigned int height,
avi_header.flags = 0x10; avi_header.flags = 0x10;
if (audio) if (audio)
{
avi_header.data_streams = 2; avi_header.data_streams = 2;
}
else else
{
avi_header.data_streams = 1; avi_header.data_streams = 1;
}
/* this field gets updated when calling gwavi_close() */ /* this field gets updated when calling gwavi_close() */
avi_header.number_of_frames = 0; avi_header.number_of_frames = 0;

View File

@ -115,6 +115,7 @@ class gwavi_t
{ {
public: public:
gwavi_t(void); gwavi_t(void);
~gwavi_t(void);
int open(const char *filename, unsigned int width, int open(const char *filename, unsigned int width,
unsigned int height, const char *fourcc, unsigned int fps, unsigned int height, const char *fourcc, unsigned int fps,