ref: 1368f4dad39f86ee1183d8d6227eb04e9ac1dd2d
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: { m_poInfoTarget->SetAvailableActions(true, false); 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; // TEMP: added to make it work, these values need to be used unsigned long inputSamples, maxOutputSize; // 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 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; } #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; } } }