📄 jpegenc.c
字号:
_wJPEGENC_Quality = JPEGENC_COMPRESSION_QUALITY_DEFAULT; _wJPEGENC_QualityStep = JPEGENC_COMPRESSION_QUALITY_DEFSTEP; _wJPEGENC_SrcWidth = JPEGENC_COMPRESSION_IMAGE_WIDTH; _wJPEGENC_SrcHeight = JPEGENC_COMPRESSION_IMAGE_HEIGHT; _dwJPEGENC_ExceedSize = 0; _dwJPEGENC_StartOutputPtr = 0; _dwJPEGENC_CurrentOutputPtr = 0; _wMempoolInitialized = FALSE;}//API export for upper-layer to get current status of JPEG encoder//WORD JPEGENC_GetStatus(VOID){ return (_wJPEGENC_Status);}//API export for upper-layer to get generated JPEG file size by JPEG encoder//DWORD JPEGENC_GetCompressedSize(DWORD mempool_start_address){ return (_dwJPEGENC_CurrentOutputPtr - mempool_start_address);}//utility functions for JPEG encoder//WORD JPEGENC_InitMemPool(DWORD mempool_addr, DWORD mempool_size){ //initialize variables related to the memory pool //mempool= jpeg_file + encoder_obj_members if (TRUE != _wMempoolInitialized) { // for JPEG file generation _dwJPEGENC_StartOutputPtr = mempool_addr; _dwJPEGENC_CurrentOutputPtr = mempool_addr; // for JPEG encoder _dwMempoolTotalSize = mempool_size - _dwJPEGENC_FileSizeMax; //check: if the mempool is large enough for generated JPEG file and encoder object members if (JPEGENC_REQUIRED_MEMPOOL_SIZE > _dwMempoolTotalSize) { return JPEGENC_COMPRESSION_MEM_NOT_ENOUGH; } _dwMemPoolFreeSize = _dwMempoolTotalSize; _dwMempoolStartAddress = mempool_addr + mempool_size; _dwMempoolCurrAddress = mempool_addr + mempool_size; _wMempoolInitialized = TRUE; //should we clear buffer at the beginning? return JPEGENC_COMPRESSION_SUCCESSED; } else { return JPEGENC_COMPRESSION_MEM_ALREADY_INIT; }}// simple malloc replacement//VOID *JPEGENC_Malloc(DWORD byte_count){ if (0 == byte_count) { return NULL; } //CHECK: if request size > available if (byte_count > _dwMemPoolFreeSize) { return NULL; } if (TRUE == _wMempoolInitialized) { //NORMAL: move current ptr to next available slot (and it should be 4x-byte aligned) //tommy1122: ok for byte-alignment //byte_count = (byte_count + 2) & 0xfffffffc; _dwMemPoolFreeSize -= byte_count; _dwMempoolCurrAddress -= byte_count; return (VOID *)_dwMempoolCurrAddress; } else { return NULL; }}// simple free replacement//VOID JPEGENC_Free(VOID *dest){ //empty: do nothing}// ---------------------------------// sample of JPEG encoder processing flow://WORD JPEGENC_StartCompression(DWORD mempool, DWORD len, DWORD start_y, DWORD start_uv, WORD width, WORD height, WORD PicStrip, WORD PicCoordH, WORD PicCoordV, WORD quality, WORD quality_step, DWORD max_filesize){ //mempool: starting address of memory pool, for both JPEG file (from the beginning) and function JPEGENC_Malloc() (from the tail) //len: size of memory pool, in bytes //start_y: Y starting address of source image //start_uv: UV starting address of source image //width: width of source image //height: height of source image //quality: starting quality of compression. If the generated JPEG file size is exceeded, JPEG encoder will adjust this value smaller automatically. //quality_step: step value for quality adjustment //max_filesize: possible maximum file size for generated JPEG file (count in bytes) volatile DWORD exceed_percentage; volatile WORD compress_status = JPEGENC_COMPRESSION_EMPTY; volatile WORD mempool_status = JPEGENC_COMPRESSION_EMPTY; //volatile WORD first_predict_quality = TRUE;#ifdef JPEGENC_EVAL_PERFORMANCE volatile DWORD jpegenc_time = OS_GetSysTimer(); volatile WORD retry_count = 0;#endif _wJPEGENC_SrcCoordH = PicCoordH; _wJPEGENC_SrcCoordV = PicCoordV; _wJPEGENC_SrcStrip = PicStrip; // initial for libmem module //DVB_MemoryCFG(mempool, len); // reset all configurable settings to default values JPEGENC_Reset(); //_dwJPEGENC_StartOutputPtr = buff; //_dwJPEGENC_CurrentOutputPtr = buff; //PTR to result buffer: reference jdatadst.c for output // use these functions to setting image, buffer, and compression parameters JPEGENC_SetCompressRegionAddress(start_y, start_uv); JPEGENC_SetCompressRegionSize(width, height); JPEGENC_SetCompressFileSizeMax(max_filesize); JPEGENC_SetCompressQuality(quality); JPEGENC_SetCompressQualityStep(quality_step); // it should be called right before JPEGENC_Main() at the first time, to confirm there is enough space in memory pool if (JPEGENC_COMPRESSION_EMPTY == mempool_status) { mempool_status = JPEGENC_InitMemPool(mempool, len); if (JPEGENC_COMPRESSION_MEM_NOT_ENOUGH == mempool_status) { DBG_Printf(DBG_THREAD_DECODER, DBG_INFO_PRINTF, "ERR: memory pool size isn't enough\n"); return JPEGENC_COMPRESSION_MEM_NOT_ENOUGH; } } // start JPEG encoder compress_status = _JPEGENC_Main();#ifdef JPEGENC_EVAL_PERFORMANCE retry_count += 1;#endif //if it's out of MAX buffer size, decrease the quality and invoke compression again: //heuristic adjustment by exceed size --> may improve time for trail to 3 (but not 5 or 6) while (JPEGENC_COMPRESSION_SIZE_EXCEEDED == compress_status) {#ifdef JPEGENC_EVAL_PERFORMANCE DWORD exceed_size = _dwJPEGENC_ExceedSize;#endif exceed_percentage = _dwJPEGENC_ExceedSize * 100 / _dwJPEGENC_FileSizeMax; //(64 * 1024) JPEGENC_Reset(); JPEGENC_SetCompressRegionAddress(start_y, start_uv); JPEGENC_SetCompressRegionSize(width, height); JPEGENC_SetCompressFileSizeMax(max_filesize); JPEGENC_SetCompressQualityStep(quality_step); //_dwJPEGENC_CurrentOutputPtr = buff; //move current PTR to the starting of buffer //if (TRUE == first_predict_quality) //{ // Heuristic partitions based-on: // (1) 64KB maximum file size constraints (and it's the most important factor of these heuristic partitions below), and // (2) resolutions of display buffer (640x448 pixels) // (3) starts from quality 90%, step is 5%. // This get a balance of compression performance and quality. // // TESTED DISC: // (1) Tommy's TestJPEG Disc#1 // (2) Tommy's TestJPEG Disc#2 // TUNED RESULTS: // (1) file size almost better than 0xB800 bytes (for max file size 64KB configuration, it reaches 71.8% usage.) // (2) only one of test pictures gets 0xB7A9 bytes. // (3) all test pictures require no more than 2 times of compression: it consumes about (or less than) 1 sec. in CT909S CheerDVD v2.38b. // (4) although current compression quality is good, some pictures may raise the quality value for 5 or 10 to get optimal compression of themselves. // we may provide better algorithm or parameters of partitions to get the compression quality optimal in the future. // if (170 <= exceed_percentage) { quality -= 60; } else if (142 <= exceed_percentage && exceed_percentage < 170) { quality -= 55; } else if (117 <= exceed_percentage && exceed_percentage < 142) { quality -= 50; } else if (95 <= exceed_percentage && exceed_percentage < 117) { quality -= 45; } else if (90 <= exceed_percentage && exceed_percentage < 95) { quality -= 40; } else if (75 <= exceed_percentage && exceed_percentage < 90) { quality -= 35; } else if (66 <= exceed_percentage && exceed_percentage < 75) { quality -= 30; } else if (54 <= exceed_percentage && exceed_percentage < 66) { quality -= 25; } else if (48 <= exceed_percentage && exceed_percentage < 54) { quality -= 20; } else if (34 <= exceed_percentage && exceed_percentage < 48) { quality -= 15; } else if (15 <= exceed_percentage && exceed_percentage < 34) { quality -= 10; } else if (exceed_percentage < 15) { quality -= 5; } else { quality -= _wJPEGENC_QualityStep; } //first_predict_quality = FALSE; //} //else //{ // quality -= _wJPEGENC_QualityStep; //decrease QUALITY for a step value //} //check quality value = 1~99 if (1 > quality || 99 < quality) { DBG_Printf(DBG_THREAD_DECODER, DBG_INFO_PRINTF, "ERR: QUALITY=(0x%x)", quality); return JPEGENC_COMPRESSION_EXIT_FAILED; } JPEGENC_SetCompressQuality(quality); JPEGENC_InitMemPool(mempool, len); compress_status = _JPEGENC_Main();#ifdef JPEGENC_EVAL_PERFORMANCE DBG_Printf(DBG_THREAD_DECODER, DBG_INFO_PRINTF, "EXCEED SIZE=0x%lx(0x%X%%); retry QUALITY=(0x%X)\n", exceed_size, exceed_percentage, quality); retry_count += 1;#endif }#ifdef JPEGENC_EVAL_PERFORMANCE //remember max retry count to evaluate possible longest compression time if (retry_count > _wJPEGENC_MaxRetryCount) { _wJPEGENC_MaxRetryCount = retry_count; } // JPEG total size= _pdwCurrentOutputPtr - buff if (1 < retry_count) { DBG_Printf(DBG_THREAD_DECODER, DBG_INFO_PRINTF, "TIME:0x%lx, SIZE:0x%lx", OS_GetSysTimer() - jpegenc_time, _dwJPEGENC_CurrentOutputPtr - mempool); } //required: 0xB0b4 bytes DBG_Printf(DBG_THREAD_DECODER, DBG_INFO_PRINTF, "MAX MEMPOOL USED:0x%lx", (DWORD)mempool + len - _dwMempoolCurrAddress);#endif //compress successfully return JPEGENC_COMPRESSION_SUCCESSED;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -