AVI RIFF viewer tool in work.

This commit is contained in:
mjbudd77 2021-10-03 04:58:15 -04:00
parent 41e04ece0b
commit 6856921c38
8 changed files with 284 additions and 142 deletions

View File

@ -2290,21 +2290,6 @@ int aviRecordClose(void)
return 0; 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) bool aviGetAudioEnable(void)
{ {
return recordAudio; return recordAudio;

View File

@ -79,7 +79,7 @@ int FCEUD_AviGetDriverList( std::vector <std::string> &formatList );
int FCEUD_AviGetFormatOpts( std::vector <std::string> &formatList ); int FCEUD_AviGetFormatOpts( std::vector <std::string> &formatList );
int aviDebugOpenFile( const char *filepath ); //int aviDebugOpenFile( const char *filepath );
class AviRecordDiskThread_t : public QThread class AviRecordDiskThread_t : public QThread
{ {

View File

@ -36,6 +36,7 @@
#include "Qt/AviRiffViewer.h" #include "Qt/AviRiffViewer.h"
#include "Qt/ConsoleUtilities.h" #include "Qt/ConsoleUtilities.h"
static bool showSizeHex = true;
static AviRiffViewerDialog *win = NULL; static AviRiffViewerDialog *win = NULL;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static int riffWalkCallback( int type, long long int fpos, const char *fourcc, size_t size, void *userData ) static int riffWalkCallback( int type, long long int fpos, const char *fourcc, size_t size, void *userData )
@ -62,6 +63,7 @@ AviRiffViewerDialog::AviRiffViewerDialog(QWidget *parent)
win = this; win = this;
avi = NULL; avi = NULL;
lastChunk = NULL;
setWindowTitle("AVI RIFF Viewer"); setWindowTitle("AVI RIFF Viewer");
@ -284,9 +286,10 @@ int AviRiffViewerDialog::openFile( const char *filepath )
} }
itemStack.clear(); itemStack.clear();
lastChunk = NULL;
avi->setRiffWalkCallback( ::riffWalkCallback, this ); avi->setRiffWalkCallback( ::riffWalkCallback, this );
avi->printHeaders(); avi->riffwalk();
return 0; return 0;
} }
@ -320,6 +323,8 @@ int AviRiffViewerDialog::riffWalkCallback( int type, long long int fpos, const c
break; break;
case gwavi_t::RIFF_END: case gwavi_t::RIFF_END:
{ {
groupItem = itemStack.back();
groupItem->setExpanded(true);
itemStack.pop_back(); itemStack.pop_back();
} }
break; break;
@ -346,6 +351,10 @@ int AviRiffViewerDialog::riffWalkCallback( int type, long long int fpos, const c
groupItem = itemStack.back(); groupItem = itemStack.back();
groupItem->addChild(item); groupItem->addChild(item);
lastChunk = item;
processChunk(lastChunk);
} }
break; break;
default: default:
@ -356,6 +365,134 @@ int AviRiffViewerDialog::riffWalkCallback( int type, long long int fpos, const c
return 0; return 0;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
int AviRiffViewerDialog::processChunk( AviRiffTreeItem *item )
{
QTreeWidgetItem *twi;
char stmp[256];
gwavi_dataBuffer data;
if ( strcmp( item->getFourcc(), "avih" ) == 0 )
{
data.malloc( item->getSize()+8 );
avi->getChunkData( item->filePos(), data.buf, item->getSize()+8 );
sprintf( stmp, "%c%c%c%c", data.buf[0], data.buf[1], data.buf[2], data.buf[3] );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("fcc") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(4) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("cb") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(8) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwMicroSecPerFrame") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(12) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwMaxBytesPerSec") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(16) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwPaddingGranularity") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "0x%X", data.readU32(20) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwFlags") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(24) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwTotalFrames") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(28) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwInitialFrames") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(32) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwStreams") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(36) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwSuggestedBufferSize") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(40) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwWidth") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(44) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwHeight") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(48) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwScale") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(52) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwRate") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(56) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwStart") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
sprintf( stmp, "%u", data.readU32(60) );
twi = new QTreeWidgetItem();
twi->setText( 0, tr("dwLength") );
twi->setText( 2, tr(stmp) );
item->addChild(twi);
}
return 0;
}
//----------------------------------------------------------------------------
//--- AVI RIFF Tree View //--- AVI RIFF Tree View
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
AviRiffTree::AviRiffTree(QWidget *parent) AviRiffTree::AviRiffTree(QWidget *parent)
@ -373,7 +510,7 @@ AviRiffTree::~AviRiffTree(void)
//--- AVI RIFF Viewer Dialog //--- AVI RIFF Viewer Dialog
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
AviRiffTreeItem::AviRiffTreeItem(int typeIn, long long int fposIn, const char *fourccIn, size_t sizeIn, QTreeWidgetItem *parent) AviRiffTreeItem::AviRiffTreeItem(int typeIn, long long int fposIn, const char *fourccIn, size_t sizeIn, QTreeWidgetItem *parent)
: QTreeWidgetItem(parent) : QTreeWidgetItem(parent,1)
{ {
char stmp[64]; char stmp[64];
@ -403,7 +540,14 @@ AviRiffTreeItem::AviRiffTreeItem(int typeIn, long long int fposIn, const char *f
setText( 1, QString(fourcc) ); setText( 1, QString(fourcc) );
if ( showSizeHex )
{
sprintf( stmp, "0x%08lX", (unsigned long)size );
}
else
{
sprintf( stmp, "%zu", size ); sprintf( stmp, "%zu", size );
}
setText( 2, QString(stmp) ); setText( 2, QString(stmp) );

View File

@ -34,6 +34,10 @@ class AviRiffTreeItem : public QTreeWidgetItem
AviRiffTreeItem(int type, long long int fpos, const char *fourcc, size_t size, QTreeWidgetItem *parent = nullptr); AviRiffTreeItem(int type, long long int fpos, const char *fourcc, size_t size, QTreeWidgetItem *parent = nullptr);
~AviRiffTreeItem(void); ~AviRiffTreeItem(void);
size_t filePos(void){ return fpos; }
size_t getSize(void){ return size; }
const char *getFourcc(void){ return fourcc; }
private: private:
int type; int type;
char fourcc[8]; char fourcc[8];
@ -69,9 +73,11 @@ protected:
int openFile( const char *filepath ); int openFile( const char *filepath );
int closeFile(void); int closeFile(void);
int processChunk( AviRiffTreeItem *item );
gwavi_t *avi; gwavi_t *avi;
AviRiffTree *riffTree; AviRiffTree *riffTree;
AviRiffTreeItem *lastChunk;
std::list <AviRiffTreeItem*> itemStack; std::list <AviRiffTreeItem*> itemStack;
private: private:

View File

@ -1780,17 +1780,6 @@ void consoleWin_t::createMainMenu(void)
movieMenu->addAction(stopAviAct); movieMenu->addAction(stopAviAct);
//#define AVI_DEBUG
#ifdef AVI_DEBUG
// 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)) );
movieMenu->addAction(act);
#endif
movieMenu->addSeparator(); movieMenu->addSeparator();
// Movie -> WAV Recording // Movie -> WAV Recording
@ -3761,76 +3750,6 @@ 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) void consoleWin_t::aviAudioEnableChange(bool checked)
{ {
aviSetAudioEnable( checked ); aviSetAudioEnable( checked );

View File

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

View File

@ -657,7 +657,7 @@ gwavi_t::set_size( unsigned int width, unsigned int height)
return 0; return 0;
} }
int gwavi_t::printHeaders(void) int gwavi_t::riffwalk(void)
{ {
char fourcc[8]; char fourcc[8];
unsigned int ret, fileSize, size; unsigned int ret, fileSize, size;
@ -673,7 +673,7 @@ int gwavi_t::printHeaders(void)
return -1; return -1;
fourcc[4] = 0; fourcc[4] = 0;
printf("RIFF Begin: '%s'\n", fourcc ); //printf("RIFF Begin: '%s'\n", fourcc );
if (read_uint(in, fileSize) == -1) if (read_uint(in, fileSize) == -1)
{ {
@ -681,14 +681,14 @@ int gwavi_t::printHeaders(void)
return -1; return -1;
} }
size = fileSize; size = fileSize;
printf("FileSize: %u\n", fileSize ); //printf("FileSize: %u\n", fileSize );
if (read_chars_bin(in, fourcc, 4) == -1) if (read_chars_bin(in, fourcc, 4) == -1)
return -1; return -1;
size -= 4; size -= 4;
fourcc[4] = 0; fourcc[4] = 0;
printf("FileType: '%s'\n", fourcc ); //printf("FileType: '%s'\n", fourcc );
if ( riffWalkCallback ) if ( riffWalkCallback )
{ {
@ -701,7 +701,7 @@ int gwavi_t::printHeaders(void)
return -1; return -1;
fourcc[4] = 0; fourcc[4] = 0;
printf("Block: '%s' %u 0x%X\n", fourcc, size, size ); //printf("Block: '%s' %u 0x%X\n", fourcc, size, size );
size -= 4; size -= 4;
@ -727,6 +727,12 @@ int gwavi_t::printHeaders(void)
} }
} }
fpos = ftell(in);
if ( riffWalkCallback )
{
riffWalkCallback( RIFF_END, fpos, fourcc, fileSize, riffWalkUserData );
}
return 0; return 0;
} }
@ -769,7 +775,7 @@ unsigned int gwavi_t::readList(int lvl)
{ {
riffWalkCallback( LIST_START, fpos-4, listType, listSize, riffWalkUserData ); riffWalkCallback( LIST_START, fpos-4, listType, listSize, riffWalkUserData );
} }
printf("%sList Start: '%s' %u\n", indent, listType, listSize ); //printf("%sList Start: '%s' %u\n", indent, listType, listSize );
while ( size >= 4 ) while ( size >= 4 )
{ {
@ -780,7 +786,7 @@ unsigned int gwavi_t::readList(int lvl)
bytesRead += 4; bytesRead += 4;
fourcc[4] = 0; fourcc[4] = 0;
printf("%sBlock: '%s %u' 0x%X\n", indent, fourcc, size, size ); //printf("%sBlock: '%s %u' 0x%X\n", indent, fourcc, size, size );
if ( strcmp( fourcc, "LIST") == 0 ) if ( strcmp( fourcc, "LIST") == 0 )
{ {
@ -818,7 +824,7 @@ unsigned int gwavi_t::readList(int lvl)
size -= r; size -= r;
bytesRead += r; bytesRead += r;
} }
printf("%sList End: %s %u\n", indent, listType, bytesRead); //printf("%sList End: %s %u\n", indent, listType, bytesRead);
if ( riffWalkCallback ) if ( riffWalkCallback )
{ {
@ -846,7 +852,7 @@ unsigned int gwavi_t::readChunk(const char *id, int lvl)
(void)fprintf(stderr, "readChunk: read_uint() failed\n"); (void)fprintf(stderr, "readChunk: read_uint() failed\n");
return 0; return 0;
} }
printf("%sChunk Start: %s %u\n", indent, id, chunkSize); //printf("%sChunk Start: %s %u\n", indent, id, chunkSize);
if ( riffWalkCallback ) if ( riffWalkCallback )
{ {
@ -866,39 +872,39 @@ unsigned int gwavi_t::readChunk(const char *id, int lvl)
size += r; size += r;
} }
if ( strcmp( id, "avih") == 0 ) //if ( strcmp( id, "avih") == 0 )
{ //{
ret = readAviHeader(); // ret = readAviHeader();
if ( ret == 0 ) // if ( ret == 0 )
{ // {
return 0; // return 0;
} // }
size -= ret; // size -= ret;
bytesRead += ret; // bytesRead += ret;
} //}
else if ( strcmp( id, "strh") == 0 ) //else if ( strcmp( id, "strh") == 0 )
{ //{
ret = readStreamHeader(); // ret = readStreamHeader();
if ( ret == 0 ) // if ( ret == 0 )
{ // {
return 0; // return 0;
} // }
size -= ret; // size -= ret;
bytesRead += ret; // bytesRead += ret;
} //}
else if ( strcmp( id, "idx1") == 0 ) //else if ( strcmp( id, "idx1") == 0 )
{ //{
ret = readIndexBlock( chunkSize ); // ret = readIndexBlock( chunkSize );
if ( ret == 0 ) // if ( ret == 0 )
{ // {
return 0; // return 0;
} // }
size -= ret; // size -= ret;
bytesRead += ret; // bytesRead += ret;
} //}
while ( size >= WORD_SIZE ) while ( size >= WORD_SIZE )
{ {
@ -925,11 +931,26 @@ unsigned int gwavi_t::readChunk(const char *id, int lvl)
bytesRead += r; bytesRead += r;
} }
printf("%sChunk End: %s %u\n", indent, id, bytesRead); //printf("%sChunk End: %s %u\n", indent, id, bytesRead);
return bytesRead+4; return bytesRead+4;
} }
int gwavi_t::getChunkData( long long int fpos, unsigned char *buf, size_t size )
{
long long int prev_fpos;
prev_fpos = ftell(in);
fseek( in, fpos, SEEK_SET );
fread( buf, 1, size, in );
fseek( in, prev_fpos, SEEK_SET );
return 0;
}
unsigned int gwavi_t::readAviHeader(void) unsigned int gwavi_t::readAviHeader(void)
{ {
gwavi_header_t hdr; gwavi_header_t hdr;
@ -1212,3 +1233,52 @@ unsigned int gwavi_t::readIndexBlock( unsigned int chunkSize )
} }
return bytesRead; return bytesRead;
} }
gwavi_dataBuffer::gwavi_dataBuffer(void)
{
buf = NULL; size = 0;
}
gwavi_dataBuffer::~gwavi_dataBuffer(void)
{
if ( buf )
{
free(buf); buf = NULL;
}
}
int gwavi_dataBuffer::malloc( size_t s )
{
buf = (unsigned char*)::malloc(s); size = s;
return 0;
}
int16_t gwavi_dataBuffer::readI16( int ofs )
{
int16_t out = 0;
out = (buf[ofs+1] << 8) | (buf[ofs]);
return out;
}
uint16_t gwavi_dataBuffer::readU16( int ofs )
{
uint16_t out = 0;
out = (buf[ofs+1] << 8) | (buf[ofs]);
return out;
}
uint32_t gwavi_dataBuffer::readU32( int ofs )
{
uint32_t out = 0;
out = (buf[3+ofs] << 24) | (buf[2+ofs] << 16) |
(buf[1+ofs] << 8) | (buf[0+ofs]);
return out;
}

View File

@ -167,6 +167,23 @@ struct gwavi_index_rec_t
#pragma pack( pop ) #pragma pack( pop )
class gwavi_dataBuffer
{
public:
gwavi_dataBuffer(void);
~gwavi_dataBuffer(void);
int malloc( size_t s );
int16_t readI16( int ofs );
uint16_t readU16( int ofs );
uint32_t readU32( int ofs );
unsigned char *buf;
size_t size;
};
class gwavi_t class gwavi_t
{ {
public: public:
@ -205,7 +222,7 @@ class gwavi_t
int openIn(const char *filename); int openIn(const char *filename);
int printHeaders(void); int riffwalk(void);
void setRiffWalkCallback( int (*cb)( int type, long long int fpos, const char *fourcc, size_t size, void *userData ), void *userData ) void setRiffWalkCallback( int (*cb)( int type, long long int fpos, const char *fourcc, size_t size, void *userData ), void *userData )
{ {
@ -213,6 +230,8 @@ class gwavi_t
riffWalkUserData = userData; riffWalkUserData = userData;
}; };
int getChunkData( long long int fpos, unsigned char *buf, size_t size );
private: private:
FILE *in; FILE *in;
FILE *out; FILE *out;