ref: 220dc0a03d5d592da832c081e8027062d16baae5
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 // constants copied from reference implementation in VC project faacgui #define PCMBUFSIZE 1024 #define BITBUFSIZE 8192 ////////////////////////////////////////////////////////////////////// // 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 *infile; SF_INFO sfinfo; // open the input file if ((infile = sf_open_read(poJob->GetFiles().GetCompleteSourceFilePath(), &sfinfo)) != NULL) { // determine input file parameters unsigned int sampleRate = sfinfo.samplerate; unsigned int numChannels = sfinfo.channels; // open and setup the encoder unsigned long inputSamples; unsigned long maxOutputSize; faacEncHandle hEncoder = faacEncOpen(sampleRate, numChannels, &inputSamples, &maxOutputSize); if (hEncoder) { HANDLE hOutfile; // set encoder configuration faacEncConfigurationPtr config = faacEncGetCurrentConfiguration(hEncoder); config->allowMidside = poJob->GetAllowMidside() ? 1 : 0; config->useTns = poJob->GetUseTns() ? 1 : 0; config->useLtp = poJob->GetUseLtp() ? 1 : 0; config->useLfe = poJob->GetUseLfe() ? 1 : 0; config->bitRate = poJob->GetBitRate(); config->bandWidth = poJob->GetBandwidth(); config->aacProfile = GetAacProfileConstant(poJob->GetAacProfile()); if (!faacEncSetConfiguration(hEncoder, config)) { faacEncClose(hEncoder); sf_close(infile); AfxMessageBox("faacEncSetConfiguration failed!", MB_OK | MB_ICONSTOP); return false; } // open the output file hOutfile = CreateFile(poJob->GetFiles().GetCompleteTargetFilePath(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hOutfile != INVALID_HANDLE_VALUE) { UINT startTime = GetTickCount(), lastUpdated = 0; DWORD totalBytesRead = 0; unsigned int bytesInput = 0, bytesConsumed = 0; DWORD numberOfBytesWritten = 0; short *pcmbuf; unsigned char *bitbuf; pcmbuf = (short*)malloc(PCMBUFSIZE*numChannels*sizeof(short)); bitbuf = (unsigned char*)malloc(BITBUFSIZE*sizeof(unsigned char)); while (true) { int bytesWritten; int samplesToRead = PCMBUFSIZE; bytesInput = sf_read_short(infile, pcmbuf, numChannels*PCMBUFSIZE) * sizeof(short); //SendDlgItemMessage (hWnd, IDC_PROGRESS, PBM_SETPOS, (unsigned long)((float)totalBytesRead * 1024.0f / (sfinfo.samples*2*numChannels)), 0); totalBytesRead += bytesInput; // call the actual encoding routine bytesWritten = faacEncEncode(hEncoder, pcmbuf, bytesInput/2, bitbuf, BITBUFSIZE); switch (m_eCurrentWorkingState) { case eRunning: { // just report our current state and process waiting window messages WriteProgress(lStartTimeMillis, (sfinfo.samples*2*numChannels), totalBytesRead); 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 (!bytesInput && !bytesWritten) { // all done, bail out break; } if (bytesWritten < 0) { AfxMessageBox("faacEncEncodeFrame failed!", MB_OK | MB_ICONSTOP); bInterrupted=true; break; } WriteFile(hOutfile, bitbuf, bytesWritten, &numberOfBytesWritten, NULL); } CloseHandle(hOutfile); if (pcmbuf) free(pcmbuf); if (bitbuf) free(bitbuf); } faacEncClose(hEncoder); } sf_close(infile); MessageBeep(1); } else { AfxMessageBox("Couldn't open input file!", MB_OK | MB_ICONSTOP); bInterrupted=true; } return !bInterrupted; } // this is a version that I will try to put more the Hungarian Notation and C++ style /*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 unsigned int uiSampleRate=sctSfInfo.samplerate; unsigned int uiNumChannels=sctSfInfo.channels; // open and setup the encoder unsigned long ulInputSamplesPerLoopCycle; unsigned long ulMaxLoopCycleCompressionOutputSize; faacEncHandle hEncoder=faacEncOpen(uiSampleRate, uiNumChannels, &ulInputSamplesPerLoopCycle, &ulMaxLoopCycleCompressionOutputSize); if (hEncoder) { HANDLE hOutfile; // 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 hOutfile=CreateFile(poJob->GetFiles().GetCompleteTargetFilePath(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hOutfile != INVALID_HANDLE_VALUE) { UINT startTime = GetTickCount(), lastUpdated = 0; DWORD totalBytesRead = 0; unsigned int bytesInput = 0, bytesConsumed = 0; DWORD numberOfBytesWritten = 0; short *pcmbuf; unsigned char *bitbuf; pcmbuf = (short*)malloc(PCMBUFSIZE*numChannels*sizeof(short)); bitbuf = (unsigned char*)malloc(BITBUFSIZE*sizeof(unsigned char)); while (true) { int bytesWritten; int samplesToRead = PCMBUFSIZE; bytesInput = sf_read_short(infile, pcmbuf, numChannels*PCMBUFSIZE) * sizeof(short); //SendDlgItemMessage (hWnd, IDC_PROGRESS, PBM_SETPOS, (unsigned long)((float)totalBytesRead * 1024.0f / (sfinfo.samples*2*numChannels)), 0); totalBytesRead += bytesInput; // call the actual encoding routine bytesWritten = faacEncEncode(hEncoder, pcmbuf, bytesInput/2, bitbuf, BITBUFSIZE); switch (m_eCurrentWorkingState) { case eRunning: { // just report our current state and process waiting window messages WriteProgress(lStartTimeMillis, (sfinfo.samples*2*numChannels), totalBytesRead); 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 (!bytesInput && !bytesWritten) { // all done, bail out break; } if (bytesWritten < 0) { AfxMessageBox("faacEncEncodeFrame failed!", MB_OK | MB_ICONSTOP); bInterrupted=true; break; } WriteFile(hOutfile, bitbuf, bytesWritten, &numberOfBytesWritten, NULL); } CloseHandle(hOutfile); if (pcmbuf) free(pcmbuf); if (bitbuf) free(bitbuf); } faacEncClose(hEncoder); } sf_close(infile); MessageBeep(1); } 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; } } } CArchive* CEncoderJobProcessingManager::GetOutputFileArchive(const CString &oFileName) { return 0; }