Added an AVI decode debug function to Qt GUI.

This commit is contained in:
mjbudd77 2021-08-25 22:04:39 -04:00
parent 5db7abf118
commit 95db43d3f9
8 changed files with 590 additions and 16 deletions

View File

@ -678,6 +678,21 @@ int aviRecordClose(void)
return 0;
}
//**************************************************************************************
int aviDebugOpenFile( const char *filepath )
{
gwavi_t inAvi;
if ( inAvi.openIn( filepath ) )
{
printf("Failed to open AVI File: '%s'\n", filepath);
return -1;
}
inAvi.printHeaders();
return 0;
}
//**************************************************************************************
bool aviGetAudioEnable(void)
{
return recordAudio;

View File

@ -44,6 +44,8 @@ void aviSetSelVideoFormat(int idx);
int FCEUD_AviGetFormatOpts( std::vector <std::string> &formatList );
int aviDebugOpenFile( const char *filepath );
class AviRecordDiskThread_t : public QThread
{
Q_OBJECT

View File

@ -1765,6 +1765,15 @@ void consoleWin_t::createMainMenu(void)
aviMenu->addAction(stopAviAct);
// Movie -> Avi Recording -> Debug
act = new QAction(tr("&Debug"), this);
//act->setShortcut( QKeySequence(tr("Shift+F5")));
act->setStatusTip(tr("AVI Debug"));
//act->setIcon( style()->standardIcon( QStyle::SP_MediaStop ) );
connect(act, SIGNAL(triggered()), this, SLOT(aviDebugFile(void)) );
aviMenu->addAction(act);
// Movie -> Avi Recording -> Video Format
subMenu = aviMenu->addMenu( tr("Video Format") );
@ -3728,6 +3737,76 @@ void consoleWin_t::aviRecordStop(void)
}
}
void consoleWin_t::aviDebugFile(void)
{
int ret, useNativeFileDialogVal;
QString filename;
std::string last;
//char dir[512];
const char *base;
QFileDialog dialog(this, tr("Select AVI Movie for Debug") );
QList<QUrl> urls;
QDir d;
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setNameFilter(tr("AVI Movies (*.avi) ;; All files (*)"));
dialog.setViewMode(QFileDialog::List);
dialog.setFilter( QDir::AllEntries | QDir::AllDirs | QDir::Hidden );
dialog.setLabelText( QFileDialog::Accept, tr("Select") );
base = FCEUI_GetBaseDirectory();
urls << QUrl::fromLocalFile( QDir::rootPath() );
urls << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::HomeLocation).first());
urls << QUrl::fromLocalFile(QStandardPaths::standardLocations(QStandardPaths::DownloadLocation).first());
if ( base )
{
urls << QUrl::fromLocalFile( QDir( base ).absolutePath() );
d.setPath( QString(base) + "/avi");
if ( d.exists() )
{
urls << QUrl::fromLocalFile( d.absolutePath() );
}
dialog.setDirectory( d.absolutePath() );
}
dialog.setDefaultSuffix( tr(".avi") );
// Check config option to use native file dialog or not
g_config->getOption ("SDL.UseNativeFileDialog", &useNativeFileDialogVal);
dialog.setOption(QFileDialog::DontUseNativeDialog, !useNativeFileDialogVal);
dialog.setSidebarUrls(urls);
ret = dialog.exec();
if ( ret )
{
QStringList fileList;
fileList = dialog.selectedFiles();
if ( fileList.size() > 0 )
{
filename = fileList[0];
}
}
if ( filename.isNull() )
{
return;
}
qDebug() << "selected file path : " << filename.toUtf8();
FCEUI_printf ("AVI Debug movie to %s\n", filename.toStdString().c_str() );
aviDebugOpenFile( filename.toStdString().c_str() );
}
void consoleWin_t::aviAudioEnableChange(bool checked)
{
aviSetAudioEnable( checked );

View File

@ -428,6 +428,7 @@ class consoleWin_t : public QMainWindow
void aviRecordStart(void);
void aviRecordAsStart(void);
void aviRecordStop(void);
void aviDebugFile(void);
void aviAudioEnableChange(bool);
void aviVideoFormatChanged(int idx);
void setAviHudEnable(bool);

View File

@ -519,7 +519,7 @@ gwavi_t::check_fourcc(const char *fourcc)
"JBYR JPEG JPGL"
"KMVC"
"L261 L263 LBYR LCMW LCW2 LEAD LGRY LJ11 LJ22 LJ2K LJ44 LJPG"
"LMP2 LMP4 LSVC LSVM LSVX LZO1"
"LMP2 LMP4 LSVC LSVM LSVX LZO1 LAGS"
"M261 M263 M4CC M4S2 MC12 MCAM MJ2C MJPG MMES MP2A MP2T MP2V"
"MP42 MP43 MP4A MP4S MP4T MP4V MPEG MPG4 MPGI MR16 MRCA MRLE"
"MSVC MSZH"

View File

@ -89,3 +89,78 @@ gwavi_t::write_chars_bin(FILE *out, const char *s, int count)
return 0;
}
int
gwavi_t::read_int(FILE *in, int &n)
{
unsigned char buffer[4];
if (fread(buffer, 1, 4, in) != 4)
return -1;
n = (buffer[3] << 24) | (buffer[2] << 16) |
(buffer[1] << 8) | (buffer[0]);
return 0;
}
int
gwavi_t::read_uint(FILE *in, unsigned int &n)
{
unsigned char buffer[4];
if (fread(buffer, 1, 4, in) != 4)
return -1;
n = (buffer[3] << 24) | (buffer[2] << 16) |
(buffer[1] << 8) | (buffer[0]);
return 0;
}
int
gwavi_t::read_short(FILE *in, int16_t &n)
{
unsigned char buffer[2];
if (fread(buffer, 1, 2, in) != 2)
return -1;
n = (buffer[1] << 8) | (buffer[0]);
return 0;
}
int
gwavi_t::read_ushort(FILE *in, uint16_t &n)
{
unsigned char buffer[2];
if (fread(buffer, 1, 2, in) != 2)
return -1;
n = (buffer[1] << 8) | (buffer[0]);
return 0;
}
int
gwavi_t::read_short(FILE *in, int &n)
{
unsigned char buffer[2];
if (fread(buffer, 1, 2, in) != 2)
return -1;
n = (buffer[1] << 8) | (buffer[0]);
return 0;
}
int
gwavi_t::read_chars_bin(FILE *in, char *s, int count)
{
if (fread(s, 1, count, in) != count)
return -1;
return 0;
}

View File

@ -67,7 +67,7 @@
gwavi_t::gwavi_t(void)
{
out = NULL;
in = out = NULL;
memset( &avi_header , 0, sizeof(struct gwavi_header_t) );
memset( &stream_header_v, 0, sizeof(struct gwavi_stream_header_t) );
memset( &stream_format_v, 0, sizeof(struct gwavi_stream_format_v_t) );
@ -85,9 +85,28 @@ gwavi_t::gwavi_t(void)
gwavi_t::~gwavi_t(void)
{
if ( in != NULL )
{
fclose(in); in = NULL;
}
if ( out != NULL )
{
fclose(out); out = NULL;
}
}
int
gwavi_t::openIn(const char *filename)
{
if ((in = fopen(filename, "rb")) == NULL)
{
perror("gwavi_open: failed to open file for reading");
return -1;
}
return 0;
}
int
gwavi_t::open(const char *filename, unsigned int width, unsigned int height,
@ -478,6 +497,7 @@ gwavi_t::close(void)
perror("gwavi_close (fclose)");
return -1;
}
out = NULL;
return 0;
@ -576,3 +596,339 @@ gwavi_t::set_size( unsigned int width, unsigned int height)
return 0;
}
int gwavi_t::printHeaders(void)
{
char fourcc[8];
int ret, fileSize, size;
if ( in == NULL )
{
return -1;
}
if (read_chars_bin(in, fourcc, 4) == -1)
return -1;
fourcc[4] = 0;
printf("RIFF Begin: '%s'\n", fourcc );
if (read_int(in, fileSize) == -1)
{
(void)fprintf(stderr, "gwavi_info: read_int() failed\n");
return -1;
}
size = fileSize;
printf("FileSize: %i\n", fileSize );
if (read_chars_bin(in, fourcc, 4) == -1)
return -1;
size -= 4;
fourcc[4] = 0;
printf("FileType: '%s'\n", fourcc );
while ( size > 0 )
{
if (read_chars_bin(in, fourcc, 4) == -1)
return -1;
fourcc[4] = 0;
printf("Block: '%s' %i\n", fourcc, size );
size -= 4;
if ( strcmp( fourcc, "LIST") == 0 )
{
ret = readList(0);
if ( ret < 0 )
{
return -1;
}
size -= ret;
}
else
{
ret = readChunk( fourcc, 0 );
if ( ret < 0 )
{
return -1;
}
size -= ret;
}
}
return 0;
}
int gwavi_t::readList(int lvl)
{
char fourcc[8], listType[8], pad[4];
int size, ret, listSize=0;
int bytesRead=0;
char indent[256];
memset( indent, ' ', lvl*3);
indent[lvl*3] = 0;
if (read_int(in, listSize) == -1)
{
(void)fprintf(stderr, "readList: read_int() failed\n");
return -1;
}
size = listSize;
if (read_chars_bin(in, listType, 4) == -1)
return -1;
listType[4] = 0;
size -= 4;
bytesRead += 4;
printf("%sList Start: '%s' %i\n", indent, listType, listSize );
while ( size >= 4 )
{
if (read_chars_bin(in, fourcc, 4) == -1)
return -1;
size -= 4;
bytesRead += 4;
fourcc[4] = 0;
//printf("Block: '%s'\n", fourcc );
if ( strcmp( fourcc, "LIST") == 0 )
{
ret = readList(lvl+1);
if ( ret < 0 )
{
return -1;
}
size -= ret;
bytesRead += ret;
}
else
{
ret = readChunk( fourcc, lvl+1 );
if ( ret < 0 )
{
return -1;
}
size -= ret;
bytesRead += ret;
}
}
if ( size > 0 )
{
int r = size % 4;
if (read_chars_bin(in, pad, r) == -1)
{
(void)fprintf(stderr, "readChunk: read_int() failed\n");
return -1;
}
size -= r;
bytesRead += r;
}
printf("%sList End: %s %i\n", indent, listType, bytesRead);
return bytesRead;
}
int gwavi_t::readChunk(const char *id, int lvl)
{
int ret, size, chunkSize, dataWord, bytesRead=0;
char indent[256];
memset( indent, ' ', lvl*3);
indent[lvl*3] = 0;
if (read_int(in, chunkSize) == -1)
{
(void)fprintf(stderr, "readChunk: read_int() failed\n");
return -1;
}
printf("%sChunk Start: %s %i\n", indent, id, chunkSize);
size = chunkSize;
if ( strcmp( id, "strh") == 0 )
{
ret = readStreamHeader();
if ( ret < 0 )
{
return -1;
}
size -= ret;
bytesRead += ret;
}
while ( size >= 4 )
{
if (read_int(in, dataWord) == -1)
{
(void)fprintf(stderr, "readChunk: read_int() failed\n");
return -1;
}
size -= 4;
bytesRead += 4;
}
if ( size > 0 )
{
char pad[4];
int r = size % 4;
if (read_chars_bin(in, pad, r) == -1)
{
(void)fprintf(stderr, "readChunk: read_int() failed\n");
return -1;
}
size -= r;
bytesRead += r;
}
printf("%sChunk End: %s %i\n", indent, id, bytesRead);
return bytesRead+4;
}
int gwavi_t::readStreamHeader(void)
{
gwavi_AVIStreamHeader hdr;
printf("HDR Size: '%zi'\n", sizeof(hdr) );
if (read_chars_bin(in, hdr.fccType, 4) == -1)
{
(void)fprintf(stderr, "readChunk: read_chars_bin() failed\n");
return -1;
}
if (read_chars_bin(in, hdr.fccHandler, 4) == -1)
{
(void)fprintf(stderr, "readChunk: read_chars_bin() failed\n");
return -1;
}
if (read_uint(in, hdr.dwFlags) == -1)
{
(void)fprintf(stderr, "readChunk: read_uint() failed\n");
return -1;
}
if (read_ushort(in, hdr.wPriority) == -1)
{
(void)fprintf(stderr, "readChunk: read_ushort() failed\n");
return -1;
}
if (read_ushort(in, hdr.wLanguage) == -1)
{
(void)fprintf(stderr, "readChunk: read_ushort() failed\n");
return -1;
}
if (read_uint(in, hdr.dwInitialFrames) == -1)
{
(void)fprintf(stderr, "readChunk: read_uint() failed\n");
return -1;
}
if (read_uint(in, hdr.dwScale) == -1)
{
(void)fprintf(stderr, "readChunk: read_uint() failed\n");
return -1;
}
if (read_uint(in, hdr.dwRate) == -1)
{
(void)fprintf(stderr, "readChunk: read_uint() failed\n");
return -1;
}
if (read_uint(in, hdr.dwStart) == -1)
{
(void)fprintf(stderr, "readChunk: read_uint() failed\n");
return -1;
}
if (read_uint(in, hdr.dwLength) == -1)
{
(void)fprintf(stderr, "readChunk: read_uint() failed\n");
return -1;
}
if (read_uint(in, hdr.dwSuggestedBufferSize) == -1)
{
(void)fprintf(stderr, "readChunk: read_uint() failed\n");
return -1;
}
if (read_uint(in, hdr.dwQuality) == -1)
{
(void)fprintf(stderr, "readChunk: read_uint() failed\n");
return -1;
}
if (read_uint(in, hdr.dwSampleSize) == -1)
{
(void)fprintf(stderr, "readChunk: read_uint() failed\n");
return -1;
}
if (read_short(in, hdr.rcFrame.left) == -1)
{
(void)fprintf(stderr, "readChunk: read_ushort() failed\n");
return -1;
}
if (read_short(in, hdr.rcFrame.top) == -1)
{
(void)fprintf(stderr, "readChunk: read_ushort() failed\n");
return -1;
}
if (read_short(in, hdr.rcFrame.right) == -1)
{
(void)fprintf(stderr, "readChunk: read_ushort() failed\n");
return -1;
}
if (read_short(in, hdr.rcFrame.bottom) == -1)
{
(void)fprintf(stderr, "readChunk: read_ushort() failed\n");
return -1;
}
printf("fccType : '%c%c%c%c'\n",
hdr.fccType[0], hdr.fccType[1],
hdr.fccType[2], hdr.fccType[3] );
printf("fccHandler: '%c%c%c%c'\n",
hdr.fccHandler[0], hdr.fccHandler[1],
hdr.fccHandler[2], hdr.fccHandler[3] );
printf("dwFlags : '%u'\n", hdr.dwFlags );
printf("wPriority : '%u'\n", hdr.wPriority );
printf("wLanguage : '%u'\n", hdr.wLanguage );
printf("dwInitialFrames : '%u'\n", hdr.dwInitialFrames );
printf("dwScale : '%u'\n", hdr.dwScale );
printf("dwRate : '%u'\n", hdr.dwRate );
printf("dwStart : '%u'\n", hdr.dwStart );
printf("dwLength : '%u'\n", hdr.dwLength );
printf("dwSuggestedBufferSize: '%u'\n", hdr.dwSuggestedBufferSize );
printf("dwQuality : '%u'\n", hdr.dwQuality );
printf("dwSampleSize : '%u'\n", hdr.dwSampleSize );
printf("rcFrame.left : '%i'\n", hdr.rcFrame.left );
printf("rcFrame.top : '%i'\n", hdr.rcFrame.top );
printf("rcFrame.right : '%i'\n", hdr.rcFrame.right );
printf("rcFrame.bottom : '%i'\n", hdr.rcFrame.bottom );
return sizeof(gwavi_AVIStreamHeader);
}

View File

@ -36,23 +36,53 @@
#include <stdint.h> /* for size_t */
#include <stddef.h> /* for size_t */
#pragma pack( push, 4 )
/* structures */
struct gwavi_header_t
{
unsigned int time_delay; /* dwMicroSecPerFrame */
unsigned int data_rate; /* dwMaxBytesPerSec */
unsigned int reserved;
unsigned int flags; /* dwFlags */
unsigned int number_of_frames; /* dwTotalFrames */
unsigned int initial_frames; /* dwInitialFrames */
unsigned int data_streams; /* dwStreams */
unsigned int buffer_size; /* dwSuggestedBufferSize */
unsigned int width; /* dwWidth */
unsigned int height; /* dwHeight */
unsigned int time_scale;
unsigned int playback_data_rate;
unsigned int starting_time;
unsigned int data_length;
char fcc[4];
uint32_t cb;
uint32_t time_delay; /* dwMicroSecPerFrame */
uint32_t data_rate; /* dwMaxBytesPerSec */
uint32_t reserved;
uint32_t flags; /* dwFlags */
uint32_t number_of_frames; /* dwTotalFrames */
uint32_t initial_frames; /* dwInitialFrames */
uint32_t data_streams; /* dwStreams */
uint32_t buffer_size; /* dwSuggestedBufferSize */
uint32_t width; /* dwWidth */
uint32_t height; /* dwHeight */
uint32_t time_scale;
uint32_t playback_data_rate;
uint32_t starting_time;
uint32_t data_length;
};
struct gwavi_AVIStreamHeader
{
char fccType[4];
char fccHandler[4];
uint32_t dwFlags;
uint16_t wPriority;
uint16_t wLanguage;
uint32_t dwInitialFrames;
uint32_t dwScale;
uint32_t dwRate;
uint32_t dwStart;
uint32_t dwLength;
uint32_t dwSuggestedBufferSize;
uint32_t dwQuality;
uint32_t dwSampleSize;
struct
{
int16_t left;
int16_t top;
int16_t right;
int16_t bottom;
} rcFrame;
};
struct gwavi_stream_header_t
@ -111,6 +141,8 @@ struct gwavi_audio_t
unsigned int samples_per_second;
};
#pragma pack( pop )
class gwavi_t
{
public:
@ -133,7 +165,12 @@ class gwavi_t
int set_framerate(double fps);
int openIn(const char *filename);
int printHeaders(void);
private:
FILE *in;
FILE *out;
struct gwavi_header_t avi_header;
struct gwavi_stream_header_t stream_header_v;
@ -165,6 +202,15 @@ class gwavi_t
int write_chars(FILE *out, const char *s);
int write_chars_bin(FILE *out, const char *s, int count);
int read_int(FILE *out, int &n);
int read_uint(FILE *out, unsigned int &n);
int read_short(FILE *in, int16_t &n);
int read_short(FILE *out, int &n);
int read_ushort(FILE *in, uint16_t &n);
int read_chars_bin(FILE *in, char *s, int count);
int readList(int lvl);
int readChunk(const char *id, int lvl);
int readStreamHeader(void);
};
#endif /* ndef H_GWAVI */