1370b324cSopenharmony_ci// LzmaEncoder.cpp 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#include "StdAfx.h" 4370b324cSopenharmony_ci 5370b324cSopenharmony_ci#include "../../../C/Alloc.h" 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#include "../Common/CWrappers.h" 8370b324cSopenharmony_ci#include "../Common/StreamUtils.h" 9370b324cSopenharmony_ci 10370b324cSopenharmony_ci#include "LzmaEncoder.h" 11370b324cSopenharmony_ci 12370b324cSopenharmony_ci// #define LOG_LZMA_THREADS 13370b324cSopenharmony_ci 14370b324cSopenharmony_ci#ifdef LOG_LZMA_THREADS 15370b324cSopenharmony_ci 16370b324cSopenharmony_ci#include <stdio.h> 17370b324cSopenharmony_ci 18370b324cSopenharmony_ci#include "../../Common/IntToString.h" 19370b324cSopenharmony_ci#include "../../Windows/TimeUtils.h" 20370b324cSopenharmony_ci 21370b324cSopenharmony_ciEXTERN_C_BEGIN 22370b324cSopenharmony_civoid LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2]); 23370b324cSopenharmony_ciEXTERN_C_END 24370b324cSopenharmony_ci 25370b324cSopenharmony_ci#endif 26370b324cSopenharmony_ci 27370b324cSopenharmony_cinamespace NCompress { 28370b324cSopenharmony_cinamespace NLzma { 29370b324cSopenharmony_ci 30370b324cSopenharmony_ciCEncoder::CEncoder() 31370b324cSopenharmony_ci{ 32370b324cSopenharmony_ci _encoder = NULL; 33370b324cSopenharmony_ci _encoder = LzmaEnc_Create(&g_AlignedAlloc); 34370b324cSopenharmony_ci if (!_encoder) 35370b324cSopenharmony_ci throw 1; 36370b324cSopenharmony_ci} 37370b324cSopenharmony_ci 38370b324cSopenharmony_ciCEncoder::~CEncoder() 39370b324cSopenharmony_ci{ 40370b324cSopenharmony_ci if (_encoder) 41370b324cSopenharmony_ci LzmaEnc_Destroy(_encoder, &g_AlignedAlloc, &g_BigAlloc); 42370b324cSopenharmony_ci} 43370b324cSopenharmony_ci 44370b324cSopenharmony_cistatic inline wchar_t GetLowCharFast(wchar_t c) 45370b324cSopenharmony_ci{ 46370b324cSopenharmony_ci return c |= 0x20; 47370b324cSopenharmony_ci} 48370b324cSopenharmony_ci 49370b324cSopenharmony_cistatic int ParseMatchFinder(const wchar_t *s, int *btMode, int *numHashBytes) 50370b324cSopenharmony_ci{ 51370b324cSopenharmony_ci const wchar_t c = GetLowCharFast(*s++); 52370b324cSopenharmony_ci if (c == 'h') 53370b324cSopenharmony_ci { 54370b324cSopenharmony_ci if (GetLowCharFast(*s++) != 'c') 55370b324cSopenharmony_ci return 0; 56370b324cSopenharmony_ci const int num = (int)(*s++ - L'0'); 57370b324cSopenharmony_ci if (num < 4 || num > 5) 58370b324cSopenharmony_ci return 0; 59370b324cSopenharmony_ci if (*s != 0) 60370b324cSopenharmony_ci return 0; 61370b324cSopenharmony_ci *btMode = 0; 62370b324cSopenharmony_ci *numHashBytes = num; 63370b324cSopenharmony_ci return 1; 64370b324cSopenharmony_ci } 65370b324cSopenharmony_ci 66370b324cSopenharmony_ci if (c != 'b') 67370b324cSopenharmony_ci return 0; 68370b324cSopenharmony_ci { 69370b324cSopenharmony_ci if (GetLowCharFast(*s++) != 't') 70370b324cSopenharmony_ci return 0; 71370b324cSopenharmony_ci const int num = (int)(*s++ - L'0'); 72370b324cSopenharmony_ci if (num < 2 || num > 5) 73370b324cSopenharmony_ci return 0; 74370b324cSopenharmony_ci if (*s != 0) 75370b324cSopenharmony_ci return 0; 76370b324cSopenharmony_ci *btMode = 1; 77370b324cSopenharmony_ci *numHashBytes = num; 78370b324cSopenharmony_ci return 1; 79370b324cSopenharmony_ci } 80370b324cSopenharmony_ci} 81370b324cSopenharmony_ci 82370b324cSopenharmony_ci#define SET_PROP_32(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = (int)v; break; 83370b324cSopenharmony_ci#define SET_PROP_32U(_id_, _dest_) case NCoderPropID::_id_: ep._dest_ = v; break; 84370b324cSopenharmony_ci 85370b324cSopenharmony_ciHRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep); 86370b324cSopenharmony_ciHRESULT SetLzmaProp(PROPID propID, const PROPVARIANT &prop, CLzmaEncProps &ep) 87370b324cSopenharmony_ci{ 88370b324cSopenharmony_ci if (propID == NCoderPropID::kMatchFinder) 89370b324cSopenharmony_ci { 90370b324cSopenharmony_ci if (prop.vt != VT_BSTR) 91370b324cSopenharmony_ci return E_INVALIDARG; 92370b324cSopenharmony_ci return ParseMatchFinder(prop.bstrVal, &ep.btMode, &ep.numHashBytes) ? S_OK : E_INVALIDARG; 93370b324cSopenharmony_ci } 94370b324cSopenharmony_ci 95370b324cSopenharmony_ci if (propID == NCoderPropID::kAffinity) 96370b324cSopenharmony_ci { 97370b324cSopenharmony_ci if (prop.vt == VT_UI8) 98370b324cSopenharmony_ci ep.affinity = prop.uhVal.QuadPart; 99370b324cSopenharmony_ci else 100370b324cSopenharmony_ci return E_INVALIDARG; 101370b324cSopenharmony_ci return S_OK; 102370b324cSopenharmony_ci } 103370b324cSopenharmony_ci 104370b324cSopenharmony_ci if (propID == NCoderPropID::kHashBits) 105370b324cSopenharmony_ci { 106370b324cSopenharmony_ci if (prop.vt == VT_UI4) 107370b324cSopenharmony_ci ep.numHashOutBits = prop.ulVal; 108370b324cSopenharmony_ci else 109370b324cSopenharmony_ci return E_INVALIDARG; 110370b324cSopenharmony_ci return S_OK; 111370b324cSopenharmony_ci } 112370b324cSopenharmony_ci 113370b324cSopenharmony_ci if (propID > NCoderPropID::kReduceSize) 114370b324cSopenharmony_ci return S_OK; 115370b324cSopenharmony_ci 116370b324cSopenharmony_ci if (propID == NCoderPropID::kReduceSize) 117370b324cSopenharmony_ci { 118370b324cSopenharmony_ci if (prop.vt == VT_UI8) 119370b324cSopenharmony_ci ep.reduceSize = prop.uhVal.QuadPart; 120370b324cSopenharmony_ci else 121370b324cSopenharmony_ci return E_INVALIDARG; 122370b324cSopenharmony_ci return S_OK; 123370b324cSopenharmony_ci } 124370b324cSopenharmony_ci 125370b324cSopenharmony_ci if (propID == NCoderPropID::kDictionarySize) 126370b324cSopenharmony_ci { 127370b324cSopenharmony_ci if (prop.vt == VT_UI8) 128370b324cSopenharmony_ci { 129370b324cSopenharmony_ci // 21.03 : we support 64-bit VT_UI8 for dictionary and (dict == 4 GiB) 130370b324cSopenharmony_ci const UInt64 v = prop.uhVal.QuadPart; 131370b324cSopenharmony_ci if (v > ((UInt64)1 << 32)) 132370b324cSopenharmony_ci return E_INVALIDARG; 133370b324cSopenharmony_ci UInt32 dict; 134370b324cSopenharmony_ci if (v == ((UInt64)1 << 32)) 135370b324cSopenharmony_ci dict = (UInt32)(Int32)-1; 136370b324cSopenharmony_ci else 137370b324cSopenharmony_ci dict = (UInt32)v; 138370b324cSopenharmony_ci ep.dictSize = dict; 139370b324cSopenharmony_ci return S_OK; 140370b324cSopenharmony_ci } 141370b324cSopenharmony_ci } 142370b324cSopenharmony_ci 143370b324cSopenharmony_ci if (prop.vt != VT_UI4) 144370b324cSopenharmony_ci return E_INVALIDARG; 145370b324cSopenharmony_ci const UInt32 v = prop.ulVal; 146370b324cSopenharmony_ci switch (propID) 147370b324cSopenharmony_ci { 148370b324cSopenharmony_ci case NCoderPropID::kDefaultProp: 149370b324cSopenharmony_ci if (v > 32) 150370b324cSopenharmony_ci return E_INVALIDARG; 151370b324cSopenharmony_ci ep.dictSize = (v == 32) ? (UInt32)(Int32)-1 : (UInt32)1 << (unsigned)v; 152370b324cSopenharmony_ci break; 153370b324cSopenharmony_ci SET_PROP_32(kLevel, level) 154370b324cSopenharmony_ci SET_PROP_32(kNumFastBytes, fb) 155370b324cSopenharmony_ci SET_PROP_32U(kMatchFinderCycles, mc) 156370b324cSopenharmony_ci SET_PROP_32(kAlgorithm, algo) 157370b324cSopenharmony_ci SET_PROP_32U(kDictionarySize, dictSize) 158370b324cSopenharmony_ci SET_PROP_32(kPosStateBits, pb) 159370b324cSopenharmony_ci SET_PROP_32(kLitPosBits, lp) 160370b324cSopenharmony_ci SET_PROP_32(kLitContextBits, lc) 161370b324cSopenharmony_ci SET_PROP_32(kNumThreads, numThreads) 162370b324cSopenharmony_ci default: return E_INVALIDARG; 163370b324cSopenharmony_ci } 164370b324cSopenharmony_ci return S_OK; 165370b324cSopenharmony_ci} 166370b324cSopenharmony_ci 167370b324cSopenharmony_ciZ7_COM7F_IMF(CEncoder::SetCoderProperties(const PROPID *propIDs, 168370b324cSopenharmony_ci const PROPVARIANT *coderProps, UInt32 numProps)) 169370b324cSopenharmony_ci{ 170370b324cSopenharmony_ci CLzmaEncProps props; 171370b324cSopenharmony_ci LzmaEncProps_Init(&props); 172370b324cSopenharmony_ci 173370b324cSopenharmony_ci for (UInt32 i = 0; i < numProps; i++) 174370b324cSopenharmony_ci { 175370b324cSopenharmony_ci const PROPVARIANT &prop = coderProps[i]; 176370b324cSopenharmony_ci const PROPID propID = propIDs[i]; 177370b324cSopenharmony_ci switch (propID) 178370b324cSopenharmony_ci { 179370b324cSopenharmony_ci case NCoderPropID::kEndMarker: 180370b324cSopenharmony_ci if (prop.vt != VT_BOOL) 181370b324cSopenharmony_ci return E_INVALIDARG; 182370b324cSopenharmony_ci props.writeEndMark = (prop.boolVal != VARIANT_FALSE); 183370b324cSopenharmony_ci break; 184370b324cSopenharmony_ci default: 185370b324cSopenharmony_ci RINOK(SetLzmaProp(propID, prop, props)) 186370b324cSopenharmony_ci } 187370b324cSopenharmony_ci } 188370b324cSopenharmony_ci return SResToHRESULT(LzmaEnc_SetProps(_encoder, &props)); 189370b324cSopenharmony_ci} 190370b324cSopenharmony_ci 191370b324cSopenharmony_ci 192370b324cSopenharmony_ciZ7_COM7F_IMF(CEncoder::SetCoderPropertiesOpt(const PROPID *propIDs, 193370b324cSopenharmony_ci const PROPVARIANT *coderProps, UInt32 numProps)) 194370b324cSopenharmony_ci{ 195370b324cSopenharmony_ci for (UInt32 i = 0; i < numProps; i++) 196370b324cSopenharmony_ci { 197370b324cSopenharmony_ci const PROPVARIANT &prop = coderProps[i]; 198370b324cSopenharmony_ci const PROPID propID = propIDs[i]; 199370b324cSopenharmony_ci if (propID == NCoderPropID::kExpectedDataSize) 200370b324cSopenharmony_ci if (prop.vt == VT_UI8) 201370b324cSopenharmony_ci LzmaEnc_SetDataSize(_encoder, prop.uhVal.QuadPart); 202370b324cSopenharmony_ci } 203370b324cSopenharmony_ci return S_OK; 204370b324cSopenharmony_ci} 205370b324cSopenharmony_ci 206370b324cSopenharmony_ci 207370b324cSopenharmony_ciZ7_COM7F_IMF(CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)) 208370b324cSopenharmony_ci{ 209370b324cSopenharmony_ci Byte props[LZMA_PROPS_SIZE]; 210370b324cSopenharmony_ci SizeT size = LZMA_PROPS_SIZE; 211370b324cSopenharmony_ci RINOK(LzmaEnc_WriteProperties(_encoder, props, &size)) 212370b324cSopenharmony_ci return WriteStream(outStream, props, size); 213370b324cSopenharmony_ci} 214370b324cSopenharmony_ci 215370b324cSopenharmony_ci 216370b324cSopenharmony_ci#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ 217370b324cSopenharmony_ci if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; 218370b324cSopenharmony_ci 219370b324cSopenharmony_ci 220370b324cSopenharmony_ci 221370b324cSopenharmony_ci#ifdef LOG_LZMA_THREADS 222370b324cSopenharmony_ci 223370b324cSopenharmony_cistatic inline UInt64 GetTime64(const FILETIME &t) { return ((UInt64)t.dwHighDateTime << 32) | t.dwLowDateTime; } 224370b324cSopenharmony_ci 225370b324cSopenharmony_cistatic void PrintNum(UInt64 val, unsigned numDigits, char c = ' ') 226370b324cSopenharmony_ci{ 227370b324cSopenharmony_ci char temp[64]; 228370b324cSopenharmony_ci char *p = temp + 32; 229370b324cSopenharmony_ci ConvertUInt64ToString(val, p); 230370b324cSopenharmony_ci unsigned len = (unsigned)strlen(p); 231370b324cSopenharmony_ci for (; len < numDigits; len++) 232370b324cSopenharmony_ci *--p = c; 233370b324cSopenharmony_ci printf("%s", p); 234370b324cSopenharmony_ci} 235370b324cSopenharmony_ci 236370b324cSopenharmony_cistatic void PrintTime(const char *s, UInt64 val, UInt64 total) 237370b324cSopenharmony_ci{ 238370b324cSopenharmony_ci printf(" %s :", s); 239370b324cSopenharmony_ci const UInt32 kFreq = 10000000; 240370b324cSopenharmony_ci UInt64 sec = val / kFreq; 241370b324cSopenharmony_ci PrintNum(sec, 6); 242370b324cSopenharmony_ci printf(" ."); 243370b324cSopenharmony_ci UInt32 ms = (UInt32)(val - (sec * kFreq)) / (kFreq / 1000); 244370b324cSopenharmony_ci PrintNum(ms, 3, '0'); 245370b324cSopenharmony_ci 246370b324cSopenharmony_ci while (val > ((UInt64)1 << 56)) 247370b324cSopenharmony_ci { 248370b324cSopenharmony_ci val >>= 1; 249370b324cSopenharmony_ci total >>= 1; 250370b324cSopenharmony_ci } 251370b324cSopenharmony_ci 252370b324cSopenharmony_ci UInt64 percent = 0; 253370b324cSopenharmony_ci if (total != 0) 254370b324cSopenharmony_ci percent = val * 100 / total; 255370b324cSopenharmony_ci printf(" ="); 256370b324cSopenharmony_ci PrintNum(percent, 4); 257370b324cSopenharmony_ci printf("%%"); 258370b324cSopenharmony_ci} 259370b324cSopenharmony_ci 260370b324cSopenharmony_ci 261370b324cSopenharmony_cistruct CBaseStat 262370b324cSopenharmony_ci{ 263370b324cSopenharmony_ci UInt64 kernelTime, userTime; 264370b324cSopenharmony_ci 265370b324cSopenharmony_ci BOOL Get(HANDLE thread, const CBaseStat *prevStat) 266370b324cSopenharmony_ci { 267370b324cSopenharmony_ci FILETIME creationTimeFT, exitTimeFT, kernelTimeFT, userTimeFT; 268370b324cSopenharmony_ci BOOL res = GetThreadTimes(thread 269370b324cSopenharmony_ci , &creationTimeFT, &exitTimeFT, &kernelTimeFT, &userTimeFT); 270370b324cSopenharmony_ci if (res) 271370b324cSopenharmony_ci { 272370b324cSopenharmony_ci kernelTime = GetTime64(kernelTimeFT); 273370b324cSopenharmony_ci userTime = GetTime64(userTimeFT); 274370b324cSopenharmony_ci if (prevStat) 275370b324cSopenharmony_ci { 276370b324cSopenharmony_ci kernelTime -= prevStat->kernelTime; 277370b324cSopenharmony_ci userTime -= prevStat->userTime; 278370b324cSopenharmony_ci } 279370b324cSopenharmony_ci } 280370b324cSopenharmony_ci return res; 281370b324cSopenharmony_ci } 282370b324cSopenharmony_ci}; 283370b324cSopenharmony_ci 284370b324cSopenharmony_ci 285370b324cSopenharmony_cistatic void PrintStat(HANDLE thread, UInt64 totalTime, const CBaseStat *prevStat) 286370b324cSopenharmony_ci{ 287370b324cSopenharmony_ci CBaseStat newStat; 288370b324cSopenharmony_ci if (!newStat.Get(thread, prevStat)) 289370b324cSopenharmony_ci return; 290370b324cSopenharmony_ci 291370b324cSopenharmony_ci PrintTime("K", newStat.kernelTime, totalTime); 292370b324cSopenharmony_ci 293370b324cSopenharmony_ci const UInt64 processTime = newStat.kernelTime + newStat.userTime; 294370b324cSopenharmony_ci 295370b324cSopenharmony_ci PrintTime("U", newStat.userTime, totalTime); 296370b324cSopenharmony_ci PrintTime("S", processTime, totalTime); 297370b324cSopenharmony_ci printf("\n"); 298370b324cSopenharmony_ci // PrintTime("G ", totalTime, totalTime); 299370b324cSopenharmony_ci} 300370b324cSopenharmony_ci 301370b324cSopenharmony_ci#endif 302370b324cSopenharmony_ci 303370b324cSopenharmony_ci 304370b324cSopenharmony_ci 305370b324cSopenharmony_ciZ7_COM7F_IMF(CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 306370b324cSopenharmony_ci const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)) 307370b324cSopenharmony_ci{ 308370b324cSopenharmony_ci CSeqInStreamWrap inWrap; 309370b324cSopenharmony_ci CSeqOutStreamWrap outWrap; 310370b324cSopenharmony_ci CCompressProgressWrap progressWrap; 311370b324cSopenharmony_ci 312370b324cSopenharmony_ci inWrap.Init(inStream); 313370b324cSopenharmony_ci outWrap.Init(outStream); 314370b324cSopenharmony_ci progressWrap.Init(progress); 315370b324cSopenharmony_ci 316370b324cSopenharmony_ci #ifdef LOG_LZMA_THREADS 317370b324cSopenharmony_ci 318370b324cSopenharmony_ci FILETIME startTimeFT; 319370b324cSopenharmony_ci NWindows::NTime::GetCurUtcFileTime(startTimeFT); 320370b324cSopenharmony_ci UInt64 totalTime = GetTime64(startTimeFT); 321370b324cSopenharmony_ci CBaseStat oldStat; 322370b324cSopenharmony_ci if (!oldStat.Get(GetCurrentThread(), NULL)) 323370b324cSopenharmony_ci return E_FAIL; 324370b324cSopenharmony_ci 325370b324cSopenharmony_ci #endif 326370b324cSopenharmony_ci 327370b324cSopenharmony_ci 328370b324cSopenharmony_ci SRes res = LzmaEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, 329370b324cSopenharmony_ci progress ? &progressWrap.vt : NULL, &g_AlignedAlloc, &g_BigAlloc); 330370b324cSopenharmony_ci 331370b324cSopenharmony_ci _inputProcessed = inWrap.Processed; 332370b324cSopenharmony_ci 333370b324cSopenharmony_ci RET_IF_WRAP_ERROR(inWrap.Res, res, SZ_ERROR_READ) 334370b324cSopenharmony_ci RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) 335370b324cSopenharmony_ci RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) 336370b324cSopenharmony_ci 337370b324cSopenharmony_ci 338370b324cSopenharmony_ci #ifdef LOG_LZMA_THREADS 339370b324cSopenharmony_ci 340370b324cSopenharmony_ci NWindows::NTime::GetCurUtcFileTime(startTimeFT); 341370b324cSopenharmony_ci totalTime = GetTime64(startTimeFT) - totalTime; 342370b324cSopenharmony_ci HANDLE lz_threads[2]; 343370b324cSopenharmony_ci LzmaEnc_GetLzThreads(_encoder, lz_threads); 344370b324cSopenharmony_ci printf("\n"); 345370b324cSopenharmony_ci printf("Main: "); PrintStat(GetCurrentThread(), totalTime, &oldStat); 346370b324cSopenharmony_ci printf("Hash: "); PrintStat(lz_threads[0], totalTime, NULL); 347370b324cSopenharmony_ci printf("BinT: "); PrintStat(lz_threads[1], totalTime, NULL); 348370b324cSopenharmony_ci // PrintTime("Total: ", totalTime, totalTime); 349370b324cSopenharmony_ci printf("\n"); 350370b324cSopenharmony_ci 351370b324cSopenharmony_ci #endif 352370b324cSopenharmony_ci 353370b324cSopenharmony_ci return SResToHRESULT(res); 354370b324cSopenharmony_ci} 355370b324cSopenharmony_ci 356370b324cSopenharmony_ci}} 357