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;
}
//**************************************************************************************
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

@ -79,7 +79,7 @@ int FCEUD_AviGetDriverList( 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
{

View File

@ -36,6 +36,7 @@
#include "Qt/AviRiffViewer.h"
#include "Qt/ConsoleUtilities.h"
static bool showSizeHex = true;
static AviRiffViewerDialog *win = NULL;
//----------------------------------------------------------------------------
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;
avi = NULL;
lastChunk = NULL;
setWindowTitle("AVI RIFF Viewer");
@ -284,9 +286,10 @@ int AviRiffViewerDialog::openFile( const char *filepath )
}
itemStack.clear();
lastChunk = NULL;
avi->setRiffWalkCallback( ::riffWalkCallback, this );
avi->printHeaders();
avi->riffwalk();
return 0;
}
@ -320,6 +323,8 @@ int AviRiffViewerDialog::riffWalkCallback( int type, long long int fpos, const c
break;
case gwavi_t::RIFF_END:
{
groupItem = itemStack.back();
groupItem->setExpanded(true);
itemStack.pop_back();
}
break;
@ -346,6 +351,10 @@ int AviRiffViewerDialog::riffWalkCallback( int type, long long int fpos, const c
groupItem = itemStack.back();
groupItem->addChild(item);
lastChunk = item;
processChunk(lastChunk);
}
break;
default:
@ -356,6 +365,134 @@ int AviRiffViewerDialog::riffWalkCallback( int type, long long int fpos, const c
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
//----------------------------------------------------------------------------
AviRiffTree::AviRiffTree(QWidget *parent)
@ -373,7 +510,7 @@ AviRiffTree::~AviRiffTree(void)
//--- AVI RIFF Viewer Dialog
//----------------------------------------------------------------------------
AviRiffTreeItem::AviRiffTreeItem(int typeIn, long long int fposIn, const char *fourccIn, size_t sizeIn, QTreeWidgetItem *parent)
: QTreeWidgetItem(parent)
: QTreeWidgetItem(parent,1)
{
char stmp[64];
@ -403,7 +540,14 @@ AviRiffTreeItem::AviRiffTreeItem(int typeIn, long long int fposIn, const char *f
setText( 1, QString(fourcc) );
sprintf( stmp, "%zu", size );
if ( showSizeHex )
{
sprintf( stmp, "0x%08lX", (unsigned long)size );
}
else
{
sprintf( stmp, "%zu", size );
}
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(void);
size_t filePos(void){ return fpos; }
size_t getSize(void){ return size; }
const char *getFourcc(void){ return fourcc; }
private:
int type;
char fourcc[8];
@ -69,9 +73,11 @@ protected:
int openFile( const char *filepath );
int closeFile(void);
int processChunk( AviRiffTreeItem *item );
gwavi_t *avi;
AviRiffTree *riffTree;
AviRiffTreeItem *lastChunk;
std::list <AviRiffTreeItem*> itemStack;
private:

View File

@ -1780,17 +1780,6 @@ void consoleWin_t::createMainMenu(void)
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();
// 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)
{
aviSetAudioEnable( checked );

View File

@ -431,7 +431,6 @@ 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

@ -657,7 +657,7 @@ gwavi_t::set_size( unsigned int width, unsigned int height)
return 0;
}
int gwavi_t::printHeaders(void)
int gwavi_t::riffwalk(void)
{
char fourcc[8];
unsigned int ret, fileSize, size;
@ -673,7 +673,7 @@ int gwavi_t::printHeaders(void)
return -1;
fourcc[4] = 0;
printf("RIFF Begin: '%s'\n", fourcc );
//printf("RIFF Begin: '%s'\n", fourcc );
if (read_uint(in, fileSize) == -1)
{
@ -681,14 +681,14 @@ int gwavi_t::printHeaders(void)
return -1;
}
size = fileSize;
printf("FileSize: %u\n", fileSize );
//printf("FileSize: %u\n", fileSize );
if (read_chars_bin(in, fourcc, 4) == -1)
return -1;
size -= 4;
fourcc[4] = 0;
printf("FileType: '%s'\n", fourcc );
//printf("FileType: '%s'\n", fourcc );
if ( riffWalkCallback )
{
@ -701,7 +701,7 @@ int gwavi_t::printHeaders(void)
return -1;
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;
@ -727,6 +727,12 @@ int gwavi_t::printHeaders(void)
}
}
fpos = ftell(in);
if ( riffWalkCallback )
{
riffWalkCallback( RIFF_END, fpos, fourcc, fileSize, riffWalkUserData );
}
return 0;
}
@ -769,7 +775,7 @@ unsigned int gwavi_t::readList(int lvl)
{
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 )
{
@ -780,7 +786,7 @@ unsigned int gwavi_t::readList(int lvl)
bytesRead += 4;
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 )
{
@ -818,7 +824,7 @@ unsigned int gwavi_t::readList(int lvl)
size -= r;
bytesRead += r;
}
printf("%sList End: %s %u\n", indent, listType, bytesRead);
//printf("%sList End: %s %u\n", indent, listType, bytesRead);
if ( riffWalkCallback )
{
@ -846,7 +852,7 @@ unsigned int gwavi_t::readChunk(const char *id, int lvl)
(void)fprintf(stderr, "readChunk: read_uint() failed\n");
return 0;
}
printf("%sChunk Start: %s %u\n", indent, id, chunkSize);
//printf("%sChunk Start: %s %u\n", indent, id, chunkSize);
if ( riffWalkCallback )
{
@ -866,39 +872,39 @@ unsigned int gwavi_t::readChunk(const char *id, int lvl)
size += r;
}
if ( strcmp( id, "avih") == 0 )
{
ret = readAviHeader();
//if ( strcmp( id, "avih") == 0 )
//{
// ret = readAviHeader();
if ( ret == 0 )
{
return 0;
}
size -= ret;
bytesRead += ret;
}
else if ( strcmp( id, "strh") == 0 )
{
ret = readStreamHeader();
// if ( ret == 0 )
// {
// return 0;
// }
// size -= ret;
// bytesRead += ret;
//}
//else if ( strcmp( id, "strh") == 0 )
//{
// ret = readStreamHeader();
if ( ret == 0 )
{
return 0;
}
size -= ret;
bytesRead += ret;
}
else if ( strcmp( id, "idx1") == 0 )
{
ret = readIndexBlock( chunkSize );
// if ( ret == 0 )
// {
// return 0;
// }
// size -= ret;
// bytesRead += ret;
//}
//else if ( strcmp( id, "idx1") == 0 )
//{
// ret = readIndexBlock( chunkSize );
if ( ret == 0 )
{
return 0;
}
size -= ret;
bytesRead += ret;
}
// if ( ret == 0 )
// {
// return 0;
// }
// size -= ret;
// bytesRead += ret;
//}
while ( size >= WORD_SIZE )
{
@ -925,11 +931,26 @@ unsigned int gwavi_t::readChunk(const char *id, int lvl)
bytesRead += r;
}
printf("%sChunk End: %s %u\n", indent, id, bytesRead);
//printf("%sChunk End: %s %u\n", indent, id, bytesRead);
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)
{
gwavi_header_t hdr;
@ -1212,3 +1233,52 @@ unsigned int gwavi_t::readIndexBlock( unsigned int chunkSize )
}
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 )
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
{
public:
@ -205,7 +222,7 @@ class gwavi_t
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 )
{
@ -213,6 +230,8 @@ class gwavi_t
riffWalkUserData = userData;
};
int getChunkData( long long int fpos, unsigned char *buf, size_t size );
private:
FILE *in;
FILE *out;