230 lines
12 KiB
C++
230 lines
12 KiB
C++
//
|
||
// AVI File Writer
|
||
//
|
||
|
||
#include "aviwriter.h"
|
||
#include "macro.h"
|
||
|
||
#pragma comment(lib, "vfw32.lib")
|
||
|
||
CAVIWriter::CAVIWriter() :
|
||
m_pAviFile(NULL),
|
||
m_pVideoStream(NULL),
|
||
m_pAudioStream(NULL),
|
||
m_pVideoStreamCompress(NULL),
|
||
m_pVideoFormat(NULL),
|
||
m_FrameNumber(0),
|
||
m_SampleNumber(0)
|
||
{
|
||
::AVIFileInit();
|
||
|
||
ZEROMEMORY( &m_VideoStreamInfo, sizeof(m_VideoStreamInfo) );
|
||
m_VideoStreamInfo.fccType = streamtypeVIDEO;
|
||
m_VideoStreamInfo.fccHandler = comptypeDIB;
|
||
m_VideoStreamInfo.dwQuality = (DWORD)-1;
|
||
|
||
// default formats
|
||
SetAudioFormat( 44100, 16, 1 );
|
||
SetFrameRate( 100, 60*100 );
|
||
|
||
ZEROMEMORY( &m_VideoOption, sizeof(m_VideoOption) );
|
||
m_VideoOption.fccType = streamtypeVIDEO;
|
||
m_VideoOption.fccHandler = comptypeDIB;
|
||
|
||
ZEROMEMORY( &m_Compvers, sizeof(m_Compvers) );
|
||
m_Compvers.cbSize = sizeof(COMPVARS);
|
||
m_Compvers.dwFlags = ICMF_COMPVARS_VALID;
|
||
m_Compvers.fccHandler = comptypeDIB;
|
||
m_Compvers.lQ = ICQUALITY_DEFAULT;
|
||
m_Compvers.lKey = 15;
|
||
}
|
||
|
||
CAVIWriter::~CAVIWriter()
|
||
{
|
||
Close();
|
||
::AVIFileExit();
|
||
}
|
||
|
||
bool CAVIWriter::Open( const char* fname )
|
||
{
|
||
if( !m_pVideoFormat )
|
||
return false;
|
||
|
||
::DeleteFile( fname );
|
||
|
||
if( ::AVIFileOpen( &m_pAviFile, fname, OF_WRITE | OF_CREATE, NULL ) ) {
|
||
return false;
|
||
}
|
||
|
||
// Video Stream
|
||
if( ::AVIFileCreateStream( m_pAviFile, &m_pVideoStream, &m_VideoStreamInfo ) ) {
|
||
Close();
|
||
return false;
|
||
}
|
||
if( ::AVIMakeCompressedStream( &m_pVideoStreamCompress, m_pVideoStream, &m_VideoOption, NULL ) != AVIERR_OK ) {
|
||
Close();
|
||
return false;
|
||
}
|
||
if( ::AVIStreamSetFormat( m_pVideoStreamCompress, 0, m_pVideoFormat, m_pVideoFormat->biSize + m_pVideoFormat->biClrUsed * sizeof(RGBQUAD) ) ) {
|
||
Close();
|
||
return false;
|
||
}
|
||
|
||
// Audio Stream
|
||
if( ::AVIFileCreateStream( m_pAviFile, &m_pAudioStream, &m_AudioStreamInfo ) ) {
|
||
Close();
|
||
return false;
|
||
}
|
||
if( ::AVIStreamSetFormat( m_pAudioStream, 0, &m_AudioFormat, sizeof(WAVEFORMATEX) ) ) {
|
||
Close();
|
||
return false;
|
||
}
|
||
|
||
m_FrameNumber = 0;
|
||
m_SampleNumber = 0;
|
||
|
||
return true;
|
||
}
|
||
|
||
void CAVIWriter::Close()
|
||
{
|
||
if( m_pAudioStream ) {
|
||
::AVIStreamClose( m_pAudioStream );
|
||
m_pAudioStream = NULL;
|
||
}
|
||
if( m_pVideoStreamCompress ) {
|
||
::AVIStreamClose( m_pVideoStreamCompress );
|
||
m_pVideoStreamCompress = NULL;
|
||
}
|
||
if( m_pVideoStream ) {
|
||
::AVIStreamClose( m_pVideoStream );
|
||
m_pVideoStream = NULL;
|
||
}
|
||
if( m_pAviFile ) {
|
||
::AVIFileClose( m_pAviFile );
|
||
m_pAviFile = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
bool CAVIWriter::SelectVideoFormat( HWND hWnd )
|
||
{
|
||
m_Compvers.dwFlags = ICMF_COMPVARS_VALID;
|
||
m_Compvers.lpState = NULL;
|
||
m_Compvers.cbState = 0;
|
||
|
||
if( !::ICCompressorChoose( hWnd, ICMF_CHOOSE_DATARATE | ICMF_CHOOSE_KEYFRAME,
|
||
m_pVideoFormat, NULL, &m_Compvers, NULL) )
|
||
return false;
|
||
|
||
m_VideoStreamInfo.fccHandler = m_Compvers.fccHandler;
|
||
|
||
ZEROMEMORY( &m_VideoOption, sizeof(m_VideoOption) );
|
||
m_VideoOption.fccType = streamtypeVIDEO;
|
||
m_VideoOption.fccHandler = m_Compvers.fccHandler;
|
||
m_VideoOption.dwKeyFrameEvery = m_Compvers.lKey;
|
||
m_VideoOption.dwQuality = m_Compvers.lQ;
|
||
m_VideoOption.dwBytesPerSecond = m_Compvers.lDataRate;
|
||
m_VideoOption.dwFlags = ((m_Compvers.lDataRate > 0) ? AVICOMPRESSF_DATARATE : 0)
|
||
|((m_Compvers.lKey > 0 ) ? AVICOMPRESSF_KEYFRAMES : 0);
|
||
|
||
::ICCompressorFree( &m_Compvers );
|
||
|
||
return true;
|
||
}
|
||
|
||
void CAVIWriter::SetVideoFormat( BITMAPINFOHEADER* bih )
|
||
{
|
||
m_pVideoFormat = bih;
|
||
}
|
||
|
||
void CAVIWriter::SetAudioFormat( const DWORD rate, const WORD bits, const INT channels )
|
||
{
|
||
m_AudioFormat.wFormatTag = WAVE_FORMAT_PCM;
|
||
m_AudioFormat.nSamplesPerSec = rate;
|
||
m_AudioFormat.wBitsPerSample = bits;
|
||
m_AudioFormat.nChannels = channels;
|
||
m_AudioFormat.nBlockAlign = m_AudioFormat.nChannels * m_AudioFormat.wBitsPerSample / 8;
|
||
m_AudioFormat.nAvgBytesPerSec = m_AudioFormat.nSamplesPerSec * m_AudioFormat.nBlockAlign;
|
||
m_AudioFormat.cbSize = 0;
|
||
|
||
ZEROMEMORY( &m_AudioStreamInfo, sizeof(m_AudioStreamInfo) );
|
||
m_AudioStreamInfo.fccType = streamtypeAUDIO;
|
||
// m_AudioStreamInfo.fccHandler = comptypeDIB;
|
||
m_AudioStreamInfo.fccHandler = m_AudioFormat.wFormatTag;
|
||
m_AudioStreamInfo.dwScale = m_AudioFormat.nBlockAlign;
|
||
m_AudioStreamInfo.dwInitialFrames = 1;
|
||
m_AudioStreamInfo.dwRate = m_AudioFormat.nAvgBytesPerSec;
|
||
m_AudioStreamInfo.dwQuality = (DWORD)-1;
|
||
m_AudioStreamInfo.dwSampleSize = m_AudioFormat.nBlockAlign;
|
||
}
|
||
|
||
void CAVIWriter::SetFrameRate( const DWORD scale, const DWORD rate )
|
||
{
|
||
m_FrameRate = rate;
|
||
|
||
// ZEROMEMORY( &m_VideoStreamInfo, sizeof(m_VideoStreamInfo) );
|
||
// m_VideoStreamInfo.fccType = streamtypeVIDEO;
|
||
// m_VideoStreamInfo.fccHandler = comptypeDIB;
|
||
m_VideoStreamInfo.dwScale = scale;
|
||
m_VideoStreamInfo.dwRate = rate;
|
||
// m_VideoStreamInfo.dwQuality = (DWORD)-1;
|
||
}
|
||
|
||
bool CAVIWriter::WriteVideo( const char* video )
|
||
{
|
||
if( !m_pAviFile )
|
||
return false;
|
||
|
||
#if 0
|
||
DWORD dwFlags = 0;
|
||
if( m_VideoOption.dwFlags & AVICOMPRESSF_KEYFRAMES ) {
|
||
if( (m_FrameNumber % m_VideoOption.dwKeyFrameEvery) == 0 ) {
|
||
dwFlags = AVIIF_KEYFRAME;
|
||
}
|
||
}
|
||
if( ::AVIStreamWrite( m_pVideoStreamCompress, m_FrameNumber, 1, (void*)video,
|
||
m_pVideoFormat->biSizeImage, dwFlags, NULL, NULL ) ) {
|
||
Close();
|
||
return false;
|
||
}
|
||
#else
|
||
if( ::AVIStreamWrite( m_pVideoStreamCompress, m_FrameNumber, 1, (void*)video,
|
||
m_pVideoFormat->biSizeImage, AVIIF_KEYFRAME, NULL, NULL ) ) {
|
||
Close();
|
||
return false;
|
||
}
|
||
#endif
|
||
m_FrameNumber++;
|
||
|
||
return true;
|
||
}
|
||
|
||
bool CAVIWriter::WriteAudio( const char* audio, const int length )
|
||
{
|
||
if( !m_pAviFile )
|
||
return false;
|
||
|
||
int samples = length / m_AudioFormat.nBlockAlign;
|
||
if( ::AVIStreamWrite( m_pAudioStream, m_SampleNumber, samples, (void*)audio,
|
||
length, 0, NULL, NULL ) ) {
|
||
Close();
|
||
return false;
|
||
}
|
||
|
||
m_SampleNumber += samples;
|
||
|
||
return true;
|
||
}
|
||
|
||
bool CAVIWriter::WriteFrame( const char* video, const char* audio, const int length )
|
||
{
|
||
if( !WriteVideo( video ) )
|
||
return false;
|
||
if( !WriteAudio( audio, length ) )
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|