#include "vpx_config.h"
#include "./vpx_scale_rtcd.h"
#include "./vpx_dsp_rtcd.h"
#include "./vp8_rtcd.h"
#include "bitstream.h"
#include "vp8/common/onyxc_int.h"
#include "vp8/common/blockd.h"
#include "onyx_int.h"
#include "vp8/common/systemdependent.h"
#include "vp8/common/vp8_skin_detection.h"
#include "vp8/encoder/quantize.h"
#include "vp8/common/alloccommon.h"
#include "mcomp.h"
#include "firstpass.h"
#include "vpx_dsp/psnr.h"
#include "vpx_scale/vpx_scale.h"
#include "vp8/common/extend.h"
#include "ratectrl.h"
#include "vp8/common/quant_common.h"
#include "segmentation.h"
#if CONFIG_POSTPROC
#include "vp8/common/postproc.h"
#endif
#include "vpx_mem/vpx_mem.h"
#include "vp8/common/reconintra.h"
#include "vp8/common/swapyv12buffer.h"
#include "vp8/common/threading.h"
#include "vpx_ports/system_state.h"
#include "vpx_ports/vpx_once.h"
#include "vpx_ports/vpx_timer.h"
#include "vpx_util/vpx_write_yuv_frame.h"
#if VPX_ARCH_ARM
#include "vpx_ports/arm.h"
#endif
#if CONFIG_MULTI_RES_ENCODING
#include "mr_dissim.h"
#endif
#include "encodeframe.h"
#if CONFIG_MULTITHREAD
#include "ethreading.h"
#endif
#include "picklpf.h"
#if !CONFIG_REALTIME_ONLY
#include "temporal_filter.h"
#endif
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <limits.h>
#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
extern int vp8_update_coef_context(VP8_COMP *cpi);
#endif
extern unsigned int vp8_get_processor_freq(void);
int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest);
static void set_default_lf_deltas(VP8_COMP *cpi);
extern const int vp8_gf_interval_table[101];
#if CONFIG_INTERNAL_STATS
#include "math.h"
#include "vpx_dsp/ssim.h"
#endif
#ifdef OUTPUT_YUV_SRC
FILE *yuv_file;
#endif
#ifdef OUTPUT_YUV_DENOISED
FILE *yuv_denoised_file;
#endif
#ifdef OUTPUT_YUV_SKINMAP
static FILE *yuv_skinmap_file = NULL;
#endif
#if 0
FILE *framepsnr;
FILE *kf_list;
FILE *keyfile;
#endif
#if 0
extern int skip_true_count;
extern int skip_false_count;
#endif
#ifdef SPEEDSTATS
unsigned int frames_at_speed[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 };
unsigned int tot_pm = 0;
unsigned int cnt_pm = 0;
unsigned int tot_ef = 0;
unsigned int cnt_ef = 0;
#endif
#ifdef MODE_STATS
extern unsigned __int64 Sectionbits[50];
extern int y_modes[5];
extern int uv_modes[4];
extern int b_modes[10];
extern int inter_y_modes[10];
extern int inter_uv_modes[4];
extern unsigned int inter_b_modes[15];
#endif
extern const int vp8_bits_per_mb[2][QINDEX_RANGE];
extern const int qrounding_factors[129];
extern const int qzbin_factors[129];
extern void vp8cx_init_quantizer(VP8_COMP *cpi);
extern const int vp8cx_base_skip_false_prob[128];
static const unsigned char kf_low_motion_minq[QINDEX_RANGE] = …;
static const unsigned char kf_high_motion_minq[QINDEX_RANGE] = …;
static const unsigned char gf_low_motion_minq[QINDEX_RANGE] = …;
static const unsigned char gf_mid_motion_minq[QINDEX_RANGE] = …;
static const unsigned char gf_high_motion_minq[QINDEX_RANGE] = …;
static const unsigned char inter_minq[QINDEX_RANGE] = …;
#ifdef PACKET_TESTING
extern FILE *vpxlogc;
#endif
void vp8_save_layer_context(VP8_COMP *cpi) { … }
void vp8_restore_layer_context(VP8_COMP *cpi, const int layer) { … }
static int rescale(int val, int num, int denom) { … }
void vp8_init_temporal_layer_context(VP8_COMP *cpi, const VP8_CONFIG *oxcf,
const int layer,
double prev_layer_framerate) { … }
void vp8_reset_temporal_layer_change(VP8_COMP *cpi, const VP8_CONFIG *oxcf,
const int prev_num_layers) { … }
static void setup_features(VP8_COMP *cpi) { … }
static void dealloc_raw_frame_buffers(VP8_COMP *cpi);
static void initialize_enc(void) { … }
void vp8_initialize_enc(void) { … }
static void dealloc_compressor_data(VP8_COMP *cpi) { … }
static void enable_segmentation(VP8_COMP *cpi) { … }
static void disable_segmentation(VP8_COMP *cpi) { … }
static void set_segmentation_map(VP8_COMP *cpi,
unsigned char *segmentation_map) { … }
static void set_segment_data(VP8_COMP *cpi, signed char *feature_data,
unsigned char abs_delta) { … }
static void cyclic_background_refresh(VP8_COMP *cpi, int Q, int lf_adjustment) { … }
static void compute_skin_map(VP8_COMP *cpi) { … }
static void set_default_lf_deltas(VP8_COMP *cpi) { … }
#define GOOD …
#define RT …
static int speed_map(int speed, const int *map) { … }
static const int thresh_mult_map_znn[] = …;
static const int thresh_mult_map_vhpred[] = …;
static const int thresh_mult_map_bpred[] = …;
static const int thresh_mult_map_tm[] = …;
static const int thresh_mult_map_new1[] = …;
static const int thresh_mult_map_new2[] = …;
static const int thresh_mult_map_split1[] = …;
static const int thresh_mult_map_split2[] = …;
static const int mode_check_freq_map_zn2[] = …;
static const int mode_check_freq_map_vhbpred[] = …;
static const int mode_check_freq_map_near2[] = …;
static const int mode_check_freq_map_new1[] = …;
static const int mode_check_freq_map_new2[] = …;
static const int mode_check_freq_map_split1[] = …;
static const int mode_check_freq_map_split2[] = …;
void vp8_set_speed_features(VP8_COMP *cpi) { … }
#undef GOOD
#undef RT
static void alloc_raw_frame_buffers(VP8_COMP *cpi) { … }
static void dealloc_raw_frame_buffers(VP8_COMP *cpi) { … }
static int vp8_alloc_partition_data(VP8_COMP *cpi) { … }
void vp8_alloc_compressor_data(VP8_COMP *cpi) { … }
static const int q_trans[] = …;
int vp8_reverse_trans(int x) { … }
void vp8_new_framerate(VP8_COMP *cpi, double framerate) { … }
static void init_config(VP8_COMP *cpi, const VP8_CONFIG *oxcf) { … }
void vp8_update_layer_contexts(VP8_COMP *cpi) { … }
void vp8_change_config(VP8_COMP *cpi, const VP8_CONFIG *oxcf) { … }
#ifndef M_LOG2_E
#define M_LOG2_E …
#endif
#define log2f(x) …
static void cal_mvsadcosts(int *mvsadcost[2]) { … }
struct VP8_COMP *vp8_create_compressor(const VP8_CONFIG *oxcf) { … }
void vp8_remove_compressor(VP8_COMP **comp) { … }
static uint64_t calc_plane_error(unsigned char *orig, int orig_stride,
unsigned char *recon, int recon_stride,
unsigned int cols, unsigned int rows) { … }
static void generate_psnr_packet(VP8_COMP *cpi) { … }
int vp8_use_as_reference(VP8_COMP *cpi, int ref_frame_flags) { … }
int vp8_update_reference(VP8_COMP *cpi, int ref_frame_flags) { … }
int vp8_get_reference(VP8_COMP *cpi, enum vpx_ref_frame_type ref_frame_flag,
YV12_BUFFER_CONFIG *sd) { … }
int vp8_set_reference(VP8_COMP *cpi, enum vpx_ref_frame_type ref_frame_flag,
YV12_BUFFER_CONFIG *sd) { … }
int vp8_update_entropy(VP8_COMP *cpi, int update) { … }
static void scale_and_extend_source(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) { … }
static int resize_key_frame(VP8_COMP *cpi) { … }
static void update_alt_ref_frame_stats(VP8_COMP *cpi) { … }
static void update_golden_frame_stats(VP8_COMP *cpi) { … }
static void update_rd_ref_frame_probs(VP8_COMP *cpi) { … }
#if !CONFIG_REALTIME_ONLY
static int decide_key_frame(VP8_COMP *cpi) {
VP8_COMMON *cm = &cpi->common;
int code_key_frame = 0;
cpi->kf_boost = 0;
if (cpi->Speed > 11) return 0;
vpx_clear_system_state();
if ((cpi->compressor_speed == 2) && (cpi->Speed >= 5) && (cpi->sf.RD == 0)) {
double change = 1.0 *
abs((int)(cpi->mb.intra_error - cpi->last_intra_error)) /
(1 + cpi->last_intra_error);
double change2 =
1.0 *
abs((int)(cpi->mb.prediction_error - cpi->last_prediction_error)) /
(1 + cpi->last_prediction_error);
double minerror = cm->MBs * 256;
cpi->last_intra_error = cpi->mb.intra_error;
cpi->last_prediction_error = cpi->mb.prediction_error;
if (10 * cpi->mb.intra_error / (1 + cpi->mb.prediction_error) < 15 &&
cpi->mb.prediction_error > minerror &&
(change > .25 || change2 > .25)) {
return 1;
}
return 0;
}
if (((cpi->this_frame_percent_intra == 100) &&
(cpi->this_frame_percent_intra > (cpi->last_frame_percent_intra + 2))) ||
((cpi->this_frame_percent_intra > 95) &&
(cpi->this_frame_percent_intra >=
(cpi->last_frame_percent_intra + 5)))) {
code_key_frame = 1;
}
else if (((cpi->this_frame_percent_intra > 60) &&
(cpi->this_frame_percent_intra >
(cpi->last_frame_percent_intra * 2))) ||
((cpi->this_frame_percent_intra > 75) &&
(cpi->this_frame_percent_intra >
(cpi->last_frame_percent_intra * 3 / 2))) ||
((cpi->this_frame_percent_intra > 90) &&
(cpi->this_frame_percent_intra >
(cpi->last_frame_percent_intra + 10)))) {
if (!cm->refresh_golden_frame) code_key_frame = 1;
}
return code_key_frame;
}
static void Pass1Encode(VP8_COMP *cpi) {
vp8_set_quantizer(cpi, 26);
vp8_first_pass(cpi);
}
#endif
#if 0
void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame)
{
FILE *yframe;
int i;
char filename[255];
sprintf(filename, "cx\\y%04d.raw", this_frame);
yframe = fopen(filename, "wb");
for (i = 0; i < frame->y_height; ++i)
fwrite(frame->y_buffer + i * frame->y_stride, frame->y_width, 1, yframe);
fclose(yframe);
sprintf(filename, "cx\\u%04d.raw", this_frame);
yframe = fopen(filename, "wb");
for (i = 0; i < frame->uv_height; ++i)
fwrite(frame->u_buffer + i * frame->uv_stride, frame->uv_width, 1, yframe);
fclose(yframe);
sprintf(filename, "cx\\v%04d.raw", this_frame);
yframe = fopen(filename, "wb");
for (i = 0; i < frame->uv_height; ++i)
fwrite(frame->v_buffer + i * frame->uv_stride, frame->uv_width, 1, yframe);
fclose(yframe);
}
#endif
#if !CONFIG_REALTIME_ONLY
static int recode_loop_test(VP8_COMP *cpi, int high_limit, int low_limit, int q,
int maxq, int minq) {
int force_recode = 0;
VP8_COMMON *cm = &cpi->common;
if ((cpi->sf.recode_loop == 1) ||
((cpi->sf.recode_loop == 2) &&
((cm->frame_type == KEY_FRAME) || cm->refresh_golden_frame ||
cm->refresh_alt_ref_frame))) {
if (((cpi->projected_frame_size > high_limit) && (q < maxq)) ||
((cpi->projected_frame_size < low_limit) && (q > minq))) {
force_recode = 1;
}
else if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) {
if ((q > cpi->cq_target_quality) &&
(cpi->projected_frame_size < ((cpi->this_frame_target * 7) >> 3))) {
force_recode = 1;
}
else if ((q > cpi->oxcf.cq_level) &&
(cpi->projected_frame_size < cpi->min_frame_bandwidth) &&
(cpi->active_best_quality > cpi->oxcf.cq_level)) {
force_recode = 1;
cpi->active_best_quality = cpi->oxcf.cq_level;
}
}
}
return force_recode;
}
#endif
static void update_reference_frames(VP8_COMP *cpi) { … }
static int measure_square_diff_partial(YV12_BUFFER_CONFIG *source,
YV12_BUFFER_CONFIG *dest,
VP8_COMP *cpi) { … }
#if CONFIG_TEMPORAL_DENOISING
static void process_denoiser_mode_change(VP8_COMP *cpi) { … }
#endif
void vp8_loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm) { … }
int vp8_check_drop_buffer(VP8_COMP *cpi) { … }
static void encode_frame_to_data_rate(VP8_COMP *cpi, size_t *size,
unsigned char *dest,
unsigned char *dest_end,
unsigned int *frame_flags) { … }
#if !CONFIG_REALTIME_ONLY
static void Pass2Encode(VP8_COMP *cpi, size_t *size, unsigned char *dest,
unsigned char *dest_end, unsigned int *frame_flags) {
if (!cpi->common.refresh_alt_ref_frame) vp8_second_pass(cpi);
encode_frame_to_data_rate(cpi, size, dest, dest_end, frame_flags);
cpi->twopass.bits_left -= 8 * (int)(*size);
if (!cpi->common.refresh_alt_ref_frame) {
double two_pass_min_rate =
(double)(cpi->oxcf.target_bandwidth *
cpi->oxcf.two_pass_vbrmin_section / 100);
cpi->twopass.bits_left += (int64_t)(two_pass_min_rate / cpi->framerate);
}
}
#endif
int vp8_receive_raw_frame(VP8_COMP *cpi, unsigned int frame_flags,
YV12_BUFFER_CONFIG *sd, int64_t time_stamp,
int64_t end_time) { … }
static int frame_is_reference(const VP8_COMP *cpi) { … }
int vp8_get_compressed_data(VP8_COMP *cpi, unsigned int *frame_flags,
size_t *size, unsigned char *dest,
unsigned char *dest_end, int64_t *time_stamp,
int64_t *time_end, int flush) { … }
int vp8_get_preview_raw_frame(VP8_COMP *cpi, YV12_BUFFER_CONFIG *dest,
vp8_ppflags_t *flags) { … }
int vp8_set_roimap(VP8_COMP *cpi, unsigned char *map, unsigned int rows,
unsigned int cols, int delta_q[4], int delta_lf[4],
unsigned int threshold[4]) { … }
int vp8_set_active_map(VP8_COMP *cpi, unsigned char *map, unsigned int rows,
unsigned int cols) { … }
int vp8_set_internal_size(VP8_COMP *cpi, VPX_SCALING_MODE horiz_mode,
VPX_SCALING_MODE vert_mode) { … }
int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest) { … }
int vp8_get_quantizer(VP8_COMP *cpi) { … }