--- codec.c 2004/01/23 11:17:24 1.1.2.31 +++ codec.c 2004/11/22 10:40:03 1.13 @@ -58,6 +58,7 @@ #include "status.h" + static const int pmvfast_presets[7] = { 0, 0, 0, 0, 0 | XVID_ME_HALFPELREFINE16 | 0, @@ -72,7 +73,7 @@ or XVID_CSP_NULL if failure */ -int get_colorspace(BITMAPINFOHEADER * hdr) +static int get_colorspace(BITMAPINFOHEADER * hdr) { /* rgb only: negative height specifies top down image */ int rgb_flip = (hdr->biHeight < 0 ? 0 : XVID_CSP_VFLIP); @@ -254,7 +255,7 @@ } -const char type2char(int type) +static char type2char(int type) { if (type==XVID_TYPE_IVOP) return 'I'; @@ -265,7 +266,7 @@ return 'S'; } -int vfw_debug(void *handle, +static int vfw_debug(void *handle, int opt, void *param1, void *param2) @@ -302,50 +303,115 @@ #define XVID_DLL_NAME "xvidcore.dll" -static int init_dll() +static int init_dll(CODEC* codec) { - if (m_hdll != NULL) return 0; + if (codec->m_hdll != NULL) + return 0; DPRINTF("init_dll"); - m_hdll = LoadLibrary(XVID_DLL_NAME); - if (m_hdll == NULL) { + codec->m_hdll = LoadLibrary(XVID_DLL_NAME); + if (codec->m_hdll == NULL) { DPRINTF("dll load failed"); - MessageBox(0, XVID_DLL_NAME " not found","Error", 0); + MessageBox(0, XVID_DLL_NAME " not found!","Error!", MB_ICONEXCLAMATION|MB_OK); return XVID_ERR_FAIL; } - xvid_global_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_global"); - if (xvid_global_func == NULL) { + codec->xvid_global_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(codec->m_hdll, "xvid_global"); + if (codec->xvid_global_func == NULL) { MessageBox(0, "xvid_global() not found", "Error", 0); return XVID_ERR_FAIL; } - xvid_encore_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_encore"); - if (xvid_encore_func == NULL) { + codec->xvid_encore_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(codec->m_hdll, "xvid_encore"); + if (codec->xvid_encore_func == NULL) { MessageBox(0, "xvid_encore() not found", "Error", 0); return XVID_ERR_FAIL; } - xvid_decore_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, "xvid_decore"); - if (xvid_decore_func == NULL) { + codec->xvid_decore_func = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(codec->m_hdll, "xvid_decore"); + if (codec->xvid_decore_func == NULL) { MessageBox(0, "xvid_decore() not found", "Error", 0); return XVID_ERR_FAIL; } - xvid_plugin_single_func = - (int (__cdecl *)(void *, int, void *, void *))(GetProcAddress(m_hdll, "xvid_plugin_single")); - xvid_plugin_2pass1_func = - (int (__cdecl *)(void *, int, void *, void *))(GetProcAddress(m_hdll, "xvid_plugin_2pass1")); - xvid_plugin_2pass2_func = - (int (__cdecl *)(void *, int, void *, void *))(GetProcAddress(m_hdll, "xvid_plugin_2pass2")); - xvid_plugin_lumimasking_func = - (int (__cdecl *)(void *, int, void *, void *))(GetProcAddress(m_hdll, "xvid_plugin_lumimasking")); - xvid_plugin_psnr_func = - (int (__cdecl *)(void *, int, void *, void *))(GetProcAddress(m_hdll, "xvid_plugin_psnr")); + codec->xvid_plugin_single_func = + (int (__cdecl *)(void *, int, void *, void *))(GetProcAddress(codec->m_hdll, "xvid_plugin_single")); + codec->xvid_plugin_2pass1_func = + (int (__cdecl *)(void *, int, void *, void *))(GetProcAddress(codec->m_hdll, "xvid_plugin_2pass1")); + codec->xvid_plugin_2pass2_func = + (int (__cdecl *)(void *, int, void *, void *))(GetProcAddress(codec->m_hdll, "xvid_plugin_2pass2")); + codec->xvid_plugin_lumimasking_func = + (int (__cdecl *)(void *, int, void *, void *))(GetProcAddress(codec->m_hdll, "xvid_plugin_lumimasking")); + codec->xvid_plugin_psnr_func = + (int (__cdecl *)(void *, int, void *, void *))(GetProcAddress(codec->m_hdll, "xvid_plugin_psnr")); return 0; } +/* constant-quant zones for fixed quant encoding */ +static void +prepare_cquant_zones(CONFIG * config) { + + int i = 0; + if (config->num_zones == 0 || config->zones[0].frame != 0) { + /* first zone does not start at frame 0 or doesn't exist */ + + if (config->num_zones >= MAX_ZONES) config->num_zones--; /* we scrifice last zone */ + + config->zones[config->num_zones].frame = 0; + config->zones[config->num_zones].mode = RC_ZONE_QUANT; + config->zones[config->num_zones].weight = 100; + config->zones[config->num_zones].quant = config->desired_quant; + config->zones[config->num_zones].type = XVID_TYPE_AUTO; + config->zones[config->num_zones].greyscale = 0; + config->zones[config->num_zones].chroma_opt = 0; + config->zones[config->num_zones].bvop_threshold = 0; + config->num_zones++; + + sort_zones(config->zones, config->num_zones, &i); + } + + /* step 2: let's change all weight zones into quant zones */ + + for(i = 0; i < config->num_zones; i++) + if (config->zones[i].mode == RC_ZONE_WEIGHT) { + config->zones[i].mode = RC_ZONE_QUANT; + config->zones[i].quant = (100*config->desired_quant) / config->zones[i].weight; + } +} + +/* full first pass zones */ +static void +prepare_full1pass_zones(CONFIG * config) { + + int i = 0; + if (config->num_zones == 0 || config->zones[0].frame != 0) { + /* first zone does not start at frame 0 or doesn't exist */ + + if (config->num_zones >= MAX_ZONES) config->num_zones--; /* we scrifice last zone */ + + config->zones[config->num_zones].frame = 0; + config->zones[config->num_zones].mode = RC_ZONE_QUANT; + config->zones[config->num_zones].weight = 100; + config->zones[config->num_zones].quant = 200; + config->zones[config->num_zones].type = XVID_TYPE_AUTO; + config->zones[config->num_zones].greyscale = 0; + config->zones[config->num_zones].chroma_opt = 0; + config->zones[config->num_zones].bvop_threshold = 0; + config->num_zones++; + + sort_zones(config->zones, config->num_zones, &i); + } + + /* step 2: let's change all weight zones into quant zones */ + + for(i = 0; i < config->num_zones; i++) + if (config->zones[i].mode == RC_ZONE_WEIGHT) { + config->zones[i].mode = RC_ZONE_QUANT; + config->zones[i].quant = 200; + } +} + LRESULT compress_begin(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput) { @@ -356,11 +422,15 @@ xvid_plugin_2pass1_t pass1; xvid_plugin_2pass2_t pass2; int i; + HANDLE hFile; + + CONFIG tmpCfg; /* if we want to alter config to suit our needs, it shouldn't be visible to user later */ + memcpy(&tmpCfg, &codec->config, sizeof(CONFIG)); - if (init_dll() != 0) return ICERR_ERROR; + if (init_dll(codec) != 0) return ICERR_ERROR; /* destroy previously created codec */ if(codec->ehandle) { - xvid_encore_func(codec->ehandle, XVID_ENC_DESTROY, NULL, NULL); + codec->xvid_encore_func(codec->ehandle, XVID_ENC_DESTROY, NULL, NULL); codec->ehandle = NULL; } @@ -368,26 +438,11 @@ init.version = XVID_VERSION; init.cpu_flags = codec->config.cpu; init.debug = codec->config.debug; - xvid_global_func(0, XVID_GBL_INIT, &init, NULL); + codec->xvid_global_func(0, XVID_GBL_INIT, &init, NULL); memset(&create, 0, sizeof(create)); create.version = XVID_VERSION; - /* zones */ - create.zones = malloc(sizeof(xvid_enc_zone_t) * codec->config.num_zones); - create.num_zones = codec->config.num_zones; - for (i=0; i < create.num_zones; i++) { - create.zones[i].frame = codec->config.zones[i].frame; - if (codec->config.zones[i].mode == RC_ZONE_QUANT) { - create.zones[i].mode = XVID_ZONE_QUANT; - create.zones[i].increment = codec->config.zones[i].quant; - }else{ - create.zones[i].mode = XVID_ZONE_WEIGHT; - create.zones[i].increment = codec->config.zones[i].weight; - } - create.zones[i].base = 100; - } - /* plugins */ create.plugins = plugins; switch (codec->config.mode) @@ -399,17 +454,20 @@ single.reaction_delay_factor = codec->config.rc_reaction_delay_factor; single.averaging_period = codec->config.rc_averaging_period; single.buffer = codec->config.rc_buffer; - plugins[create.num_plugins].func = xvid_plugin_single_func; + plugins[create.num_plugins].func = codec->xvid_plugin_single_func; plugins[create.num_plugins].param = &single; create.num_plugins++; + if (!codec->config.use_2pass_bitrate) /* constant-quant mode */ + prepare_cquant_zones(&tmpCfg); break; case RC_MODE_2PASS1 : memset(&pass1, 0, sizeof(pass1)); pass1.version = XVID_VERSION; pass1.filename = codec->config.stats; - - plugins[create.num_plugins].func = xvid_plugin_2pass1_func; + if (codec->config.full1pass) + prepare_full1pass_zones(&tmpCfg); + plugins[create.num_plugins].func = codec->xvid_plugin_2pass1_func; plugins[create.num_plugins].param = &pass1; create.num_plugins++; break; @@ -419,11 +477,21 @@ pass2.version = XVID_VERSION; if (codec->config.use_2pass_bitrate) { pass2.bitrate = codec->config.bitrate * CONFIG_KBPS; - }else{ + } else { pass2.bitrate = -codec->config.desired_size; /* kilobytes */ } pass2.filename = codec->config.stats; + hFile = CreateFile(pass2.filename, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + MessageBox(0, "Statsfile not found!","Error!", MB_ICONEXCLAMATION|MB_OK); + return XVID_ERR_FAIL; + } else + { + CloseHandle(hFile); + } + pass2.keyframe_boost = codec->config.keyframe_boost; /* keyframe boost percentage: [0..100...]; */ pass2.curve_compression_high = codec->config.curve_compression_high; pass2.curve_compression_low = codec->config.curve_compression_low; @@ -434,7 +502,13 @@ pass2.kfthreshold = codec->config.kfthreshold; pass2.container_frame_overhead = 24; /* AVI */ - plugins[create.num_plugins].func = xvid_plugin_2pass2_func; + /* VBV */ + pass2.vbv_size = profiles[codec->config.profile].max_vbv_size; + pass2.vbv_initial = (profiles[codec->config.profile].max_vbv_size*3)/4; + pass2.vbv_maxrate = 1000*profiles[codec->config.profile].max_bitrate; + pass2.vbv_peakrate = 10000000; /* 10mbps -- fixme */ + + plugins[create.num_plugins].func = codec->xvid_plugin_2pass2_func; plugins[create.num_plugins].param = &pass2; create.num_plugins++; break; @@ -446,8 +520,24 @@ break; } + /* zones - copy from tmpCfg in case we automatically altered them above */ + create.zones = malloc(sizeof(xvid_enc_zone_t) * tmpCfg.num_zones); + create.num_zones = tmpCfg.num_zones; + for (i=0; i < create.num_zones; i++) { + create.zones[i].frame = tmpCfg.zones[i].frame; + if (tmpCfg.zones[i].mode == RC_ZONE_QUANT) { + create.zones[i].mode = XVID_ZONE_QUANT; + create.zones[i].increment = tmpCfg.zones[i].quant; + }else{ + create.zones[i].mode = XVID_ZONE_WEIGHT; + create.zones[i].increment = tmpCfg.zones[i].weight; + } + create.zones[i].base = 100; + } + + /* lumimasking plugin */ if ((profiles[codec->config.profile].flags & PROFILE_ADAPTQUANT) && codec->config.lum_masking) { - plugins[create.num_plugins].func = xvid_plugin_lumimasking_func; + plugins[create.num_plugins].func = codec->xvid_plugin_lumimasking_func; plugins[create.num_plugins].param = NULL; create.num_plugins++; } @@ -489,7 +579,7 @@ create.num_threads = codec->config.num_threads; - switch(xvid_encore_func(0, XVID_ENC_CREATE, &create, NULL)) + switch(codec->xvid_encore_func(0, XVID_ENC_CREATE, &create, NULL)) { case XVID_ERR_FAIL : return ICERR_ERROR; @@ -504,6 +594,7 @@ return ICERR_UNSUPPORTED; } + free(create.zones); codec->ehandle = create.handle; codec->framenum = 0; codec->keyspacing = 0; @@ -519,13 +610,11 @@ LRESULT compress_end(CODEC * codec) { - if (m_hdll != NULL) { + if (codec->m_hdll != NULL) { if (codec->ehandle != NULL) { - xvid_encore_func(codec->ehandle, XVID_ENC_DESTROY, NULL, NULL); + codec->xvid_encore_func(codec->ehandle, XVID_ENC_DESTROY, NULL, NULL); codec->ehandle = NULL; } - FreeLibrary(m_hdll); - m_hdll = NULL; } if (codec->config.display_status) @@ -560,6 +649,8 @@ } +#define CALC_BI_STRIDE(width,bitcount) ((((width * bitcount) + 31) & ~31) >> 3) + LRESULT compress(CODEC * codec, ICCOMPRESS * icc) { BITMAPINFOHEADER * inhdr = icc->lpbiInput; @@ -628,6 +719,10 @@ frame.vop_flags |= XVID_VOP_HALFPEL; frame.vop_flags |= XVID_VOP_HQACPRED; + if (codec->config.interlacing && codec->config.tff) + frame.vop_flags |= XVID_VOP_TOPFIELDFIRST; + + if (codec->config.vop_debug) frame.vop_flags |= XVID_VOP_DEBUG; @@ -653,6 +748,9 @@ frame.motion |= pmvfast_presets[codec->config.motion_search]; + if (codec->config.vhq_bframe) frame.vop_flags |= XVID_VOP_RD_BVOP; + + switch (codec->config.vhq_mode) { case VHQ_MODE_DECISION : @@ -689,13 +787,15 @@ } frame.input.plane[0] = icc->lpInput; - frame.input.stride[0] = (((icc->lpbiInput->biWidth * icc->lpbiInput->biBitCount) + 31) & ~31) >> 3; + frame.input.stride[0] = CALC_BI_STRIDE(icc->lpbiInput->biWidth, icc->lpbiInput->biBitCount); if ((frame.input.csp = get_colorspace(inhdr)) == XVID_CSP_NULL) return ICERR_BADFORMAT; - if (frame.input.csp == XVID_CSP_I420 || frame.input.csp == XVID_CSP_YV12) - frame.input.stride[0] = (frame.input.stride[0]*2)/3; + if (frame.input.csp == XVID_CSP_I420 || frame.input.csp == XVID_CSP_YV12) { + frame.input.stride[0] = (4 * icc->lpbiInput->biWidth + 3) / 4; + frame.input.stride[1] = frame.input.stride[2] = frame.input.stride[0] / 2 ; + } frame.bitstream = icc->lpOutput; frame.length = icc->lpbiOutput->biSizeImage; @@ -720,7 +820,7 @@ memset(&stats, 0, sizeof(stats)); stats.version = XVID_VERSION; - length = xvid_encore_func(codec->ehandle, XVID_ENC_ENCODE, &frame, &stats); + length = codec->xvid_encore_func(codec->ehandle, XVID_ENC_ENCODE, &frame, &stats); switch (length) { case XVID_ERR_FAIL : @@ -840,7 +940,8 @@ outhdr->biPlanes = 1; outhdr->biBitCount = 24; outhdr->biCompression = BI_RGB; /* sonic foundry vegas video v3 only supports BI_RGB */ - outhdr->biSizeImage = outhdr->biWidth * outhdr->biHeight * outhdr->biBitCount; + outhdr->biSizeImage = outhdr->biHeight * CALC_BI_STRIDE(outhdr->biWidth, outhdr->biBitCount); + outhdr->biXPelsPerMeter = 0; outhdr->biYPelsPerMeter = 0; outhdr->biClrUsed = 0; @@ -863,21 +964,21 @@ xvid_dec_create_t create; HKEY hKey; - if (init_dll() != 0) return ICERR_ERROR; + if (init_dll(codec) != 0) return ICERR_ERROR; memset(&init, 0, sizeof(init)); init.version = XVID_VERSION; init.cpu_flags = codec->config.cpu; - xvid_global_func(0, XVID_GBL_INIT, &init, NULL); + codec->xvid_global_func(0, XVID_GBL_INIT, &init, NULL); memset(&create, 0, sizeof(create)); create.version = XVID_VERSION; create.width = lpbiInput->bmiHeader.biWidth; create.height = lpbiInput->bmiHeader.biHeight; - switch(xvid_decore_func(0, XVID_DEC_CREATE, &create, NULL)) + switch(codec->xvid_decore_func(0, XVID_DEC_CREATE, &create, NULL)) { - case XVID_ERR_FAIL : + case XVID_ERR_FAIL : return ICERR_ERROR; case XVID_ERR_MEMORY : @@ -894,9 +995,11 @@ RegOpenKeyEx(XVID_REG_KEY, XVID_REG_PARENT "\\" XVID_REG_CHILD, 0, KEY_READ, &hKey); + REG_GET_N("Brightness", pp_brightness, 0); REG_GET_N("Deblock_Y", pp_dy, 0) REG_GET_N("Deblock_UV", pp_duv, 0) - REG_GET_N("Dering", pp_dr, 0) + REG_GET_N("Dering_Y", pp_dry, 0) + REG_GET_N("Dering_UV", pp_druv, 0) REG_GET_N("FilmEffect", pp_fe, 0) RegCloseKey(hKey); @@ -907,13 +1010,11 @@ LRESULT decompress_end(CODEC * codec) { - if (m_hdll != NULL) { + if (codec->m_hdll != NULL) { if (codec->dhandle != NULL) { - xvid_decore_func(codec->dhandle, XVID_DEC_DESTROY, NULL, NULL); + codec->xvid_decore_func(codec->dhandle, XVID_DEC_DESTROY, NULL, NULL); codec->dhandle = NULL; } - FreeLibrary(m_hdll); - m_hdll = NULL; } return ICERR_OK; @@ -946,13 +1047,13 @@ convert.input.csp = get_colorspace(icd->lpbiInput); convert.input.plane[0] = icd->lpInput; - convert.input.stride[0] = (((icd->lpbiInput->biWidth *icd->lpbiInput->biBitCount) + 31) & ~31) >> 3; + convert.input.stride[0] = CALC_BI_STRIDE(icd->lpbiInput->biWidth, icd->lpbiInput->biBitCount); if (convert.input.csp == XVID_CSP_I420 || convert.input.csp == XVID_CSP_YV12) convert.input.stride[0] = (convert.input.stride[0]*2)/3; convert.output.csp = get_colorspace(icd->lpbiOutput); convert.output.plane[0] = icd->lpOutput; - convert.output.stride[0] = (((icd->lpbiOutput->biWidth *icd->lpbiOutput->biBitCount) + 31) & ~31) >> 3; + convert.output.stride[0] = CALC_BI_STRIDE(icd->lpbiOutput->biWidth, icd->lpbiOutput->biBitCount); if (convert.output.csp == XVID_CSP_I420 || convert.output.csp == XVID_CSP_YV12) convert.output.stride[0] = (convert.output.stride[0]*2)/3; @@ -961,7 +1062,7 @@ convert.interlacing = 0; if (convert.input.csp == XVID_CSP_NULL || convert.output.csp == XVID_CSP_NULL || - xvid_global_func(0, XVID_GBL_CONVERT, &convert, NULL) < 0) + codec->xvid_global_func(0, XVID_GBL_CONVERT, &convert, NULL) < 0) { return ICERR_BADFORMAT; } @@ -982,9 +1083,9 @@ return ICERR_BADFORMAT; } frame.output.plane[0] = icd->lpOutput; - frame.output.stride[0] = (((icd->lpbiOutput->biWidth * icd->lpbiOutput->biBitCount) + 31) & ~31) >> 3; + frame.output.stride[0] = CALC_BI_STRIDE(icd->lpbiOutput->biWidth, icd->lpbiOutput->biBitCount); if (frame.output.csp == XVID_CSP_I420 || frame.output.csp == XVID_CSP_YV12) - frame.output.stride[0] = (frame.output.stride[0]*2)/3; + frame.output.stride[0] = CALC_BI_STRIDE(icd->lpbiOutput->biWidth, 8); } else { @@ -993,10 +1094,13 @@ if (pp_dy)frame.general |= XVID_DEBLOCKY; if (pp_duv) frame.general |= XVID_DEBLOCKUV; -/* if (pp_dr) frame.general |= XVID_DERING; */ + if (pp_dry) frame.general |= XVID_DERINGY; + if (pp_druv) frame.general |= XVID_DERINGUV; if (pp_fe) frame.general |= XVID_FILMEFFECT; - switch (xvid_decore_func(codec->dhandle, XVID_DEC_DECODE, &frame, NULL)) + frame.brightness = pp_brightness; + + switch (codec->xvid_decore_func(codec->dhandle, XVID_DEC_DECODE, &frame, NULL)) { case XVID_ERR_FAIL : return ICERR_ERROR;