mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-09 21:14:02 +00:00
update libvpx to hash 133f83e2c tag v1.7.0 from https://chromium.googlesource.com/webm/libvpx
This commit is contained in:
committed by
Andrey Volk
parent
9bfd5255b2
commit
731ee28fe7
@@ -151,7 +151,7 @@ static void write_ivf_frame_header(FILE *outfile,
|
||||
if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) return;
|
||||
|
||||
pts = pkt->data.frame.pts;
|
||||
mem_put_le32(header, pkt->data.frame.sz);
|
||||
mem_put_le32(header, (int)pkt->data.frame.sz);
|
||||
mem_put_le32(header + 4, pts & 0xFFFFFFFF);
|
||||
mem_put_le32(header + 8, pts >> 32);
|
||||
|
||||
@@ -190,7 +190,7 @@ static void set_temporal_layer_pattern(int num_temporal_layers,
|
||||
cfg->ts_layer_id[0] = 0;
|
||||
cfg->ts_layer_id[1] = 1;
|
||||
// Use 60/40 bit allocation as example.
|
||||
cfg->ts_target_bitrate[0] = 0.6f * bitrate;
|
||||
cfg->ts_target_bitrate[0] = (int)(0.6f * bitrate);
|
||||
cfg->ts_target_bitrate[1] = bitrate;
|
||||
|
||||
/* 0=L, 1=GF */
|
||||
@@ -240,9 +240,9 @@ static void set_temporal_layer_pattern(int num_temporal_layers,
|
||||
cfg->ts_layer_id[1] = 2;
|
||||
cfg->ts_layer_id[2] = 1;
|
||||
cfg->ts_layer_id[3] = 2;
|
||||
// Use 40/20/40 bit allocation as example.
|
||||
cfg->ts_target_bitrate[0] = 0.4f * bitrate;
|
||||
cfg->ts_target_bitrate[1] = 0.6f * bitrate;
|
||||
// Use 45/20/35 bit allocation as example.
|
||||
cfg->ts_target_bitrate[0] = (int)(0.45f * bitrate);
|
||||
cfg->ts_target_bitrate[1] = (int)(0.65f * bitrate);
|
||||
cfg->ts_target_bitrate[2] = bitrate;
|
||||
|
||||
/* 0=L, 1=GF, 2=ARF */
|
||||
@@ -294,8 +294,8 @@ int main(int argc, char **argv) {
|
||||
vpx_codec_err_t res[NUM_ENCODERS];
|
||||
|
||||
int i;
|
||||
long width;
|
||||
long height;
|
||||
int width;
|
||||
int height;
|
||||
int length_frame;
|
||||
int frame_avail;
|
||||
int got_data;
|
||||
@@ -347,9 +347,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
printf("Using %s\n", vpx_codec_iface_name(interface));
|
||||
|
||||
width = strtol(argv[1], NULL, 0);
|
||||
height = strtol(argv[2], NULL, 0);
|
||||
framerate = strtol(argv[3], NULL, 0);
|
||||
width = (int)strtol(argv[1], NULL, 0);
|
||||
height = (int)strtol(argv[2], NULL, 0);
|
||||
framerate = (int)strtol(argv[3], NULL, 0);
|
||||
|
||||
if (width < 16 || width % 2 || height < 16 || height % 2)
|
||||
die("Invalid resolution: %ldx%ld", width, height);
|
||||
@@ -371,12 +371,13 @@ int main(int argc, char **argv) {
|
||||
|
||||
// Bitrates per spatial layer: overwrite default rates above.
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
target_bitrate[i] = strtol(argv[NUM_ENCODERS + 5 + i], NULL, 0);
|
||||
target_bitrate[i] = (int)strtol(argv[NUM_ENCODERS + 5 + i], NULL, 0);
|
||||
}
|
||||
|
||||
// Temporal layers per spatial layers: overwrite default settings above.
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
num_temporal_layers[i] = strtol(argv[2 * NUM_ENCODERS + 5 + i], NULL, 0);
|
||||
num_temporal_layers[i] =
|
||||
(int)strtol(argv[2 * NUM_ENCODERS + 5 + i], NULL, 0);
|
||||
if (num_temporal_layers[i] < 1 || num_temporal_layers[i] > 3)
|
||||
die("Invalid temporal layers: %d, Must be 1, 2, or 3. \n",
|
||||
num_temporal_layers);
|
||||
@@ -391,9 +392,9 @@ int main(int argc, char **argv) {
|
||||
downsampled_input[i] = fopen(filename, "wb");
|
||||
}
|
||||
|
||||
key_frame_insert = strtol(argv[3 * NUM_ENCODERS + 5], NULL, 0);
|
||||
key_frame_insert = (int)strtol(argv[3 * NUM_ENCODERS + 5], NULL, 0);
|
||||
|
||||
show_psnr = strtol(argv[3 * NUM_ENCODERS + 6], NULL, 0);
|
||||
show_psnr = (int)strtol(argv[3 * NUM_ENCODERS + 6], NULL, 0);
|
||||
|
||||
/* Populate default encoder configuration */
|
||||
for (i = 0; i < NUM_ENCODERS; i++) {
|
||||
@@ -460,7 +461,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
// Set the number of threads per encode/spatial layer.
|
||||
// (1, 1, 1) means no encoder threading.
|
||||
cfg[0].g_threads = 2;
|
||||
cfg[0].g_threads = 1;
|
||||
cfg[1].g_threads = 1;
|
||||
cfg[2].g_threads = 1;
|
||||
|
||||
@@ -469,7 +470,7 @@ int main(int argc, char **argv) {
|
||||
if (!vpx_img_alloc(&raw[i], VPX_IMG_FMT_I420, cfg[i].g_w, cfg[i].g_h, 32))
|
||||
die("Failed to allocate image", cfg[i].g_w, cfg[i].g_h);
|
||||
|
||||
if (raw[0].stride[VPX_PLANE_Y] == raw[0].d_w)
|
||||
if (raw[0].stride[VPX_PLANE_Y] == (int)raw[0].d_w)
|
||||
read_frame_p = read_frame;
|
||||
else
|
||||
read_frame_p = read_frame_by_row;
|
||||
@@ -507,9 +508,11 @@ int main(int argc, char **argv) {
|
||||
|
||||
/* Set NOISE_SENSITIVITY to do TEMPORAL_DENOISING */
|
||||
/* Enable denoising for the highest-resolution encoder. */
|
||||
if (vpx_codec_control(&codec[0], VP8E_SET_NOISE_SENSITIVITY, 4))
|
||||
if (vpx_codec_control(&codec[0], VP8E_SET_NOISE_SENSITIVITY, 1))
|
||||
die_codec(&codec[0], "Failed to set noise_sensitivity");
|
||||
for (i = 1; i < NUM_ENCODERS; i++) {
|
||||
if (vpx_codec_control(&codec[1], VP8E_SET_NOISE_SENSITIVITY, 1))
|
||||
die_codec(&codec[1], "Failed to set noise_sensitivity");
|
||||
for (i = 2; i < NUM_ENCODERS; i++) {
|
||||
if (vpx_codec_control(&codec[i], VP8E_SET_NOISE_SENSITIVITY, 0))
|
||||
die_codec(&codec[i], "Failed to set noise_sensitivity");
|
||||
}
|
||||
@@ -556,7 +559,8 @@ int main(int argc, char **argv) {
|
||||
/* Write out down-sampled input. */
|
||||
length_frame = cfg[i].g_w * cfg[i].g_h * 3 / 2;
|
||||
if (fwrite(raw[i].planes[0], 1, length_frame,
|
||||
downsampled_input[NUM_ENCODERS - i - 1]) != length_frame) {
|
||||
downsampled_input[NUM_ENCODERS - i - 1]) !=
|
||||
(unsigned int)length_frame) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -617,10 +621,6 @@ int main(int argc, char **argv) {
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
printf(pkt[i]->kind == VPX_CODEC_CX_FRAME_PKT &&
|
||||
(pkt[i]->data.frame.flags & VPX_FRAME_IS_KEY)
|
||||
? "K"
|
||||
: "");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
@@ -661,7 +661,6 @@ int main(int argc, char **argv) {
|
||||
write_ivf_file_header(outfile[i], &cfg[i], frame_cnt - 1);
|
||||
fclose(outfile[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,8 @@ static const arg_def_t speed_arg =
|
||||
ARG_DEF("sp", "speed", 1, "speed configuration");
|
||||
static const arg_def_t aqmode_arg =
|
||||
ARG_DEF("aq", "aqmode", 1, "aq-mode off/on");
|
||||
static const arg_def_t bitrates_arg =
|
||||
ARG_DEF("bl", "bitrates", 1, "bitrates[sl * num_tl + tl]");
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
static const struct arg_enum_list bitdepth_enum[] = {
|
||||
@@ -124,6 +126,7 @@ static const arg_def_t *svc_args[] = { &frames_arg,
|
||||
#endif
|
||||
&speed_arg,
|
||||
&rc_end_usage_arg,
|
||||
&bitrates_arg,
|
||||
NULL };
|
||||
|
||||
static const uint32_t default_frames_to_skip = 0;
|
||||
@@ -165,7 +168,7 @@ void usage_exit(void) {
|
||||
static void parse_command_line(int argc, const char **argv_,
|
||||
AppInput *app_input, SvcContext *svc_ctx,
|
||||
vpx_codec_enc_cfg_t *enc_cfg) {
|
||||
struct arg arg = { 0 };
|
||||
struct arg arg;
|
||||
char **argv = NULL;
|
||||
char **argi = NULL;
|
||||
char **argj = NULL;
|
||||
@@ -250,6 +253,9 @@ static void parse_command_line(int argc, const char **argv_,
|
||||
} else if (arg_match(&arg, &scale_factors_arg, argi)) {
|
||||
snprintf(string_options, sizeof(string_options), "%s scale-factors=%s",
|
||||
string_options, arg.val);
|
||||
} else if (arg_match(&arg, &bitrates_arg, argi)) {
|
||||
snprintf(string_options, sizeof(string_options), "%s bitrates=%s",
|
||||
string_options, arg.val);
|
||||
} else if (arg_match(&arg, &passes_arg, argi)) {
|
||||
passes = arg_parse_uint(&arg);
|
||||
if (passes < 1 || passes > 2) {
|
||||
@@ -417,7 +423,6 @@ static void set_rate_control_stats(struct RateControlStats *rc,
|
||||
for (sl = 0; sl < cfg->ss_number_layers; ++sl) {
|
||||
for (tl = 0; tl < cfg->ts_number_layers; ++tl) {
|
||||
const int layer = sl * cfg->ts_number_layers + tl;
|
||||
const int tlayer0 = sl * cfg->ts_number_layers;
|
||||
if (cfg->ts_number_layers == 1)
|
||||
rc->layer_framerate[layer] = framerate;
|
||||
else
|
||||
@@ -428,8 +433,8 @@ static void set_rate_control_stats(struct RateControlStats *rc,
|
||||
cfg->layer_target_bitrate[layer - 1]) /
|
||||
(rc->layer_framerate[layer] - rc->layer_framerate[layer - 1]);
|
||||
} else {
|
||||
rc->layer_pfb[tlayer0] = 1000.0 * cfg->layer_target_bitrate[tlayer0] /
|
||||
rc->layer_framerate[tlayer0];
|
||||
rc->layer_pfb[layer] = 1000.0 * cfg->layer_target_bitrate[layer] /
|
||||
rc->layer_framerate[layer];
|
||||
}
|
||||
rc->layer_input_frames[layer] = 0;
|
||||
rc->layer_enc_frames[layer] = 0;
|
||||
@@ -449,12 +454,13 @@ static void printout_rate_control_summary(struct RateControlStats *rc,
|
||||
vpx_codec_enc_cfg_t *cfg,
|
||||
int frame_cnt) {
|
||||
unsigned int sl, tl;
|
||||
int tot_num_frames = 0;
|
||||
double perc_fluctuation = 0.0;
|
||||
int tot_num_frames = 0;
|
||||
printf("Total number of processed frames: %d\n\n", frame_cnt - 1);
|
||||
printf("Rate control layer stats for sl%d tl%d layer(s):\n\n",
|
||||
cfg->ss_number_layers, cfg->ts_number_layers);
|
||||
for (sl = 0; sl < cfg->ss_number_layers; ++sl) {
|
||||
tot_num_frames = 0;
|
||||
for (tl = 0; tl < cfg->ts_number_layers; ++tl) {
|
||||
const int layer = sl * cfg->ts_number_layers + tl;
|
||||
const int num_dropped =
|
||||
@@ -462,7 +468,7 @@ static void printout_rate_control_summary(struct RateControlStats *rc,
|
||||
? (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer])
|
||||
: (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer] -
|
||||
1);
|
||||
if (!sl) tot_num_frames += rc->layer_input_frames[layer];
|
||||
tot_num_frames += rc->layer_input_frames[layer];
|
||||
rc->layer_encoding_bitrate[layer] = 0.001 * rc->layer_framerate[layer] *
|
||||
rc->layer_encoding_bitrate[layer] /
|
||||
tot_num_frames;
|
||||
@@ -503,7 +509,7 @@ static void printout_rate_control_summary(struct RateControlStats *rc,
|
||||
}
|
||||
|
||||
vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz,
|
||||
uint32_t sizes[8], int *count) {
|
||||
uint64_t sizes[8], int *count) {
|
||||
// A chunk ending with a byte matching 0xc0 is an invalid chunk unless
|
||||
// it is a super frame index. If the last byte of real video compression
|
||||
// data is 0xc0 the encoder must add a 0 byte. If we have the marker but
|
||||
@@ -600,9 +606,9 @@ void set_frame_flags_bypass_mode(int sl, int tl, int num_spatial_layers,
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
AppInput app_input = { 0 };
|
||||
AppInput app_input;
|
||||
VpxVideoWriter *writer = NULL;
|
||||
VpxVideoInfo info = { 0 };
|
||||
VpxVideoInfo info;
|
||||
vpx_codec_ctx_t codec;
|
||||
vpx_codec_enc_cfg_t enc_cfg;
|
||||
SvcContext svc_ctx;
|
||||
@@ -620,7 +626,7 @@ int main(int argc, const char **argv) {
|
||||
struct RateControlStats rc;
|
||||
vpx_svc_layer_id_t layer_id;
|
||||
vpx_svc_ref_frame_config_t ref_frame_config;
|
||||
int sl, tl;
|
||||
unsigned int sl, tl;
|
||||
double sum_bitrate = 0.0;
|
||||
double sum_bitrate2 = 0.0;
|
||||
double framerate = 30.0;
|
||||
@@ -634,8 +640,9 @@ int main(int argc, const char **argv) {
|
||||
|
||||
// Allocate image buffer
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
if (!vpx_img_alloc(&raw, enc_cfg.g_input_bit_depth == 8 ? VPX_IMG_FMT_I420
|
||||
: VPX_IMG_FMT_I42016,
|
||||
if (!vpx_img_alloc(&raw,
|
||||
enc_cfg.g_input_bit_depth == 8 ? VPX_IMG_FMT_I420
|
||||
: VPX_IMG_FMT_I42016,
|
||||
enc_cfg.g_w, enc_cfg.g_h, 32)) {
|
||||
die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h);
|
||||
}
|
||||
@@ -673,7 +680,7 @@ int main(int argc, const char **argv) {
|
||||
}
|
||||
#if OUTPUT_RC_STATS
|
||||
// For now, just write temporal layer streams.
|
||||
// TODO(wonkap): do spatial by re-writing superframe.
|
||||
// TODO(marpan): do spatial by re-writing superframe.
|
||||
if (svc_ctx.output_rc_stat) {
|
||||
for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) {
|
||||
char file_name[PATH_MAX];
|
||||
@@ -691,10 +698,18 @@ int main(int argc, const char **argv) {
|
||||
|
||||
if (svc_ctx.speed != -1)
|
||||
vpx_codec_control(&codec, VP8E_SET_CPUUSED, svc_ctx.speed);
|
||||
if (svc_ctx.threads)
|
||||
if (svc_ctx.threads) {
|
||||
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (svc_ctx.threads >> 1));
|
||||
if (svc_ctx.threads > 1)
|
||||
vpx_codec_control(&codec, VP9E_SET_ROW_MT, 1);
|
||||
else
|
||||
vpx_codec_control(&codec, VP9E_SET_ROW_MT, 0);
|
||||
}
|
||||
if (svc_ctx.speed >= 5 && svc_ctx.aqmode == 1)
|
||||
vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
|
||||
if (svc_ctx.speed >= 5)
|
||||
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
|
||||
vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, 900);
|
||||
|
||||
// Encode frames
|
||||
while (!end_of_stream) {
|
||||
@@ -730,7 +745,7 @@ int main(int argc, const char **argv) {
|
||||
&ref_frame_config);
|
||||
// Keep track of input frames, to account for frame drops in rate control
|
||||
// stats/metrics.
|
||||
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
|
||||
for (sl = 0; sl < (unsigned int)enc_cfg.ss_number_layers; ++sl) {
|
||||
++rc.layer_input_frames[sl * enc_cfg.ts_number_layers +
|
||||
layer_id.temporal_layer_id];
|
||||
}
|
||||
@@ -755,18 +770,20 @@ int main(int argc, const char **argv) {
|
||||
SvcInternal_t *const si = (SvcInternal_t *)svc_ctx.internal;
|
||||
if (cx_pkt->data.frame.sz > 0) {
|
||||
#if OUTPUT_RC_STATS
|
||||
uint32_t sizes[8];
|
||||
uint64_t sizes[8];
|
||||
int count = 0;
|
||||
#endif
|
||||
vpx_video_writer_write_frame(writer, cx_pkt->data.frame.buf,
|
||||
cx_pkt->data.frame.sz,
|
||||
cx_pkt->data.frame.pts);
|
||||
#if OUTPUT_RC_STATS
|
||||
// TODO(marpan/wonkap): Put this (to line728) in separate function.
|
||||
// TODO(marpan): Put this (to line728) in separate function.
|
||||
if (svc_ctx.output_rc_stat) {
|
||||
vpx_codec_control(&codec, VP9E_GET_SVC_LAYER_ID, &layer_id);
|
||||
parse_superframe_index(cx_pkt->data.frame.buf,
|
||||
cx_pkt->data.frame.sz, sizes, &count);
|
||||
if (enc_cfg.ss_number_layers == 1)
|
||||
sizes[0] = cx_pkt->data.frame.sz;
|
||||
// Note computing input_layer_frames here won't account for frame
|
||||
// drops in rate control stats.
|
||||
// TODO(marpan): Fix this for non-bypass mode so we can get stats
|
||||
@@ -793,7 +810,7 @@ int main(int argc, const char **argv) {
|
||||
rc.layer_encoding_bitrate[layer] += 8.0 * sizes[sl];
|
||||
// Keep count of rate control stats per layer, for non-key
|
||||
// frames.
|
||||
if (tl == layer_id.temporal_layer_id &&
|
||||
if (tl == (unsigned int)layer_id.temporal_layer_id &&
|
||||
!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
|
||||
rc.layer_avg_frame_size[layer] += 8.0 * sizes[sl];
|
||||
rc.layer_avg_rate_mismatch[layer] +=
|
||||
@@ -807,7 +824,7 @@ int main(int argc, const char **argv) {
|
||||
// Update for short-time encoding bitrate states, for moving
|
||||
// window of size rc->window, shifted by rc->window / 2.
|
||||
// Ignore first window segment, due to key frame.
|
||||
if (frame_cnt > rc.window_size) {
|
||||
if (frame_cnt > (unsigned int)rc.window_size) {
|
||||
tl = layer_id.temporal_layer_id;
|
||||
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
|
||||
sum_bitrate += 0.001 * 8.0 * sizes[sl] * framerate;
|
||||
@@ -823,13 +840,14 @@ int main(int argc, const char **argv) {
|
||||
}
|
||||
|
||||
// Second shifted window.
|
||||
if (frame_cnt > rc.window_size + rc.window_size / 2) {
|
||||
if (frame_cnt >
|
||||
(unsigned int)(rc.window_size + rc.window_size / 2)) {
|
||||
tl = layer_id.temporal_layer_id;
|
||||
for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
|
||||
sum_bitrate2 += 0.001 * 8.0 * sizes[sl] * framerate;
|
||||
}
|
||||
|
||||
if (frame_cnt > 2 * rc.window_size &&
|
||||
if (frame_cnt > (unsigned int)(2 * rc.window_size) &&
|
||||
frame_cnt % rc.window_size == 0) {
|
||||
rc.window_count += 1;
|
||||
rc.avg_st_encoding_bitrate += sum_bitrate2 / rc.window_size;
|
||||
@@ -842,10 +860,11 @@ int main(int argc, const char **argv) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
printf("SVC frame: %d, kf: %d, size: %d, pts: %d\n", frames_received,
|
||||
!!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY),
|
||||
(int)cx_pkt->data.frame.sz, (int)cx_pkt->data.frame.pts);
|
||||
*/
|
||||
if (enc_cfg.ss_number_layers == 1 && enc_cfg.ts_number_layers == 1)
|
||||
si->bytes_sum[0] += (int)cx_pkt->data.frame.sz;
|
||||
++frames_received;
|
||||
|
||||
@@ -304,6 +304,7 @@ int main(int argc, char **argv) {
|
||||
const char *height_arg = NULL;
|
||||
const char *infile_arg = NULL;
|
||||
const char *outfile_arg = NULL;
|
||||
const char *update_frame_num_arg = NULL;
|
||||
unsigned int limit = 0;
|
||||
|
||||
vp9_zero(ecodec);
|
||||
@@ -318,18 +319,21 @@ int main(int argc, char **argv) {
|
||||
height_arg = argv[2];
|
||||
infile_arg = argv[3];
|
||||
outfile_arg = argv[4];
|
||||
update_frame_num_arg = argv[5];
|
||||
|
||||
encoder = get_vpx_encoder_by_name("vp9");
|
||||
if (!encoder) die("Unsupported codec.");
|
||||
|
||||
update_frame_num = atoi(argv[5]);
|
||||
update_frame_num = (unsigned int)strtoul(update_frame_num_arg, NULL, 0);
|
||||
// In VP9, the reference buffers (cm->buffer_pool->frame_bufs[i].buf) are
|
||||
// allocated while calling vpx_codec_encode(), thus, setting reference for
|
||||
// 1st frame isn't supported.
|
||||
if (update_frame_num <= 1) die("Couldn't parse frame number '%s'\n", argv[5]);
|
||||
if (update_frame_num <= 1) {
|
||||
die("Couldn't parse frame number '%s'\n", update_frame_num_arg);
|
||||
}
|
||||
|
||||
if (argc > 6) {
|
||||
limit = atoi(argv[6]);
|
||||
limit = (unsigned int)strtoul(argv[6], NULL, 0);
|
||||
if (update_frame_num > limit)
|
||||
die("Update frame number couldn't larger than limit\n");
|
||||
}
|
||||
|
||||
@@ -26,17 +26,27 @@
|
||||
#include "../tools_common.h"
|
||||
#include "../video_writer.h"
|
||||
|
||||
#define VP8_ROI_MAP 0
|
||||
|
||||
static const char *exec_name;
|
||||
|
||||
void usage_exit(void) { exit(EXIT_FAILURE); }
|
||||
|
||||
// Denoiser states, for temporal denoising.
|
||||
enum denoiserState {
|
||||
kDenoiserOff,
|
||||
kDenoiserOnYOnly,
|
||||
kDenoiserOnYUV,
|
||||
kDenoiserOnYUVAggressive,
|
||||
kDenoiserOnAdaptive
|
||||
// Denoiser states for vp8, for temporal denoising.
|
||||
enum denoiserStateVp8 {
|
||||
kVp8DenoiserOff,
|
||||
kVp8DenoiserOnYOnly,
|
||||
kVp8DenoiserOnYUV,
|
||||
kVp8DenoiserOnYUVAggressive,
|
||||
kVp8DenoiserOnAdaptive
|
||||
};
|
||||
|
||||
// Denoiser states for vp9, for temporal denoising.
|
||||
enum denoiserStateVp9 {
|
||||
kVp9DenoiserOff,
|
||||
kVp9DenoiserOnYOnly,
|
||||
// For SVC: denoise the top two spatial layers.
|
||||
kVp9DenoiserOnYTwoSpatialLayers
|
||||
};
|
||||
|
||||
static int mode_to_num_layers[13] = { 1, 2, 2, 3, 3, 3, 3, 5, 2, 3, 3, 3, 3 };
|
||||
@@ -154,6 +164,53 @@ static void printout_rate_control_summary(struct RateControlMetrics *rc,
|
||||
die("Error: Number of input frames not equal to output! \n");
|
||||
}
|
||||
|
||||
#if VP8_ROI_MAP
|
||||
static void vp8_set_roi_map(vpx_codec_enc_cfg_t *cfg, vpx_roi_map_t *roi) {
|
||||
unsigned int i, j;
|
||||
memset(roi, 0, sizeof(*roi));
|
||||
|
||||
// ROI is based on the segments (4 for vp8, 8 for vp9), smallest unit for
|
||||
// segment is 16x16 for vp8, 8x8 for vp9.
|
||||
roi->rows = (cfg->g_h + 15) / 16;
|
||||
roi->cols = (cfg->g_w + 15) / 16;
|
||||
|
||||
// Applies delta QP on the segment blocks, varies from -63 to 63.
|
||||
// Setting to negative means lower QP (better quality).
|
||||
// Below we set delta_q to the extreme (-63) to show strong effect.
|
||||
roi->delta_q[0] = 0;
|
||||
roi->delta_q[1] = -63;
|
||||
roi->delta_q[2] = 0;
|
||||
roi->delta_q[3] = 0;
|
||||
|
||||
// Applies delta loopfilter strength on the segment blocks, varies from -63 to
|
||||
// 63. Setting to positive means stronger loopfilter.
|
||||
roi->delta_lf[0] = 0;
|
||||
roi->delta_lf[1] = 0;
|
||||
roi->delta_lf[2] = 0;
|
||||
roi->delta_lf[3] = 0;
|
||||
|
||||
// Applies skip encoding threshold on the segment blocks, varies from 0 to
|
||||
// UINT_MAX. Larger value means more skipping of encoding is possible.
|
||||
// This skip threshold only applies on delta frames.
|
||||
roi->static_threshold[0] = 0;
|
||||
roi->static_threshold[1] = 0;
|
||||
roi->static_threshold[2] = 0;
|
||||
roi->static_threshold[3] = 0;
|
||||
|
||||
// Use 2 states: 1 is center square, 0 is the rest.
|
||||
roi->roi_map =
|
||||
(uint8_t *)calloc(roi->rows * roi->cols, sizeof(*roi->roi_map));
|
||||
for (i = 0; i < roi->rows; ++i) {
|
||||
for (j = 0; j < roi->cols; ++j) {
|
||||
if (i > (roi->rows >> 2) && i < ((roi->rows * 3) >> 2) &&
|
||||
j > (roi->cols >> 2) && j < ((roi->cols * 3) >> 2)) {
|
||||
roi->roi_map[i * roi->cols + j] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Temporal scaling parameters:
|
||||
// NOTE: The 3 prediction frames cannot be used interchangeably due to
|
||||
// differences in the way they are handled throughout the code. The
|
||||
@@ -495,6 +552,7 @@ int main(int argc, char **argv) {
|
||||
vpx_codec_err_t res;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
uint32_t error_resilient = 0;
|
||||
int speed;
|
||||
int frame_avail;
|
||||
int got_data;
|
||||
@@ -505,16 +563,15 @@ int main(int argc, char **argv) {
|
||||
int layering_mode = 0;
|
||||
int layer_flags[VPX_TS_MAX_PERIODICITY] = { 0 };
|
||||
int flag_periodicity = 1;
|
||||
#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
|
||||
vpx_svc_layer_id_t layer_id = { 0, 0 };
|
||||
#else
|
||||
vpx_svc_layer_id_t layer_id = { 0 };
|
||||
#if VP8_ROI_MAP
|
||||
vpx_roi_map_t roi;
|
||||
#endif
|
||||
vpx_svc_layer_id_t layer_id = { 0, 0 };
|
||||
const VpxInterface *encoder = NULL;
|
||||
FILE *infile = NULL;
|
||||
struct RateControlMetrics rc;
|
||||
int64_t cx_time = 0;
|
||||
const int min_args_base = 11;
|
||||
const int min_args_base = 13;
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
vpx_bit_depth_t bit_depth = VPX_BITS_8;
|
||||
int input_bit_depth = 8;
|
||||
@@ -531,12 +588,14 @@ int main(int argc, char **argv) {
|
||||
if (argc < min_args) {
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
|
||||
"<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> "
|
||||
"<rate_num> <rate_den> <speed> <frame_drop_threshold> "
|
||||
"<error_resilient> <threads> <mode> "
|
||||
"<Rate_0> ... <Rate_nlayers-1> <bit-depth> \n",
|
||||
argv[0]);
|
||||
#else
|
||||
die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
|
||||
"<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> "
|
||||
"<rate_num> <rate_den> <speed> <frame_drop_threshold> "
|
||||
"<error_resilient> <threads> <mode> "
|
||||
"<Rate_0> ... <Rate_nlayers-1> \n",
|
||||
argv[0]);
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
@@ -553,9 +612,9 @@ int main(int argc, char **argv) {
|
||||
die("Invalid resolution: %d x %d", width, height);
|
||||
}
|
||||
|
||||
layering_mode = (int)strtol(argv[10], NULL, 0);
|
||||
layering_mode = (int)strtol(argv[12], NULL, 0);
|
||||
if (layering_mode < 0 || layering_mode > 13) {
|
||||
die("Invalid layering mode (0..12) %s", argv[10]);
|
||||
die("Invalid layering mode (0..12) %s", argv[12]);
|
||||
}
|
||||
|
||||
if (argc != min_args + mode_to_num_layers[layering_mode]) {
|
||||
@@ -619,11 +678,11 @@ int main(int argc, char **argv) {
|
||||
|
||||
for (i = min_args_base;
|
||||
(int)i < min_args_base + mode_to_num_layers[layering_mode]; ++i) {
|
||||
rc.layer_target_bitrate[i - 11] = (int)strtol(argv[i], NULL, 0);
|
||||
rc.layer_target_bitrate[i - 13] = (int)strtol(argv[i], NULL, 0);
|
||||
if (strncmp(encoder->name, "vp8", 3) == 0)
|
||||
cfg.ts_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11];
|
||||
cfg.ts_target_bitrate[i - 13] = rc.layer_target_bitrate[i - 13];
|
||||
else if (strncmp(encoder->name, "vp9", 3) == 0)
|
||||
cfg.layer_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11];
|
||||
cfg.layer_target_bitrate[i - 13] = rc.layer_target_bitrate[i - 13];
|
||||
}
|
||||
|
||||
// Real time parameters.
|
||||
@@ -634,7 +693,7 @@ int main(int argc, char **argv) {
|
||||
if (strncmp(encoder->name, "vp9", 3) == 0) cfg.rc_max_quantizer = 52;
|
||||
cfg.rc_undershoot_pct = 50;
|
||||
cfg.rc_overshoot_pct = 50;
|
||||
cfg.rc_buf_initial_sz = 500;
|
||||
cfg.rc_buf_initial_sz = 600;
|
||||
cfg.rc_buf_optimal_sz = 600;
|
||||
cfg.rc_buf_sz = 1000;
|
||||
|
||||
@@ -642,10 +701,14 @@ int main(int argc, char **argv) {
|
||||
cfg.rc_resize_allowed = 0;
|
||||
|
||||
// Use 1 thread as default.
|
||||
cfg.g_threads = 1;
|
||||
cfg.g_threads = (unsigned int)strtoul(argv[11], NULL, 0);
|
||||
|
||||
error_resilient = (uint32_t)strtoul(argv[10], NULL, 0);
|
||||
if (error_resilient != 0 && error_resilient != 1) {
|
||||
die("Invalid value for error resilient (0, 1): %d.", error_resilient);
|
||||
}
|
||||
// Enable error resilient mode.
|
||||
cfg.g_error_resilient = 1;
|
||||
cfg.g_error_resilient = error_resilient;
|
||||
cfg.g_lag_in_frames = 0;
|
||||
cfg.kf_mode = VPX_KF_AUTO;
|
||||
|
||||
@@ -700,18 +763,33 @@ int main(int argc, char **argv) {
|
||||
|
||||
if (strncmp(encoder->name, "vp8", 3) == 0) {
|
||||
vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed);
|
||||
vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOff);
|
||||
vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kVp8DenoiserOff);
|
||||
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
|
||||
vpx_codec_control(&codec, VP8E_SET_GF_CBR_BOOST_PCT, 0);
|
||||
#if VP8_ROI_MAP
|
||||
vp8_set_roi_map(&cfg, &roi);
|
||||
if (vpx_codec_control(&codec, VP8E_SET_ROI_MAP, &roi))
|
||||
die_codec(&codec, "Failed to set ROI map");
|
||||
#endif
|
||||
|
||||
} else if (strncmp(encoder->name, "vp9", 3) == 0) {
|
||||
vpx_svc_extra_cfg_t svc_params;
|
||||
memset(&svc_params, 0, sizeof(svc_params));
|
||||
vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed);
|
||||
vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
|
||||
vpx_codec_control(&codec, VP9E_SET_GF_CBR_BOOST_PCT, 0);
|
||||
vpx_codec_control(&codec, VP9E_SET_FRAME_PARALLEL_DECODING, 0);
|
||||
vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0);
|
||||
vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, kDenoiserOff);
|
||||
vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, kVp9DenoiserOff);
|
||||
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
|
||||
vpx_codec_control(&codec, VP9E_SET_TUNE_CONTENT, 0);
|
||||
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1));
|
||||
// TODO(marpan/jianj): There is an issue with row-mt for low resolutons at
|
||||
// high speed settings, disable its use for those cases for now.
|
||||
if (cfg.g_threads > 1 && ((cfg.g_w > 320 && cfg.g_h > 240) || speed < 7))
|
||||
vpx_codec_control(&codec, VP9E_SET_ROW_MT, 1);
|
||||
else
|
||||
vpx_codec_control(&codec, VP9E_SET_ROW_MT, 0);
|
||||
if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1 : 0))
|
||||
die_codec(&codec, "Failed to set SVC");
|
||||
for (i = 0; i < cfg.ts_number_layers; ++i) {
|
||||
@@ -730,7 +808,7 @@ int main(int argc, char **argv) {
|
||||
// For generating smaller key frames, use a smaller max_intra_size_pct
|
||||
// value, like 100 or 200.
|
||||
{
|
||||
const int max_intra_size_pct = 900;
|
||||
const int max_intra_size_pct = 1000;
|
||||
vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT,
|
||||
max_intra_size_pct);
|
||||
}
|
||||
@@ -740,10 +818,8 @@ int main(int argc, char **argv) {
|
||||
struct vpx_usec_timer timer;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
const vpx_codec_cx_pkt_t *pkt;
|
||||
#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
|
||||
// Update the temporal layer_id. No spatial layers in this test.
|
||||
layer_id.spatial_layer_id = 0;
|
||||
#endif
|
||||
layer_id.temporal_layer_id =
|
||||
cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
|
||||
if (strncmp(encoder->name, "vp9", 3) == 0) {
|
||||
|
||||
Reference in New Issue
Block a user