#define MAKE_MEDIA_PATH(pFileName) (TEXT("C:\\LEADTOOLS 17.5\\Media\\")TEXT(pFileName)) // include the LEAD Multimedia TOOLKIT header #include "ltmm.h" #include "resource.h" #include <tchar.h> #include <stdio.h> #include <assert.h> HINSTANCE g_hInstance; // application instance handle IltmmConvert* g_pConvert; // convert object's interface pointer // user defined message id used for conversion events #define WM_CONVERTNOTIFY (WM_USER + 1000) // // ConvertDlgProc // starts the conversion process and provides status feedback // // controls: // IDC_CONVERTSTATUS - static control used for status messages // IDC_CONVERTPROGRESS - static control used for conversion progress // IDC_USERABORT - button control used to abort the conversion or exit the dialog BOOL CALLBACK ConvertDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { TCHAR sz[256]; HRESULT hr; long state; switch (msg) { case WM_INITDIALOG: // assign the notification window g_pConvert->SetNotifyWindow((long) hwnd, WM_CONVERTNOTIFY); // set the abort button text SetDlgItemText(hwnd, IDC_USERABORT, _T("Abort")); // start the conversion hr = g_pConvert->StartConvert(); if(FAILED(hr)) { _stprintf(sz, _T("conversion error 0x%.8X"), lParam); SetDlgItemText(hwnd, IDC_CONVERTSTATUS, sz); UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTSTATUS)); SetDlgItemText(hwnd, IDC_USERABORT, _T("Exit")); MessageBeep(0); } return TRUE; break; case WM_DESTROY: // reset the notification window g_pConvert->SetNotifyWindow((long) NULL, 0); #ifdef _DEBUG { long state, err, pc; TCHAR sz[1024]; // get the current state g_pConvert->get_State(&state); // get the current state g_pConvert->get_ConvertError(&err); // get the amount converted g_pConvert->get_PercentComplete(&pc); _stprintf(sz, _T("state = %d, error = 0x%.8X, complete = %d%%"), state, err, pc); MessageBox(NULL, sz, _T("debug"), MB_OK); } #endif break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_USERABORT: // user abort... stop conversion g_pConvert->get_State(&state); if(state == ltmmConvert_State_Running) g_pConvert->StopConvert(); else { g_pConvert->get_ConvertError((long*) &hr); EndDialog(hwnd, (long)hr); } return TRUE; break; } break; case WM_CONVERTNOTIFY: switch(wParam) { case ltmmConvert_Notify_Started: // indicate conversion has started SetDlgItemText(hwnd, IDC_CONVERTSTATUS, TEXT("Starting conversion")); UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTSTATUS)); break; case ltmmConvert_Notify_Complete: // indicate an conversion complete _stprintf(sz, _T("conversion complete")); SetDlgItemText(hwnd, IDC_CONVERTSTATUS, sz); UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTSTATUS)); SetDlgItemText(hwnd, IDC_USERABORT, _T("Exit")); break; case ltmmConvert_Notify_ErrorAbort: // indicate an error _stprintf(sz, _T("conversion error 0x%.8X"), lParam); SetDlgItemText(hwnd, IDC_CONVERTSTATUS, sz); UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTSTATUS)); SetDlgItemText(hwnd, IDC_USERABORT, _T("Exit")); MessageBeep(0); break; case ltmmConvert_Notify_UserAbort: // indicate user abort _stprintf(sz, _T("conversion aborted\n")); SetDlgItemText(hwnd, IDC_CONVERTSTATUS, sz); UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTSTATUS)); SetDlgItemText(hwnd, IDC_USERABORT, _T("Exit")); MessageBeep(0); break; case ltmmConvert_Notify_Progress: // indicate conversion progress _stprintf(sz, _T("%3d%% complete"), lParam); SetDlgItemText(hwnd, IDC_CONVERTPROGRESS, sz); UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTPROGRESS)); break; } return TRUE; break; } return FALSE; } // // SetAVIRecompression // sets up LEAD video compression, MP3 audio compression, and AVI file output // // hwndParent = parent window for compressor property dialog boxes // HRESULT SetAVIRecompression(HWND hwndParent) { IltmmCompressors* pCompressors; long index; VARIANT_BOOL f; BSTR bstr; // select the LEAD video compressor g_pConvert->get_VideoCompressors(&pCompressors); bstr = SysAllocString(L"@device:sw:{33D9A760-90C8-11D0-BD43-00A0C911CE86}\\LEAD MCMP/MJPEG Codec (2.0)"); pCompressors->Find(bstr, &index); SysFreeString(bstr); if(index < 0) { // compressor isn't registered pCompressors->Release(); return E_FAIL; } pCompressors->put_Selection(index); pCompressors->Release(); // select the MP3 audio video compressor g_pConvert->get_AudioCompressors(&pCompressors); bstr = SysAllocString(L"@device:cm:{33D9A761-90C8-11D0-BD43-00A0C911CE86}\\85MPEG Layer-3"); pCompressors->Find(bstr, &index); SysFreeString(bstr); if(index < 0) { // compressor isn't registered pCompressors->Release(); return E_FAIL; } pCompressors->put_Selection(index); pCompressors->Release(); // set output format to AVI g_pConvert->put_TargetFormat(ltmmConvert_TargetFormat_Avi); // set video compressor properties g_pConvert->HasDialog(ltmmConvert_Dlg_VideoCompressor, &f); if(f) g_pConvert->ShowDialog(ltmmConvert_Dlg_VideoCompressor, (long) hwndParent); // set audio compressor properties g_pConvert->HasDialog(ltmmConvert_Dlg_AudioCompressor, &f); if(f) g_pConvert->ShowDialog(ltmmConvert_Dlg_AudioCompressor, (long) hwndParent); return S_OK; } // // RecompressMemory // recompresses from global memory to a file using the LEAD video and MP3 audio compressors // // 1. the source file is preloaded into memory object // 2. the source memory is recompressed to the target file // // pszSource = source file path // pszTarget = target file path // HRESULT RecompressMemory(LPCTSTR pszSource, LPCTSTR pszTarget) { HRESULT hr; HANDLE hfile; DWORD size, dwRead; VARIANT var; IltmmMemory *pMemSource = NULL, *pMemTarget = NULL; #ifndef _UNICODE WCHAR wsz[MAX_PATH]; #endif // open the source file hfile = CreateFile(pszSource, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(hfile == INVALID_HANDLE_VALUE) return E_FAIL; // allocate same-sized buffer size = GetFileSize(hfile, NULL); // create the source memory object hr = CoCreateInstance(CLSID_ltmmMemory, NULL, CLSCTX_ALL, IID_IltmmMemory, (void**) &pMemSource); if (FAILED(hr)) { AfxMessageBox(TEXT("Error allocating source memory object. Conversion aborted.")); goto error; } hr = pMemSource->put_BufferSize(size); if (FAILED(hr)) goto error; VariantInit(&var); pMemSource->LockBuffer(&var); // read the source file contents ReadFile(hfile, var.parray->pvData, size, &dwRead, NULL); pMemSource->Unlock(); VariantClear(&var); CloseHandle(hfile); hfile = NULL; // assign the source object hr = g_pConvert->put_SourceStream(pMemSource); if(FAILED(hr)) goto error; // create the target memory stream hr = CoCreateInstance(CLSID_ltmmMemory, NULL, CLSCTX_ALL, IID_IltmmMemory, (void**)&pMemTarget); if (FAILED(hr)) { AfxMessageBox(TEXT("Error allocating target memory object. Conversion aborted.")); goto error; } // set target stream hr = g_pConvert->put_TargetStream(pMemTarget); if (FAILED(hr)) goto error; // setup AVI recompression hr = SetAVIRecompression(NULL); if (FAILED(hr)) goto error; // do conversion hr = (HRESULT)DialogBox(g_hInstance, (LPCTSTR)IDD_CONVERTDLG, NULL, ConvertDlgProc); if (FAILED(hr)) goto error; // write the data to a file hfile = CreateFile(pszTarget, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); long fl = 0; unsigned long lBytesWritten; IltmmMemory *pTarget = NULL; VARIANT varData; unsigned char *pBuffer = NULL; SAFEARRAY sa; hr = g_pConvert->get_TargetStream((IUnknown**)&pTarget); if (FAILED(hr)) goto error; pTarget->get_BufferSize(&fl); VariantInit(&varData); // pass data memset(&sa, 0, sizeof(sa)); sa.cbElements = sizeof(unsigned char); sa.cDims = 1; sa.fFeatures = (FADF_AUTO | FADF_FIXEDSIZE); sa.pvData = new UCHAR[fl]; sa.rgsabound[0].cElements = fl; V_VT(&varData) = (VT_ARRAY | VT_UI1); V_ARRAY(&varData) = &sa; // // To lock the buffer for synchronization, use the following // line instead of the line below : // pTarget->LockBuffer(&varData); // or // pTarget->LockRegion(0, fl, &varData); // You may also use the GetData() function // To get the data without allocating a SAFEARRAY : // pTarget->GetData(0, fl, &varData); // pTarget->CopyData(0, fl, &varData); SafeArrayAccessData(V_ARRAY(&varData), (void**)&pBuffer); // to manipulate the buffer bytes directly without a buffer pointer // use the SetByte method, for example to change the first two // bytes in the buffer : // pTarget->SetByte(0, 0x10); // pTarget->SetByte(1, 0x13); WriteFile(hfile, pBuffer, fl, &lBytesWritten, NULL); // if LockBuffer() or LockRegion() is used, Unloack() must be called : // g_pTarget->Unlock(); SafeArrayUnaccessData(V_ARRAY(&varData)); VariantClear(&varData); CloseHandle(hfile); hfile = NULL; pTarget->Release(); error: g_pConvert->ResetSource(); g_pConvert->ResetTarget(); if(pMemSource) pMemSource->Release(); if(pMemTarget) pMemTarget->Release(); if (hfile) CloseHandle(hfile); return hr; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HRESULT hr; g_hInstance = hInstance; // initialize COM library hr = CoInitialize(NULL); if(FAILED(hr)) goto error; // create the convert object hr = CoCreateInstance(CLSID_ltmmConvert, NULL, CLSCTX_INPROC_SERVER, IID_IltmmConvert, (void**) &g_pConvert); if(FAILED(hr)) goto error; hr = RecompressMemory(MAKE_MEDIA_PATH("source.avi"), MAKE_MEDIA_PATH("target.avi")); if(FAILED(hr)) goto error; error: // cleanup if (g_pConvert) g_pConvert->Release(); CoUninitialize(); return 0; }