ref: f451c32474504a0329b572f436f8eacd904fba9c
dir: /wingui/EncoderJobProcessingManager.cpp/
// EncoderJobProcessingManager.cpp: implementation of the CEncoderJobProcessingManager class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "faac_wingui.h" #include "EncoderJobProcessingManager.h" #include "WindowUtil.h" #include <sndfile.h> #include "faac.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif //#define DUMMY_ENCODERJOB_PROCESSING ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CEncoderJobProcessingManager::CEncoderJobProcessingManager(const CEncoderJob *poJobToProcess): m_poJobToProcess(poJobToProcess), m_poInfoTarget(0), m_eCurrentWorkingState(eInitial) { } CEncoderJobProcessingManager::~CEncoderJobProcessingManager() { } void CEncoderJobProcessingManager::Start( CProcessingStatusDialogInfoFeedbackCallbackInterface *poInfoTarget) { if (poInfoTarget!=0) { m_poInfoTarget=poInfoTarget; } switch (m_eCurrentWorkingState) { case eInitial: { // initialize the status dialog { // define supported buttons m_poInfoTarget->SetAvailableActions(true, false); // set the dialog caption m_poInfoTarget->SetAdditionalCaptionInfo(m_poJobToProcess->GetJobProcessingAdditionalCaptionBarInformation()); } // initialize ourselves and run the job m_eCurrentWorkingState=eRunning; m_poInfoTarget->ReturnToCaller(DoProcessing()); break; } case ePaused: { m_eCurrentWorkingState=eRunning; break; } default: { // call to Start() is invalid except in the above two cases ASSERT(false); } } } void CEncoderJobProcessingManager::Stop() { switch (m_eCurrentWorkingState) { case eRunning: case ePaused: { m_eCurrentWorkingState=eStopped; break; } case eCleanup: { // ignore break; } default: { // call to Stop() is invalid except in the above two cases ASSERT(false); } } } void CEncoderJobProcessingManager::Pause() { switch (m_eCurrentWorkingState) { case eRunning: { m_eCurrentWorkingState=ePaused; break; } default: { // call to Pause() is invalid except in the above case ASSERT(false); } } } #ifdef DUMMY_ENCODERJOB_PROCESSING bool CEncoderJobProcessingManager::DoProcessing() { long lStartTimeMillis=::GetTickCount(); long lMaxCount=250*64000/(5+m_poJobToProcess->GetBitRate()); for (long lPos=0; lPos<lMaxCount; lPos++) { long lMultiplicationDummy; for (long lPosInner=0; lPosInner<10000000; lPosInner++) { // just a pause to simulate work lMultiplicationDummy=234985; lMultiplicationDummy*=301872; } switch (m_eCurrentWorkingState) { case eRunning: { // just report our current state WriteProgress(lStartTimeMillis, lMaxCount, lPos); m_poInfoTarget->ProcessUserMessages(); break; } case ePaused: { // must wait while (m_eCurrentWorkingState==ePaused) { // be idle m_poInfoTarget->ProcessUserMessages(); Sleep(200); } break; } case eStopped: { // must interrupt return false; } } } m_eCurrentWorkingState=eCleanup; return true; } #else bool CEncoderJobProcessingManager::DoProcessing() { long lStartTimeMillis=::GetTickCount(); const CEncoderJob *poJob=m_poJobToProcess; bool bInterrupted=false; SNDFILE *phInFile; SF_INFO sctSfInfo; // open the input file if ((phInFile=sf_open_read(poJob->GetFiles().GetCompleteSourceFilePath(), &sctSfInfo)) != NULL) { // determine input file parameters long lSampleRate=sctSfInfo.samplerate; long lNumChannels=sctSfInfo.channels; // open and setup the encoder unsigned long ulInputSamplesPerLoopCycle; unsigned long ulMaxLoopCycleOutputSize; faacEncHandle hEncoder=faacEncOpen(lSampleRate, lNumChannels, &ulInputSamplesPerLoopCycle, &ulMaxLoopCycleOutputSize); if (hEncoder!=0) { // set encoder configuration faacEncConfigurationPtr pEncConfig=faacEncGetCurrentConfiguration(hEncoder); pEncConfig->allowMidside = poJob->GetAllowMidside() ? 1 : 0; pEncConfig->useTns = poJob->GetUseTns() ? 1 : 0; pEncConfig->useLtp = poJob->GetUseLtp() ? 1 : 0; pEncConfig->useLfe = poJob->GetUseLfe() ? 1 : 0; pEncConfig->bitRate = poJob->GetBitRate(); pEncConfig->bandWidth = poJob->GetBandwidth(); pEncConfig->aacProfile = GetAacProfileConstant(poJob->GetAacProfile()); if (!faacEncSetConfiguration(hEncoder, pEncConfig)) { faacEncClose(hEncoder); sf_close(phInFile); AfxMessageBox("faacEncSetConfiguration failed!", MB_OK | MB_ICONSTOP); return false; } // open the output file CFile *poFile; CArchive *poTargetFileOutputArchive; if (OpenOutputFileArchive(poJob->GetFiles().GetCompleteTargetFilePath(), poFile, poTargetFileOutputArchive)) { long lStartTime=GetTickCount(); long lLastUpdated=0; long lTotalBytesRead = 0; long lSamplesInput=0; long lBytesConsumed=0; short *parsPcmBuf; char *parcBitBuf; parsPcmBuf=new short[ulInputSamplesPerLoopCycle]; parcBitBuf=new char[ulMaxLoopCycleOutputSize]; while (true) { long lBytesWritten; lSamplesInput=sf_read_short(phInFile, parsPcmBuf, ulInputSamplesPerLoopCycle); lTotalBytesRead+=lSamplesInput*sizeof(short); // call the actual encoding routine lBytesWritten=faacEncEncode( hEncoder, parsPcmBuf, lSamplesInput, parcBitBuf, ulMaxLoopCycleOutputSize); switch (m_eCurrentWorkingState) { case eRunning: { // just report our current state and process waiting window messages WriteProgress(lStartTimeMillis, (sctSfInfo.samples*sizeof(short)*lNumChannels), lTotalBytesRead); m_poInfoTarget->ProcessUserMessages(); break; } case ePaused: { // must wait while (m_eCurrentWorkingState==ePaused) { // be idle m_poInfoTarget->ProcessUserMessages(); Sleep(200); } break; } case eStopped: { // must interrupt bInterrupted=true; break; } } if (bInterrupted) { // Stop Pressed break; } if (lSamplesInput==0 && lBytesWritten==0) { // all done, bail out break; } if (lBytesWritten < 0) { AfxMessageBox("faacEncEncodeFrame failed!", MB_OK | MB_ICONSTOP); bInterrupted=true; break; } poTargetFileOutputArchive->Write(parcBitBuf, lBytesWritten); } // close the target file if (poTargetFileOutputArchive!=0) delete poTargetFileOutputArchive; if (poFile!=0) delete poFile; if (parsPcmBuf!=0) delete[] parsPcmBuf; if (parcBitBuf!=0) delete[] parcBitBuf; } faacEncClose(hEncoder); } sf_close(phInFile); //MessageBeep(1); // no more done here } else { AfxMessageBox("Couldn't open input file!", MB_OK | MB_ICONSTOP); bInterrupted=true; } return !bInterrupted; } #endif void CEncoderJobProcessingManager::WriteProgress(long lOperationStartTickCount, long lMaxSteps, long lCurSteps) { long lCurTime=::GetTickCount(); double dProgress=100.*lCurSteps/lMaxSteps; if (dProgress>100) dProgress=100; // just security if (dProgress<0) dProgress=0; // just security CString oTopStatusText=m_poJobToProcess->GetDetailedDescriptionForStatusDialog(); long lElapsedTime=lCurTime-lOperationStartTickCount; long lEstimateEntireTime=(long)((double)(lElapsedTime)/(dProgress/100)); long lETA=lEstimateEntireTime-lElapsedTime; CString oElapsedTime(CWindowUtil::GetTimeDescription(lElapsedTime)); CString oEntireTime(CWindowUtil::GetTimeDescription(lEstimateEntireTime)); CString oETA(CWindowUtil::GetTimeDescription(lETA)); CString oBottomStatusText; oBottomStatusText.Format("%.1f %%\n\n%s / %s - %s", dProgress, oElapsedTime, oEntireTime, oETA); m_poInfoTarget->SetStatus(dProgress, oTopStatusText, oBottomStatusText); } int CEncoderJobProcessingManager::GetAacProfileConstant(CEncoderJob::EAacProfile eAacProfile) { switch (eAacProfile) { case CEncoderJob::eAacProfileLc: { return LOW; } default: { ASSERT(false); } case CEncoderJob::eAacProfileMain: { return MAIN; } case CEncoderJob::eAacProfileSsr: { return SSR; } } } bool CEncoderJobProcessingManager::OpenOutputFileArchive(const CString &oFileName, CFile* &poFile, CArchive* &poArchive) { try { poFile=0; poArchive=0; // open the file poFile=new CFile(oFileName, CFile::modeCreate | CFile::modeWrite | CFile::shareDenyWrite); poArchive=new CArchive(poFile, CArchive::store); return true; } catch (...) { // error opening the file for exclusive writing if (poArchive!=0) { delete poArchive; } if (poFile!=0) { delete poFile; } return false; } }