mupen64plus-oldsvn/main/vcr_compress_old.cpp
2008-04-25 04:41:33 +00:00

564 lines
15 KiB
C++

#ifdef VCR_SUPPORT
#include "vcr_compress.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <avifile.h>
#include <aviplay.h>
#include <version.h>
#include <avm_creators.h>
#include <avm_except.h>
#include <iostream>
#define __MODULE__ "mupen64-vcr_compress"
#ifndef SAFE_DELETE
# define SAFE_DELETE(p) if (p) delete p;
#endif
using namespace std;
static BitmapInfo *m_videoFormat = 0;
static WAVEFORMATEX *m_audioFormat = 0;
static IAviWriteFile *m_file = 0;
static IAviVideoWriteStream *m_videoStream = 0;
static IAviAudioWriteStream *m_audioStream = 0;
static avm::vector<const CodecInfo*> m_videoCodecs;
static avm::vector<const CodecInfo*> m_audioCodecs;
static int m_selectedVideoCodec = 0;
static int m_selectedAudioCodec = 0;
extern "C" void
VCRComp_init()
{
CodecInfo::Get( m_videoCodecs, CodecInfo::Video, CodecInfo::Encode );
CodecInfo::Get( m_audioCodecs, CodecInfo::Audio, CodecInfo::Encode );
}
extern "C" void
VCRComp_startFile( const char *filename, long width, long height, int fps )
{
if (GetAvifileVersion() != AVIFILE_VERSION)
{
cout << "[VCR]: This binary was compiled for Avifile ver. " << AVIFILE_VERSION
<< ", but the library is ver. " << GetAvifileVersion() << ". Aborting." << endl;
return;
}
SAFE_DELETE(m_videoFormat);
SAFE_DELETE(m_audioFormat);
SAFE_DELETE(m_file);
m_videoFormat = 0;
m_audioFormat = 0;
m_file = 0;
m_videoStream = 0;
m_audioStream = 0;
try
{
m_videoFormat = new BitmapInfo( width, -height, 24 ); // RGB, flipped
m_audioFormat = new WAVEFORMATEX;
memset( m_audioFormat, 0, sizeof (WAVEFORMATEX) );
m_audioFormat->wFormatTag = WAVE_FORMAT_PCM;
m_audioFormat->nChannels = 2;
m_audioFormat->nSamplesPerSec = 44100;
m_audioFormat->nBlockAlign = 4;
m_audioFormat->nAvgBytesPerSec = m_audioFormat->nSamplesPerSec * m_audioFormat->nBlockAlign;
m_audioFormat->wBitsPerSample = 16;
m_file = CreateIAviWriteFile( filename );
m_videoStream = m_file->AddVideoStream( *m_videoCodecs[m_selectedVideoCodec], m_videoFormat, 1000000/fps );
m_videoStream->SetQuality( 8000 ); // 0...10000
m_videoStream->Start();
m_audioStream = m_file->AddAudioStream( *m_audioCodecs[m_selectedAudioCodec], m_audioFormat, 24000 ); // 192 kbit/s
m_audioStream->Start();
}
catch (FatalError &error)
{
error.Print();
SAFE_DELETE(m_videoFormat);
SAFE_DELETE(m_audioFormat);
SAFE_DELETE(m_file);
m_videoFormat = 0;
m_audioFormat = 0;
m_file = 0;
m_videoStream = 0;
m_audioStream = 0;
}
catch (...)
{
cout << "[VCR]: ERROR: Caught unknown exception!" << endl;
}
}
extern "C" void
VCRComp_finishFile()
{
if (m_file == 0)
{
cout << "VCRComp_finishFile: not recording" << endl;
return;
}
if (m_videoStream != 0)
m_videoStream->Stop();
if (m_audioStream != 0)
m_audioStream->Stop();
delete m_file;
m_file = 0;
SAFE_DELETE(m_videoFormat);
SAFE_DELETE(m_audioFormat);
m_videoFormat = 0;
m_audioFormat = 0;
m_videoStream = 0;
m_audioStream = 0;
cout << "[VCR]: Finished capturing to file." << endl;
}
extern "C" void VCRComp_addVideoFrame( const unsigned char *data )
{
static int count = 0;
if (m_videoFormat == 0 || m_file == 0 || m_videoStream == 0)
{
cout << "VCRComp_addVideoFrame: not recording" << endl;
SAFE_DELETE(m_videoFormat);
SAFE_DELETE(m_audioFormat);
SAFE_DELETE(m_file);
m_videoFormat = 0;
m_audioFormat = 0;
m_file = 0;
m_videoStream = 0;
m_audioStream = 0;
return;
}
try
{
CImage im( (BitmapInfo *)m_videoFormat, data, false );
m_videoStream->AddFrame( &im );
count++;
if ((count % 50) == 0)
cout << "[VCR]: " << count << " frames captured..." << endl;
}
catch (FatalError &error)
{
error.Print();
SAFE_DELETE(m_videoFormat);
SAFE_DELETE(m_audioFormat);
SAFE_DELETE(m_file);
m_videoFormat = 0;
m_audioFormat = 0;
m_file = 0;
m_videoStream = 0;
m_audioStream = 0;
}
catch (...)
{
cout << "[VCR]: ERROR: Caught unknown exception!" << endl;
}
}
extern "C" void
VCRComp_addAudioData( const unsigned char *data, int len )
{
try
{
m_audioStream->AddData( (void *)data, len );
}
catch (FatalError &error)
{
error.Print();
SAFE_DELETE(m_videoFormat);
SAFE_DELETE(m_audioFormat);
SAFE_DELETE(m_file);
m_videoFormat = 0;
m_audioFormat = 0;
m_file = 0;
m_videoStream = 0;
m_audioStream = 0;
}
catch (...)
{
cout << "[VCR]: ERROR: Caught unknown exception!" << endl;
}
}
// codec stuff
extern "C" int
VCRComp_numVideoCodecs()
{
return m_videoCodecs.size();
}
extern "C" const char *
VCRComp_videoCodecName( int index )
{
if (index < 0 || index >= (int)m_videoCodecs.size())
return "<cindex out of range>";
return m_videoCodecs[index]->GetName();
}
extern "C" int
VCRComp_numVideoCodecAttribs( int index )
{
if (index < 0 || index >= (int)m_videoCodecs.size())
return 0;
return m_videoCodecs[index]->encoder_info.size();
}
extern "C" const char *
VCRComp_videoCodecAttribName( int cindex, int aindex )
{
if (cindex < 0 || cindex >= (int)m_videoCodecs.size())
return "<cindex out of range>";
if (aindex < 0 || aindex >= (int)m_videoCodecs[cindex]->encoder_info.size())
return "<aindex out of range>";
return m_videoCodecs[cindex]->encoder_info[aindex].GetName();
}
extern "C" int
VCRComp_videoCodecAttribKind( int cindex, int aindex )
{
if (cindex < 0 || cindex >= (int)m_videoCodecs.size())
return -1;
if (aindex < 0 || aindex >= (int)m_videoCodecs[cindex]->encoder_info.size())
return -1;
switch (m_videoCodecs[cindex]->encoder_info[aindex].GetKind())
{
case AttributeInfo::Integer:
return ATTRIB_INTEGER;
break;
case AttributeInfo::String:
return ATTRIB_STRING;
break;
case AttributeInfo::Select:
return ATTRIB_SELECT;
break;
case AttributeInfo::Float:
return ATTRIB_FLOAT;
break;
}
return -1;
}
extern "C" const char *
VCRComp_videoCodecAttribValue( int cindex, int aindex )
{
static char buf[256];
char *cVal;
int iVal;
//float fVal;
if (cindex < 0 || cindex >= (int)m_videoCodecs.size())
return "<cindex out of range>";
if (aindex < 0 || aindex >= (int)m_videoCodecs[cindex]->encoder_info.size())
return "<aindex out of range>";
switch (VCRComp_videoCodecAttribKind( cindex, aindex ))
{
case ATTRIB_INTEGER:
Creators::GetCodecAttr( *m_videoCodecs[cindex],
VCRComp_videoCodecAttribName( cindex, aindex ), iVal );
sprintf( buf, "%d", iVal );
break;
case ATTRIB_STRING:
Creators::GetCodecAttr( *m_videoCodecs[cindex],
VCRComp_videoCodecAttribName( cindex, aindex ), (const char **)&cVal );
strncpy( buf, cVal, 256 );
free( cVal );
break;
case ATTRIB_SELECT:
Creators::GetCodecAttr( *m_videoCodecs[cindex],
VCRComp_videoCodecAttribName( cindex, aindex ), iVal );
strncpy( buf, VCRComp_videoCodecAttribOption( cindex, aindex, iVal ), 256 );
break;
/* case ATTRIB_FLOAT:
IVideoEncoder::GetExtendedAttr( m_videoCodecs[cindex]->fourcc,
VCRComp_videoCodecAttribName( cindex, aindex ), fVal );
sprintf( buf, "%f", fVal );
break;*/
default:
strcpy( buf, "Unknown type!" );
break;
}
return buf;
}
extern "C" void
VCRComp_videoCodecAttribSetValue( int cindex, int aindex, const char *val )
{
int i;
if (cindex < 0 || cindex >= (int)m_videoCodecs.size())
return;
if (aindex < 0 || aindex >= (int)m_videoCodecs[cindex]->encoder_info.size())
return;
switch (VCRComp_videoCodecAttribKind( cindex, aindex ))
{
case ATTRIB_INTEGER:
i = atoi( val );
Creators::SetCodecAttr( *m_videoCodecs[cindex],
VCRComp_videoCodecAttribName( cindex, aindex ), i );
break;
case ATTRIB_STRING:
Creators::SetCodecAttr( *m_videoCodecs[cindex],
VCRComp_videoCodecAttribName( cindex, aindex ), val );
break;
case ATTRIB_SELECT:
for (int i = 0; i < VCRComp_numVideoCodecAttribOptions( cindex, aindex ); i++)
{
if (!strcmp( val, VCRComp_videoCodecAttribOption( cindex, aindex, i ) ))
{
Creators::SetCodecAttr( *m_videoCodecs[cindex],
VCRComp_videoCodecAttribName( cindex, aindex ), i );
}
}
break;
}
}
extern "C" int
VCRComp_numVideoCodecAttribOptions( int cindex, int aindex )
{
if (cindex < 0 || cindex >= (int)m_videoCodecs.size())
return 0;
if (aindex < 0 || aindex >= (int)m_videoCodecs[cindex]->encoder_info.size())
return 0;
return m_videoCodecs[cindex]->encoder_info[aindex].options.size();
}
extern "C" const char *
VCRComp_videoCodecAttribOption( int cindex, int aindex, int oindex )
{
if (cindex < 0 || cindex >= (int)m_videoCodecs.size())
return "<cindex out of range>";
if (aindex < 0 || aindex >= (int)m_videoCodecs[cindex]->encoder_info.size())
return "<aindex out of range>";
if (oindex < 0 || oindex >= (int)m_videoCodecs[cindex]->encoder_info[aindex].options.size())
return "<oindex out of range>";
return m_videoCodecs[cindex]->encoder_info[aindex].options[oindex].c_str();
}
extern "C" void
VCRComp_selectVideoCodec( int index )
{
if (index < 0 || index >= (int)m_videoCodecs.size())
return;
m_selectedVideoCodec = index;
}
extern "C" int
VCRComp_numAudioCodecs()
{
return m_audioCodecs.size();
}
extern "C" const char *
VCRComp_audioCodecName( int index )
{
if (index < 0 || index >= (int)m_audioCodecs.size())
return "<cindex out of range>";
return m_audioCodecs[index]->GetName();
}
extern "C" int
VCRComp_numAudioCodecAttribs( int index )
{
if (index < 0 || index >= (int)m_audioCodecs.size())
return 0;
return m_audioCodecs[index]->encoder_info.size();
}
extern "C" const char *
VCRComp_audioCodecAttribName( int cindex, int aindex )
{
if (cindex < 0 || cindex >= (int)m_audioCodecs.size())
return "<cindex out of range>";
if (aindex < 0 || aindex >= (int)m_audioCodecs[cindex]->encoder_info.size())
return "<aindex out of range>";
return m_audioCodecs[cindex]->encoder_info[aindex].GetName();
}
extern "C" int
VCRComp_audioCodecAttribKind( int cindex, int aindex )
{
if (cindex < 0 || cindex >= (int)m_audioCodecs.size())
return -1;
if (aindex < 0 || aindex >= (int)m_audioCodecs[cindex]->encoder_info.size())
return -1;
switch (m_audioCodecs[cindex]->encoder_info[aindex].GetKind())
{
case AttributeInfo::Integer:
return ATTRIB_INTEGER;
break;
case AttributeInfo::String:
return ATTRIB_STRING;
break;
case AttributeInfo::Select:
return ATTRIB_SELECT;
break;
case AttributeInfo::Float:
return ATTRIB_FLOAT;
break;
}
return -1;
}
extern "C" const char *
VCRComp_audioCodecAttribValue( int cindex, int aindex )
{
static char buf[256];
char *cVal;
int iVal;
//float fVal;
if (cindex < 0 || cindex >= (int)m_audioCodecs.size())
return "<cindex out of range>";
if (aindex < 0 || aindex >= (int)m_audioCodecs[cindex]->encoder_info.size())
return "<aindex out of range>";
switch (VCRComp_audioCodecAttribKind( cindex, aindex ))
{
case ATTRIB_INTEGER:
Creators::GetCodecAttr( *m_audioCodecs[cindex],
VCRComp_audioCodecAttribName( cindex, aindex ), iVal );
sprintf( buf, "%d", iVal );
break;
case ATTRIB_STRING:
Creators::GetCodecAttr( *m_audioCodecs[cindex],
VCRComp_audioCodecAttribName( cindex, aindex ), (const char **)&cVal );
strncpy( buf, cVal, 256 );
free( cVal );
break;
case ATTRIB_SELECT:
Creators::GetCodecAttr( *m_audioCodecs[cindex],
VCRComp_audioCodecAttribName( cindex, aindex ), iVal );
strncpy( buf, VCRComp_audioCodecAttribOption( cindex, aindex, iVal ), 256 );
break;
/* case ATTRIB_FLOAT:
IVideoEncoder::GetExtendedAttr( m_videoCodecs[cindex]->fourcc,
VCRComp_videoCodecAttribName( cindex, aindex ), fVal );
sprintf( buf, "%f", fVal );
break;*/
default:
strcpy( buf, "Unknown type!" );
break;
}
return buf;
}
extern "C" void
VCRComp_audioCodecAttribSetValue( int cindex, int aindex, const char *val )
{
int i;
if (cindex < 0 || cindex >= (int)m_audioCodecs.size())
return;
if (aindex < 0 || aindex >= (int)m_audioCodecs[cindex]->encoder_info.size())
return;
switch (VCRComp_audioCodecAttribKind( cindex, aindex ))
{
case ATTRIB_INTEGER:
i = atoi( val );
Creators::SetCodecAttr( *m_audioCodecs[cindex],
VCRComp_audioCodecAttribName( cindex, aindex ), i );
break;
case ATTRIB_STRING:
Creators::SetCodecAttr( *m_audioCodecs[cindex],
VCRComp_audioCodecAttribName( cindex, aindex ), val );
break;
case ATTRIB_SELECT:
for (int i = 0; i < VCRComp_numAudioCodecAttribOptions( cindex, aindex ); i++)
{
if (!strcmp( val, VCRComp_audioCodecAttribOption( cindex, aindex, i ) ))
{
Creators::SetCodecAttr( *m_audioCodecs[cindex],
VCRComp_audioCodecAttribName( cindex, aindex ), i );
}
}
break;
}
}
extern "C" int
VCRComp_numAudioCodecAttribOptions( int cindex, int aindex )
{
if (cindex < 0 || cindex >= (int)m_audioCodecs.size())
return 0;
if (aindex < 0 || aindex >= (int)m_audioCodecs[cindex]->encoder_info.size())
return 0;
return m_audioCodecs[cindex]->encoder_info[aindex].options.size();
}
extern "C" const char *
VCRComp_audioCodecAttribOption( int cindex, int aindex, int oindex )
{
if (cindex < 0 || cindex >= (int)m_audioCodecs.size())
return "<cindex out of range>";
if (aindex < 0 || aindex >= (int)m_audioCodecs[cindex]->encoder_info.size())
return "<aindex out of range>";
if (oindex < 0 || oindex >= (int)m_audioCodecs[cindex]->encoder_info[aindex].options.size())
return "<oindex out of range>";
return m_audioCodecs[cindex]->encoder_info[aindex].options[oindex].c_str();
}
extern "C" void
VCRComp_selectAudioCodec( int index )
{
if (index < 0 || index >= (int)m_audioCodecs.size())
return;
m_selectedAudioCodec = index;
}
#endif // VCR_SUPPORT