www.pudn.com > mediator15src.zip > OpenDMLAVIOutput.cpp


/* 
 * OpenDMLAVIOutput.cpp 
 * Copyright (C) 2002 Arno Hornberger  
 * 
 * This file is part of MPEG Mediator, a free MPEG stream converter. 
 * 
 * MPEG Mediator is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 2 of the License, or 
 * (at your option) any later version. 
 * 
 * MPEG Mediator is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */ 
 
#include "stdafx.h" 
#include "error.h" 
#include "OpenDMLAVIOutput.h" 
#include "OptionsDlg.h" 
#include  
#include  
#include  
#include  
 
#pragma warning( disable : 4731 ) 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
PREMPLUGENTRY xCompileEntry(int selector, compStdParms *stdParms, long param1, long param2); 
  
// 
//	Note! 
// 
//		If this DLL is dynamically linked against the MFC 
//		DLLs, any functions exported from this DLL which 
//		call into MFC must have the AFX_MANAGE_STATE macro 
//		added at the very beginning of the function. 
// 
//		For example: 
// 
//		extern "C" BOOL PASCAL EXPORT ExportedFunction() 
//		{ 
//			AFX_MANAGE_STATE(AfxGetStaticModuleState()); 
//			// normal function body here 
//		} 
// 
//		It is very important that this macro appear in each 
//		function, prior to any calls into MFC.  This means that 
//		it must appear as the first statement within the  
//		function, even before any object variable declarations 
//		as their constructors may generate calls into the MFC 
//		DLL. 
// 
//		Please see MFC Technical Notes 33 and 58 for additional 
//		details. 
// 
 
///////////////////////////////////////////////////////////////////////////// 
// COpenDMLAVIOutputApp 
 
BEGIN_MESSAGE_MAP(COpenDMLAVIOutputApp, CWinApp) 
	//{{AFX_MSG_MAP(COpenDMLAVIOutputApp) 
		// NOTE - the ClassWizard will add and remove mapping macros here. 
		//    DO NOT EDIT what you see in these blocks of generated code! 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// COpenDMLAVIOutputApp construction 
 
COpenDMLAVIOutputApp::COpenDMLAVIOutputApp() 
{ 
	// TODO: add construction code here, 
	// Place all significant initialization in InitInstance 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// The one and only COpenDMLAVIOutputApp object 
COpenDMLAVIOutputApp theApp; 
 
PREMPLUGENTRY xCompileEntry(int selector, compStdParms *stdParms, long param1, long param2) 
{ 
  AFX_MANAGE_STATE(AfxGetStaticModuleState()); 
   
  switch (selector) 
  { 
		case compStartup: 
			return theApp.StartUp((compInfoRec *)param1); 
		case compDoShutdown: 
			return theApp.ShutDown(); 
		case compGetIndFormat: 
			return theApp.GetIndFormat((compFileInfoRec *)param1, param2); 
		case compGetAudioIndFormat: 
			return theApp.GetAudioIndFormat(stdParms, (compAudioInfoRec *)param1, param2); 
		case compQueryOutputFormat: 
			return theApp.QueryOutputFormat((compOutputRec *)param1); 
		case compDoCompile: 
			return theApp.DoCompile(stdParms, (compDoCompileInfo *)param1); 
		case compGetFilePrefs: 
			return theApp.GetFilePrefs(stdParms, (compGetFilePrefsRec *)param1); 
		default: 
			return comp_ErrNone; 
  } 
} 
 
int COpenDMLAVIOutputApp::StartUp(compInfoRec *infoRec) 
{ 
	memset(infoRec, 0, sizeof(compInfoRec)); 
 
	infoRec->compilerID = 76; 
  infoRec->fileType = 'LMDO'; 
	infoRec->classID = 'yuv@'; 
  infoRec->hasSetup = 1; 
  infoRec->compilesVideo = 1; 
  infoRec->compilesAudio = 1; 
  infoRec->hasAllocator = 0; 
  infoRec->canCopyFrames = 0; 
  infoRec->canOpen = 1; 
	infoRec->singleFrame = 0; 
	infoRec->extension = 'true'; 
	infoRec->suppOutputFormat = PrI_RGB32 | PrI_RGB24 | PrI_YUY2 | PrI_YV12 | 
															PrI_YVYU | PrI_VYUY | PrI_UYVY | PrI_IYUV; 
 
  strcpy(infoRec->compilerName, "OpenDML AVI Output"); 
 
  return comp_ErrNone; 
} 
 
int COpenDMLAVIOutputApp::ShutDown() 
{ 
  return comp_ErrNone; 
} 
 
int COpenDMLAVIOutputApp::GetIndFormat(compFileInfoRec *fileInfoRec, int idx) 
{ 
  if (idx != 0) 
    return comp_BadFormatIndex; 
 
  fileInfoRec->subtype = compUncompressed; 
  strcpy(fileInfoRec->name, "OpenDML AVI Video"); 
  fileInfoRec->canForceKeyframes = 0; 
  fileInfoRec->depthsSupported = compDepth24; 
  fileInfoRec->paletteAtDepth = 0; 
  fileInfoRec->frameMultiple = 1; 
  fileInfoRec->minWidth = 16; 
  fileInfoRec->minHeight = 16; 
  fileInfoRec->maxWidth = 2048; 
  fileInfoRec->maxHeight = 1536; 
  fileInfoRec->canDoFields = 0; 
  fileInfoRec->canDoQuality = 0; 
  fileInfoRec->canSetDataRate = 0; 
  fileInfoRec->hasSetup = 0; 
  fileInfoRec->canDelta = 0; 
  fileInfoRec->fixedTimebase = 0; 
  fileInfoRec->defaultQuality = -1; 
  fileInfoRec->defaultKeyFrameRate = -1; 
 
  return comp_ErrNone; 
} 
 
int COpenDMLAVIOutputApp::GetAudioIndFormat(compStdParms *stdParms, compAudioInfoRec *audioInfoRec, int idx) 
{ 
  if (idx != 0) 
    return comp_BadFormatIndex; 
 
  audioInfoRec->subtype = compUncompressed; 
  audioInfoRec->hasSetup = false; 
  strcpy(audioInfoRec->name, "OpenDML AVI Audio"); 
  audioInfoRec->audioFormats = 0; 
 
  return comp_ErrNone; 
} 
   
int COpenDMLAVIOutputApp::QueryOutputFormat(compOutputRec *outputRec) 
{ 
  if (outputRec->doVideo) 
  { 
    if ((outputRec->width < 16) || (outputRec->height < 16) || 
        (outputRec->width > 2048) || (outputRec->height > 1536)) 
      return comp_OutputFormatDecline; 
 
    if ((outputRec->width % 16 != 0) || (outputRec->height % 16 != 0)) 
      return comp_OutputFormatDecline; 
  } 
 
  if (outputRec->doAudio && outputRec->audsamplesize != 16) 
		return comp_OutputFormatDecline; 
 
  return comp_OutputFormatAccept; 
} 
 
int COpenDMLAVIOutputApp::GetFilePrefs(compStdParms *stdParms, compGetFilePrefsRec *fileInfoRec) 
{ 
	WAVEFORMATEX wfx; 
	BITMAPINFOHEADER bih; 
	long frame_format; 
	bool extended_api = (GetInputSettings(stdParms, kSettingsSubtype) == 'EXTD'); 
 
	frame_format = extended_api ? GetInputSettings(stdParms, kSettingsVidFormat) : PrI_RGB24; 
 
	if (!PrepareInputFrameFormat(&bih, frame_format, 640, 480)) 
		return comp_InternalError; 
 
	m_VidEnum.Enumerate(&bih); 
 
	memset(&wfx, 0, sizeof(WAVEFORMATEX)); 
	wfx.nSamplesPerSec = GetInputSettings(stdParms, kSettingsGetAudRate); 
 
	if (wfx.nSamplesPerSec > 0) 
	{ 
		wfx.wFormatTag = WAVE_FORMAT_PCM; 
		wfx.nChannels = GetInputSettings(stdParms, kSettingsIsStereo) ? 2 : 1; 
		wfx.wBitsPerSample = GetInputSettings(stdParms, kSettingsIs16BitAudio) ? 16 : 8; 
		wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8; 
		wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; 
		m_AudEnum.Enumerate(&wfx); 
	} 
 
	ShowOptionsDialog((bih.biCompression == BI_RGB) && (bih.biBitCount == 24), wfx.nSamplesPerSec <= 0); 
  
  return comp_ErrNone; 
} 
 
bool COpenDMLAVIOutputApp::ShowOptionsDialog(bool allow_rgb, bool disable_audio) 
{ 
  int tagIdx, formatIdx; 
 
  // Codecs are supposed to be enumerated already 
  // Also a valid state for m_oStateManager is assumed.  
 
  COptionsDlg optDlg; 
 
  optDlg.m_vVideoCodecList.Copy(m_VidEnum.GetEnumeratedCodecs()); 
  optDlg.m_vAudioCodecList.Copy(m_AudEnum.GetEnumeratedCodecs()); 
  optDlg.m_sResult.status = 0;  
 
  int idx; 
 
  if (m_oStateManager.GetFccHandler() != 0) 
  { 
    if (m_VidEnum.IsEnumerated(m_oStateManager.GetFccHandler(), &idx)) 
      optDlg.m_sResult.videoSelected = idx; 
    else 
      optDlg.m_sResult.status |= VIDEO_DEFAULT; 
  } 
  else 
    optDlg.m_sResult.status |= VIDEO_DEFAULT; 
 
	if (allow_rgb) 
		optDlg.m_sResult.status |= VIDEO_ALLOWRGB; 
 
	if (disable_audio) 
		optDlg.m_sResult.status |= AUDIO_DISABLE; 
	else 
	{ 
		if (m_oStateManager.GetWfxSize() > 0) 
		{ 
			if (m_AudEnum.IsEnumerated(m_oStateManager.GetAcmDriverID(), m_oStateManager.GetWfx(), m_oStateManager.GetWfxSize(), &tagIdx, &formatIdx)) 
			{ 
				optDlg.m_sResult.audioTagSelected = tagIdx; 
				optDlg.m_sResult.audioFormatSelected = formatIdx; 
			} 
			else 
				optDlg.m_sResult.status |= AUDIO_DEFAULT; 
		} 
		else 
			optDlg.m_sResult.status |= AUDIO_DEFAULT; 
 
		if (m_oStateManager.IsHQAudio()) 
			optDlg.m_sResult.status |= AUDIO_HQ; 
	} 
 
	optDlg.m_sResult.lQuality = m_oStateManager.GetQuality(); 
	optDlg.m_sResult.lKeyRate = m_oStateManager.GetKeyRate(); 
	optDlg.m_sResult.lDataRate = m_oStateManager.GetDataRate(); 
   
	if (optDlg.DoModal() != IDOK) 
		return false; 
 
	if (!allow_rgb && !!(optDlg.m_sResult.status & VIDEO_UNCOMPRESSED)) 
		return false; 
   
	if (optDlg.m_sResult.status & VIDEO_UNCOMPRESSED) 
		m_oStateManager.SetFccHandler(0); 
  else 
  { 
    m_oStateManager.SetFccHandler(optDlg.m_vVideoCodecList[optDlg.m_sResult.videoSelected].fccHandler);  
    m_oStateManager.SetHic(optDlg.m_vVideoCodecList[optDlg.m_sResult.videoSelected].hic); 
  } 
 
	m_oStateManager.SetQuality(optDlg.m_sResult.lQuality); 
	m_oStateManager.SetKeyRate(optDlg.m_sResult.lKeyRate); 
	m_oStateManager.SetDataRate(optDlg.m_sResult.lDataRate); 
 
	if (!disable_audio) 
	{ 
		if (optDlg.m_sResult.status & AUDIO_UNCOMPRESSED) 
			m_oStateManager.SetWfx(NULL, 0); 
		else 
		{ 
			tagIdx    = optDlg.m_sResult.audioTagSelected; 
			formatIdx = optDlg.m_sResult.audioFormatSelected; 
			m_oStateManager.SetWfx( 
				optDlg.m_vAudioCodecList[tagIdx].m_vWaveFormatExList[formatIdx].Get(), 
				optDlg.m_vAudioCodecList[tagIdx].m_vWaveFormatExList[formatIdx].GetSize()); 
 
			m_oStateManager.SetAcmDriverID(optDlg.m_vAudioCodecList[tagIdx].hadid); 
		} 
		m_oStateManager.SetHQAudio((optDlg.m_sResult.status & AUDIO_HQ) != 0); 
	} 
 
	return true; 
} 
 
bool COpenDMLAVIOutputApp::CompileConfigure(compStdParms *stdParms, compDoCompileInfo *compileInfo, LPBITMAPINFOHEADER lpbih) 
{ 
	int formatTagId, formatId; 
	bool bShowDialog = false; 
	int idx; 
 
  m_VidEnum.Enumerate(lpbih); 
 
	if (compileInfo->outputRec.doAudio) 
		m_AudEnum.Enumerate((LPWAVEFORMATEX)compileInfo->outputRec.audCompression.AudCompRec); 
 
  if (m_oStateManager.GetFccHandler()) 
	{ 
    if (!m_VidEnum.IsEnumerated(m_oStateManager.GetFccHandler(), &idx)) 
		{ 
			m_oStateManager.SetFccHandler(0); 
			bShowDialog = true; 
		} 
	} 
	else if (!((lpbih->biCompression == BI_RGB) && (lpbih->biBitCount == 24))) 
		bShowDialog = true; 
 
  if (compileInfo->outputRec.doAudio && m_oStateManager.GetWfxSize()) 
    if (!m_AudEnum.IsEnumerated(m_oStateManager.GetAcmDriverID(), m_oStateManager.GetWfx(), 
															  m_oStateManager.GetWfxSize(), &formatTagId, &formatId)) 
		{ 
	    m_oStateManager.SetWfx(NULL, 0); 
			bShowDialog = true; 
		} 
 
	if (bShowDialog) 
		return ShowOptionsDialog((lpbih->biCompression == BI_RGB) && (lpbih->biBitCount == 24),  
															!compileInfo->outputRec.doAudio); 
	return true; 
} 
 
void COpenDMLAVIOutputApp::From32to24(PBYTE inImage, PBYTE outImage, long inSize) 
{ 
	__asm 
  { 
      push	ebp 
      push	edi 
      push	esi 
      push	edx 
      push	ecx 
      push	ebx 
      push	eax 
       
      mov	esi,inImage 
      mov	edi,outImage 
 
      mov ecx, inSize 
      shr ecx, 4        ;our image has to be mod(4) pixels 
 
main_loop: 
      mov	eax,[esi]		  ;EAX = xxr0g0b0 
      mov	ebx,[esi+4]		;EBX = xxr1g1b1 
      mov	edx,ebx			  ;EDX = xxr1g1b1 
      mov	ebp,[esi+8]		;EBP = xxr2g2b2 
      shl	ebx,24			  ;EBX = b1000000 
      and	eax,00ffffffh	;EAX = 00r0g0b0 
      shr	edx,8			    ;EDX = 00xxr1g1 
      or	eax,ebx			  ;EAX = b1r0g0b0 
      mov	[edi+0],eax 
      mov	ebx,ebp       ;EBX = xxr2g2b2 
      shl	ebp,16			  ;EBP = g2b20000 
      and	edx,0000ffffh ;EDX = 0000r1g1 
      or	ebp,edx       ;EBP = g2b2r1g1 
      mov	eax,[esi+12]  ;EAX = xxr3g3b3 
      shr	ebx,16        ;EBX = 0000xxr2 
      add	edi,12 
      shl	eax,8         ;EAX = r3g3b300 
      and	ebx,000000ffh ;EBX = 000000r2 
      or	eax,ebx       ;EAX = r3g3b3r2 
      mov	[edi+4-12],ebp 
      add	esi,16 
      mov	[edi+8-12],eax 
      dec	ecx 
      jg	main_loop 
       
      pop	eax 
      pop	ebx 
      pop	ecx 
      pop	edx 
      pop	esi 
      pop	edi 
      pop	ebp 
  } 
} 
 
void COpenDMLAVIOutputApp::AppendExtension(char *outfilename) 
{ 
	int len = strlen(outfilename); 
 
	if (!len) 
		return; 
 
	len--; 
 
	while ((len >= 0) && isspace(outfilename[len])) 
		outfilename[len--] = '\0'; 
 
	len++; 
	if (len < 4 || _stricmp(&outfilename[len - 4], ".avi")) 
		strcat(outfilename, ".avi"); 
} 
 
bool COpenDMLAVIOutputApp::FileExists(const char *outfilename) 
{ 
	FILE *fh; 
 
	if (fh = fopen(outfilename, "rb")) 
	{ 
		fclose(fh); 
		return true; 
	} 
	return false; 
} 
 
int COpenDMLAVIOutputApp::DoCompile(compStdParms *stdParms, compDoCompileInfo *compileInfo) 
{ 
	bool extended_api = (GetInputSettings(stdParms, kSettingsSubtype) == 'EXTD'); 
	char outfilename[260]; 
	int ret = comp_ErrNone; 
 
	// video 
 
	BITMAPINFOHEADER bih; 
  PBYTE pRgb24 = 0; 
	void *buffer; 
  long rowbytes; 
  compGetFrameReturnRec frameReturn; 
  bool isKeyFrame; 
  long frameSize; 
  BYTE *compFrame = 0; 
	long lSampleDelay; 
     
	// audio 
   
	char **uncompAudio; 
  BufferReturnType theBuffer = &uncompAudio; 
  PBYTE compAudio; 
  long  compAudioSize, uncompAudioSize; 
  int nBlockAlign; 
	 
	// objects 
	 
	AVIOutputFile *avi_out; 
	VideoSequenceCompressor *video_comp = 0; 
	CAudioCompressor *audio_comp = 0; 
	AudioL3Corrector *audioCorrector = 0; 
 
 
	if (!compileInfo->outputRec.doVideo) 
		return comp_InternalError; 
	 
	strncpy(outfilename, compileInfo->outputFile.name, 256); 
	outfilename[255] = '\0'; 
	AppendExtension(outfilename); 
	 
	if (FileExists(outfilename)) 
	{ 
		char message[350]; 
 
		sprintf(message, "File '%s' already exists. Continue anyway?", outfilename); 
		if (MessageBox(0, message, "OpenDML AVI Output", MB_YESNO) != IDYES) 
			return comp_CompileAbort; 
	} 
 
	if (!PrepareInputFrameFormat(&bih, extended_api ? GetInputSettings(stdParms, kSettingsVidFormat) : PrI_RGB24, 
															 compileInfo->outputRec.width, compileInfo->outputRec.height)) 
		return comp_InternalError; 
	 
  if (!CompileConfigure(stdParms, compileInfo, &bih)) 
    return comp_InternalError; 
 
  if (!(avi_out = new AVIOutputFile)) 
    return comp_InternalError; 
 
  bool audioIsCompressed = m_oStateManager.GetWfxSize() > 0; 
  bool videoIsCompressed = m_oStateManager.GetFccHandler() != 0; 
 
  try 
  { 
		if (!extended_api) 
			if (!(pRgb24 = new BYTE[bih.biWidth * bih.biHeight * 3])) 
				throw MyError("not enough memory for rgb conversion buffer"); 
 
		if (videoIsCompressed) 
			video_comp = new VideoSequenceCompressor(m_oStateManager.GetHic(), &bih, 
																							 compileInfo->outputRec.timebase.scale,  
																							 compileInfo->outputRec.timebase.sampleSize, 
																							 m_oStateManager.GetQuality() * 100, 
																							 m_oStateManager.GetKeyRate(), 
																							 m_oStateManager.GetDataRate() * 1024); 
 
		if (compileInfo->outputRec.doAudio) 
		{																					  
      nBlockAlign = ((LPWAVEFORMATEX)compileInfo->outputRec.audCompression.AudCompRec)->nBlockAlign; 
			lSampleDelay = 0; 
 
			if (audioIsCompressed) 
			{ 
				audio_comp = new CAudioCompressor(m_oStateManager.GetAcmDriverID(),  
					                                (LPWAVEFORMATEX)compileInfo->outputRec.audCompression.AudCompRec, 
						                              m_oStateManager.GetWfx(), m_oStateManager.IsHQAudio()); 
		 
				if (m_oStateManager.GetWfx()->wFormatTag == WAVE_FORMAT_MPEGLAYER3) 
				{ 
					if (!(audioCorrector = new AudioL3Corrector())) 
						throw MyError("error creating AudioL3Corrector"); 
 
					lSampleDelay = ((MPEGLAYER3WAVEFORMAT *)m_oStateManager.GetWfx())->nCodecDelay; 
				} 
			} 
		} 
 
    if (!InitAVIStreams(avi_out, stdParms, compileInfo, &bih, video_comp)) 
			throw MyError("error initializing avi-streams"); 
 
		if (!avi_out->init(outfilename, bih.biWidth, bih.biHeight, TRUE, 
											 compileInfo->outputRec.doAudio, 100000, true)) 
			throw MyError("error initializing avi-file"); 
     
    for (int i = compileInfo->startFrame; i <= compileInfo->endFrame; i++) 
    { 
			stdParms->funcs->videoFuncs->getFrame(i, &buffer, &rowbytes, &frameReturn, true, 0); 
 
			if (frameReturn.returnVal != comp_ErrNone) 
				break; 
       
			if (!extended_api) 
	      From32to24((PBYTE)buffer, (PBYTE)pRgb24, bih.biWidth * bih.biHeight * 4); 
 
      if (videoIsCompressed) 
        compFrame = (BYTE *)video_comp->packFrame(extended_api ? buffer : pRgb24, &isKeyFrame, &frameSize); 
      else 
      { 
        compFrame = (BYTE *)(extended_api ? buffer : pRgb24); 
        frameSize = bih.biSizeImage; 
        isKeyFrame = true; 
      } 
 
      avi_out->videoOut->write(isKeyFrame ? AVIIF_KEYFRAME : 0 , compFrame, frameSize, 1); 
       
      if (compileInfo->outputRec.doAudio) 
      {      
        long frameCount = 1; 
  
				stdParms->funcs->audioFuncs->getAudio(i, &frameCount, &uncompAudioSize, 0, theBuffer, 0); 
  
        if (audioIsCompressed) 
				{ 
					if (lSampleDelay > 0) 
					{ 
						if (lSampleDelay * nBlockAlign < uncompAudioSize) 
						{ 
							audio_comp->Compress((PBYTE)*uncompAudio + lSampleDelay * nBlockAlign, 
																	 uncompAudioSize - lSampleDelay * nBlockAlign, 
																	 compAudio, compAudioSize); 
 
							if (audioCorrector && compAudioSize) 
								audioCorrector->Process(compAudio, compAudioSize); 
 
							lSampleDelay = 0; 
						}	 
						else { 
							compAudioSize = 0; 
							lSampleDelay -= uncompAudioSize / nBlockAlign; 
						} 
					} 
					else 
					{ 
						audio_comp->Compress((PBYTE)*uncompAudio, uncompAudioSize, compAudio, compAudioSize); 
 
						if (audioCorrector && compAudioSize) 
							audioCorrector->Process(compAudio, compAudioSize); 
					} 
				} 
        else 
        { 
          compAudioSize = uncompAudioSize; 
          compAudio = (PBYTE)*uncompAudio; 
        } 
         
        if (compAudioSize) 
          avi_out->audioOut->write(0, compAudio, compAudioSize, 0); 
      } 
		} 
 
		// fix compressed audio info 
		if (compileInfo->outputRec.doAudio) 
		{ 
			WAVEFORMATEX *pWfx = (WAVEFORMATEX *)avi_out->audioOut->getFormat(); 
 
			if (audioIsCompressed && (pWfx->wFormatTag == WAVE_FORMAT_MPEGLAYER3)) 
			{ 
				pWfx->nAvgBytesPerSec = audioCorrector->ComputeByterate(pWfx->nSamplesPerSec); 
				avi_out->audioOut->streamInfo.dwRate = pWfx->nAvgBytesPerSec * avi_out->audioOut->streamInfo.dwScale; 
			} 
		} 
  } 
  catch (MyError &me) 
  { 
		MessageBox(0, me.gets(), "OpenDML AVI Output", MB_OK); 
    ret = comp_InternalError; 
  } 
 
	delete audioCorrector; 
	delete audio_comp; 
	delete video_comp; 
	delete []pRgb24; 
  avi_out->finalize(); 
  delete avi_out; 
 
  return ret; 
} 
 
bool COpenDMLAVIOutputApp::InitAVIStreams(AVIOutputFile *pAVIFile, compStdParms *stdParms, 
																					compDoCompileInfo *compileInfo, LPBITMAPINFOHEADER lpbih, 
																					VideoSequenceCompressor *video_comp) 
{ 
  LPBITMAPINFOHEADER	pBitmapInfoHdr; 
  long								nBitmapInfoHdrSize; 
  LPWAVEFORMATEX			pWaveFormatEx; 
  long								nWaveFormatExSize; 
 
  bool audioIsCompressed = m_oStateManager.GetWfxSize() > 0; 
  bool videoIsCompressed = m_oStateManager.GetFccHandler() != 0;   
 
  if (!(pAVIFile->initOutputStreams())) 
		return false; 
 
	// video 
	 
	if (videoIsCompressed) 
	{ 
		pBitmapInfoHdr = video_comp->GetOutputFormat(); 
		nBitmapInfoHdrSize = video_comp->GetOutputFormatSize(); 
	} 
	else 
	{ 
		pBitmapInfoHdr = lpbih; 
		nBitmapInfoHdrSize = sizeof(BITMAPINFOHEADER); 
	} 
 
  memset(&pAVIFile->videoOut->streamInfo, 0, sizeof(AVIStreamHeader_fixed)); 
 
  pAVIFile->videoOut->streamInfo.fccType						= streamtypeVIDEO; 
  pAVIFile->videoOut->streamInfo.fccHandler					= pBitmapInfoHdr->biCompression; 
  pAVIFile->videoOut->streamInfo.dwFlags						= 0; 
  pAVIFile->videoOut->streamInfo.dwScale						= compileInfo->outputRec.timebase.sampleSize; 
  pAVIFile->videoOut->streamInfo.dwRate							= compileInfo->outputRec.timebase.scale; 
  pAVIFile->videoOut->streamInfo.dwStart						= 0; 
  pAVIFile->videoOut->streamInfo.dwLength						= 1; 
  pAVIFile->videoOut->streamInfo.dwInitialFrames		= 0; 
  pAVIFile->videoOut->streamInfo.dwSuggestedBufferSize = pBitmapInfoHdr->biSizeImage; // CHECK!! 
  pAVIFile->videoOut->streamInfo.dwQuality					= -1; 
  pAVIFile->videoOut->streamInfo.dwSampleSize				= 0; 
  pAVIFile->videoOut->streamInfo.rcFrame.left				= 0; 
  pAVIFile->videoOut->streamInfo.rcFrame.top				= 0; 
  pAVIFile->videoOut->streamInfo.rcFrame.right			= (short)pBitmapInfoHdr->biWidth; 
  pAVIFile->videoOut->streamInfo.rcFrame.bottom			= (short)pBitmapInfoHdr->biHeight; 
       
  pAVIFile->videoOut->setCompressed(videoIsCompressed); 
 
  if (!pAVIFile->videoOut->allocFormat(nBitmapInfoHdrSize)) 
		return false; 
 
  memcpy(pAVIFile->videoOut->getImageFormat(), pBitmapInfoHdr, nBitmapInfoHdrSize); 
 
	// audio 
 
	if (compileInfo->outputRec.doAudio) 
	{ 
		if (audioIsCompressed) 
		{ 
			pWaveFormatEx = m_oStateManager.GetWfx(); 
			nWaveFormatExSize = m_oStateManager.GetWfxSize(); 
		} 
		else 
		{ 
			pWaveFormatEx	= (LPWAVEFORMATEX)compileInfo->outputRec.audCompression.AudCompRec; 
			nWaveFormatExSize = sizeof(WAVEFORMATEX); 
		} 
 
    memset(&pAVIFile->audioOut->streamInfo, 0, sizeof(AVIStreamHeader_fixed)); 
 
    pAVIFile->audioOut->streamInfo.fccType					= streamtypeAUDIO; 
    pAVIFile->audioOut->streamInfo.fccHandler				= 0; 
    pAVIFile->audioOut->streamInfo.dwFlags					= 0; 
    pAVIFile->audioOut->streamInfo.dwScale					= pWaveFormatEx->nBlockAlign; 
    pAVIFile->audioOut->streamInfo.dwRate						= pWaveFormatEx->nAvgBytesPerSec; 
    pAVIFile->audioOut->streamInfo.dwStart					= 0; 
    pAVIFile->audioOut->streamInfo.dwLength					= 1; 
    pAVIFile->audioOut->streamInfo.dwInitialFrames	= 0; 
    pAVIFile->audioOut->streamInfo.dwSuggestedBufferSize = 0; 
    pAVIFile->audioOut->streamInfo.dwQuality				= 0; 
    pAVIFile->audioOut->streamInfo.dwSampleSize			= pWaveFormatEx->nBlockAlign; 
    pAVIFile->audioOut->streamInfo.rcFrame.left			= 0; 
    pAVIFile->audioOut->streamInfo.rcFrame.top			= 0; 
    pAVIFile->audioOut->streamInfo.rcFrame.right		= 0; 
    pAVIFile->audioOut->streamInfo.rcFrame.bottom		= 0; 
 
    if (!pAVIFile->audioOut->allocFormat(nWaveFormatExSize)) 
			return false; 
 
    memcpy(pAVIFile->audioOut->getWaveFormat(), pWaveFormatEx, nWaveFormatExSize); 
	} 
	return true; 
} 
 
bool COpenDMLAVIOutputApp::PrepareInputFrameFormat(LPBITMAPINFOHEADER lpbih, long frame_format, 
																									 int width, int height) 
{ 
  memset(lpbih, 0, sizeof(BITMAPINFOHEADER)); 
  lpbih->biSize = sizeof(BITMAPINFOHEADER); 
  lpbih->biWidth = width; 
  lpbih->biHeight = height; 
  lpbih->biPlanes = 1; 
 
	switch (frame_format) 
	{ 
		case PrI_RGB32:		// packed 
			lpbih->biBitCount = 32; 
		  lpbih->biCompression = BI_RGB; 
			lpbih->biSizeImage = ((lpbih->biWidth * lpbih->biBitCount + 31) / 32) * 4 * lpbih->biHeight; 
			break; 
		case PrI_RGB24:		// packed 
			lpbih->biBitCount = 24; 
		  lpbih->biCompression = BI_RGB; 
			lpbih->biSizeImage = ((lpbih->biWidth * lpbih->biBitCount + 31) / 32) * 4 * lpbih->biHeight; 
			break; 
		case PrI_YUY2:		// packed 
			lpbih->biBitCount = 16; 
			lpbih->biCompression = mmioFOURCC('Y', 'U', 'Y', '2'); 
			lpbih->biSizeImage = ((lpbih->biWidth * lpbih->biBitCount + 31) / 32) * 4 * lpbih->biHeight; 
			break; 
		case PrI_YV12:		// planar 
		  lpbih->biBitCount = 12; 
			lpbih->biCompression = mmioFOURCC('Y', 'V', '1', '2'); 
			lpbih->biSizeImage = ((lpbih->biWidth + 3) / 4) * 4 * lpbih->biHeight + 
													 2 * (((lpbih->biWidth / 2 + 3) / 4) * 4 * lpbih->biHeight / 2); 
			break; 
		case PrI_YVYU:		// packed 
		  lpbih->biBitCount = 16; 
			lpbih->biCompression = mmioFOURCC('Y', 'V', 'Y', 'U'); 
			lpbih->biSizeImage = ((lpbih->biWidth * lpbih->biBitCount + 31) / 32) * 4 * lpbih->biHeight; 
			break; 
		case PrI_VYUY:		// packed 
		  lpbih->biBitCount = 16; 
			lpbih->biCompression = mmioFOURCC('V', 'Y', 'U', 'Y'); 
			lpbih->biSizeImage = ((lpbih->biWidth * lpbih->biBitCount + 31) / 32) * 4 * lpbih->biHeight; 
			break; 
		case PrI_UYVY:		// packed 
		  lpbih->biBitCount = 16; 
			lpbih->biCompression = mmioFOURCC('U', 'Y', 'V', 'Y'); 
			lpbih->biSizeImage = ((lpbih->biWidth * lpbih->biBitCount + 31) / 32) * 4 * lpbih->biHeight; 
			break; 
		case PrI_IYUV:		// planar 
		  lpbih->biBitCount = 12; 
			lpbih->biCompression = mmioFOURCC('I', 'Y', 'U', 'V'); 
			lpbih->biSizeImage = ((lpbih->biWidth + 3) / 4) * 4 * lpbih->biHeight + 
													 2 * (((lpbih->biWidth / 2 + 3) / 4) * 4 * lpbih->biHeight / 2); 
			break; 
		default: 
			return false; 
	} 
	 
	return true; 
} 
 
long COpenDMLAVIOutputApp::GetInputSettings(compStdParms *stdParms, long setting) 
{ 
  if (stdParms && stdParms->piSuites && stdParms->piSuites->utilFuncs && stdParms->piSuites->utilFuncs->getSettings) 
    return stdParms->piSuites->utilFuncs->getSettings(setting); 
  else 
    return 0; 
}