X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=vp8%2Fencoder%2Fonyx_if.c;h=9227f750d55979b572d6d6be054069c9e9ae972f;hb=ff42e04f9cb60e63ca3fe12ac497f27c68555e1f;hp=49ee37a5b5145debdde5bd41fa5528cab0b2b7ab;hpb=bde905cba1ab29346706b0d706d97a00a6a441ae;p=libvpx diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 49ee37a5b..9227f750d 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -16,6 +16,7 @@ #include "vp8/common/blockd.h" #include "onyx_int.h" #include "vp8/common/systemdependent.h" +#include "vp8/common/skin_detection.h" #include "vp8/encoder/quantize.h" #include "vp8/common/alloccommon.h" #include "mcomp.h" @@ -43,6 +44,7 @@ #endif #include "encodeframe.h" +#include #include #include #include @@ -86,6 +88,9 @@ FILE *yuv_file; #ifdef OUTPUT_YUV_DENOISED FILE *yuv_denoised_file; #endif +#ifdef OUTPUT_YUV_SKINMAP +FILE *yuv_skinmap_file = NULL; +#endif #if 0 FILE *framepsnr; @@ -446,6 +451,18 @@ static void dealloc_compressor_data(VP8_COMP *cpi) { cpi->mb.pip = 0; #if CONFIG_MULTITHREAD + /* De-allocate mutex */ + if (cpi->pmutex != NULL) { + VP8_COMMON *const pc = &cpi->common; + int i; + + for (i = 0; i < pc->mb_rows; ++i) { + pthread_mutex_destroy(&cpi->pmutex[i]); + } + vpx_free(cpi->pmutex); + cpi->pmutex = NULL; + } + vpx_free(cpi->mt_current_mb_col); cpi->mt_current_mb_col = NULL; #endif @@ -715,6 +732,7 @@ void vp8_set_speed_features(VP8_COMP *cpi) { SPEED_FEATURES *sf = &cpi->sf; int Mode = cpi->compressor_speed; int Speed = cpi->Speed; + int Speed2; int i; VP8_COMMON *cm = &cpi->common; int last_improved_quant = sf->improved_quant; @@ -816,9 +834,16 @@ void vp8_set_speed_features(VP8_COMP *cpi) { cpi->mode_check_freq[THR_V_PRED] = cpi->mode_check_freq[THR_H_PRED] = cpi->mode_check_freq[THR_B_PRED] = speed_map(Speed, mode_check_freq_map_vhbpred); - cpi->mode_check_freq[THR_NEW1] = speed_map(Speed, mode_check_freq_map_new1); + + // For real-time mode at speed 10 keep the mode_check_freq threshold + // for NEW1 similar to that of speed 9. + Speed2 = Speed; + if (cpi->Speed == 10 && Mode == 2) Speed2 = RT(9); + cpi->mode_check_freq[THR_NEW1] = speed_map(Speed2, mode_check_freq_map_new1); + cpi->mode_check_freq[THR_NEW2] = cpi->mode_check_freq[THR_NEW3] = speed_map(Speed, mode_check_freq_map_new2); + cpi->mode_check_freq[THR_SPLIT1] = speed_map(Speed, mode_check_freq_map_split1); cpi->mode_check_freq[THR_SPLIT2] = cpi->mode_check_freq[THR_SPLIT3] = @@ -1075,6 +1100,9 @@ void vp8_alloc_compressor_data(VP8_COMP *cpi) { int width = cm->Width; int height = cm->Height; +#if CONFIG_MULTITHREAD + int prev_mb_rows = cm->mb_rows; +#endif if (vp8_alloc_frame_buffers(cm, width, height)) { vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, @@ -1164,6 +1192,25 @@ void vp8_alloc_compressor_data(VP8_COMP *cpi) { } if (cpi->oxcf.multi_threaded > 1) { + int i; + + /* De-allocate and re-allocate mutex */ + if (cpi->pmutex != NULL) { + for (i = 0; i < prev_mb_rows; ++i) { + pthread_mutex_destroy(&cpi->pmutex[i]); + } + vpx_free(cpi->pmutex); + cpi->pmutex = NULL; + } + + CHECK_MEM_ERROR(cpi->pmutex, + vpx_malloc(sizeof(*cpi->pmutex) * cm->mb_rows)); + if (cpi->pmutex) { + for (i = 0; i < cm->mb_rows; ++i) { + pthread_mutex_init(&cpi->pmutex[i], NULL); + } + } + vpx_free(cpi->mt_current_mb_col); CHECK_MEM_ERROR(cpi->mt_current_mb_col, vpx_malloc(sizeof(*cpi->mt_current_mb_col) * cm->mb_rows)); @@ -1467,6 +1514,12 @@ void vp8_change_config(VP8_COMP *cpi, VP8_CONFIG *oxcf) { cpi->baseline_gf_interval = cpi->oxcf.alt_freq ? cpi->oxcf.alt_freq : DEFAULT_GF_INTERVAL; + // GF behavior for 1 pass CBR, used when error_resilience is off. + if (!cpi->oxcf.error_resilient_mode && + cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER && + cpi->oxcf.Mode == MODE_REALTIME) + cpi->baseline_gf_interval = cpi->gf_interval_onepass_cbr; + #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING) cpi->oxcf.token_partitions = 3; #endif @@ -1593,8 +1646,7 @@ void vp8_change_config(VP8_COMP *cpi, VP8_CONFIG *oxcf) { cm->sharpness_level = cpi->oxcf.Sharpness; if (cm->horiz_scale != NORMAL || cm->vert_scale != NORMAL) { - int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs); - int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs); + int hr, hs, vr, vs; Scale2Ratio(cm->horiz_scale, &hr, &hs); Scale2Ratio(cm->vert_scale, &vr, &vs); @@ -1766,9 +1818,13 @@ struct VP8_COMP *vp8_create_compressor(VP8_CONFIG *oxcf) { cpi->mse_source_denoised = 0; /* Should we use the cyclic refresh method. - * Currently this is tied to error resilliant mode + * Currently there is no external control for this. + * Enable it for error_resilient_mode, or for 1 pass CBR mode. */ - cpi->cyclic_refresh_mode_enabled = cpi->oxcf.error_resilient_mode; + cpi->cyclic_refresh_mode_enabled = + (cpi->oxcf.error_resilient_mode || + (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER && + cpi->oxcf.Mode <= 2)); cpi->cyclic_refresh_mode_max_mbs_perframe = (cpi->common.mb_rows * cpi->common.mb_cols) / 7; if (cpi->oxcf.number_of_layers == 1) { @@ -1781,6 +1837,23 @@ struct VP8_COMP *vp8_create_compressor(VP8_CONFIG *oxcf) { cpi->cyclic_refresh_mode_index = 0; cpi->cyclic_refresh_q = 32; + // GF behavior for 1 pass CBR, used when error_resilience is off. + cpi->gf_update_onepass_cbr = 0; + cpi->gf_noboost_onepass_cbr = 0; + if (!cpi->oxcf.error_resilient_mode && + cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER && cpi->oxcf.Mode <= 2) { + cpi->gf_update_onepass_cbr = 1; + cpi->gf_noboost_onepass_cbr = 1; + cpi->gf_interval_onepass_cbr = + cpi->cyclic_refresh_mode_max_mbs_perframe > 0 + ? (2 * (cpi->common.mb_rows * cpi->common.mb_cols) / + cpi->cyclic_refresh_mode_max_mbs_perframe) + : 10; + cpi->gf_interval_onepass_cbr = + VPXMIN(40, VPXMAX(6, cpi->gf_interval_onepass_cbr)); + cpi->baseline_gf_interval = cpi->gf_interval_onepass_cbr; + } + if (cpi->cyclic_refresh_mode_enabled) { CHECK_MEM_ERROR(cpi->cyclic_refresh_map, vpx_calloc((cpi->common.mb_rows * cpi->common.mb_cols), 1)); @@ -1864,6 +1937,9 @@ struct VP8_COMP *vp8_create_compressor(VP8_CONFIG *oxcf) { #ifdef OUTPUT_YUV_DENOISED yuv_denoised_file = fopen("denoised.yuv", "ab"); #endif +#ifdef OUTPUT_YUV_SKINMAP + yuv_skinmap_file = fopen("skinmap.yuv", "ab"); +#endif #if 0 framepsnr = fopen("framepsnr.stt", "a"); @@ -2029,11 +2105,7 @@ void vp8_remove_compressor(VP8_COMP **ptr) { double time_encoded = (cpi->last_end_time_stamp_seen - cpi->first_time_stamp_ever) / 10000000.000; - double total_encode_time = - (cpi->time_receive_data + cpi->time_compress_data) / 1000.000; double dr = (double)cpi->bytes * 8.0 / 1000.0 / time_encoded; - const double target_rate = (double)cpi->oxcf.target_bandwidth / 1000; - const double rate_err = ((100.0 * (dr - target_rate)) / target_rate); if (cpi->b_calculate_psnr) { if (cpi->oxcf.number_of_layers > 1) { @@ -2041,7 +2113,7 @@ void vp8_remove_compressor(VP8_COMP **ptr) { fprintf(f, "Layer\tBitrate\tAVGPsnr\tGLBPsnr\tAVPsnrP\t" - "GLPsnrP\tVPXSSIM\t\n"); + "GLPsnrP\tVPXSSIM\n"); for (i = 0; i < (int)cpi->oxcf.number_of_layers; ++i) { double dr = (double)cpi->bytes_in_layer[i] * 8.0 / 1000.0 / time_encoded; @@ -2073,14 +2145,12 @@ void vp8_remove_compressor(VP8_COMP **ptr) { fprintf(f, "Bitrate\tAVGPsnr\tGLBPsnr\tAVPsnrP\t" - "GLPsnrP\tVPXSSIM\tTime(us)\tRc-Err\t" - "Abs Err\n"); + "GLPsnrP\tVPXSSIM\n"); fprintf(f, "%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t" - "%7.3f\t%8.0f\t%7.2f\t%7.2f\n", + "%7.3f\n", dr, cpi->total / cpi->count, total_psnr, - cpi->totalp / cpi->count, total_psnr2, total_ssim, - total_encode_time, rate_err, fabs(rate_err)); + cpi->totalp / cpi->count, total_psnr2, total_ssim); } } fclose(f); @@ -2235,6 +2305,9 @@ void vp8_remove_compressor(VP8_COMP **ptr) { #ifdef OUTPUT_YUV_DENOISED fclose(yuv_denoised_file); #endif +#ifdef OUTPUT_YUV_SKINMAP + fclose(yuv_skinmap_file); +#endif #if 0 @@ -2411,10 +2484,11 @@ int vp8_update_entropy(VP8_COMP *cpi, int update) { return 0; } -#if defined(OUTPUT_YUV_SRC) || defined(OUTPUT_YUV_DENOISED) +#if defined(OUTPUT_YUV_SRC) || defined(OUTPUT_YUV_DENOISED) || \ + defined(OUTPUT_YUV_SKINMAP) void vp8_write_yuv_frame(FILE *yuv_file, YV12_BUFFER_CONFIG *s) { unsigned char *src = s->y_buffer; - int h = s->y_height; + int h = s->y_crop_height; do { fwrite(src, s->y_width, 1, yuv_file); @@ -2422,7 +2496,7 @@ void vp8_write_yuv_frame(FILE *yuv_file, YV12_BUFFER_CONFIG *s) { } while (--h); src = s->u_buffer; - h = s->uv_height; + h = s->uv_crop_height; do { fwrite(src, s->uv_width, 1, yuv_file); @@ -2430,7 +2504,7 @@ void vp8_write_yuv_frame(FILE *yuv_file, YV12_BUFFER_CONFIG *s) { } while (--h); src = s->v_buffer; - h = s->uv_height; + h = s->uv_crop_height; do { fwrite(src, s->uv_width, 1, yuv_file); @@ -2445,8 +2519,7 @@ static void scale_and_extend_source(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) { /* are we resizing the image */ if (cm->horiz_scale != 0 || cm->vert_scale != 0) { #if CONFIG_SPATIAL_RESAMPLING - int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs); - int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs); + int hr, hs, vr, vs; int tmp_height; if (cm->vert_scale == 3) { @@ -2479,8 +2552,7 @@ static int resize_key_frame(VP8_COMP *cpi) { */ if (cpi->oxcf.allow_spatial_resampling && (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER)) { - int UNINITIALIZED_IS_SAFE(hr), UNINITIALIZED_IS_SAFE(hs); - int UNINITIALIZED_IS_SAFE(vr), UNINITIALIZED_IS_SAFE(vs); + int hr, hs, vr, vs; int new_width, new_height; /* If we are below the resample DOWN watermark then scale down a @@ -2996,6 +3068,7 @@ static int measure_square_diff_partial(YV12_BUFFER_CONFIG *source, } // Only return non-zero if we have at least ~1/16 samples for estimate. if (num_blocks > (tot_num_blocks >> 4)) { + assert(num_blocks != 0); return (Total / num_blocks); } else { return 0; @@ -3927,7 +4000,6 @@ static void encode_frame_to_data_rate(VP8_COMP *cpi, size_t *size, #else /* transform / motion compensation build reconstruction frame */ vp8_encode_frame(cpi); - if (cpi->oxcf.screen_content_mode == 2) { if (vp8_drop_encodedframe_overshoot(cpi, Q)) return; } @@ -4004,9 +4076,9 @@ static void encode_frame_to_data_rate(VP8_COMP *cpi, size_t *size, #if !CONFIG_REALTIME_ONLY top_index = cpi->active_worst_quality; #endif // !CONFIG_REALTIME_ONLY - /* If we have updated the active max Q do not call - * vp8_update_rate_correction_factors() this loop. - */ + /* If we have updated the active max Q do not call + * vp8_update_rate_correction_factors() this loop. + */ active_worst_qchanged = 1; } else { active_worst_qchanged = 0; @@ -4205,6 +4277,20 @@ static void encode_frame_to_data_rate(VP8_COMP *cpi, size_t *size, } } while (Loop == 1); +#if defined(DROP_UNCODED_FRAMES) + /* if there are no coded macroblocks at all drop this frame */ + if (cpi->common.MBs == cpi->mb.skip_true_count && + (cpi->drop_frame_count & 7) != 7 && cm->frame_type != KEY_FRAME) { + cpi->common.current_video_frame++; + cpi->frames_since_key++; + cpi->drop_frame_count++; + // We advance the temporal pattern for dropped frames. + cpi->temporal_pattern_counter++; + return; + } + cpi->drop_frame_count = 0; +#endif + #if 0 /* Experimental code for lagged and one pass * Update stats used for one pass GF selection @@ -4346,6 +4432,12 @@ static void encode_frame_to_data_rate(VP8_COMP *cpi, size_t *size, } #endif +#ifdef OUTPUT_YUV_SKINMAP + if (cpi->common.current_video_frame > 1) { + compute_skin_map(cpi, yuv_skinmap_file); + } +#endif + #if CONFIG_MULTITHREAD if (cpi->b_multi_threaded) { /* start loopfilter in separate thread */