home *** CD-ROM | disk | FTP | other *** search
- //
- // lococodec v0.1 based on:
- //
- // Huffyuv v2.1.1, by Ben Rudiak-Gould.
- // http://www.math.berkeley.edu/~benrg/huffyuv.html
- //
- // Based on MSYUV sample code, which is:
- // Copyright (c) 1993 Microsoft Corporation.
- // All Rights Reserved.
- //
- // Changes copyright 2000 Ben Rudiak-Gould, and distributed under
- // the terms of the GNU General Public License, v2 or later. See
- // http://www.gnu.org/copyleft/gpl.html.
- //
- // I edit these files in 10-point Verdana, a proportionally-spaced font.
- // You may notice formatting oddities if you use a monospaced font.
- //
-
-
- extern "C" {
- #include "loco.h"
- }
-
- #include "lococodec.h"
- #include "lococodec_a.h"
- #include "resource.h"
-
- #include <crtdbg.h>
-
- #include <stdio.h>
-
- #include <commctrl.h>
-
- TCHAR szDescription[] = TEXT("LOCO Codec Version 0.2"); // Moh
- TCHAR szName[] = TEXT("lococodec");
-
- #define VERSION 0x00000002 // 0.2; version number changes when file format changes
-
-
- /********************************************************************
- ********************************************************************/
-
- // these tables are generated at runtime from the data in tables.cpp
-
-
- CodecInst *encode_table_owner, *decode_table_owner;
-
- /********************************************************************
- ********************************************************************/
-
- void Msg(const char fmt[], ...) {
- static int debug = GetPrivateProfileInt("debug", "log", 0, INI_FILE);
- if (!debug) return;
-
- DWORD written;
- char buf[2000];
- va_list val;
-
- va_start(val, fmt);
- wvsprintf(buf, fmt, val);
-
- const COORD _80x50 = {80,5000};
- static BOOL startup = (AllocConsole(), SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), _80x50));
- WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), buf, lstrlen(buf), &written, 0);
- }
-
-
- int AppFlags() {
- static int flags = -1;
- if (flags < 0) {
- flags = 0;
- TCHAR apppath[MAX_PATH];
- if (GetModuleFileName(NULL, apppath, MAX_PATH)) {
- TCHAR* appname = strrchr(apppath, '\\');
- appname = appname ? appname+1 : apppath;
- Msg("App name is %s; ", appname);
- if (!lstrcmpi(appname, TEXT("premiere.exe")))
- flags = 1;
- if (!lstrcmpi(appname, TEXT("veditor.exe")))
- flags = 1;
- if (!lstrcmpi(appname, TEXT("avi2mpg2_vfw.exe")))
- flags = 1;
- if (!lstrcmpi(appname, TEXT("bink.exe")))
- flags = 1;
- if (!lstrcmpi(appname, TEXT("afterfx.exe")))
- flags = 2;
- // new flag for ccesp/ccesp trial for buggy YUY2 handling - bastel
- if (!lstrcmpi(appname, TEXT("cctsp.exe")) || !lstrcmpi(appname, TEXT("cctspt.exe")))
- flags = 4;
- Msg("flags=%d\n", flags);
- }
- }
- return flags;
- }
-
- bool SuggestRGB() {
- return !!GetPrivateProfileInt("debug", "rgboutput", AppFlags()&1, INI_FILE);
- }
-
- bool AllowRGBA() {
- return !!GetPrivateProfileInt("general", "enable_rgba", AppFlags()&2, INI_FILE);
- }
-
- // ignore top-down (i.e. negative height) - bastel
- bool IgnoreTopDown() {
- return !!GetPrivateProfileInt("debug", "ignore_topdown", AppFlags()&4, INI_FILE);
- }
-
-
- /********************************************************************
- ********************************************************************/
-
- CodecInst* Open(ICOPEN* icinfo) {
- if (icinfo && icinfo->fccType != ICTYPE_VIDEO)
- return NULL;
-
- CodecInst* pinst = new CodecInst();
-
- if (icinfo) icinfo->dwError = pinst ? ICERR_OK : ICERR_MEMORY;
-
- return pinst;
- }
-
- DWORD Close(CodecInst* pinst) {
- // delete pinst; // this caused problems when deleting at app close time
- return 1;
- }
-
- /********************************************************************
- ********************************************************************/
-
- enum {
- methodAsRGB=0,
- methodConvertToYUY2=-1
- };
-
- static inline int GetLocoOutputType(LPBITMAPINFOHEADER lpbi) {
- if (lpbi->biCompression == FOURCC_LOCO && lpbi->biSize > sizeof(BITMAPINFOHEADER)+sizeof(int)*1) {
- int output_type = *((int*)((char*)lpbi + sizeof(BITMAPINFOHEADER) + sizeof(int)*1));
- if (output_type)
- return output_type;
- }
- return 0;
- }
-
- static inline int GetBitCount(LPBITMAPINFOHEADER lpbi) {
- return lpbi->biBitCount;
- }
-
- struct MethodName { int method; const char* name; };
-
- MethodName rgb_method_names[] = {
- { methodAsRGB, "As RGB (not recommended)" },
- { methodConvertToYUY2, "Convert to YUY2" }
- };
-
- MethodName max_losses[] = {
- { 0, "0" },
- { 1, "1" },
- { 2, "2" },
- { 3, "3" },
- { 4, "4" },
- { 5, "5" }
- };
-
- struct { UINT item; UINT tip; } item2tip[] = {
- { IDC_RGBMETHOD, IDS_TIP_METHOD_RGB },
- { IDC_IS_INTERLACED, IDS_TIP_SOURCE_IS_INTERLACED },
- { IDC_RGBOUTPUT, IDS_TIP_RGB_ONLY },
- { IDC_RGBA, IDS_TIP_RGBA_COMPR },
- { IDC_SWAPFIELDS, IDS_TIP_SWAPFIELDS },
- { IDC_LOG, IDS_TIP_LOG },
- { IDC_FULL_SIZE_BUFFER, IDS_TIP_FULL_SIZE_BUFFER},
- { IDC_MAX_LOSS, IDS_TIP_MAX_LOSS},
- { 0,0 }
- };
-
-
-
- /********************************************************************
- ********************************************************************/
-
- BOOL CodecInst::QueryAbout() { return TRUE; }
-
- BOOL CodecInst::QueryConfigure() { return TRUE; }
-
- static BOOL CALLBACK AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- if (uMsg == WM_COMMAND) {
- switch (LOWORD(wParam)) {
- case IDOK:
- EndDialog(hwndDlg, 0);
- break;
- case IDC_HOMEPAGE:
- ShellExecute(NULL, NULL, "http://www.math.berkeley.edu/~benrg/huffyuv.html", NULL, NULL, SW_SHOW);
- break;
- case IDC_EMAIL:
- ShellExecute(NULL, NULL, "mailto:mrezaei@sourceforge.net", NULL, NULL, SW_SHOW);
- break;
- }
- }
- return FALSE;
- }
-
-
- // add a tooltip to a tooltip control, might be buggy, though - bastel
- int AddTooltip(HWND tooltip, HWND client, UINT stringid)
- {
- HINSTANCE ghThisInstance=(HINSTANCE)GetWindowLong(client, GWL_HINSTANCE);
-
- TOOLINFO ti; // struct specifying info about tool in tooltip control
- static unsigned int uid = 0; // for ti initialization
- RECT rect; // for client area coordinates
- TCHAR buf[2000]; // a static buffer is sufficent, TTM_ADDTOOL seems to copy it
-
- // load the string manually, passing the id directly to TTM_ADDTOOL truncates the message :(
- if ( !LoadString(ghThisInstance, stringid, buf, 2000) ) return -1;
-
- // get coordinates of the main client area
- GetClientRect(client, &rect);
-
- // initialize members of the toolinfo structure
- ti.cbSize = sizeof(TOOLINFO);
- ti.uFlags = TTF_SUBCLASS;
- ti.hwnd = client;
- ti.hinst = ghThisInstance; // not necessary if lpszText is not a resource id
- ti.uId = uid;
- ti.lpszText = buf;
-
- // Tooltip control will cover the whole window
- ti.rect.left = rect.left;
- ti.rect.top = rect.top;
- ti.rect.right = rect.right;
- ti.rect.bottom = rect.bottom;
-
- // send a addtool message to the tooltip control window
- SendMessage(tooltip, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
- return uid++;
- }
-
- // create a tooltip control over the entire window area - bastel
- HWND CreateTooltip(HWND hwnd)
- {
- // initialize common controls
- INITCOMMONCONTROLSEX iccex; // struct specifying control classes to register
- iccex.dwICC = ICC_WIN95_CLASSES;
- iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
- InitCommonControlsEx(&iccex);
-
-
- HINSTANCE ghThisInstance=(HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
- HWND hwndTT; // handle to the tooltip control
-
- // create a tooltip window
- hwndTT = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
- hwnd, NULL, ghThisInstance, NULL);
-
- SetWindowPos(hwndTT, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
-
- // set some timeouts so tooltips appear fast and stay long (32767 seems to be a limit here)
- SendMessage(hwndTT, TTM_SETDELAYTIME, (WPARAM)(DWORD)TTDT_INITIAL, (LPARAM)10);
- SendMessage(hwndTT, TTM_SETDELAYTIME, (WPARAM)(DWORD)TTDT_AUTOPOP, (LPARAM)30*1000);
-
- return hwndTT;
- }
-
-
- static BOOL CALLBACK ConfigureDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
- if (uMsg == WM_INITDIALOG) {
-
-
- HWND hctlRGBMethod = GetDlgItem(hwndDlg, IDC_RGBMETHOD);
- int rgbmethod = GetPrivateProfileInt("general", "rgbmethod", methodConvertToYUY2, INI_FILE);
- for (int j = 0; j < sizeof(rgb_method_names)/sizeof(rgb_method_names[0]); ++j) {
- SendMessage(hctlRGBMethod, CB_ADDSTRING, 0, (LPARAM)rgb_method_names[j].name);
- if (rgb_method_names[j].method == rgbmethod)
- SendMessage(hctlRGBMethod, CB_SETCURSEL, j, 0);
- }
-
- HWND hctlMaxLoss = GetDlgItem(hwndDlg, IDC_MAX_LOSS);
- int maxLoss = GetPrivateProfileInt("general", "max_loss", 0, INI_FILE);
- char temp[12] = {0};
- bool dupe = false;
- int k;
-
- _snprintf(temp, 11, "%d", maxLoss);
- SendMessage(hctlMaxLoss, CB_LIMITTEXT, 11, 0);
- for (k = 0; k < sizeof(max_losses)/sizeof(max_losses[0]); k++) {
- SendMessage(hctlMaxLoss, CB_ADDSTRING, 0, (LPARAM)max_losses[k].name);
- if ( max_losses[k].method==maxLoss ) dupe=true;
- }
- if ( !dupe) SendMessage(hctlMaxLoss, CB_ADDSTRING, 0, (LPARAM)temp);
- SendMessage(hctlMaxLoss, CB_SETCURSEL, SendMessage(hctlMaxLoss, CB_FINDSTRINGEXACT, -1, (LPARAM)temp), 0);
-
-
- CheckDlgButton(hwndDlg, IDC_IS_INTERLACED,
- GetPrivateProfileInt("general", "source_interlaced", false, INI_FILE) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_RGBOUTPUT,
- GetPrivateProfileInt("debug", "rgboutput", false, INI_FILE) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_RGBA,
- GetPrivateProfileInt("general", "enable_rgba", false, INI_FILE) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_SWAPFIELDS,
- GetPrivateProfileInt("debug", "decomp_swap_fields", false, INI_FILE) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_LOG,
- GetPrivateProfileInt("debug", "log", false, INI_FILE) ? BST_CHECKED : BST_UNCHECKED);
- CheckDlgButton(hwndDlg, IDC_FULL_SIZE_BUFFER,
- GetPrivateProfileInt("debug", "full_size_buffer", FULL_SIZE_BUFFER, INI_FILE) ? BST_CHECKED : BST_UNCHECKED);
-
-
- // create a tooltip window and add tooltips - bastel
- HWND hwndTip = CreateTooltip(hwndDlg);
- for (int l=0; item2tip[l].item; l++ )
- AddTooltip(hwndTip, GetDlgItem(hwndDlg, item2tip[l].item), item2tip[l].tip);
- SendMessage(hwndTip, TTM_SETMAXTIPWIDTH, 0, (LPARAM)(INT)350); // ah well this is totally wrong but works
- }
-
- else if (uMsg == WM_COMMAND) {
-
- switch (LOWORD(wParam)) {
-
- case IDOK:
- {
- char methodstring[4];
- wsprintf(methodstring, "%d",
- rgb_method_names[SendMessage(GetDlgItem(hwndDlg, IDC_RGBMETHOD), CB_GETCURSEL, 0, 0)].method);
- WritePrivateProfileString("general", "rgbmethod", methodstring, INI_FILE);
- }
- WritePrivateProfileString("general", "source_interlaced",
- (IsDlgButtonChecked(hwndDlg, IDC_IS_INTERLACED) == BST_CHECKED) ? "1" : "0", INI_FILE);
- WritePrivateProfileString("debug", "rgboutput",
- (IsDlgButtonChecked(hwndDlg, IDC_RGBOUTPUT) == BST_CHECKED) ? "1" : NULL, INI_FILE);
- WritePrivateProfileString("general", "enable_rgba",
- (IsDlgButtonChecked(hwndDlg, IDC_RGBA) == BST_CHECKED) ? "1" : NULL, INI_FILE);
- WritePrivateProfileString("debug", "decomp_swap_fields",
- (IsDlgButtonChecked(hwndDlg, IDC_SWAPFIELDS) == BST_CHECKED) ? "1" : "0", INI_FILE);
- WritePrivateProfileString("debug", "log",
- (IsDlgButtonChecked(hwndDlg, IDC_LOG) == BST_CHECKED) ? "1" : "0", INI_FILE);
- WritePrivateProfileString("debug", "full_size_buffer",
- (IsDlgButtonChecked(hwndDlg, IDC_FULL_SIZE_BUFFER) == BST_CHECKED) ? "1" : "0", INI_FILE);
-
-
- // write max loss setting. accept only if numeric and 0 < ft <= 100
- {
- char temp[12]= {0};
- char* endp = 0;
- SendMessage(GetDlgItem(hwndDlg, IDC_MAX_LOSS), WM_GETTEXT, 11, (LPARAM)temp);
- int max_loss = strtoul(temp, &endp, 10);
- if ( strchr(" \t\r\n", *endp) && max_loss>=0 && max_loss<=100 ) {
- // could pass old temp, but this way whitespace is removed
- _snprintf(temp, 11, "%d", max_loss);
- WritePrivateProfileString("general", "max_loss", temp, INI_FILE);
- }
- }
-
- case IDCANCEL:
- EndDialog(hwndDlg, 0);
- break;
-
- default:
- return AboutDialogProc(hwndDlg, uMsg, wParam, lParam); // handle email and home-page buttons
- }
- }
- return FALSE;
- }
-
- DWORD CodecInst::About(HWND hwnd) {
- DialogBox(hmoduleLocoCodec, MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDialogProc);
- return ICERR_OK;
- }
-
- DWORD CodecInst::Configure(HWND hwnd) {
- DialogBox(hmoduleLocoCodec, MAKEINTRESOURCE(IDD_CONFIGURE), hwnd, ConfigureDialogProc);
- return ICERR_OK;
- }
-
-
-
- /********************************************************************
- ********************************************************************/
-
-
- // we have no state information which needs to be stored
-
- DWORD CodecInst::GetState(LPVOID pv, DWORD dwSize) { return 0; }
-
- DWORD CodecInst::SetState(LPVOID pv, DWORD dwSize) { return 0; }
-
-
- DWORD CodecInst::GetInfo(ICINFO* icinfo, DWORD dwSize) {
- if (icinfo == NULL)
- return sizeof(ICINFO);
-
- if (dwSize < sizeof(ICINFO))
- return 0;
-
- icinfo->dwSize = sizeof(ICINFO);
- icinfo->fccType = ICTYPE_VIDEO;
- icinfo->fccHandler = FOURCC_LOCO;
- icinfo->dwFlags = 0;
-
- icinfo->dwVersion = VERSION;
- icinfo->dwVersionICM = ICVERSION;
- MultiByteToWideChar(CP_ACP, 0, szDescription, -1, icinfo->szDescription, sizeof(icinfo->szDescription)/sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, szName, -1, icinfo->szName, sizeof(icinfo->szName)/sizeof(WCHAR));
-
- return sizeof(ICINFO);
- }
-
-
- /********************************************************************
- ********************************************************************/
-
-
- struct PrintBitmapType {
- char s[32];
- PrintBitmapType(LPBITMAPINFOHEADER lpbi) {
- if (!lpbi)
- strcpy(s, "(null)");
- else {
- *(DWORD*)s = lpbi->biCompression;
- s[4] = 0;
- if (!isalnum(s[0]) || !isalnum(s[1]) || !isalnum(s[2]) || !isalnum(s[3]))
- wsprintfA(s, "%x", lpbi->biCompression);
- wsprintfA(strchr(s, 0), ", %d bits", GetBitCount(lpbi));
- if (lpbi->biCompression == FOURCC_LOCO && GetLocoOutputType(lpbi))
- wsprintfA(strchr(s, 0), ", output_type %d", GetLocoOutputType(lpbi));
- }
- }
- };
-
-
- // fast clipping of values to unsigned char range
-
- static unsigned char clip[896];
-
- static void InitClip() {
- memset(clip, 0, 320);
- for (int i=0; i<256; ++i) clip[i+320] = i;
- memset(clip+320+256, 255, 320);
- }
-
- static inline unsigned char Clip(int x)
- { return clip[320 + ((x+0x8000) >> 16)]; }
-
-
- /********************************************************************
- ********************************************************************/
-
-
-
- // 0=unknown, -1=compressed YUY2, -2=compressed RGB, -3=compressed RGBA, 1=YUY2, 2=UYVY, 3=RGB 24-bit, 4=RGB 32-bit
- static int GetBitmapType(LPBITMAPINFOHEADER lpbi) {
- if (!lpbi)
- return BITMAP_TYPE_UNKNOWN;
- const int fourcc = lpbi->biCompression;
- if (fourcc == FOURCC_VYUY || fourcc == FOURCC_YUY2)
- return BITMAP_TYPE_YUY2;
- if (fourcc == FOURCC_UYVY)
- return BITMAP_TYPE_UYVY;
- if (fourcc == FOURCC_YV12)
- return BITMAP_TYPE_YV12;
- const int bitcount = GetBitCount(lpbi);
- if (fourcc == 0 || fourcc == ' BID')
- return (bitcount == 24) ? BITMAP_TYPE_RGB : (bitcount == 32) ? BITMAP_TYPE_RGBA : 0;
- if (fourcc == FOURCC_LOCO)
- {
- return GetLocoOutputType(lpbi);
- }
- return 0;
- }
-
-
- static bool CanCompress(LPBITMAPINFOHEADER lpbiIn) {
- int intype = GetBitmapType(lpbiIn);
- return (intype == BITMAP_TYPE_YUY2 || intype == BITMAP_TYPE_UYVY
- || intype == BITMAP_TYPE_RGB || intype == BITMAP_TYPE_YV12 || (intype == BITMAP_TYPE_RGBA && AllowRGBA()));
- }
-
-
- static bool CanCompress(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
- if (!lpbiOut) return CanCompress(lpbiIn);
-
- int intype = GetBitmapType(lpbiIn);
- int outtype = GetBitmapType(lpbiOut);
-
- switch (intype) {
- case BITMAP_TYPE_YUY2: case BITMAP_TYPE_UYVY:
- return (outtype == BITMAP_TYPE_COMPRESSED_YUY2);
- case BITMAP_TYPE_RGB:
- return (outtype == BITMAP_TYPE_YUY2 || outtype == BITMAP_TYPE_COMPRESSED_YUY2
- || outtype == BITMAP_TYPE_COMPRESSED_RGB);
- case BITMAP_TYPE_RGBA:
- return (outtype == BITMAP_TYPE_COMPRESSED_RGBA && AllowRGBA());
- case BITMAP_TYPE_YV12:
- return (outtype == BITMAP_TYPE_COMPRESSED_YV12);
- default:
- return false;
- }
- }
-
-
- /********************************************************************
- ********************************************************************/
-
-
-
- #define HUFFTABLE_CLASSIC_YUV ((const unsigned char*)-1)
- #define HUFFTABLE_CLASSIC_RGB ((const unsigned char*)-2)
- #define HUFFTABLE_CLASSIC_YUV_CHROMA ((const unsigned char*)-3)
-
-
-
- DWORD CodecInst::CompressQuery(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
- Msg("CompressQuery: input = %s, output = %s\n", &PrintBitmapType(lpbiIn), &PrintBitmapType(lpbiOut));
- return CanCompress(lpbiIn, lpbiOut) ? ICERR_OK : ICERR_BADFORMAT;
- }
-
- #define EXTRA_INFO_SIZE sizeof(int)*4
- #define EXTRA_INFO_VERSION 2
-
- DWORD CodecInst::CompressGetFormat(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
- if (!CanCompress(lpbiIn))
- return ICERR_BADFORMAT;
-
- int intype = GetBitmapType(lpbiIn);
-
- bool compress_as_yuy2 = (intype == BITMAP_TYPE_YUY2 || intype == BITMAP_TYPE_UYVY);
- int output_type = 0;
- if (!compress_as_yuy2 && (intype == BITMAP_TYPE_RGB || intype == BITMAP_TYPE_RGBA)) {
- int method = GetPrivateProfileInt("general", "rgbmethod", methodConvertToYUY2, INI_FILE);
- if (method==methodConvertToYUY2)
- {
- compress_as_yuy2 = true;
- }
- else
- {
- if (intype == BITMAP_TYPE_RGB) output_type = BITMAP_TYPE_COMPRESSED_RGB;
- if (intype == BITMAP_TYPE_RGBA) output_type = BITMAP_TYPE_COMPRESSED_RGBA;
- }
- }
-
- if (compress_as_yuy2)
- output_type = BITMAP_TYPE_COMPRESSED_YUY2;
- if (intype == BITMAP_TYPE_YV12) output_type = BITMAP_TYPE_COMPRESSED_YV12;
-
- int total_size = sizeof(BITMAPINFOHEADER)+EXTRA_INFO_SIZE;
- if (!lpbiOut)
- return total_size;
-
- int real_bit_count = (intype==BITMAP_TYPE_RGBA) ? 32 : (compress_as_yuy2 || intype == BITMAP_TYPE_YV12) ? 16 : 24;
- max_loss = GetPrivateProfileInt("general", "max_loss", 0, INI_FILE);
- source_interlaced = GetPrivateProfileInt("general", "source_interlaced", 0, INI_FILE) == 1 ? true : false;
-
- *lpbiOut = *lpbiIn;
- lpbiOut->biSize = total_size;
- lpbiOut->biCompression = FOURCC_LOCO;
- lpbiOut->biClrImportant = lpbiOut->biClrUsed = 0;
- lpbiOut->biPlanes = 1;
- lpbiOut->biBitCount = max(24, real_bit_count);
- int* extra_data = (int*)((unsigned char*)lpbiOut + sizeof(BITMAPINFOHEADER));
- extra_data[0] = EXTRA_INFO_VERSION;
- extra_data[1] = output_type;
- extra_data[2] = max_loss;
- extra_data[3] = source_interlaced ? 1 : 0;
- return ICERR_OK;
- }
-
-
- const unsigned char* GetEmbeddedHuffmanTable(LPBITMAPINFOHEADER lpbi) {
- if (lpbi->biSize == sizeof(BITMAPINFOHEADER) && !(lpbi->biBitCount&7))
- return lpbi->biBitCount>=24 ? HUFFTABLE_CLASSIC_RGB : HUFFTABLE_CLASSIC_YUV;
- else
- return (const unsigned char*)lpbi + sizeof(BITMAPINFOHEADER) + ((lpbi->biBitCount&7) ? 0 : 4);
- }
-
-
- DWORD CodecInst::CompressBegin(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
- Msg("CompressBegin: input = %s, output = %s\n", &PrintBitmapType(lpbiIn), &PrintBitmapType(lpbiOut));
-
- if (!CanCompress(lpbiIn, lpbiOut))
- return ICERR_BADFORMAT;
-
- CompressEnd(); // free resources if necessary
-
- int intype = GetBitmapType(lpbiIn);
- int outtype = GetLocoOutputType(lpbiOut);
-
- // load field threshold - bastel
- source_interlaced = GetPrivateProfileInt("general", "source_interlaced", 0, INI_FILE) == 1 ? true : false;
- max_loss = GetPrivateProfileInt("general", "max_loss", 0, INI_FILE);
- Msg("CompressBegin: source interlaced %s\n",
- source_interlaced ? "yes" : "no");
-
- // allocate buffer if compressing RGB->YUY2->HFYU
- if (outtype == BITMAP_TYPE_COMPRESSED_YUY2 && intype == BITMAP_TYPE_RGB)
- yuy2_buffer = new unsigned char[lpbiIn->biWidth * lpbiIn->biHeight * 2 + 4];
-
- InitClip();
-
- return ICERR_OK;
- }
-
- DWORD CodecInst::CompressGetSize(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
- // Assume 24 bpp worst-case for YUY2 input, 40 bpp for RGB.
- // The actual worst case is 43/51 bpp currently, but this is exceedingly improbable
- // (probably impossible with real captured video)
- // bastel: never say impossible. try to capture static noise with the original huffyuv and be surprised.
- // virtualdub has a workaround for it. avi_io not. anyway, i don't think it slows down processing.
- // if you think it does you can still enable the old behaviour. full buffer costs memory, though :)
- int fullsize = GetPrivateProfileInt("debug", "full_size_buffer", FULL_SIZE_BUFFER, INI_FILE);
- return fullsize ? ((lpbiIn->biWidth * lpbiIn->biHeight * ((GetBitmapType(lpbiIn) <= 2) ? 43 : 51)) + 7) / 8
- : lpbiIn->biWidth * lpbiIn->biHeight * ((GetBitmapType(lpbiIn) <= 2) ? 3 : 5);
- }
-
-
- template<typename T> static inline T* Align8(T* ptr) { return (T*)((unsigned(ptr)+7)&~7); }
-
-
- DWORD CodecInst::Compress(ICCOMPRESS* icinfo, DWORD dwSize) {
-
- if (icinfo->lpckid)
- *icinfo->lpckid = FOURCC_LOCO;
- *icinfo->lpdwFlags = AVIIF_KEYFRAME;
-
- int intype = GetBitmapType(icinfo->lpbiInput);
- int outtype = GetLocoOutputType(icinfo->lpbiOutput);
-
- if (outtype < 0) { // compressing (as opposed to converting RGB->YUY2)
-
-
- unsigned char* in = (unsigned char*)icinfo->lpInput;
- unsigned long* out = (unsigned long*)icinfo->lpOutput;
-
- unsigned long* out_end = out;
-
- if (outtype == BITMAP_TYPE_COMPRESSED_YUY2) { // compressing to LOCOYUY2 (4:2:2 YUV)
- int rowsize = icinfo->lpbiInput->biWidth * 2;
- int yStep = 1;
- #ifdef LATER
- if (icinfo->lpbiInput->biHeight > field_threshold) yStep = 2; // if image is interlaced, double stride so fields are treated separately
- #endif
- unsigned char* yuy2in = in;
-
- if (intype == BITMAP_TYPE_RGB) { // RGB24->YUY2->LOCOYUY2
- ConvertRGB24toYUY2(in, yuy2_buffer, icinfo->lpbiInput->biWidth, icinfo->lpbiInput->biHeight);
- yuy2in = yuy2_buffer;
- }
- if (intype==BITMAP_TYPE_UYVY) { // UYVY->LOCOYUY2
-
- // first Y
- out_end = (unsigned long *)loco_codec_compress_lossy(yuy2in, (unsigned char *)out_end, icinfo->lpbiInput->biHeight, rowsize,
- 1, 2, 0, yStep, max_loss);
- // then U:
- out_end = (unsigned long *)loco_codec_compress_lossy(yuy2in, (unsigned char *)out_end, icinfo->lpbiInput->biHeight, rowsize,
- 0, 4, 0, yStep, max_loss);
- // then V:
- out_end = (unsigned long *)loco_codec_compress_lossy(yuy2in, (unsigned char *)out_end, icinfo->lpbiInput->biHeight, rowsize,
- 2, 4, 0, yStep, max_loss);
-
- } else { // YUY2->HFYU16
- // first Y
- out_end = (unsigned long *)loco_codec_compress_lossy(yuy2in, (unsigned char *)out_end, icinfo->lpbiInput->biHeight, rowsize,
- 0, 2, 0, yStep, max_loss);
- // then U:
- out_end = (unsigned long *)loco_codec_compress_lossy(yuy2in, (unsigned char *)out_end, icinfo->lpbiInput->biHeight, rowsize,
- 1, 4, 0, yStep, max_loss);
- // then V:
- out_end = (unsigned long *)loco_codec_compress_lossy(yuy2in, (unsigned char *)out_end, icinfo->lpbiInput->biHeight, rowsize,
- 3, 4, 0, yStep, max_loss);
-
- }
- }
- else if (outtype == BITMAP_TYPE_COMPRESSED_YV12) // compressing to LOCO YV12
- {
- int rowsize = icinfo->lpbiInput->biWidth;
- int yStep = 1;
- unsigned long* out_temp;
- // Y:
- out_end = (unsigned long *)loco_codec_compress(in, (unsigned char *)out_end,
- icinfo->lpbiInput->biHeight, rowsize, 0, 1, 0, yStep);
- out_temp = out_end;
- rowsize = icinfo->lpbiInput->biWidth >> 1;
- // V:
- in += icinfo->lpbiInput->biHeight*icinfo->lpbiInput->biWidth;
- out_end = (unsigned long *)loco_codec_compress(in,
- (unsigned char *)out_end, icinfo->lpbiInput->biHeight >> 1, rowsize, 0, 1, 0, yStep);
- // U:
- in += (icinfo->lpbiInput->biHeight*icinfo->lpbiInput->biWidth) >> 2;
- out_end = (unsigned long *)loco_codec_compress(in,
- (unsigned char *)out_end, icinfo->lpbiInput->biHeight >> 1, rowsize, 0, 1, 0, yStep);
- }
- else if (outtype == BITMAP_TYPE_COMPRESSED_RGB) { // compressing to LOCO RGB24
- int xStep = 3;
- int rowsize = icinfo->lpbiInput->biWidth * xStep;
- int size = rowsize * icinfo->lpbiInput->biHeight;
- int yStep = 1;
- #ifdef LATER
- if (icinfo->lpbiInput->biHeight > field_threshold) stride *= 2; // if image is interlaced, double stride so fields are treated separately
- #endif
-
- out_end = (unsigned long *)loco_codec_compress_lossy(in, (unsigned char *)out_end,
- icinfo->lpbiInput->biHeight, rowsize, 0, xStep, 0, yStep, max_loss);
-
- out_end = (unsigned long *)loco_codec_compress_lossy(in, (unsigned char *)out_end,
- icinfo->lpbiInput->biHeight, rowsize, 1, xStep, 0, yStep, max_loss);
-
- out_end = (unsigned long *)loco_codec_compress_lossy(in, (unsigned char *)out_end,
- icinfo->lpbiInput->biHeight, rowsize, 2, xStep, 0, yStep, max_loss);
-
-
- }
- else if (outtype == BITMAP_TYPE_COMPRESSED_RGBA) { // compressing to LOCO RGBA
- int xStep = 4;
- int rowsize = icinfo->lpbiInput->biWidth * xStep;
- int size = rowsize * icinfo->lpbiInput->biHeight;
- int yStep = 1;
- #ifdef LATER
- if (icinfo->lpbiInput->biHeight > field_threshold) stride *= 2; // if image is interlaced, double stride so fields are treated separately
- #endif
- out_end = (unsigned long *)loco_codec_compress_lossy(in, (unsigned char *)out_end,
- icinfo->lpbiInput->biHeight, rowsize, 0, xStep, 0, yStep, max_loss);
-
- out_end = (unsigned long *)loco_codec_compress_lossy(in, (unsigned char *)out_end,
- icinfo->lpbiInput->biHeight, rowsize, 1, xStep, 0, yStep, max_loss);
-
- out_end = (unsigned long *)loco_codec_compress_lossy(in, (unsigned char *)out_end,
- icinfo->lpbiInput->biHeight, rowsize, 2, xStep, 0, yStep, max_loss);
-
- out_end = (unsigned long *)loco_codec_compress_lossy(in, (unsigned char *)out_end,
- icinfo->lpbiInput->biHeight, rowsize, 3, xStep, 0, yStep, max_loss);
- }
- icinfo->lpbiOutput->biSizeImage = DWORD(out_end) - DWORD(out);
- return ICERR_OK;
- }
- else if (outtype == 1) { // RGB24->YUY2
- ConvertRGB24toYUY2((unsigned char*)icinfo->lpInput, (unsigned char*)icinfo->lpOutput,
- icinfo->lpbiInput->biWidth, icinfo->lpbiInput->biHeight);
- icinfo->lpbiOutput->biSizeImage = (icinfo->lpbiOutput->biWidth * icinfo->lpbiOutput->biHeight * GetBitCount(icinfo->lpbiOutput)) >> 3;
- return ICERR_OK;
- }
- else
- return ICERR_BADFORMAT;
- }
-
-
- void CodecInst::ConvertRGB24toYUY2(const unsigned char* src, unsigned char* dst, int width, int height) {
- const int cyb = int(0.114*219/255*65536+0.5);
- const int cyg = int(0.587*219/255*65536+0.5);
- const int cyr = int(0.299*219/255*65536+0.5);
-
- for (int row = 0; row < height; ++row) {
- const unsigned char* rgb = src + width * 3 * (height-1-row);
- unsigned char* yuv = dst + width * 2 * row;
- for (int col = 0; col < width; col += 2) {
- // y1 and y2 can't overflow
- int y1 = (cyb*rgb[0] + cyg*rgb[1] + cyr*rgb[2] + 0x108000) >> 16;
- yuv[0] = y1;
- int y2 = (cyb*rgb[3] + cyg*rgb[4] + cyr*rgb[5] + 0x108000) >> 16;
- yuv[2] = y2;
- int scaled_y = (y1+y2 - 32) * int(255.0/219.0*32768+0.5);
- int b_y = ((rgb[0]+rgb[3]) << 15) - scaled_y;
- yuv[1] = Clip((b_y >> 10) * int(1/2.018*1024+0.5) + 0x800000); // u
- int r_y = ((rgb[2]+rgb[5]) << 15) - scaled_y;
- yuv[3] = Clip((r_y >> 10) * int(1/1.596*1024+0.5) + 0x800000); // v
- yuv += 4;
- rgb += 6;
- }
- }
- }
-
-
- DWORD CodecInst::CompressEnd() {
- if (yuy2_buffer) {
- delete[] yuy2_buffer;
- yuy2_buffer = 0;
- }
- if (median_buffer) {
- delete[] median_buffer;
- median_buffer = 0;
- }
- if (rgb_buffer) {
- delete[] rgb_buffer;
- rgb_buffer = 0;
- }
- return ICERR_OK;
- }
-
-
- /********************************************************************
- ********************************************************************/
-
- static bool CanDecompress(LPBITMAPINFOHEADER lpbiIn) {
- int intype = GetBitmapType(lpbiIn);
- if (intype < 0) // one of our compressed formats
- return true;
- else
- return (intype == BITMAP_TYPE_YUY2 || intype == BITMAP_TYPE_UYVY);
- }
-
-
- static bool CanDecompress(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
- if (!lpbiOut)
- return CanDecompress(lpbiIn);
-
- // ccesp sets negative output height with YUY2 - a request for a top-down bitmap.
- // but what it really wants is a bottom-up bitmap. this is fine with huffyuv, so we change it. - bastel
- lpbiOut->biHeight = IgnoreTopDown() ? abs(lpbiOut->biHeight) : lpbiOut->biHeight;
-
- Msg("CanDecompress %d %d %d %d\n",lpbiOut->biWidth,lpbiIn->biWidth ,lpbiOut->biHeight,lpbiIn->biHeight);
- // must be 1:1 (no stretching)
- if (lpbiOut && (lpbiOut->biWidth != lpbiIn->biWidth || lpbiOut->biHeight != lpbiIn->biHeight))
- return false;
-
- int intype = GetBitmapType(lpbiIn);
- int outtype = GetBitmapType(lpbiOut);
-
- Msg("CanDecompress: input = %d, output = %d\n", intype,outtype);
-
- switch (intype) {
- case BITMAP_TYPE_COMPRESSED_YUY2:
- // YUY2, RGB-24, RGB-32 output for compressed YUY2
- return (outtype == BITMAP_TYPE_YUY2 || outtype == BITMAP_TYPE_RGB);
- case BITMAP_TYPE_COMPRESSED_RGB: case BITMAP_TYPE_YUY2: case BITMAP_TYPE_UYVY:
- // RGB-24, RGB-32 output only for YUY2/UYVY and compressed RGB
- return (outtype == BITMAP_TYPE_RGB);
- case BITMAP_TYPE_COMPRESSED_RGBA:
- // RGB-32 output for compressed RGBA
- return (outtype == BITMAP_TYPE_RGBA);
- case BITMAP_TYPE_COMPRESSED_YV12:
- return (outtype == BITMAP_TYPE_YV12 || outtype == BITMAP_TYPE_YUY2
- || outtype == BITMAP_TYPE_RGB );
- default:
- return false;
- }
- }
-
- /********************************************************************
- ********************************************************************/
-
-
- DWORD CodecInst::DecompressQuery(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
- Msg("DecompressQuery: input = %s, output = %s\n", &PrintBitmapType(lpbiIn), &PrintBitmapType(lpbiOut));
- return CanDecompress(lpbiIn, lpbiOut) ? ICERR_OK : ICERR_BADFORMAT;
- }
-
-
- // This function should return "the output format which preserves the most
- // information." However, I now provide the option to return RGB format
- // instead, since some programs treat the default format as the ONLY format.
-
- DWORD CodecInst::DecompressGetFormat(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
-
- Msg("DecompressGetFormat: input = %s, output = %s\n", &PrintBitmapType(lpbiIn), &PrintBitmapType(lpbiOut));
- // if lpbiOut == NULL, then return the size required to hold an output format struct
- if (lpbiOut == NULL)
- return sizeof(BITMAPINFOHEADER);
-
- if (!CanDecompress(lpbiIn))
- return ICERR_BADFORMAT;
-
- *lpbiOut = *lpbiIn;
- lpbiOut->biSize = sizeof(BITMAPINFOHEADER);
- lpbiOut->biPlanes = 1;
-
- int intype = GetBitmapType(lpbiIn);
- if (intype == BITMAP_TYPE_COMPRESSED_RGBA) {
- lpbiOut->biBitCount = 32; // RGBA
- lpbiOut->biCompression = 0;
- lpbiOut->biSizeImage = lpbiIn->biWidth * lpbiIn->biHeight * 4;
- } else if (intype == BITMAP_TYPE_COMPRESSED_RGB || intype == BITMAP_TYPE_YUY2 ||
- intype == BITMAP_TYPE_UYVY || SuggestRGB()) {
- lpbiOut->biBitCount = 24; // RGB
- lpbiOut->biCompression = 0;
- lpbiOut->biSizeImage = lpbiIn->biWidth * lpbiIn->biHeight * 3;
- } else if (intype == BITMAP_TYPE_COMPRESSED_YV12) {
- lpbiOut->biBitCount = 12; // YV12
- lpbiOut->biCompression = FOURCC_YV12;
- lpbiOut->biSizeImage = lpbiIn->biWidth * lpbiIn->biHeight * 3/2;
- }
- else {
- lpbiOut->biBitCount = 16; // YUY2
- lpbiOut->biCompression = FOURCC_YUY2;
- lpbiOut->biSizeImage = lpbiIn->biWidth * lpbiIn->biHeight * 2;
- }
- Msg("DecompressGetFormat: input = %s, output = %s\n", &PrintBitmapType(lpbiIn), &PrintBitmapType(lpbiOut));
-
- return ICERR_OK;
- }
-
-
-
-
- DWORD CodecInst::DecompressBegin(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
- Msg("DecompressBegin: input = %s, output = %s\n", &PrintBitmapType(lpbiIn), &PrintBitmapType(lpbiOut));
-
- DecompressEnd(); // free resources if necessary
-
- if (!CanDecompress(lpbiIn, lpbiOut))
- return ICERR_BADFORMAT;
-
- // ccesp keeps the in CanDecompress() overwritten output height atm,
- // so we are gonna have postive height in CodecInst::Decompress().
- // but to be sure it is stored in the instance here and accessed in CodecInst::Decompress() - bastel
- ignoretopdown = IgnoreTopDown();
- Msg("DecompressBegin: Top-Down output requests are %s.\n",
- ignoretopdown ? "converted to bottum-up" : "processed normal");
-
- decompressing = true;
-
- int intype = GetBitmapType(lpbiIn);
- int outtype = GetBitmapType(lpbiOut);
-
- int sourceInterlacedInt = *((int*)((char*)(lpbiIn) + sizeof(BITMAPINFOHEADER) + sizeof(int)*3));
-
- source_interlaced = (sourceInterlacedInt == 1) ? true : false;
- Msg("DecompressBegin: source interlaced = %s\n",
- source_interlaced ? "yes" : "no");
-
- // allocate buffer if decompressing HFYU->YUY2->RGB
- if ((intype == BITMAP_TYPE_COMPRESSED_YUY2 || intype == BITMAP_TYPE_COMPRESSED_YV12)
- && (outtype == BITMAP_TYPE_RGB || outtype == BITMAP_TYPE_RGBA))
- decompress_yuy2_buffer = new unsigned char[lpbiIn->biWidth * lpbiIn->biHeight * 2];
-
- InitClip();
-
- swapfields = !!GetPrivateProfileInt("debug", "decomp_swap_fields", false, INI_FILE);
-
- return ICERR_OK;
- }
-
-
- static DWORD ConvertYUY2toRGB(LPBITMAPINFOHEADER lpbiOutput, void* _src, void* _dst) {
- const unsigned char* src = (const unsigned char*)_src;
- unsigned char* dst = (unsigned char*)_dst;
- int stride = lpbiOutput->biWidth * 2;
- const unsigned char* src_end = src + stride*lpbiOutput->biHeight;
- if (lpbiOutput->biBitCount == 32)
- mmx_YUY2toRGB32(src, dst, src_end, stride);
- else
- mmx_YUY2toRGB24(src, dst, src_end, stride);
- return ICERR_OK;
- }
-
- static DWORD ConvertUYVYtoRGB(LPBITMAPINFOHEADER lpbiOutput, void* _src, void* _dst) {
- const unsigned char* src = (const unsigned char*)_src;
- unsigned char* dst = (unsigned char*)_dst;
- int stride = lpbiOutput->biWidth * 2;
- const unsigned char* src_end = src + stride*lpbiOutput->biHeight;
- if (lpbiOutput->biBitCount == 32)
- mmx_UYVYtoRGB32(src, dst, src_end, stride);
- else
- mmx_UYVYtoRGB24(src, dst, src_end, stride);
- return ICERR_OK;
- }
-
-
- static void ExpandYV12toYUY2Interlaced(LPBITMAPINFOHEADER lpbiOutput, void* src) {
-
- int i,j;
- int rowsize = lpbiOutput->biWidth << 1;
- unsigned char *dest_row;
- unsigned char *src_row;
-
- i = lpbiOutput->biHeight-1;
- dest_row = (unsigned char *) src;
- dest_row += rowsize * (i); // this is odd.
- src_row = (unsigned char *) src;
- src_row += rowsize * ((i >> 1) & (~1));
- // copy the last 2 lines. they can't be averaged.
- for(j=1;j<rowsize;j+=2)
- {
- dest_row[j] = src_row[j];
- }
- dest_row -= rowsize;
- src_row -= rowsize;
- for(j=1;j<rowsize;j+=2)
- {
- dest_row[j] = src_row[j];
- }
-
- dest_row -= rowsize;
- dest_row -= rowsize;
-
- for(i=lpbiOutput->biHeight-4;i > 1;i-=4)
- {
- for(j=1;j<rowsize;j+=2)
- {
- dest_row[j] = dest_row[j - (rowsize << 1)] = src_row[j+rowsize];
- dest_row[j+rowsize] = dest_row[j-rowsize] = src_row[j];
- }
- dest_row -= rowsize << 2;
- src_row -= rowsize;
- src_row -= rowsize;
- }
-
-
- }
-
- static void ExpandYV12toYUY2(LPBITMAPINFOHEADER lpbiOutput, void* src) {
-
- int i,j;
- int rowsize = lpbiOutput->biWidth << 1;
- unsigned char *dest_row;
- unsigned char *src_row;
-
- i = lpbiOutput->biHeight-1;
- dest_row = (unsigned char *) src;
- dest_row += rowsize * (i); // this is odd.
- src_row = (unsigned char *) src;
- src_row += rowsize * (i >> 1);
-
- for(i=lpbiOutput->biHeight-1;i > 0;i-=2)
- {
- for(j=1;j<rowsize;j+=2)
- {
- dest_row[j] = dest_row[j - rowsize] = src_row[j];
- }
- dest_row -= rowsize << 1;
- src_row -= rowsize;
- }
-
- }
-
- DWORD CodecInst::Decompress(ICDECOMPRESS* icinfo, DWORD dwSize) {
-
- // If you insert a Huffyuv-compressed AVI to a Premiere project and then
- // drag it on to the timeline, the following dialogue occurs:
- //
- // 1. Premiere calls ICDecompressBegin, asking Huffyuv to decompress
- // to a bitmap with different dimensions than the compressed frame.
- //
- // 2. Huffyuv can't resize, so it returns ICERR_BADFORMAT.
- //
- // 3. Premiere calls ICDecompress without making another call to
- // ICDecompressBegin.
- //
- // Therefore I now check for this case and compensate for Premiere's
- // negligence by making the DecompressBegin call myself.
-
- if (!decompressing) {
- DWORD retval = DecompressBegin(icinfo->lpbiInput, icinfo->lpbiOutput);
- if (retval != ICERR_OK)
- return retval;
- }
-
- // we change a top-down output request to a bottom-up one here. - bastel
- // (imho it should be possible to always do this, this code should never be reached with a negative height)
- if ( ignoretopdown ) icinfo->lpbiOutput->biHeight = abs(icinfo->lpbiOutput->biHeight);
-
- icinfo->lpbiOutput->biSizeImage = (icinfo->lpbiOutput->biWidth * icinfo->lpbiOutput->biHeight * icinfo->lpbiOutput->biBitCount) >> 3;
- int maxLoss = *((int*)((char*)(icinfo->lpbiInput) + sizeof(BITMAPINFOHEADER) + sizeof(int)*2));
- int extraVersion = *((int*)((char*)(icinfo->lpbiInput) + sizeof(BITMAPINFOHEADER)));
- if (extraVersion == 1) maxLoss = 0;
-
- int intype = GetBitmapType(icinfo->lpbiInput);
- if (intype < 0) {
- int outtype = GetBitmapType(icinfo->lpbiOutput);
-
- unsigned char* in = (unsigned char*)icinfo->lpInput;
- unsigned char* out = (unsigned char*)icinfo->lpOutput;
- unsigned char* in_end = in;
- unsigned char* out_end = out;
-
- if (intype == BITMAP_TYPE_COMPRESSED_YUY2) { // decompressing LOCO YUY2
- int rowsize = icinfo->lpbiOutput->biWidth * 2;
- int yStep = 1;
- #ifdef LATER
- if (icinfo->lpbiOutput->biHeight > field_threshold) stride *= 2; // if image is interlaced, double stride so fields are treated separately
- #endif
-
- unsigned char* yuy2 = (outtype == BITMAP_TYPE_RGB || outtype == BITMAP_TYPE_RGBA) ? decompress_yuy2_buffer : out;
- //memset((void *) yuy2, 128, icinfo->lpbiOutput->biHeight*icinfo->lpbiOutput->biWidth*2);
-
- // first Y
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)yuy2, icinfo->lpbiOutput->biHeight, rowsize,
- 0, 2, 0, yStep, maxLoss);
- // then U:
-
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)yuy2, icinfo->lpbiInput->biHeight, rowsize,
- 1, 4, 0, yStep, maxLoss);
-
- // then V:
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)yuy2, icinfo->lpbiInput->biHeight, rowsize,
- 3, 4, 0, yStep, maxLoss);
-
- if (outtype == BITMAP_TYPE_RGB || outtype == BITMAP_TYPE_RGBA) // LOCO YUY2->RGB
- ConvertYUY2toRGB(icinfo->lpbiOutput, yuy2, out);
- }
- else if (intype == BITMAP_TYPE_COMPRESSED_YV12) // decompressing LOCO YV12
- {
- if (outtype == BITMAP_TYPE_YV12)
- {
- int rowsize = icinfo->lpbiOutput->biWidth;
- int yStep = 1;
- // first Y
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)out_end, icinfo->lpbiOutput->biHeight, rowsize,
- 0, 1, 0, yStep, maxLoss);
-
- // then U:
- out_end += rowsize*icinfo->lpbiInput->biHeight;
- rowsize = icinfo->lpbiInput->biWidth >> 1;
-
- in_end = (unsigned char *)loco_codec_decompress(in_end,
- (unsigned char *)out_end, icinfo->lpbiInput->biHeight >> 1, rowsize, 0, 1, 0, yStep, maxLoss);
-
- out_end += (rowsize*icinfo->lpbiInput->biHeight) >> 1;
-
- // then V:
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)out_end,
- icinfo->lpbiInput->biHeight >> 1, rowsize, 0, 1, 0, yStep, maxLoss);
- #ifdef GREY
- memset(out+icinfo->lpbiOutput->biWidth*icinfo->lpbiInput->biHeight,128,(rowsize*icinfo->lpbiInput->biHeight)* sizeof(char));
- #endif
- }
- else if (outtype == BITMAP_TYPE_YUY2 || outtype == BITMAP_TYPE_RGB)
- {
- int rowsize = icinfo->lpbiOutput->biWidth << 1;
- int yStep = 1;
- // first Y
- unsigned char* yuy2 = (outtype == BITMAP_TYPE_RGB || outtype == BITMAP_TYPE_RGBA) ? decompress_yuy2_buffer : out;
-
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)yuy2,
- icinfo->lpbiOutput->biHeight, rowsize, 0, 2, 0, yStep, maxLoss);
-
- // then V:
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)yuy2,
- icinfo->lpbiOutput->biHeight >> 1, rowsize, 3, 4, 0, yStep, maxLoss);
-
- // then U:
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)yuy2,
- icinfo->lpbiOutput->biHeight >> 1, rowsize, 1, 4, 0, yStep, maxLoss);
-
- if (source_interlaced) ExpandYV12toYUY2Interlaced(icinfo->lpbiOutput, yuy2);
- else ExpandYV12toYUY2(icinfo->lpbiOutput, yuy2);
-
- if (outtype == BITMAP_TYPE_RGB || outtype == BITMAP_TYPE_RGBA) // LOCO YUY2->RGB
- ConvertYUY2toRGB(icinfo->lpbiOutput, yuy2, out);
- }
- }
- else if (intype == BITMAP_TYPE_COMPRESSED_RGB) { // LOCO RGB24
- int rowsize = icinfo->lpbiOutput->biWidth * 3;
- int yStep = 1;
-
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)out_end,
- icinfo->lpbiOutput->biHeight, rowsize, 0, 3, 0, yStep, maxLoss);
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)out_end,
- icinfo->lpbiOutput->biHeight, rowsize, 1, 3, 0, yStep, maxLoss);
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)out_end,
- icinfo->lpbiOutput->biHeight, rowsize, 2, 3, 0, yStep, maxLoss);
- }
- else if (intype == BITMAP_TYPE_COMPRESSED_RGBA) { // LOCO RGB32
- int rowsize = icinfo->lpbiOutput->biWidth * 4;
- int yStep = 1;
-
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)out_end,
- icinfo->lpbiOutput->biHeight, rowsize, 0, 4, 0, yStep, maxLoss);
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)out_end,
- icinfo->lpbiOutput->biHeight, rowsize, 1, 4, 0, yStep, maxLoss);
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)out_end,
- icinfo->lpbiOutput->biHeight, rowsize, 2, 4, 0, yStep, maxLoss);
- in_end = (unsigned char *)loco_codec_decompress(in_end, (unsigned char *)out_end,
- icinfo->lpbiOutput->biHeight, rowsize, 3, 4, 0, yStep, maxLoss);
- }
-
- if (swapfields && source_interlaced)
- asm_SwapFields(out, out+icinfo->lpbiOutput->biSizeImage,
- (icinfo->lpbiOutput->biWidth * icinfo->lpbiOutput->biBitCount) >> 3);
-
- return ICERR_OK;
- }
- else if (intype == BITMAP_TYPE_YUY2) { // YUY2->RGB
- return ConvertYUY2toRGB(icinfo->lpbiOutput, icinfo->lpInput, icinfo->lpOutput);
- }
- else if (intype == BITMAP_TYPE_UYVY) { // UYVY->RGB
- return ConvertUYVYtoRGB(icinfo->lpbiOutput, icinfo->lpInput, icinfo->lpOutput);
- }
- else
- return ICERR_BADFORMAT;
- }
-
-
- // palette-mapped output only
- DWORD CodecInst::DecompressGetPalette(LPBITMAPINFOHEADER lpbiIn, LPBITMAPINFOHEADER lpbiOut) {
- return ICERR_BADFORMAT;
- }
-
-
- DWORD CodecInst::DecompressEnd() {
- if (decompress_yuy2_buffer) {
- delete[] decompress_yuy2_buffer;
- decompress_yuy2_buffer = 0;
- }
- decompressing = false;
- return ICERR_OK;
- }
-
-
-