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