#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"
#endif
#include "encodeframe.h"
+#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <limits.h>
#ifdef OUTPUT_YUV_DENOISED
FILE *yuv_denoised_file;
#endif
+#ifdef OUTPUT_YUV_SKINMAP
+FILE *yuv_skinmap_file = NULL;
+#endif
#if 0
FILE *framepsnr;
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
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;
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] =
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,
}
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));
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
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);
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));
#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");
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) {
#ifdef OUTPUT_YUV_DENOISED
fclose(yuv_denoised_file);
#endif
+#ifdef OUTPUT_YUV_SKINMAP
+ fclose(yuv_skinmap_file);
+#endif
#if 0
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);
} while (--h);
src = s->u_buffer;
- h = s->uv_height;
+ h = s->uv_crop_height;
do {
fwrite(src, s->uv_width, 1, yuv_file);
} while (--h);
src = s->v_buffer;
- h = s->uv_height;
+ h = s->uv_crop_height;
do {
fwrite(src, s->uv_width, 1, yuv_file);
/* 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) {
*/
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
}
// 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;
#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;
}
#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;
}
} 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
}
#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 */