LRESULT compress_begin(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput) { xvid_gbl_init_t init; xvid_enc_create_t create; xvid_enc_plugin_t plugins[3]; xvid_plugin_single_t single; 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(codec) != 0) return ICERR_ERROR; /* destroy previously created codec */ if(codec->ehandle) { codec->xvid_encore_func(codec->ehandle, XVID_ENC_DESTROY, NULL, NULL); codec->ehandle = NULL; } memset(&init, 0, sizeof(init)); init.version = XVID_VERSION; init.cpu_flags = codec->config.cpu; init.debug = codec->config.debug; codec->xvid_global_func(0, XVID_GBL_INIT, &init, NULL); memset(&create, 0, sizeof(create)); create.version = XVID_VERSION; /* plugins */ create.plugins = plugins; switch (codec->config.mode) { case RC_MODE_1PASS : memset(&single, 0, sizeof(single)); single.version = XVID_VERSION; single.bitrate = codec->config.bitrate * CONFIG_KBPS; 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 = 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; 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; case RC_MODE_2PASS2 : memset(&pass2, 0, sizeof(pass2)); pass2.version = XVID_VERSION; if (codec->config.use_2pass_bitrate) { pass2.bitrate = codec->config.bitrate * CONFIG_KBPS; } 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; pass2.overflow_control_strength = codec->config.overflow_control_strength; pass2.max_overflow_improvement = codec->config.twopass_max_overflow_improvement; pass2.max_overflow_degradation = codec->config.twopass_max_overflow_degradation; pass2.kfreduction = codec->config.kfreduction; pass2.kfthreshold = codec->config.kfthreshold; pass2.container_frame_overhead = 24; /* AVI */ plugins[create.num_plugins].func = codec->xvid_plugin_2pass2_func; plugins[create.num_plugins].param = &pass2; create.num_plugins++; break; case RC_MODE_NULL : return ICERR_OK; default : 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 = codec->xvid_plugin_lumimasking_func; plugins[create.num_plugins].param = NULL; create.num_plugins++; } plugins[create.num_plugins].func = vfw_debug; plugins[create.num_plugins].param = NULL; create.num_plugins++; create.profile = profiles[codec->config.profile].id; create.width = lpbiInput->bmiHeader.biWidth; create.height = lpbiInput->bmiHeader.biHeight; create.fincr = codec->fincr; create.fbase = codec->fbase; create.max_key_interval = codec->config.max_key_interval; create.min_quant[0] = codec->config.min_iquant; create.max_quant[0] = codec->config.max_iquant; create.min_quant[1] = codec->config.min_pquant; create.max_quant[1] = codec->config.max_pquant; create.min_quant[2] = codec->config.min_bquant; create.max_quant[2] = codec->config.max_bquant; if ((profiles[codec->config.profile].flags & PROFILE_BVOP) && codec->config.use_bvop) { create.max_bframes = codec->config.max_bframes; create.bquant_ratio = codec->config.bquant_ratio; create.bquant_offset = codec->config.bquant_offset; if (codec->config.packed) create.global |= XVID_GLOBAL_PACKED; if (codec->config.closed_gov) create.global |= XVID_GLOBAL_CLOSED_GOP; } create.frame_drop_ratio = codec->config.frame_drop_ratio; create.num_threads = codec->config.num_threads; switch(codec->xvid_encore_func(0, XVID_ENC_CREATE, &create, NULL)) { case XVID_ERR_FAIL : return ICERR_ERROR; case XVID_ERR_MEMORY : return ICERR_MEMORY; case XVID_ERR_FORMAT : return ICERR_BADFORMAT; case XVID_ERR_VERSION : return ICERR_UNSUPPORTED; } free(create.zones); codec->ehandle = create.handle; codec->framenum = 0; codec->keyspacing = 0; if (codec->config.display_status) { status_destroy_always(&codec->status); status_create(&codec->status, codec->fincr, codec->fbase); } return ICERR_OK; }
/* __declspec(dllexport) */ LRESULT WINAPI DriverProc( DWORD_PTR dwDriverId, HDRVR hDriver, UINT uMsg, LPARAM lParam1, LPARAM lParam2) { CODEC * codec = (CODEC *)dwDriverId; switch(uMsg) { /* driver primitives */ case DRV_LOAD : case DRV_FREE : return DRVCNF_OK; case DRV_OPEN : DPRINTF("DRV_OPEN"); { ICOPEN * icopen = (ICOPEN *)lParam2; if (icopen != NULL && icopen->fccType != ICTYPE_VIDEO) { return DRVCNF_CANCEL; } codec = malloc(sizeof(CODEC)); if (codec == NULL) { if (icopen != NULL) { icopen->dwError = ICERR_MEMORY; } return 0; } memset(codec, 0, sizeof(CODEC)); codec->status.hDlg = NULL; codec->config.ci_valid = 0; codec->ehandle = codec->dhandle = NULL; codec->fbase = 25; codec->fincr = 1; config_reg_get(&codec->config); #if 0 /* bad things happen if this piece of code is activated */ if (lstrcmp(XVID_BUILD, codec->config.build)) { config_reg_default(&codec->config); } #endif if (icopen != NULL) { icopen->dwError = ICERR_OK; } return (LRESULT)codec; } case DRV_CLOSE : DPRINTF("DRV_CLOSE"); /* compress_end/decompress_end don't always get called */ compress_end(codec); decompress_end(codec); clean_dll_bindings(codec); status_destroy_always(&codec->status); free(codec); return DRVCNF_OK; case DRV_DISABLE : case DRV_ENABLE : return DRVCNF_OK; case DRV_INSTALL : case DRV_REMOVE : return DRVCNF_OK; case DRV_QUERYCONFIGURE : case DRV_CONFIGURE : return DRVCNF_CANCEL; /* info */ case ICM_GETINFO : DPRINTF("ICM_GETINFO"); if (lParam1 && lParam2 >= sizeof(ICINFO)) { ICINFO *icinfo = (ICINFO *)lParam1; icinfo->fccType = ICTYPE_VIDEO; icinfo->fccHandler = FOURCC_XVID; icinfo->dwFlags = VIDCF_FASTTEMPORALC | VIDCF_FASTTEMPORALD | VIDCF_COMPRESSFRAMES; icinfo->dwVersion = 0; #if !defined(ICVERSION) #define ICVERSION 0x0104 #endif icinfo->dwVersionICM = ICVERSION; wcscpy(icinfo->szName, XVID_NAME_L); wcscpy(icinfo->szDescription, XVID_DESC_L); return lParam2; /* size of struct */ } return 0; /* error */ /* state control */ case ICM_ABOUT : DPRINTF("ICM_ABOUT"); DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), (HWND)lParam1, about_proc, 0); return ICERR_OK; case ICM_CONFIGURE : DPRINTF("ICM_CONFIGURE"); if (lParam1 != -1) { CONFIG temp; codec->config.save = FALSE; memcpy(&temp, &codec->config, sizeof(CONFIG)); DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_MAIN), (HWND)lParam1, main_proc, (LPARAM)&temp); if (temp.save) { memcpy(&codec->config, &temp, sizeof(CONFIG)); config_reg_set(&codec->config); } } return ICERR_OK; case ICM_GETSTATE : DPRINTF("ICM_GETSTATE"); if ((void*)lParam1 == NULL) { return sizeof(CONFIG); } memcpy((void*)lParam1, &codec->config, sizeof(CONFIG)); return ICERR_OK; case ICM_SETSTATE : DPRINTF("ICM_SETSTATE"); if ((void*)lParam1 == NULL) { DPRINTF("ICM_SETSTATE : DEFAULT"); config_reg_get(&codec->config); return 0; } memcpy(&codec->config,(void*)lParam1, sizeof(CONFIG)); return 0; /* sizeof(CONFIG); */ /* not sure the difference, private/public data? */ case ICM_GET : case ICM_SET : return ICERR_OK; /* older-stype config */ case ICM_GETDEFAULTQUALITY : case ICM_GETQUALITY : case ICM_SETQUALITY : case ICM_GETBUFFERSWANTED : case ICM_GETDEFAULTKEYFRAMERATE : return ICERR_UNSUPPORTED; /* compressor */ case ICM_COMPRESS_QUERY : DPRINTF("ICM_COMPRESS_QUERY"); return compress_query(codec, (BITMAPINFO *)lParam1, (BITMAPINFO *)lParam2); case ICM_COMPRESS_GET_FORMAT : DPRINTF("ICM_COMPRESS_GET_FORMAT"); return compress_get_format(codec, (BITMAPINFO *)lParam1, (BITMAPINFO *)lParam2); case ICM_COMPRESS_GET_SIZE : DPRINTF("ICM_COMPRESS_GET_SIZE"); return compress_get_size(codec, (BITMAPINFO *)lParam1, (BITMAPINFO *)lParam2); case ICM_COMPRESS_FRAMES_INFO : DPRINTF("ICM_COMPRESS_FRAMES_INFO"); return compress_frames_info(codec, (ICCOMPRESSFRAMES *)lParam1); case ICM_COMPRESS_BEGIN : DPRINTF("ICM_COMPRESS_BEGIN"); return compress_begin(codec, (BITMAPINFO *)lParam1, (BITMAPINFO *)lParam2); case ICM_COMPRESS_END : DPRINTF("ICM_COMPRESS_END"); return compress_end(codec); case ICM_COMPRESS : DPRINTF("ICM_COMPRESS"); return compress(codec, (ICCOMPRESS *)lParam1); /* decompressor */ case ICM_DECOMPRESS_QUERY : DPRINTF("ICM_DECOMPRESS_QUERY"); return decompress_query(codec, (BITMAPINFO *)lParam1, (BITMAPINFO *)lParam2); case ICM_DECOMPRESS_GET_FORMAT : DPRINTF("ICM_DECOMPRESS_GET_FORMAT"); return decompress_get_format(codec, (BITMAPINFO *)lParam1, (BITMAPINFO *)lParam2); case ICM_DECOMPRESS_BEGIN : DPRINTF("ICM_DECOMPRESS_BEGIN"); return decompress_begin(codec, (BITMAPINFO *)lParam1, (BITMAPINFO *)lParam2); case ICM_DECOMPRESS_END : DPRINTF("ICM_DECOMPRESS_END"); return decompress_end(codec); case ICM_DECOMPRESS : DPRINTF("ICM_DECOMPRESS"); return decompress(codec, (ICDECOMPRESS *)lParam1); case ICM_DECOMPRESS_GET_PALETTE : case ICM_DECOMPRESS_SET_PALETTE : case ICM_DECOMPRESSEX_QUERY: case ICM_DECOMPRESSEX_BEGIN: case ICM_DECOMPRESSEX_END: case ICM_DECOMPRESSEX: return ICERR_UNSUPPORTED; /* VFWEXT entry point */ case ICM_USER+0x0fff : if (lParam1 == VFWEXT_CONFIGURE_INFO) { VFWEXT_CONFIGURE_INFO_T * info = (VFWEXT_CONFIGURE_INFO_T*)lParam2; DPRINTF("%i %i %i %i %i %i", info->ciWidth, info->ciHeight, info->ciRate, info->ciScale, info->ciActiveFrame, info->ciFrameCount); codec->config.ci_valid = 1; memcpy(&codec->config.ci, (void*)lParam2, sizeof(VFWEXT_CONFIGURE_INFO_T)); return ICERR_OK; } return ICERR_UNSUPPORTED; default: if (uMsg < DRV_USER) return DefDriverProc(dwDriverId, hDriver, uMsg, lParam1, lParam2); else return ICERR_UNSUPPORTED; } }
LRESULT compress_begin(CODEC * codec, BITMAPINFO * lpbiInput, BITMAPINFO * lpbiOutput) { xvid_gbl_init_t init; xvid_enc_create_t create; xvid_enc_plugin_t plugins[3]; xvid_plugin_single_t single; xvid_plugin_2pass1_t pass1; xvid_plugin_2pass2_t pass2; xvid_plugin_lumimasking_t masking; xvid_gbl_info_t info; int i; HANDLE hFile; const quality_t* quality_preset = (codec->config.quality==quality_table_num) ? &codec->config.quality_user : &quality_table[codec->config.quality]; 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(codec) != 0) return ICERR_ERROR; /* destroy previously created codec */ if(codec->ehandle) { codec->xvid_encore_func(codec->ehandle, XVID_ENC_DESTROY, NULL, NULL); codec->ehandle = NULL; } memset(&init, 0, sizeof(init)); init.version = XVID_VERSION; init.cpu_flags = codec->config.cpu; init.debug = codec->config.debug; codec->xvid_global_func(0, XVID_GBL_INIT, &init, NULL); memset(&info, 0, sizeof(info)); info.version = XVID_VERSION; codec->xvid_global_func(0, XVID_GBL_INFO, &info, NULL); memset(&create, 0, sizeof(create)); create.version = XVID_VERSION; /* Encoder threads */ if (codec->config.cpu & XVID_CPU_FORCE) create.num_threads = codec->config.num_threads; else create.num_threads = info.num_threads; /* Autodetect */ /* Encoder slices */ if ((profiles[codec->config.profile].flags & PROFILE_RESYNCMARKER) && codec->config.num_slices != 1) { if (codec->config.num_slices == 0) { /* auto */ int mb_width = (lpbiInput->bmiHeader.biWidth + 15) / 16; int mb_height = (lpbiInput->bmiHeader.biHeight + 15) / 16; int slices = (int)((mb_width*mb_height) / 811); /* use multiple slices only above SD resolutions for now */ if (slices > 1) { if (create.num_threads <= 1) slices &= ~1; /* make even */ else if (create.num_threads <= slices) slices = (slices / create.num_threads) * create.num_threads; /* multiple of threads */ else if (create.num_threads % slices) slices = (!(create.num_threads%2)) ? (create.num_threads/2) : (create.num_threads/3); } create.num_slices = slices; } else { create.num_slices = codec->config.num_slices; /* force manual value - by registry edit */ } } /* plugins */ create.plugins = plugins; switch (codec->config.mode) { case RC_MODE_1PASS : memset(&single, 0, sizeof(single)); single.version = XVID_VERSION; single.bitrate = codec->config.bitrate * CONFIG_KBPS; 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 = 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; 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; case RC_MODE_2PASS2 : memset(&pass2, 0, sizeof(pass2)); pass2.version = XVID_VERSION; if (codec->config.use_2pass_bitrate) { pass2.bitrate = codec->config.bitrate * CONFIG_KBPS; } 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; pass2.overflow_control_strength = codec->config.overflow_control_strength; pass2.max_overflow_improvement = codec->config.twopass_max_overflow_improvement; pass2.max_overflow_degradation = codec->config.twopass_max_overflow_degradation; pass2.kfreduction = codec->config.kfreduction; pass2.kfthreshold = codec->config.kfthreshold; pass2.container_frame_overhead = 24; /* AVI */ /* VBV */ pass2.vbv_size = profiles[codec->config.profile].max_vbv_size; pass2.vbv_initial = (profiles[codec->config.profile].max_vbv_size*3)/4; /* 75% */ pass2.vbv_maxrate = profiles[codec->config.profile].max_bitrate; pass2.vbv_peakrate = profiles[codec->config.profile].vbv_peakrate; plugins[create.num_plugins].func = codec->xvid_plugin_2pass2_func; plugins[create.num_plugins].param = &pass2; create.num_plugins++; break; case RC_MODE_NULL : return ICERR_OK; default : 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>0)) { memset(&masking, 0, sizeof(masking)); masking.method = (codec->config.lum_masking==2); plugins[create.num_plugins].func = codec->xvid_plugin_lumimasking_func; plugins[create.num_plugins].param = &masking; create.num_plugins++; } plugins[create.num_plugins].func = vfw_debug; plugins[create.num_plugins].param = NULL; create.num_plugins++; create.profile = profiles[codec->config.profile].id; create.width = lpbiInput->bmiHeader.biWidth; create.height = lpbiInput->bmiHeader.biHeight; create.fincr = codec->fincr; create.fbase = codec->fbase; create.max_key_interval = quality_preset->max_key_interval; create.min_quant[0] = quality_preset->min_iquant; create.max_quant[0] = quality_preset->max_iquant; create.min_quant[1] = quality_preset->min_pquant; create.max_quant[1] = quality_preset->max_pquant; create.min_quant[2] = quality_preset->min_bquant; create.max_quant[2] = quality_preset->max_bquant; if ((profiles[codec->config.profile].flags & PROFILE_BVOP) && codec->config.use_bvop) { /* dxn: prevent bframes usage if interlacing is selected */ if (!((profiles[codec->config.profile].flags & PROFILE_EXTRA) && codec->config.interlacing)) { create.max_bframes = codec->config.max_bframes; create.bquant_ratio = codec->config.bquant_ratio; create.bquant_offset = codec->config.bquant_offset; if (codec->config.packed) create.global |= XVID_GLOBAL_PACKED; create.global |= XVID_GLOBAL_CLOSED_GOP; /* restrict max bframes */ if ((create.max_bframes > profiles[codec->config.profile].xvid_max_bframes) && (profiles[codec->config.profile].xvid_max_bframes >= 0)) create.max_bframes = profiles[codec->config.profile].xvid_max_bframes; /* DXN: enable packed bframes */ if ((profiles[codec->config.profile].flags & PROFILE_PACKED)) { create.global |= XVID_GLOBAL_PACKED; } } } /* dxn: always write divx5 userdata */ if ((profiles[codec->config.profile].flags & PROFILE_EXTRA)) create.global |= XVID_GLOBAL_DIVX5_USERDATA; if ((profiles[codec->config.profile].flags & PROFILE_EXTRA) || (profiles[codec->config.profile].flags & PROFILE_XVID)) { create.frame_drop_ratio = 0; } else { create.frame_drop_ratio = quality_preset->frame_drop_ratio; } switch(codec->xvid_encore_func(0, XVID_ENC_CREATE, &create, NULL)) { case XVID_ERR_FAIL : return ICERR_ERROR; case XVID_ERR_MEMORY : return ICERR_MEMORY; case XVID_ERR_FORMAT : return ICERR_BADFORMAT; case XVID_ERR_VERSION : return ICERR_UNSUPPORTED; } free(create.zones); codec->ehandle = create.handle; codec->framenum = 0; codec->keyspacing = 0; if (codec->config.display_status) { status_destroy_always(&codec->status); status_create(&codec->status, codec->fincr, codec->fbase); } return ICERR_OK; }