Merge "Palette code cleanup:" into nextgenv2
diff --git a/configure b/configure
index a50db74..2b0722d 100755
--- a/configure
+++ b/configure
@@ -250,7 +250,6 @@
unistd_h
"
EXPERIMENT_LIST="
- spatial_svc
fp_mb_stats
emulate_hardware
var_tx
diff --git a/examples.mk b/examples.mk
index 178b2b0..30fade1 100644
--- a/examples.mk
+++ b/examples.mk
@@ -109,14 +109,6 @@
vpxenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
vpxenc.DESCRIPTION = Full featured encoder
-EXAMPLES-$(CONFIG_ENCODERS) += vpx_temporal_svc_encoder.c
-vpx_temporal_svc_encoder.SRCS += ivfenc.c ivfenc.h
-vpx_temporal_svc_encoder.SRCS += tools_common.c tools_common.h
-vpx_temporal_svc_encoder.SRCS += video_common.h
-vpx_temporal_svc_encoder.SRCS += video_writer.h video_writer.c
-vpx_temporal_svc_encoder.SRCS += vpx_ports/msvc.h
-vpx_temporal_svc_encoder.GUID = B18C08F2-A439-4502-A78E-849BE3D60947
-vpx_temporal_svc_encoder.DESCRIPTION = Temporal SVC Encoder
EXAMPLES-$(CONFIG_DECODERS) += simple_decoder.c
simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
simple_decoder.SRCS += ivfdec.h ivfdec.c
diff --git a/examples/vp8cx_set_ref.c b/examples/vp8cx_set_ref.c
deleted file mode 100644
index 8b4cc30..0000000
--- a/examples/vp8cx_set_ref.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-
-// VP8 Set Reference Frame
-// =======================
-//
-// This is an example demonstrating how to overwrite the VP8 encoder's
-// internal reference frame. In the sample we set the last frame to the
-// current frame. If this is done at a cut scene it will avoid a keyframe.
-// This technique could be used to bounce between two cameras.
-//
-// Note that the decoder would also have to set the reference frame to the
-// same value on the same frame, or the video will become corrupt.
-//
-// Usage
-// -----
-// This example adds a single argument to the `simple_encoder` example,
-// which specifies the frame number to update the reference frame on.
-// The parameter is parsed as follows:
-//
-//
-// Extra Variables
-// ---------------
-// This example maintains the frame number passed on the command line
-// in the `update_frame_num` variable.
-//
-//
-// Configuration
-// -------------
-//
-// The reference frame is updated on the frame specified on the command
-// line.
-//
-// Observing The Effects
-// ---------------------
-// Use the `simple_encoder` example to encode a sample with a cut scene.
-// Determine the frame number of the cut scene by looking for a generated
-// key-frame (indicated by a 'K'). Supply that frame number as an argument
-// to this example, and observe that no key-frame is generated.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "vpx/vp8cx.h"
-#include "vpx/vpx_encoder.h"
-
-#include "../tools_common.h"
-#include "../video_writer.h"
-
-static const char *exec_name;
-
-void usage_exit(void) {
- fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile> <frame>\n",
- exec_name);
- exit(EXIT_FAILURE);
-}
-
-static int encode_frame(vpx_codec_ctx_t *codec,
- vpx_image_t *img,
- int frame_index,
- VpxVideoWriter *writer) {
- int got_pkts = 0;
- vpx_codec_iter_t iter = NULL;
- const vpx_codec_cx_pkt_t *pkt = NULL;
- const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1, 0,
- VPX_DL_GOOD_QUALITY);
- if (res != VPX_CODEC_OK)
- die_codec(codec, "Failed to encode frame");
-
- while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
- got_pkts = 1;
-
- if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
- const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
- if (!vpx_video_writer_write_frame(writer,
- pkt->data.frame.buf,
- pkt->data.frame.sz,
- pkt->data.frame.pts)) {
- die_codec(codec, "Failed to write compressed frame");
- }
-
- printf(keyframe ? "K" : ".");
- fflush(stdout);
- }
- }
-
- return got_pkts;
-}
-
-int main(int argc, char **argv) {
- FILE *infile = NULL;
- vpx_codec_ctx_t codec = {0};
- vpx_codec_enc_cfg_t cfg = {0};
- int frame_count = 0;
- vpx_image_t raw;
- vpx_codec_err_t res;
- VpxVideoInfo info = {0};
- VpxVideoWriter *writer = NULL;
- const VpxInterface *encoder = NULL;
- int update_frame_num = 0;
- const int fps = 30; // TODO(dkovalev) add command line argument
- const int bitrate = 200; // kbit/s TODO(dkovalev) add command line argument
-
- exec_name = argv[0];
-
- if (argc != 6)
- die("Invalid number of arguments");
-
- // TODO(dkovalev): add vp9 support and rename the file accordingly
- encoder = get_vpx_encoder_by_name("vp8");
- if (!encoder)
- die("Unsupported codec.");
-
- update_frame_num = atoi(argv[5]);
- if (!update_frame_num)
- die("Couldn't parse frame number '%s'\n", argv[5]);
-
- info.codec_fourcc = encoder->fourcc;
- info.frame_width = strtol(argv[1], NULL, 0);
- info.frame_height = strtol(argv[2], NULL, 0);
- info.time_base.numerator = 1;
- info.time_base.denominator = fps;
-
- if (info.frame_width <= 0 ||
- info.frame_height <= 0 ||
- (info.frame_width % 2) != 0 ||
- (info.frame_height % 2) != 0) {
- die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
- }
-
- if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
- info.frame_height, 1)) {
- die("Failed to allocate image.");
- }
-
- printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
-
- res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
- if (res)
- die_codec(&codec, "Failed to get default codec config.");
-
- cfg.g_w = info.frame_width;
- cfg.g_h = info.frame_height;
- cfg.g_timebase.num = info.time_base.numerator;
- cfg.g_timebase.den = info.time_base.denominator;
- cfg.rc_target_bitrate = bitrate;
-
- writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
- if (!writer)
- die("Failed to open %s for writing.", argv[4]);
-
- if (!(infile = fopen(argv[3], "rb")))
- die("Failed to open %s for reading.", argv[3]);
-
- if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
- die_codec(&codec, "Failed to initialize encoder");
-
- // Encode frames.
- while (vpx_img_read(&raw, infile)) {
- if (frame_count + 1 == update_frame_num) {
- vpx_ref_frame_t ref;
- ref.frame_type = VP8_LAST_FRAME;
- ref.img = raw;
- if (vpx_codec_control(&codec, VP8_SET_REFERENCE, &ref))
- die_codec(&codec, "Failed to set reference frame");
- }
-
- encode_frame(&codec, &raw, frame_count++, writer);
- }
-
- // Flush encoder.
- while (encode_frame(&codec, NULL, -1, writer)) {}
-
- printf("\n");
- fclose(infile);
- printf("Processed %d frames.\n", frame_count);
-
- vpx_img_free(&raw);
- if (vpx_codec_destroy(&codec))
- die_codec(&codec, "Failed to destroy codec.");
-
- vpx_video_writer_close(writer);
-
- return EXIT_SUCCESS;
-}
diff --git a/examples/vpx_temporal_svc_encoder.c b/examples/vpx_temporal_svc_encoder.c
deleted file mode 100644
index e6c09fb..0000000
--- a/examples/vpx_temporal_svc_encoder.c
+++ /dev/null
@@ -1,852 +0,0 @@
-/*
- * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-// This is an example demonstrating how to implement a multi-layer VPx
-// encoding scheme based on temporal scalability for video applications
-// that benefit from a scalable bitstream.
-
-#include <assert.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "./vpx_config.h"
-#include "../vpx_ports/vpx_timer.h"
-#include "vpx/vp8cx.h"
-#include "vpx/vpx_encoder.h"
-
-#include "../tools_common.h"
-#include "../video_writer.h"
-
-static const char *exec_name;
-
-void usage_exit(void) {
- exit(EXIT_FAILURE);
-}
-
-// Denoiser states, for temporal denoising.
-enum denoiserState {
- kDenoiserOff,
- kDenoiserOnYOnly,
- kDenoiserOnYUV,
- kDenoiserOnYUVAggressive,
- kDenoiserOnAdaptive
-};
-
-static int mode_to_num_layers[13] = {1, 2, 2, 3, 3, 3, 3, 5, 2, 3, 3, 3, 3};
-
-// For rate control encoding stats.
-struct RateControlMetrics {
- // Number of input frames per layer.
- int layer_input_frames[VPX_TS_MAX_LAYERS];
- // Total (cumulative) number of encoded frames per layer.
- int layer_tot_enc_frames[VPX_TS_MAX_LAYERS];
- // Number of encoded non-key frames per layer.
- int layer_enc_frames[VPX_TS_MAX_LAYERS];
- // Framerate per layer layer (cumulative).
- double layer_framerate[VPX_TS_MAX_LAYERS];
- // Target average frame size per layer (per-frame-bandwidth per layer).
- double layer_pfb[VPX_TS_MAX_LAYERS];
- // Actual average frame size per layer.
- double layer_avg_frame_size[VPX_TS_MAX_LAYERS];
- // Average rate mismatch per layer (|target - actual| / target).
- double layer_avg_rate_mismatch[VPX_TS_MAX_LAYERS];
- // Actual encoding bitrate per layer (cumulative).
- double layer_encoding_bitrate[VPX_TS_MAX_LAYERS];
- // Average of the short-time encoder actual bitrate.
- // TODO(marpan): Should we add these short-time stats for each layer?
- double avg_st_encoding_bitrate;
- // Variance of the short-time encoder actual bitrate.
- double variance_st_encoding_bitrate;
- // Window (number of frames) for computing short-timee encoding bitrate.
- int window_size;
- // Number of window measurements.
- int window_count;
- int layer_target_bitrate[VPX_MAX_LAYERS];
-};
-
-// Note: these rate control metrics assume only 1 key frame in the
-// sequence (i.e., first frame only). So for temporal pattern# 7
-// (which has key frame for every frame on base layer), the metrics
-// computation will be off/wrong.
-// TODO(marpan): Update these metrics to account for multiple key frames
-// in the stream.
-static void set_rate_control_metrics(struct RateControlMetrics *rc,
- vpx_codec_enc_cfg_t *cfg) {
- unsigned int i = 0;
- // Set the layer (cumulative) framerate and the target layer (non-cumulative)
- // per-frame-bandwidth, for the rate control encoding stats below.
- const double framerate = cfg->g_timebase.den / cfg->g_timebase.num;
- rc->layer_framerate[0] = framerate / cfg->ts_rate_decimator[0];
- rc->layer_pfb[0] = 1000.0 * rc->layer_target_bitrate[0] /
- rc->layer_framerate[0];
- for (i = 0; i < cfg->ts_number_layers; ++i) {
- if (i > 0) {
- rc->layer_framerate[i] = framerate / cfg->ts_rate_decimator[i];
- rc->layer_pfb[i] = 1000.0 *
- (rc->layer_target_bitrate[i] - rc->layer_target_bitrate[i - 1]) /
- (rc->layer_framerate[i] - rc->layer_framerate[i - 1]);
- }
- rc->layer_input_frames[i] = 0;
- rc->layer_enc_frames[i] = 0;
- rc->layer_tot_enc_frames[i] = 0;
- rc->layer_encoding_bitrate[i] = 0.0;
- rc->layer_avg_frame_size[i] = 0.0;
- rc->layer_avg_rate_mismatch[i] = 0.0;
- }
- rc->window_count = 0;
- rc->window_size = 15;
- rc->avg_st_encoding_bitrate = 0.0;
- rc->variance_st_encoding_bitrate = 0.0;
-}
-
-static void printout_rate_control_summary(struct RateControlMetrics *rc,
- vpx_codec_enc_cfg_t *cfg,
- int frame_cnt) {
- unsigned int i = 0;
- int tot_num_frames = 0;
- double perc_fluctuation = 0.0;
- printf("Total number of processed frames: %d\n\n", frame_cnt -1);
- printf("Rate control layer stats for %d layer(s):\n\n",
- cfg->ts_number_layers);
- for (i = 0; i < cfg->ts_number_layers; ++i) {
- const int num_dropped = (i > 0) ?
- (rc->layer_input_frames[i] - rc->layer_enc_frames[i]) :
- (rc->layer_input_frames[i] - rc->layer_enc_frames[i] - 1);
- tot_num_frames += rc->layer_input_frames[i];
- rc->layer_encoding_bitrate[i] = 0.001 * rc->layer_framerate[i] *
- rc->layer_encoding_bitrate[i] / tot_num_frames;
- rc->layer_avg_frame_size[i] = rc->layer_avg_frame_size[i] /
- rc->layer_enc_frames[i];
- rc->layer_avg_rate_mismatch[i] = 100.0 * rc->layer_avg_rate_mismatch[i] /
- rc->layer_enc_frames[i];
- printf("For layer#: %d \n", i);
- printf("Bitrate (target vs actual): %d %f \n", rc->layer_target_bitrate[i],
- rc->layer_encoding_bitrate[i]);
- printf("Average frame size (target vs actual): %f %f \n", rc->layer_pfb[i],
- rc->layer_avg_frame_size[i]);
- printf("Average rate_mismatch: %f \n", rc->layer_avg_rate_mismatch[i]);
- printf("Number of input frames, encoded (non-key) frames, "
- "and perc dropped frames: %d %d %f \n", rc->layer_input_frames[i],
- rc->layer_enc_frames[i],
- 100.0 * num_dropped / rc->layer_input_frames[i]);
- printf("\n");
- }
- rc->avg_st_encoding_bitrate = rc->avg_st_encoding_bitrate / rc->window_count;
- rc->variance_st_encoding_bitrate =
- rc->variance_st_encoding_bitrate / rc->window_count -
- (rc->avg_st_encoding_bitrate * rc->avg_st_encoding_bitrate);
- perc_fluctuation = 100.0 * sqrt(rc->variance_st_encoding_bitrate) /
- rc->avg_st_encoding_bitrate;
- printf("Short-time stats, for window of %d frames: \n",rc->window_size);
- printf("Average, rms-variance, and percent-fluct: %f %f %f \n",
- rc->avg_st_encoding_bitrate,
- sqrt(rc->variance_st_encoding_bitrate),
- perc_fluctuation);
- if ((frame_cnt - 1) != tot_num_frames)
- die("Error: Number of input frames not equal to output! \n");
-}
-
-// 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
-// frames should be allocated to layers in the order LAST, GF, ARF.
-// Other combinations work, but may produce slightly inferior results.
-static void set_temporal_layer_pattern(int layering_mode,
- vpx_codec_enc_cfg_t *cfg,
- int *layer_flags,
- int *flag_periodicity) {
- switch (layering_mode) {
- case 0: {
- // 1-layer.
- int ids[1] = {0};
- cfg->ts_periodicity = 1;
- *flag_periodicity = 1;
- cfg->ts_number_layers = 1;
- cfg->ts_rate_decimator[0] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
- // Update L only.
- layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF |
- VP8_EFLAG_NO_UPD_ARF;
- break;
- }
- case 1: {
- // 2-layers, 2-frame period.
- int ids[2] = {0, 1};
- cfg->ts_periodicity = 2;
- *flag_periodicity = 2;
- cfg->ts_number_layers = 2;
- cfg->ts_rate_decimator[0] = 2;
- cfg->ts_rate_decimator[1] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
-#if 1
- // 0=L, 1=GF, Intra-layer prediction enabled.
- layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF |
- VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
- layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_REF_ARF;
-#else
- // 0=L, 1=GF, Intra-layer prediction disabled.
- layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF |
- VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
- layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST;
-#endif
- break;
- }
- case 2: {
- // 2-layers, 3-frame period.
- int ids[3] = {0, 1, 1};
- cfg->ts_periodicity = 3;
- *flag_periodicity = 3;
- cfg->ts_number_layers = 2;
- cfg->ts_rate_decimator[0] = 3;
- cfg->ts_rate_decimator[1] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
- // 0=L, 1=GF, Intra-layer prediction enabled.
- layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
- VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
- layer_flags[1] =
- layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
- VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
- break;
- }
- case 3: {
- // 3-layers, 6-frame period.
- int ids[6] = {0, 2, 2, 1, 2, 2};
- cfg->ts_periodicity = 6;
- *flag_periodicity = 6;
- cfg->ts_number_layers = 3;
- cfg->ts_rate_decimator[0] = 6;
- cfg->ts_rate_decimator[1] = 3;
- cfg->ts_rate_decimator[2] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
- // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled.
- layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
- VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
- layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
- VP8_EFLAG_NO_UPD_LAST;
- layer_flags[1] =
- layer_flags[2] =
- layer_flags[4] =
- layer_flags[5] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
- break;
- }
- case 4: {
- // 3-layers, 4-frame period.
- int ids[4] = {0, 2, 1, 2};
- cfg->ts_periodicity = 4;
- *flag_periodicity = 4;
- cfg->ts_number_layers = 3;
- cfg->ts_rate_decimator[0] = 4;
- cfg->ts_rate_decimator[1] = 2;
- cfg->ts_rate_decimator[2] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
- // 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled.
- layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
- VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
- layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
- VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
- layer_flags[1] =
- layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
- break;
- }
- case 5: {
- // 3-layers, 4-frame period.
- int ids[4] = {0, 2, 1, 2};
- cfg->ts_periodicity = 4;
- *flag_periodicity = 4;
- cfg->ts_number_layers = 3;
- cfg->ts_rate_decimator[0] = 4;
- cfg->ts_rate_decimator[1] = 2;
- cfg->ts_rate_decimator[2] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
- // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled in layer 1, disabled
- // in layer 2.
- layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
- VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
- layer_flags[2] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_ARF;
- layer_flags[1] =
- layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
- break;
- }
- case 6: {
- // 3-layers, 4-frame period.
- int ids[4] = {0, 2, 1, 2};
- cfg->ts_periodicity = 4;
- *flag_periodicity = 4;
- cfg->ts_number_layers = 3;
- cfg->ts_rate_decimator[0] = 4;
- cfg->ts_rate_decimator[1] = 2;
- cfg->ts_rate_decimator[2] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
- // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled.
- layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
- VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
- layer_flags[2] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_ARF;
- layer_flags[1] =
- layer_flags[3] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
- break;
- }
- case 7: {
- // NOTE: Probably of academic interest only.
- // 5-layers, 16-frame period.
- int ids[16] = {0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4};
- cfg->ts_periodicity = 16;
- *flag_periodicity = 16;
- cfg->ts_number_layers = 5;
- cfg->ts_rate_decimator[0] = 16;
- cfg->ts_rate_decimator[1] = 8;
- cfg->ts_rate_decimator[2] = 4;
- cfg->ts_rate_decimator[3] = 2;
- cfg->ts_rate_decimator[4] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
- layer_flags[0] = VPX_EFLAG_FORCE_KF;
- layer_flags[1] =
- layer_flags[3] =
- layer_flags[5] =
- layer_flags[7] =
- layer_flags[9] =
- layer_flags[11] =
- layer_flags[13] =
- layer_flags[15] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
- VP8_EFLAG_NO_UPD_ARF;
- layer_flags[2] =
- layer_flags[6] =
- layer_flags[10] =
- layer_flags[14] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF;
- layer_flags[4] =
- layer_flags[12] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_ARF;
- layer_flags[8] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF;
- break;
- }
- case 8: {
- // 2-layers, with sync point at first frame of layer 1.
- int ids[2] = {0, 1};
- cfg->ts_periodicity = 2;
- *flag_periodicity = 8;
- cfg->ts_number_layers = 2;
- cfg->ts_rate_decimator[0] = 2;
- cfg->ts_rate_decimator[1] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
- // 0=L, 1=GF.
- // ARF is used as predictor for all frames, and is only updated on
- // key frame. Sync point every 8 frames.
-
- // Layer 0: predict from L and ARF, update L and G.
- layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
- VP8_EFLAG_NO_UPD_ARF;
- // Layer 1: sync point: predict from L and ARF, and update G.
- layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_ARF;
- // Layer 0, predict from L and ARF, update L.
- layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
- VP8_EFLAG_NO_UPD_ARF;
- // Layer 1: predict from L, G and ARF, and update G.
- layer_flags[3] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_ENTROPY;
- // Layer 0.
- layer_flags[4] = layer_flags[2];
- // Layer 1.
- layer_flags[5] = layer_flags[3];
- // Layer 0.
- layer_flags[6] = layer_flags[4];
- // Layer 1.
- layer_flags[7] = layer_flags[5];
- break;
- }
- case 9: {
- // 3-layers: Sync points for layer 1 and 2 every 8 frames.
- int ids[4] = {0, 2, 1, 2};
- cfg->ts_periodicity = 4;
- *flag_periodicity = 8;
- cfg->ts_number_layers = 3;
- cfg->ts_rate_decimator[0] = 4;
- cfg->ts_rate_decimator[1] = 2;
- cfg->ts_rate_decimator[2] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
- // 0=L, 1=GF, 2=ARF.
- layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
- VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
- layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
- VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
- layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
- VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
- layer_flags[3] =
- layer_flags[5] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
- layer_flags[4] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
- VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
- layer_flags[6] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_ARF;
- layer_flags[7] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
- VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_ENTROPY;
- break;
- }
- case 10: {
- // 3-layers structure where ARF is used as predictor for all frames,
- // and is only updated on key frame.
- // Sync points for layer 1 and 2 every 8 frames.
-
- int ids[4] = {0, 2, 1, 2};
- cfg->ts_periodicity = 4;
- *flag_periodicity = 8;
- cfg->ts_number_layers = 3;
- cfg->ts_rate_decimator[0] = 4;
- cfg->ts_rate_decimator[1] = 2;
- cfg->ts_rate_decimator[2] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
- // 0=L, 1=GF, 2=ARF.
- // Layer 0: predict from L and ARF; update L and G.
- layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_ARF |
- VP8_EFLAG_NO_REF_GF;
- // Layer 2: sync point: predict from L and ARF; update none.
- layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
- VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_ENTROPY;
- // Layer 1: sync point: predict from L and ARF; update G.
- layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF |
- VP8_EFLAG_NO_UPD_LAST;
- // Layer 2: predict from L, G, ARF; update none.
- layer_flags[3] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
- VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY;
- // Layer 0: predict from L and ARF; update L.
- layer_flags[4] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
- VP8_EFLAG_NO_REF_GF;
- // Layer 2: predict from L, G, ARF; update none.
- layer_flags[5] = layer_flags[3];
- // Layer 1: predict from L, G, ARF; update G.
- layer_flags[6] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
- // Layer 2: predict from L, G, ARF; update none.
- layer_flags[7] = layer_flags[3];
- break;
- }
- case 11: {
- // 3-layers structure with one reference frame.
- // This works same as temporal_layering_mode 3.
- // This was added to compare with vp9_spatial_svc_encoder.
-
- // 3-layers, 4-frame period.
- int ids[4] = {0, 2, 1, 2};
- cfg->ts_periodicity = 4;
- *flag_periodicity = 4;
- cfg->ts_number_layers = 3;
- cfg->ts_rate_decimator[0] = 4;
- cfg->ts_rate_decimator[1] = 2;
- cfg->ts_rate_decimator[2] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
- // 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled.
- layer_flags[0] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
- VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
- layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
- VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
- layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
- VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
- layer_flags[3] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_ARF |
- VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
- break;
- }
- case 12:
- default: {
- // 3-layers structure as in case 10, but no sync/refresh points for
- // layer 1 and 2.
- int ids[4] = {0, 2, 1, 2};
- cfg->ts_periodicity = 4;
- *flag_periodicity = 8;
- cfg->ts_number_layers = 3;
- cfg->ts_rate_decimator[0] = 4;
- cfg->ts_rate_decimator[1] = 2;
- cfg->ts_rate_decimator[2] = 1;
- memcpy(cfg->ts_layer_id, ids, sizeof(ids));
- // 0=L, 1=GF, 2=ARF.
- // Layer 0: predict from L and ARF; update L.
- layer_flags[0] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
- VP8_EFLAG_NO_REF_GF;
- layer_flags[4] = layer_flags[0];
- // Layer 1: predict from L, G, ARF; update G.
- layer_flags[2] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
- layer_flags[6] = layer_flags[2];
- // Layer 2: predict from L, G, ARF; update none.
- layer_flags[1] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
- VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY;
- layer_flags[3] = layer_flags[1];
- layer_flags[5] = layer_flags[1];
- layer_flags[7] = layer_flags[1];
- break;
- }
- }
-}
-
-int main(int argc, char **argv) {
- VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL};
- vpx_codec_ctx_t codec;
- vpx_codec_enc_cfg_t cfg;
- int frame_cnt = 0;
- vpx_image_t raw;
- vpx_codec_err_t res;
- unsigned int width;
- unsigned int height;
- int speed;
- int frame_avail;
- int got_data;
- int flags = 0;
- unsigned int i;
- int pts = 0; // PTS starts at 0.
- int frame_duration = 1; // 1 timebase tick per frame.
- 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};
-#endif
- const VpxInterface *encoder = NULL;
- FILE *infile = NULL;
- struct RateControlMetrics rc;
- int64_t cx_time = 0;
- const int min_args_base = 11;
-#if CONFIG_VP9_HIGHBITDEPTH
- vpx_bit_depth_t bit_depth = VPX_BITS_8;
- int input_bit_depth = 8;
- const int min_args = min_args_base + 1;
-#else
- const int min_args = min_args_base;
-#endif // CONFIG_VP9_HIGHBITDEPTH
- double sum_bitrate = 0.0;
- double sum_bitrate2 = 0.0;
- double framerate = 30.0;
-
- exec_name = argv[0];
- // Check usage and arguments.
- 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_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_0> ... <Rate_nlayers-1> \n", argv[0]);
-#endif // CONFIG_VP9_HIGHBITDEPTH
- }
-
- encoder = get_vpx_encoder_by_name(argv[3]);
- if (!encoder)
- die("Unsupported codec.");
-
- printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
-
- width = strtol(argv[4], NULL, 0);
- height = strtol(argv[5], NULL, 0);
- if (width < 16 || width % 2 || height < 16 || height % 2) {
- die("Invalid resolution: %d x %d", width, height);
- }
-
- layering_mode = strtol(argv[10], NULL, 0);
- if (layering_mode < 0 || layering_mode > 13) {
- die("Invalid layering mode (0..12) %s", argv[10]);
- }
-
- if (argc != min_args + mode_to_num_layers[layering_mode]) {
- die("Invalid number of arguments");
- }
-
-#if CONFIG_VP9_HIGHBITDEPTH
- switch (strtol(argv[argc-1], NULL, 0)) {
- case 8:
- bit_depth = VPX_BITS_8;
- input_bit_depth = 8;
- break;
- case 10:
- bit_depth = VPX_BITS_10;
- input_bit_depth = 10;
- break;
- case 12:
- bit_depth = VPX_BITS_12;
- input_bit_depth = 12;
- break;
- default:
- die("Invalid bit depth (8, 10, 12) %s", argv[argc-1]);
- }
- if (!vpx_img_alloc(&raw,
- bit_depth == VPX_BITS_8 ? VPX_IMG_FMT_I420 :
- VPX_IMG_FMT_I42016,
- width, height, 32)) {
- die("Failed to allocate image", width, height);
- }
-#else
- if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 32)) {
- die("Failed to allocate image", width, height);
- }
-#endif // CONFIG_VP9_HIGHBITDEPTH
-
- // Populate encoder configuration.
- res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
- if (res) {
- printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
- return EXIT_FAILURE;
- }
-
- // Update the default configuration with our settings.
- cfg.g_w = width;
- cfg.g_h = height;
-
-#if CONFIG_VP9_HIGHBITDEPTH
- if (bit_depth != VPX_BITS_8) {
- cfg.g_bit_depth = bit_depth;
- cfg.g_input_bit_depth = input_bit_depth;
- cfg.g_profile = 2;
- }
-#endif // CONFIG_VP9_HIGHBITDEPTH
-
- // Timebase format e.g. 30fps: numerator=1, demoninator = 30.
- cfg.g_timebase.num = strtol(argv[6], NULL, 0);
- cfg.g_timebase.den = strtol(argv[7], NULL, 0);
-
- speed = strtol(argv[8], NULL, 0);
- if (speed < 0) {
- die("Invalid speed setting: must be positive");
- }
-
- for (i = min_args_base;
- (int)i < min_args_base + mode_to_num_layers[layering_mode];
- ++i) {
- rc.layer_target_bitrate[i - 11] = strtol(argv[i], NULL, 0);
- if (strncmp(encoder->name, "vp8", 3) == 0)
- cfg.ts_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11];
- else if (strncmp(encoder->name, "vp9", 3) == 0)
- cfg.layer_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11];
- }
-
- // Real time parameters.
- cfg.rc_dropframe_thresh = strtol(argv[9], NULL, 0);
- cfg.rc_end_usage = VPX_CBR;
- cfg.rc_min_quantizer = 2;
- cfg.rc_max_quantizer = 56;
- 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_optimal_sz = 600;
- cfg.rc_buf_sz = 1000;
-
- // Disable dynamic resizing by default.
- cfg.rc_resize_allowed = 0;
-
- // Use 1 thread as default.
- cfg.g_threads = 1;
-
- // Enable error resilient mode.
- cfg.g_error_resilient = 1;
- cfg.g_lag_in_frames = 0;
- cfg.kf_mode = VPX_KF_AUTO;
-
- // Disable automatic keyframe placement.
- cfg.kf_min_dist = cfg.kf_max_dist = 3000;
-
- cfg.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
-
- set_temporal_layer_pattern(layering_mode,
- &cfg,
- layer_flags,
- &flag_periodicity);
-
- set_rate_control_metrics(&rc, &cfg);
-
- // Target bandwidth for the whole stream.
- // Set to layer_target_bitrate for highest layer (total bitrate).
- cfg.rc_target_bitrate = rc.layer_target_bitrate[cfg.ts_number_layers - 1];
-
- // Open input file.
- if (!(infile = fopen(argv[1], "rb"))) {
- die("Failed to open %s for reading", argv[1]);
- }
-
- framerate = cfg.g_timebase.den / cfg.g_timebase.num;
- // Open an output file for each stream.
- for (i = 0; i < cfg.ts_number_layers; ++i) {
- char file_name[PATH_MAX];
- VpxVideoInfo info;
- info.codec_fourcc = encoder->fourcc;
- info.frame_width = cfg.g_w;
- info.frame_height = cfg.g_h;
- info.time_base.numerator = cfg.g_timebase.num;
- info.time_base.denominator = cfg.g_timebase.den;
-
- snprintf(file_name, sizeof(file_name), "%s_%d.ivf", argv[2], i);
- outfile[i] = vpx_video_writer_open(file_name, kContainerIVF, &info);
- if (!outfile[i])
- die("Failed to open %s for writing", file_name);
-
- assert(outfile[i] != NULL);
- }
- // No spatial layers in this encoder.
- cfg.ss_number_layers = 1;
-
- // Initialize codec.
-#if CONFIG_VP9_HIGHBITDEPTH
- if (vpx_codec_enc_init(
- &codec, encoder->codec_interface(), &cfg,
- bit_depth == VPX_BITS_8 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH))
-#else
- if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
-#endif // CONFIG_VP9_HIGHBITDEPTH
- die_codec(&codec, "Failed to initialize encoder");
-
- 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_STATIC_THRESHOLD, 1);
- } else if (strncmp(encoder->name, "vp9", 3) == 0) {
- vpx_svc_extra_cfg_t 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_FRAME_PERIODIC_BOOST, 0);
- vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, kDenoiserOff);
- 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));
- 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) {
- svc_params.max_quantizers[i] = cfg.rc_max_quantizer;
- svc_params.min_quantizers[i] = cfg.rc_min_quantizer;
- }
- svc_params.scaling_factor_num[0] = cfg.g_h;
- svc_params.scaling_factor_den[0] = cfg.g_h;
- vpx_codec_control(&codec, VP9E_SET_SVC_PARAMETERS, &svc_params);
- }
- if (strncmp(encoder->name, "vp8", 3) == 0) {
- vpx_codec_control(&codec, VP8E_SET_SCREEN_CONTENT_MODE, 0);
- }
- vpx_codec_control(&codec, VP8E_SET_TOKEN_PARTITIONS, 1);
- // This controls the maximum target size of the key frame.
- // For generating smaller key frames, use a smaller max_intra_size_pct
- // value, like 100 or 200.
- {
- const int max_intra_size_pct = 900;
- vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT,
- max_intra_size_pct);
- }
-
- frame_avail = 1;
- while (frame_avail || got_data) {
- 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) {
- vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id);
- } else if (strncmp(encoder->name, "vp8", 3) == 0) {
- vpx_codec_control(&codec, VP8E_SET_TEMPORAL_LAYER_ID,
- layer_id.temporal_layer_id);
- }
- flags = layer_flags[frame_cnt % flag_periodicity];
- if (layering_mode == 0)
- flags = 0;
- frame_avail = vpx_img_read(&raw, infile);
- if (frame_avail)
- ++rc.layer_input_frames[layer_id.temporal_layer_id];
- vpx_usec_timer_start(&timer);
- if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts, 1, flags,
- VPX_DL_REALTIME)) {
- die_codec(&codec, "Failed to encode frame");
- }
- vpx_usec_timer_mark(&timer);
- cx_time += vpx_usec_timer_elapsed(&timer);
- // Reset KF flag.
- if (layering_mode != 7) {
- layer_flags[0] &= ~VPX_EFLAG_FORCE_KF;
- }
- got_data = 0;
- while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
- got_data = 1;
- switch (pkt->kind) {
- case VPX_CODEC_CX_FRAME_PKT:
- for (i = cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
- i < cfg.ts_number_layers; ++i) {
- vpx_video_writer_write_frame(outfile[i], pkt->data.frame.buf,
- pkt->data.frame.sz, pts);
- ++rc.layer_tot_enc_frames[i];
- rc.layer_encoding_bitrate[i] += 8.0 * pkt->data.frame.sz;
- // Keep count of rate control stats per layer (for non-key frames).
- if (i == cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity] &&
- !(pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
- rc.layer_avg_frame_size[i] += 8.0 * pkt->data.frame.sz;
- rc.layer_avg_rate_mismatch[i] +=
- fabs(8.0 * pkt->data.frame.sz - rc.layer_pfb[i]) /
- rc.layer_pfb[i];
- ++rc.layer_enc_frames[i];
- }
- }
- // 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) {
- sum_bitrate += 0.001 * 8.0 * pkt->data.frame.sz * framerate;
- if (frame_cnt % rc.window_size == 0) {
- rc.window_count += 1;
- rc.avg_st_encoding_bitrate += sum_bitrate / rc.window_size;
- rc.variance_st_encoding_bitrate +=
- (sum_bitrate / rc.window_size) *
- (sum_bitrate / rc.window_size);
- sum_bitrate = 0.0;
- }
- }
- // Second shifted window.
- if (frame_cnt > rc.window_size + rc.window_size / 2) {
- sum_bitrate2 += 0.001 * 8.0 * pkt->data.frame.sz * framerate;
- if (frame_cnt > 2 * rc.window_size &&
- frame_cnt % rc.window_size == 0) {
- rc.window_count += 1;
- rc.avg_st_encoding_bitrate += sum_bitrate2 / rc.window_size;
- rc.variance_st_encoding_bitrate +=
- (sum_bitrate2 / rc.window_size) *
- (sum_bitrate2 / rc.window_size);
- sum_bitrate2 = 0.0;
- }
- }
- break;
- default:
- break;
- }
- }
- ++frame_cnt;
- pts += frame_duration;
- }
- fclose(infile);
- printout_rate_control_summary(&rc, &cfg, frame_cnt);
- printf("\n");
- printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n",
- frame_cnt,
- 1000 * (float)cx_time / (double)(frame_cnt * 1000000),
- 1000000 * (double)frame_cnt / (double)cx_time);
-
- if (vpx_codec_destroy(&codec))
- die_codec(&codec, "Failed to destroy codec");
-
- // Try to rewrite the output file headers with the actual frame count.
- for (i = 0; i < cfg.ts_number_layers; ++i)
- vpx_video_writer_close(outfile[i]);
-
- vpx_img_free(&raw);
- return EXIT_SUCCESS;
-}
diff --git a/libs.mk b/libs.mk
index 13c33ca..b42c623 100644
--- a/libs.mk
+++ b/libs.mk
@@ -66,7 +66,6 @@
CODEC_EXPORTS-yes += $(addprefix $(VP10_PREFIX),$(VP10_CX_EXPORTS))
CODEC_SRCS-yes += $(VP10_PREFIX)vp10cx.mk vpx/vp8.h vpx/vp8cx.h
INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8cx.h
- INSTALL-LIBS-$(CONFIG_SPATIAL_SVC) += include/vpx/svc_context.h
INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP10_PREFIX)/%
CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8cx.h
CODEC_DOC_SECTIONS += vp9 vp9_encoder
@@ -127,9 +126,6 @@
endif
CODEC_EXPORTS-yes += vpx/exports_com
CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_enc
-ifeq ($(CONFIG_SPATIAL_SVC),yes)
-CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_spatial_svc
-endif
CODEC_EXPORTS-$(CONFIG_DECODERS) += vpx/exports_dec
INSTALL-LIBS-yes += include/vpx/vpx_codec.h
@@ -265,7 +261,7 @@
$(qexec)echo LIBRARY $(LIBVPX_SO:.dll=) INITINSTANCE TERMINSTANCE > $@
$(qexec)echo "DATA MULTIPLE NONSHARED" >> $@
$(qexec)echo "EXPORTS" >> $@
- $(qexec)awk '!/vpx_svc_*/ {print "_"$$2}' $^ >>$@
+ $(qexec)awk '{print "_"$$2}' $^ >>$@
CLEAN-OBJS += libvpx.def
libvpx_dll.a: $(LIBVPX_SO)
diff --git a/test/cx_set_ref.sh b/test/cx_set_ref.sh
index 678399e..dddb366 100755
--- a/test/cx_set_ref.sh
+++ b/test/cx_set_ref.sh
@@ -29,10 +29,6 @@
local codec="$1"
local encoder="${LIBVPX_BIN_PATH}/vpxcx_set_ref${VPX_TEST_EXE_SUFFIX}"
- if [ "$codec" = "vp8" ]; then
- encoder="${LIBVPX_BIN_PATH}/vp8cx_set_ref${VPX_TEST_EXE_SUFFIX}"
- fi
-
local output_file="${VPX_TEST_OUTPUT_DIR}/${codec}cx_set_ref_${codec}.ivf"
local ref_frame_num=90
@@ -54,24 +50,12 @@
[ -e "${output_file}" ] || return 1
}
-cx_set_ref_vp8() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_set_ref vp8 || return 1
- fi
-}
-
-cx_set_ref_vp9() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_set_ref vp9 || return 1
- fi
-}
-
cx_set_ref_vp10() {
if [ "$(vp10_encode_available)" = "yes" ]; then
vpx_set_ref vp10 || return 1
fi
}
-cx_set_ref_tests="cx_set_ref_vp8 cx_set_ref_vp9 cx_set_ref_vp10"
+cx_set_ref_tests="cx_set_ref_vp10"
run_tests cx_set_ref_verify_environment "${cx_set_ref_tests}"
diff --git a/test/datarate_test.cc b/test/datarate_test.cc
index 13f12e2..89761e7 100644
--- a/test/datarate_test.cc
+++ b/test/datarate_test.cc
@@ -19,198 +19,13 @@
namespace {
class DatarateTestLarge : public ::libvpx_test::EncoderTest,
- public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
public:
DatarateTestLarge() : EncoderTest(GET_PARAM(0)) {}
+ protected:
virtual ~DatarateTestLarge() {}
- protected:
- virtual void SetUp() {
- InitializeConfig();
- SetMode(GET_PARAM(1));
- ResetModel();
- }
-
- virtual void ResetModel() {
- last_pts_ = 0;
- bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
- frame_number_ = 0;
- first_drop_ = 0;
- bits_total_ = 0;
- duration_ = 0.0;
- denoiser_offon_test_ = 0;
- denoiser_offon_period_ = -1;
- }
-
- virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
- ::libvpx_test::Encoder *encoder) {
- if (video->frame() == 0)
- encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
-
- if (denoiser_offon_test_) {
- ASSERT_GT(denoiser_offon_period_, 0)
- << "denoiser_offon_period_ is not positive.";
- if ((video->frame() + 1) % denoiser_offon_period_ == 0) {
- // Flip denoiser_on_ periodically
- denoiser_on_ ^= 1;
- }
- encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
- }
-
- const vpx_rational_t tb = video->timebase();
- timebase_ = static_cast<double>(tb.num) / tb.den;
- duration_ = 0;
- }
-
- virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
- // Time since last timestamp = duration.
- vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
-
- // TODO(jimbankoski): Remove these lines when the issue:
- // http://code.google.com/p/webm/issues/detail?id=496 is fixed.
- // For now the codec assumes buffer starts at starting buffer rate
- // plus one frame's time.
- if (last_pts_ == 0)
- duration = 1;
-
- // Add to the buffer the bits we'd expect from a constant bitrate server.
- bits_in_buffer_model_ += static_cast<int64_t>(
- duration * timebase_ * cfg_.rc_target_bitrate * 1000);
-
- /* Test the buffer model here before subtracting the frame. Do so because
- * the way the leaky bucket model works in libvpx is to allow the buffer to
- * empty - and then stop showing frames until we've got enough bits to
- * show one. As noted in comment below (issue 495), this does not currently
- * apply to key frames. For now exclude key frames in condition below. */
- const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY)
- ? true: false;
- if (!key_frame) {
- ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
- << pkt->data.frame.pts;
- }
-
- const int64_t frame_size_in_bits = pkt->data.frame.sz * 8;
-
- // Subtract from the buffer the bits associated with a played back frame.
- bits_in_buffer_model_ -= frame_size_in_bits;
-
- // Update the running total of bits for end of test datarate checks.
- bits_total_ += frame_size_in_bits;
-
- // If first drop not set and we have a drop set it to this time.
- if (!first_drop_ && duration > 1)
- first_drop_ = last_pts_ + 1;
-
- // Update the most recent pts.
- last_pts_ = pkt->data.frame.pts;
-
- // We update this so that we can calculate the datarate minus the last
- // frame encoded in the file.
- bits_in_last_frame_ = frame_size_in_bits;
-
- ++frame_number_;
- }
-
- virtual void EndPassHook(void) {
- if (bits_total_) {
- const double file_size_in_kb = bits_total_ / 1000.; // bits per kilobit
-
- duration_ = (last_pts_ + 1) * timebase_;
-
- // Effective file datarate includes the time spent prebuffering.
- effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0
- / (cfg_.rc_buf_initial_sz / 1000.0 + duration_);
-
- file_datarate_ = file_size_in_kb / duration_;
- }
- }
-
- vpx_codec_pts_t last_pts_;
- int64_t bits_in_buffer_model_;
- double timebase_;
- int frame_number_;
- vpx_codec_pts_t first_drop_;
- int64_t bits_total_;
- double duration_;
- double file_datarate_;
- double effective_datarate_;
- int64_t bits_in_last_frame_;
- int denoiser_on_;
- int denoiser_offon_test_;
- int denoiser_offon_period_;
-};
-
-
-TEST_P(DatarateTestLarge, BasicBufferModel) {
- denoiser_on_ = 0;
- cfg_.rc_buf_initial_sz = 500;
- cfg_.rc_dropframe_thresh = 1;
- cfg_.rc_max_quantizer = 56;
- cfg_.rc_end_usage = VPX_CBR;
- // 2 pass cbr datarate control has a bug hidden by the small # of
- // frames selected in this encode. The problem is that even if the buffer is
- // negative we produce a keyframe on a cutscene. Ignoring datarate
- // constraints
- // TODO(jimbankoski): ( Fix when issue
- // http://code.google.com/p/webm/issues/detail?id=495 is addressed. )
- ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
- 30, 1, 0, 140);
-
- // There is an issue for low bitrates in real-time mode, where the
- // effective_datarate slightly overshoots the target bitrate.
- // This is same the issue as noted about (#495).
- // TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100),
- // when the issue is resolved.
- for (int i = 100; i < 800; i += 200) {
- cfg_.rc_target_bitrate = i;
- ResetModel();
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
- << " The datarate for the file exceeds the target!";
-
- ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3)
- << " The datarate for the file missed the target!";
- }
-}
-
-TEST_P(DatarateTestLarge, ChangingDropFrameThresh) {
- denoiser_on_ = 0;
- cfg_.rc_buf_initial_sz = 500;
- cfg_.rc_max_quantizer = 36;
- cfg_.rc_end_usage = VPX_CBR;
- cfg_.rc_target_bitrate = 200;
- cfg_.kf_mode = VPX_KF_DISABLED;
-
- const int frame_count = 40;
- ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
- 30, 1, 0, frame_count);
-
- // Here we check that the first dropped frame gets earlier and earlier
- // as the drop frame threshold is increased.
-
- const int kDropFrameThreshTestStep = 30;
- vpx_codec_pts_t last_drop = frame_count;
- for (int i = 1; i < 91; i += kDropFrameThreshTestStep) {
- cfg_.rc_dropframe_thresh = i;
- ResetModel();
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- ASSERT_LE(first_drop_, last_drop)
- << " The first dropped frame for drop_thresh " << i
- << " > first dropped frame for drop_thresh "
- << i - kDropFrameThreshTestStep;
- last_drop = first_drop_;
- }
-}
-
-class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
- public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
- public:
- DatarateTestVP9Large() : EncoderTest(GET_PARAM(0)) {}
-
- protected:
- virtual ~DatarateTestVP9Large() {}
-
virtual void SetUp() {
InitializeConfig();
SetMode(GET_PARAM(1));
@@ -227,77 +42,11 @@
num_drops_ = 0;
// Denoiser is off by default.
denoiser_on_ = 0;
- // For testing up to 3 layers.
- for (int i = 0; i < 3; ++i) {
- bits_total_[i] = 0;
- }
+ bits_total_ = 0;
denoiser_offon_test_ = 0;
denoiser_offon_period_ = -1;
}
- //
- // Frame flags and layer id for temporal layers.
- //
-
- // For two layers, test pattern is:
- // 1 3
- // 0 2 .....
- // For three layers, test pattern is:
- // 1 3 5 7
- // 2 6
- // 0 4 ....
- // LAST is always update on base/layer 0, GOLDEN is updated on layer 1.
- // For this 3 layer example, the 2nd enhancement layer (layer 2) does not
- // update any reference frames.
- int SetFrameFlags(int frame_num, int num_temp_layers) {
- int frame_flags = 0;
- if (num_temp_layers == 2) {
- if (frame_num % 2 == 0) {
- // Layer 0: predict from L and ARF, update L.
- frame_flags = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
- VP8_EFLAG_NO_UPD_ARF;
- } else {
- // Layer 1: predict from L, G and ARF, and update G.
- frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_ENTROPY;
- }
- } else if (num_temp_layers == 3) {
- if (frame_num % 4 == 0) {
- // Layer 0: predict from L and ARF; update L.
- frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
- VP8_EFLAG_NO_REF_GF;
- } else if ((frame_num - 2) % 4 == 0) {
- // Layer 1: predict from L, G, ARF; update G.
- frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
- } else if ((frame_num - 1) % 2 == 0) {
- // Layer 2: predict from L, G, ARF; update none.
- frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
- VP8_EFLAG_NO_UPD_LAST;
- }
- }
- return frame_flags;
- }
-
- int SetLayerId(int frame_num, int num_temp_layers) {
- int layer_id = 0;
- if (num_temp_layers == 2) {
- if (frame_num % 2 == 0) {
- layer_id = 0;
- } else {
- layer_id = 1;
- }
- } else if (num_temp_layers == 3) {
- if (frame_num % 4 == 0) {
- layer_id = 0;
- } else if ((frame_num - 2) % 4 == 0) {
- layer_id = 1;
- } else if ((frame_num - 1) % 2 == 0) {
- layer_id = 2;
- }
- }
- return layer_id;
- }
-
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
::libvpx_test::Encoder *encoder) {
if (video->frame() == 0)
@@ -314,23 +63,11 @@
encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);
- if (cfg_.ts_number_layers > 1) {
- if (video->frame() == 0) {
- encoder->Control(VP9E_SET_SVC, 1);
- }
- vpx_svc_layer_id_t layer_id;
- layer_id.spatial_layer_id = 0;
- frame_flags_ = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
- layer_id.temporal_layer_id = SetLayerId(video->frame(),
- cfg_.ts_number_layers);
- encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id);
- }
const vpx_rational_t tb = video->timebase();
timebase_ = static_cast<double>(tb.num) / tb.den;
duration_ = 0;
}
-
virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
// Time since last timestamp = duration.
vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
@@ -346,8 +83,6 @@
tot_frame_number_ += static_cast<int>(duration - 1);
}
- int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers);
-
// Add to the buffer the bits we'd expect from a constant bitrate server.
bits_in_buffer_model_ += static_cast<int64_t>(
duration * timebase_ * cfg_.rc_target_bitrate * 1000);
@@ -358,11 +93,8 @@
const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
- // Update the total encoded bits. For temporal layers, update the cumulative
- // encoded bits per layer.
- for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
- bits_total_[i] += frame_size_in_bits;
- }
+ // Update the total encoded bits.
+ bits_total_ += frame_size_in_bits;
// Update the most recent pts.
last_pts_ = pkt->data.frame.pts;
@@ -371,23 +103,18 @@
}
virtual void EndPassHook(void) {
- for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
- ++layer) {
- duration_ = (last_pts_ + 1) * timebase_;
- if (bits_total_[layer]) {
- // Effective file datarate:
- effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_;
- }
- }
+ duration_ = (last_pts_ + 1) * timebase_;
+ // Effective file datarate:
+ effective_datarate_ = (bits_total_ / 1000.0) / duration_;
}
vpx_codec_pts_t last_pts_;
double timebase_;
int frame_number_; // Counter for number of non-dropped/encoded frames.
int tot_frame_number_; // Counter for total number of input frames.
- int64_t bits_total_[3];
+ int64_t bits_total_;
double duration_;
- double effective_datarate_[3];
+ double effective_datarate_;
int set_cpu_used_;
int64_t bits_in_buffer_model_;
vpx_codec_pts_t first_drop_;
@@ -398,7 +125,7 @@
};
// Check basic rate targeting for VBR mode.
-TEST_P(DatarateTestVP9Large, BasicRateTargetingVBR) {
+TEST_P(DatarateTestLarge, BasicRateTargetingVBR) {
cfg_.rc_min_quantizer = 0;
cfg_.rc_max_quantizer = 63;
cfg_.g_error_resilient = 0;
@@ -411,15 +138,15 @@
cfg_.rc_target_bitrate = i;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
+ ASSERT_GE(effective_datarate_, cfg_.rc_target_bitrate * 0.75)
<< " The datarate for the file is lower than target by too much!";
- ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.25)
+ ASSERT_LE(effective_datarate_, cfg_.rc_target_bitrate * 1.25)
<< " The datarate for the file is greater than target by too much!";
}
}
// Check basic rate targeting for CBR,
-TEST_P(DatarateTestVP9Large, BasicRateTargeting) {
+TEST_P(DatarateTestLarge, BasicRateTargeting) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -435,15 +162,15 @@
cfg_.rc_target_bitrate = i;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+ ASSERT_GE(effective_datarate_, cfg_.rc_target_bitrate * 0.85)
<< " The datarate for the file is lower than target by too much!";
- ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+ ASSERT_LE(effective_datarate_, cfg_.rc_target_bitrate * 1.15)
<< " The datarate for the file is greater than target by too much!";
}
}
// Check basic rate targeting for CBR.
-TEST_P(DatarateTestVP9Large, BasicRateTargeting444) {
+TEST_P(DatarateTestLarge, BasicRateTargeting444) {
::libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 140);
cfg_.g_profile = 1;
@@ -462,10 +189,10 @@
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
ASSERT_GE(static_cast<double>(cfg_.rc_target_bitrate),
- effective_datarate_[0] * 0.85)
+ effective_datarate_ * 0.85)
<< " The datarate for the file exceeds the target by too much!";
ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate),
- effective_datarate_[0] * 1.15)
+ effective_datarate_ * 1.15)
<< " The datarate for the file missed the target!"
<< cfg_.rc_target_bitrate << " "<< effective_datarate_;
}
@@ -475,7 +202,7 @@
// as the drop frame threshold is increased, and (2) that the total number of
// frame drops does not decrease as we increase frame drop threshold.
// Use a lower qp-max to force some frame drops.
-TEST_P(DatarateTestVP9Large, ChangingDropFrameThresh) {
+TEST_P(DatarateTestLarge, ChangingDropFrameThresh) {
cfg_.rc_buf_initial_sz = 500;
cfg_.rc_buf_optimal_sz = 500;
cfg_.rc_buf_sz = 1000;
@@ -501,9 +228,9 @@
cfg_.rc_dropframe_thresh = i;
ResetModel();
ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+ ASSERT_GE(effective_datarate_, cfg_.rc_target_bitrate * 0.85)
<< " The datarate for the file is lower than target by too much!";
- ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+ ASSERT_LE(effective_datarate_, cfg_.rc_target_bitrate * 1.15)
<< " The datarate for the file is greater than target by too much!";
ASSERT_LE(first_drop_, last_drop)
<< " The first dropped frame for drop_thresh " << i
@@ -518,521 +245,8 @@
}
}
-// Check basic rate targeting for 2 temporal layers.
-TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) {
- cfg_.rc_buf_initial_sz = 500;
- cfg_.rc_buf_optimal_sz = 500;
- cfg_.rc_buf_sz = 1000;
- cfg_.rc_dropframe_thresh = 1;
- cfg_.rc_min_quantizer = 0;
- cfg_.rc_max_quantizer = 63;
- cfg_.rc_end_usage = VPX_CBR;
- cfg_.g_lag_in_frames = 0;
-
- // 2 Temporal layers, no spatial layers: Framerate decimation (2, 1).
- cfg_.ss_number_layers = 1;
- cfg_.ts_number_layers = 2;
- cfg_.ts_rate_decimator[0] = 2;
- cfg_.ts_rate_decimator[1] = 1;
-
- cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
-
- if (deadline_ == VPX_DL_REALTIME)
- cfg_.g_error_resilient = 1;
-
- ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
- 30, 1, 0, 200);
- for (int i = 200; i <= 800; i += 200) {
- cfg_.rc_target_bitrate = i;
- ResetModel();
- // 60-40 bitrate allocation for 2 temporal layers.
- cfg_.layer_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
- cfg_.layer_target_bitrate[1] = cfg_.rc_target_bitrate;
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
- ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
- << " The datarate for the file is lower than target by too much, "
- "for layer: " << j;
- ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
- << " The datarate for the file is greater than target by too much, "
- "for layer: " << j;
- }
- }
-}
-
-// Check basic rate targeting for 3 temporal layers.
-TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayers) {
- cfg_.rc_buf_initial_sz = 500;
- cfg_.rc_buf_optimal_sz = 500;
- cfg_.rc_buf_sz = 1000;
- cfg_.rc_dropframe_thresh = 1;
- cfg_.rc_min_quantizer = 0;
- cfg_.rc_max_quantizer = 63;
- cfg_.rc_end_usage = VPX_CBR;
- cfg_.g_lag_in_frames = 0;
-
- // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
- cfg_.ss_number_layers = 1;
- cfg_.ts_number_layers = 3;
- cfg_.ts_rate_decimator[0] = 4;
- cfg_.ts_rate_decimator[1] = 2;
- cfg_.ts_rate_decimator[2] = 1;
-
- cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
-
- ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
- 30, 1, 0, 200);
- for (int i = 200; i <= 800; i += 200) {
- cfg_.rc_target_bitrate = i;
- ResetModel();
- // 40-20-40 bitrate allocation for 3 temporal layers.
- cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
- cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
- cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
- // TODO(yaowu): Work out more stable rc control strategy and
- // Adjust the thresholds to be tighter than .75.
- ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.75)
- << " The datarate for the file is lower than target by too much, "
- "for layer: " << j;
- // TODO(yaowu): Work out more stable rc control strategy and
- // Adjust the thresholds to be tighter than 1.25.
- ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.25)
- << " The datarate for the file is greater than target by too much, "
- "for layer: " << j;
- }
- }
-}
-
-// Check basic rate targeting for 3 temporal layers, with frame dropping.
-// Only for one (low) bitrate with lower max_quantizer, and somewhat higher
-// frame drop threshold, to force frame dropping.
-TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayersFrameDropping) {
- cfg_.rc_buf_initial_sz = 500;
- cfg_.rc_buf_optimal_sz = 500;
- cfg_.rc_buf_sz = 1000;
- // Set frame drop threshold and rc_max_quantizer to force some frame drops.
- cfg_.rc_dropframe_thresh = 20;
- cfg_.rc_max_quantizer = 45;
- cfg_.rc_min_quantizer = 0;
- cfg_.rc_end_usage = VPX_CBR;
- cfg_.g_lag_in_frames = 0;
-
- // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
- cfg_.ss_number_layers = 1;
- cfg_.ts_number_layers = 3;
- cfg_.ts_rate_decimator[0] = 4;
- cfg_.ts_rate_decimator[1] = 2;
- cfg_.ts_rate_decimator[2] = 1;
-
- cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
-
- ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
- 30, 1, 0, 200);
- cfg_.rc_target_bitrate = 200;
- ResetModel();
- // 40-20-40 bitrate allocation for 3 temporal layers.
- cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
- cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
- cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
- ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
- << " The datarate for the file is lower than target by too much, "
- "for layer: " << j;
- ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
- << " The datarate for the file is greater than target by too much, "
- "for layer: " << j;
- // Expect some frame drops in this test: for this 200 frames test,
- // expect at least 10% and not more than 60% drops.
- ASSERT_GE(num_drops_, 20);
- ASSERT_LE(num_drops_, 130);
- }
-}
-
-class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest,
- public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
- public:
- DatarateOnePassCbrSvc() : EncoderTest(GET_PARAM(0)) {}
- virtual ~DatarateOnePassCbrSvc() {}
- protected:
- virtual void SetUp() {
- InitializeConfig();
- SetMode(GET_PARAM(1));
- speed_setting_ = GET_PARAM(2);
- ResetModel();
- }
- virtual void ResetModel() {
- last_pts_ = 0;
- bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
- frame_number_ = 0;
- first_drop_ = 0;
- bits_total_ = 0;
- duration_ = 0.0;
- mismatch_psnr_ = 0.0;
- mismatch_nframes_ = 0;
- }
- virtual void BeginPassHook(unsigned int /*pass*/) {
- }
- virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
- ::libvpx_test::Encoder *encoder) {
- if (video->frame() == 0) {
- int i;
- for (i = 0; i < VPX_MAX_LAYERS; ++i) {
- svc_params_.max_quantizers[i] = 63;
- svc_params_.min_quantizers[i] = 0;
- }
- encoder->Control(VP9E_SET_SVC, 1);
- encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
- encoder->Control(VP8E_SET_CPUUSED, speed_setting_);
- encoder->Control(VP9E_SET_TILE_COLUMNS, 0);
- encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 300);
- encoder->Control(VP9E_SET_TILE_COLUMNS, (cfg_.g_threads >> 1));
- }
- const vpx_rational_t tb = video->timebase();
- timebase_ = static_cast<double>(tb.num) / tb.den;
- duration_ = 0;
- }
- virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
- vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
- if (last_pts_ == 0)
- duration = 1;
- bits_in_buffer_model_ += static_cast<int64_t>(
- duration * timebase_ * cfg_.rc_target_bitrate * 1000);
- const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY)
- ? true: false;
- if (!key_frame) {
- ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
- << pkt->data.frame.pts;
- }
- const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
- bits_in_buffer_model_ -= frame_size_in_bits;
- bits_total_ += frame_size_in_bits;
- if (!first_drop_ && duration > 1)
- first_drop_ = last_pts_ + 1;
- last_pts_ = pkt->data.frame.pts;
- bits_in_last_frame_ = frame_size_in_bits;
- ++frame_number_;
- }
- virtual void EndPassHook(void) {
- if (bits_total_) {
- const double file_size_in_kb = bits_total_ / 1000.; // bits per kilobit
- duration_ = (last_pts_ + 1) * timebase_;
- file_datarate_ = file_size_in_kb / duration_;
- }
- }
-
- virtual void MismatchHook(const vpx_image_t *img1,
- const vpx_image_t *img2) {
- double mismatch_psnr = compute_psnr(img1, img2);
- mismatch_psnr_ += mismatch_psnr;
- ++mismatch_nframes_;
- }
-
- unsigned int GetMismatchFrames() {
- return mismatch_nframes_;
- }
-
- vpx_codec_pts_t last_pts_;
- int64_t bits_in_buffer_model_;
- double timebase_;
- int frame_number_;
- vpx_codec_pts_t first_drop_;
- int64_t bits_total_;
- double duration_;
- double file_datarate_;
- size_t bits_in_last_frame_;
- vpx_svc_extra_cfg_t svc_params_;
- int speed_setting_;
- double mismatch_psnr_;
- int mismatch_nframes_;
-};
-static void assign_layer_bitrates(vpx_codec_enc_cfg_t *const enc_cfg,
- const vpx_svc_extra_cfg_t *svc_params,
- int spatial_layers,
- int temporal_layers,
- int temporal_layering_mode) {
- int sl, spatial_layer_target;
- float total = 0;
- float alloc_ratio[VPX_MAX_LAYERS] = {0};
- for (sl = 0; sl < spatial_layers; ++sl) {
- if (svc_params->scaling_factor_den[sl] > 0) {
- alloc_ratio[sl] = (float)(svc_params->scaling_factor_num[sl] *
- 1.0 / svc_params->scaling_factor_den[sl]);
- total += alloc_ratio[sl];
- }
- }
- for (sl = 0; sl < spatial_layers; ++sl) {
- enc_cfg->ss_target_bitrate[sl] = spatial_layer_target =
- (unsigned int)(enc_cfg->rc_target_bitrate *
- alloc_ratio[sl] / total);
- const int index = sl * temporal_layers;
- if (temporal_layering_mode == 3) {
- enc_cfg->layer_target_bitrate[index] =
- spatial_layer_target >> 1;
- enc_cfg->layer_target_bitrate[index + 1] =
- (spatial_layer_target >> 1) + (spatial_layer_target >> 2);
- enc_cfg->layer_target_bitrate[index + 2] =
- spatial_layer_target;
- } else if (temporal_layering_mode == 2) {
- enc_cfg->layer_target_bitrate[index] =
- spatial_layer_target * 2 / 3;
- enc_cfg->layer_target_bitrate[index + 1] =
- spatial_layer_target;
- }
- }
-}
-
-// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and
-// 3 temporal layers. Run CIF clip with 1 thread.
-TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers) {
- cfg_.rc_buf_initial_sz = 500;
- cfg_.rc_buf_optimal_sz = 500;
- cfg_.rc_buf_sz = 1000;
- cfg_.rc_min_quantizer = 0;
- cfg_.rc_max_quantizer = 63;
- cfg_.rc_end_usage = VPX_CBR;
- cfg_.g_lag_in_frames = 0;
- cfg_.ss_number_layers = 2;
- cfg_.ts_number_layers = 3;
- cfg_.ts_rate_decimator[0] = 4;
- cfg_.ts_rate_decimator[1] = 2;
- cfg_.ts_rate_decimator[2] = 1;
- cfg_.g_error_resilient = 1;
- cfg_.g_threads = 1;
- cfg_.temporal_layering_mode = 3;
- svc_params_.scaling_factor_num[0] = 144;
- svc_params_.scaling_factor_den[0] = 288;
- svc_params_.scaling_factor_num[1] = 288;
- svc_params_.scaling_factor_den[1] = 288;
- cfg_.rc_dropframe_thresh = 10;
- cfg_.kf_max_dist = 9999;
- ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
- 30, 1, 0, 200);
- // TODO(wonkap/marpan): Check that effective_datarate for each layer hits the
- // layer target_bitrate.
- for (int i = 200; i <= 800; i += 200) {
- cfg_.rc_target_bitrate = i;
- ResetModel();
- assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
- cfg_.ts_number_layers, cfg_.temporal_layering_mode);
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
- << " The datarate for the file exceeds the target by too much!";
- ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
- << " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
- }
-}
-
-// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 3
-// temporal layers. Run CIF clip with 1 thread, and few short key frame periods.
-TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayersSmallKf) {
- cfg_.rc_buf_initial_sz = 500;
- cfg_.rc_buf_optimal_sz = 500;
- cfg_.rc_buf_sz = 1000;
- cfg_.rc_min_quantizer = 0;
- cfg_.rc_max_quantizer = 63;
- cfg_.rc_end_usage = VPX_CBR;
- cfg_.g_lag_in_frames = 0;
- cfg_.ss_number_layers = 2;
- cfg_.ts_number_layers = 3;
- cfg_.ts_rate_decimator[0] = 4;
- cfg_.ts_rate_decimator[1] = 2;
- cfg_.ts_rate_decimator[2] = 1;
- cfg_.g_error_resilient = 1;
- cfg_.g_threads = 1;
- cfg_.temporal_layering_mode = 3;
- svc_params_.scaling_factor_num[0] = 144;
- svc_params_.scaling_factor_den[0] = 288;
- svc_params_.scaling_factor_num[1] = 288;
- svc_params_.scaling_factor_den[1] = 288;
- cfg_.rc_dropframe_thresh = 10;
- ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
- 30, 1, 0, 200);
- cfg_.rc_target_bitrate = 400;
- // For this 3 temporal layer case, pattern repeats every 4 frames, so choose
- // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
- for (int j = 64; j <= 67; j++) {
- cfg_.kf_max_dist = j;
- ResetModel();
- assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
- cfg_.ts_number_layers, cfg_.temporal_layering_mode);
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
- << " The datarate for the file exceeds the target by too much!";
- ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
- << " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
- }
-}
-
-// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and
-// 3 temporal layers. Run HD clip with 4 threads.
-TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers4threads) {
- cfg_.rc_buf_initial_sz = 500;
- cfg_.rc_buf_optimal_sz = 500;
- cfg_.rc_buf_sz = 1000;
- cfg_.rc_min_quantizer = 0;
- cfg_.rc_max_quantizer = 63;
- cfg_.rc_end_usage = VPX_CBR;
- cfg_.g_lag_in_frames = 0;
- cfg_.ss_number_layers = 2;
- cfg_.ts_number_layers = 3;
- cfg_.ts_rate_decimator[0] = 4;
- cfg_.ts_rate_decimator[1] = 2;
- cfg_.ts_rate_decimator[2] = 1;
- cfg_.g_error_resilient = 1;
- cfg_.g_threads = 4;
- cfg_.temporal_layering_mode = 3;
- svc_params_.scaling_factor_num[0] = 144;
- svc_params_.scaling_factor_den[0] = 288;
- svc_params_.scaling_factor_num[1] = 288;
- svc_params_.scaling_factor_den[1] = 288;
- cfg_.rc_dropframe_thresh = 10;
- cfg_.kf_max_dist = 9999;
- ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720,
- 30, 1, 0, 300);
- cfg_.rc_target_bitrate = 800;
- ResetModel();
- assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
- cfg_.ts_number_layers, cfg_.temporal_layering_mode);
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
- << " The datarate for the file exceeds the target by too much!";
- ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
- << " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
-}
-
-// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and
-// 3 temporal layers. Run CIF clip with 1 thread.
-TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers) {
- cfg_.rc_buf_initial_sz = 500;
- cfg_.rc_buf_optimal_sz = 500;
- cfg_.rc_buf_sz = 1000;
- cfg_.rc_min_quantizer = 0;
- cfg_.rc_max_quantizer = 63;
- cfg_.rc_end_usage = VPX_CBR;
- cfg_.g_lag_in_frames = 0;
- cfg_.ss_number_layers = 3;
- cfg_.ts_number_layers = 3;
- cfg_.ts_rate_decimator[0] = 4;
- cfg_.ts_rate_decimator[1] = 2;
- cfg_.ts_rate_decimator[2] = 1;
- cfg_.g_error_resilient = 1;
- cfg_.g_threads = 1;
- cfg_.temporal_layering_mode = 3;
- svc_params_.scaling_factor_num[0] = 72;
- svc_params_.scaling_factor_den[0] = 288;
- svc_params_.scaling_factor_num[1] = 144;
- svc_params_.scaling_factor_den[1] = 288;
- svc_params_.scaling_factor_num[2] = 288;
- svc_params_.scaling_factor_den[2] = 288;
- cfg_.rc_dropframe_thresh = 10;
- cfg_.kf_max_dist = 9999;
- ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720,
- 30, 1, 0, 300);
- cfg_.rc_target_bitrate = 800;
- ResetModel();
- assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
- cfg_.ts_number_layers, cfg_.temporal_layering_mode);
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
- << " The datarate for the file exceeds the target by too much!";
- ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22)
- << " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
-}
-
-// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3
-// temporal layers. Run CIF clip with 1 thread, and few short key frame periods.
-TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayersSmallKf) {
- cfg_.rc_buf_initial_sz = 500;
- cfg_.rc_buf_optimal_sz = 500;
- cfg_.rc_buf_sz = 1000;
- cfg_.rc_min_quantizer = 0;
- cfg_.rc_max_quantizer = 63;
- cfg_.rc_end_usage = VPX_CBR;
- cfg_.g_lag_in_frames = 0;
- cfg_.ss_number_layers = 3;
- cfg_.ts_number_layers = 3;
- cfg_.ts_rate_decimator[0] = 4;
- cfg_.ts_rate_decimator[1] = 2;
- cfg_.ts_rate_decimator[2] = 1;
- cfg_.g_error_resilient = 1;
- cfg_.g_threads = 1;
- cfg_.temporal_layering_mode = 3;
- svc_params_.scaling_factor_num[0] = 72;
- svc_params_.scaling_factor_den[0] = 288;
- svc_params_.scaling_factor_num[1] = 144;
- svc_params_.scaling_factor_den[1] = 288;
- svc_params_.scaling_factor_num[2] = 288;
- svc_params_.scaling_factor_den[2] = 288;
- cfg_.rc_dropframe_thresh = 10;
- ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720,
- 30, 1, 0, 300);
- cfg_.rc_target_bitrate = 800;
- // For this 3 temporal layer case, pattern repeats every 4 frames, so choose
- // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
- for (int j = 32; j <= 35; j++) {
- cfg_.kf_max_dist = j;
- ResetModel();
- assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
- cfg_.ts_number_layers, cfg_.temporal_layering_mode);
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
- << " The datarate for the file exceeds the target by too much!";
- ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.30)
- << " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
- }
-}
-
-// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and
-// 3 temporal layers. Run HD clip with 4 threads.
-TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers4threads) {
- cfg_.rc_buf_initial_sz = 500;
- cfg_.rc_buf_optimal_sz = 500;
- cfg_.rc_buf_sz = 1000;
- cfg_.rc_min_quantizer = 0;
- cfg_.rc_max_quantizer = 63;
- cfg_.rc_end_usage = VPX_CBR;
- cfg_.g_lag_in_frames = 0;
- cfg_.ss_number_layers = 3;
- cfg_.ts_number_layers = 3;
- cfg_.ts_rate_decimator[0] = 4;
- cfg_.ts_rate_decimator[1] = 2;
- cfg_.ts_rate_decimator[2] = 1;
- cfg_.g_error_resilient = 1;
- cfg_.g_threads = 4;
- cfg_.temporal_layering_mode = 3;
- svc_params_.scaling_factor_num[0] = 72;
- svc_params_.scaling_factor_den[0] = 288;
- svc_params_.scaling_factor_num[1] = 144;
- svc_params_.scaling_factor_den[1] = 288;
- svc_params_.scaling_factor_num[2] = 288;
- svc_params_.scaling_factor_den[2] = 288;
- cfg_.rc_dropframe_thresh = 10;
- cfg_.kf_max_dist = 9999;
- ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720,
- 30, 1, 0, 300);
- cfg_.rc_target_bitrate = 800;
- ResetModel();
- assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
- cfg_.ts_number_layers, cfg_.temporal_layering_mode);
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
- << " The datarate for the file exceeds the target by too much!";
- ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22)
- << " The datarate for the file is lower than the target by too much!";
- EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
-}
-
-/* VP10 does not support multiple layers yet.
-VP10_INSTANTIATE_TEST_CASE(DatarateOnePassCbrSvc,
- ::testing::Values(::libvpx_test::kRealTime),
- ::testing::Range(5, 8));
- */
+VP10_INSTANTIATE_TEST_CASE(DatarateTestLarge,
+ ::testing::Values(::libvpx_test::kOnePassGood,
+ ::libvpx_test::kRealTime),
+ ::testing::Range(2, 9));
} // namespace
diff --git a/test/encode_test_driver.h b/test/encode_test_driver.h
index e444a92..720ec84 100644
--- a/test/encode_test_driver.h
+++ b/test/encode_test_driver.h
@@ -134,15 +134,6 @@
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
}
- void Control(int ctrl_id, struct vpx_svc_layer_id *arg) {
- const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
- ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
- }
-
- void Control(int ctrl_id, struct vpx_svc_parameters *arg) {
- const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
- ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
- }
#if CONFIG_VP10_ENCODER
void Control(int ctrl_id, vpx_active_map_t *arg) {
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
diff --git a/test/error_resilience_test.cc b/test/error_resilience_test.cc
index d6deb75..99419ad 100644
--- a/test/error_resilience_test.cc
+++ b/test/error_resilience_test.cc
@@ -20,11 +20,10 @@
const int kMaxDroppableFrames = 12;
class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest,
- public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, bool> {
+ public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
protected:
ErrorResilienceTestLarge()
: EncoderTest(GET_PARAM(0)),
- svc_support_(GET_PARAM(2)),
psnr_(0.0),
nframes_(0),
mismatch_psnr_(0.0),
@@ -58,77 +57,23 @@
nframes_++;
}
- //
- // Frame flags and layer id for temporal layers.
- // For two layers, test pattern is:
- // 1 3
- // 0 2 .....
- // LAST is updated on base/layer 0, GOLDEN updated on layer 1.
- // Non-zero pattern_switch parameter means pattern will switch to
- // not using LAST for frame_num >= pattern_switch.
- int SetFrameFlags(int frame_num,
- int num_temp_layers,
- int pattern_switch) {
- int frame_flags = 0;
- if (num_temp_layers == 2) {
- if (frame_num % 2 == 0) {
- if (frame_num < pattern_switch || pattern_switch == 0) {
- // Layer 0: predict from LAST and ARF, update LAST.
- frame_flags = VP8_EFLAG_NO_REF_GF |
- VP8_EFLAG_NO_UPD_GF |
- VP8_EFLAG_NO_UPD_ARF;
- } else {
- // Layer 0: predict from GF and ARF, update GF.
- frame_flags = VP8_EFLAG_NO_REF_LAST |
- VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_ARF;
- }
- } else {
- if (frame_num < pattern_switch || pattern_switch == 0) {
- // Layer 1: predict from L, GF, and ARF, update GF.
- frame_flags = VP8_EFLAG_NO_UPD_ARF |
- VP8_EFLAG_NO_UPD_LAST;
- } else {
- // Layer 1: predict from GF and ARF, update GF.
- frame_flags = VP8_EFLAG_NO_REF_LAST |
- VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_ARF;
- }
- }
- }
- return frame_flags;
- }
-
virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
::libvpx_test::Encoder * /*encoder*/) {
frame_flags_ &= ~(VP8_EFLAG_NO_UPD_LAST |
VP8_EFLAG_NO_UPD_GF |
VP8_EFLAG_NO_UPD_ARF);
- // For temporal layer case.
- if (cfg_.ts_number_layers > 1) {
- frame_flags_ = SetFrameFlags(video->frame(),
- cfg_.ts_number_layers,
- pattern_switch_);
+ if (droppable_nframes_ > 0 &&
+ (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
for (unsigned int i = 0; i < droppable_nframes_; ++i) {
if (droppable_frames_[i] == video->frame()) {
std::cout << "Encoding droppable frame: "
<< droppable_frames_[i] << "\n";
+ frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST |
+ VP8_EFLAG_NO_UPD_GF |
+ VP8_EFLAG_NO_UPD_ARF);
+ return;
}
}
- } else {
- if (droppable_nframes_ > 0 &&
- (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
- for (unsigned int i = 0; i < droppable_nframes_; ++i) {
- if (droppable_frames_[i] == video->frame()) {
- std::cout << "Encoding droppable frame: "
- << droppable_frames_[i] << "\n";
- frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_GF |
- VP8_EFLAG_NO_UPD_ARF);
- return;
- }
- }
- }
}
}
@@ -195,8 +140,6 @@
pattern_switch_ = frame_switch;
}
- bool svc_support_;
-
private:
double psnr_;
unsigned int nframes_;
@@ -301,297 +244,5 @@
#endif
}
-// Check for successful decoding and no encoder/decoder mismatch
-// if we lose (i.e., drop before decoding) the enhancement layer frames for a
-// two layer temporal pattern. The base layer does not predict from the top
-// layer, so successful decoding is expected.
-TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) {
- // This test doesn't run if SVC is not supported.
- if (!svc_support_)
- return;
-
- const vpx_rational timebase = { 33333333, 1000000000 };
- cfg_.g_timebase = timebase;
- cfg_.rc_target_bitrate = 500;
- cfg_.g_lag_in_frames = 0;
-
- cfg_.rc_end_usage = VPX_CBR;
- // 2 Temporal layers, no spatial layers, CBR mode.
- cfg_.ss_number_layers = 1;
- cfg_.ts_number_layers = 2;
- cfg_.ts_rate_decimator[0] = 2;
- cfg_.ts_rate_decimator[1] = 1;
- cfg_.ts_periodicity = 2;
- cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
- cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
-
- init_flags_ = VPX_CODEC_USE_PSNR;
-
- libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
- timebase.den, timebase.num, 0, 40);
-
- // Error resilient mode ON.
- cfg_.g_error_resilient = 1;
- cfg_.kf_mode = VPX_KF_DISABLED;
- SetPatternSwitch(0);
-
- // The odd frames are the enhancement layer for 2 layer pattern, so set
- // those frames as droppable. Drop the last 7 frames.
- unsigned int num_droppable_frames = 7;
- unsigned int droppable_frame_list[] = {27, 29, 31, 33, 35, 37, 39};
- SetDroppableFrames(num_droppable_frames, droppable_frame_list);
- SetErrorFrames(num_droppable_frames, droppable_frame_list);
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- // Test that no mismatches have been found
- std::cout << " Mismatch frames: "
- << GetMismatchFrames() << "\n";
- EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
-
- // Reset previously set of error/droppable frames.
- Reset();
-}
-
-// Check for successful decoding and no encoder/decoder mismatch
-// for a two layer temporal pattern, where at some point in the
-// sequence, the LAST ref is not used anymore.
-TEST_P(ErrorResilienceTestLarge, 2LayersNoRefLast) {
- // This test doesn't run if SVC is not supported.
- if (!svc_support_)
- return;
-
- const vpx_rational timebase = { 33333333, 1000000000 };
- cfg_.g_timebase = timebase;
- cfg_.rc_target_bitrate = 500;
- cfg_.g_lag_in_frames = 0;
-
- cfg_.rc_end_usage = VPX_CBR;
- // 2 Temporal layers, no spatial layers, CBR mode.
- cfg_.ss_number_layers = 1;
- cfg_.ts_number_layers = 2;
- cfg_.ts_rate_decimator[0] = 2;
- cfg_.ts_rate_decimator[1] = 1;
- cfg_.ts_periodicity = 2;
- cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
- cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
-
- init_flags_ = VPX_CODEC_USE_PSNR;
-
- libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
- timebase.den, timebase.num, 0, 100);
-
- // Error resilient mode ON.
- cfg_.g_error_resilient = 1;
- cfg_.kf_mode = VPX_KF_DISABLED;
- SetPatternSwitch(60);
-
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- // Test that no mismatches have been found
- std::cout << " Mismatch frames: "
- << GetMismatchFrames() << "\n";
- EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
-
- // Reset previously set of error/droppable frames.
- Reset();
-}
-
-class ErrorResilienceTestLargeCodecControls : public ::libvpx_test::EncoderTest,
- public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
- protected:
- ErrorResilienceTestLargeCodecControls()
- : EncoderTest(GET_PARAM(0)),
- encoding_mode_(GET_PARAM(1)) {
- Reset();
- }
-
- virtual ~ErrorResilienceTestLargeCodecControls() {}
-
- void Reset() {
- last_pts_ = 0;
- tot_frame_number_ = 0;
- // For testing up to 3 layers.
- for (int i = 0; i < 3; ++i) {
- bits_total_[i] = 0;
- }
- duration_ = 0.0;
- }
-
- virtual void SetUp() {
- InitializeConfig();
- SetMode(encoding_mode_);
- }
-
- //
- // Frame flags and layer id for temporal layers.
- //
-
- // For two layers, test pattern is:
- // 1 3
- // 0 2 .....
- // For three layers, test pattern is:
- // 1 3 5 7
- // 2 6
- // 0 4 ....
- // LAST is always update on base/layer 0, GOLDEN is updated on layer 1,
- // and ALTREF is updated on top layer for 3 layer pattern.
- int SetFrameFlags(int frame_num, int num_temp_layers) {
- int frame_flags = 0;
- if (num_temp_layers == 2) {
- if (frame_num % 2 == 0) {
- // Layer 0: predict from L and ARF, update L.
- frame_flags = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
- VP8_EFLAG_NO_UPD_ARF;
- } else {
- // Layer 1: predict from L, G and ARF, and update G.
- frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_UPD_ENTROPY;
- }
- } else if (num_temp_layers == 3) {
- if (frame_num % 4 == 0) {
- // Layer 0: predict from L, update L.
- frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
- VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
- } else if ((frame_num - 2) % 4 == 0) {
- // Layer 1: predict from L, G, update G.
- frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
- VP8_EFLAG_NO_REF_ARF;
- } else if ((frame_num - 1) % 2 == 0) {
- // Layer 2: predict from L, G, ARF; update ARG.
- frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
- }
- }
- return frame_flags;
- }
-
- int SetLayerId(int frame_num, int num_temp_layers) {
- int layer_id = 0;
- if (num_temp_layers == 2) {
- if (frame_num % 2 == 0) {
- layer_id = 0;
- } else {
- layer_id = 1;
- }
- } else if (num_temp_layers == 3) {
- if (frame_num % 4 == 0) {
- layer_id = 0;
- } else if ((frame_num - 2) % 4 == 0) {
- layer_id = 1;
- } else if ((frame_num - 1) % 2 == 0) {
- layer_id = 2;
- }
- }
- return layer_id;
- }
-
- virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
- libvpx_test::Encoder *encoder) {
- if (cfg_.ts_number_layers > 1) {
- int layer_id = SetLayerId(video->frame(), cfg_.ts_number_layers);
- int frame_flags = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
- if (video->frame() > 0) {
- encoder->Control(VP8E_SET_TEMPORAL_LAYER_ID, layer_id);
- encoder->Control(VP8E_SET_FRAME_FLAGS, frame_flags);
- }
- const vpx_rational_t tb = video->timebase();
- timebase_ = static_cast<double>(tb.num) / tb.den;
- duration_ = 0;
- return;
- }
- }
-
- virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
- // Time since last timestamp = duration.
- vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
- if (duration > 1) {
- // Update counter for total number of frames (#frames input to encoder).
- // Needed for setting the proper layer_id below.
- tot_frame_number_ += static_cast<int>(duration - 1);
- }
- int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers);
- const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
- // Update the total encoded bits. For temporal layers, update the cumulative
- // encoded bits per layer.
- for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
- bits_total_[i] += frame_size_in_bits;
- }
- // Update the most recent pts.
- last_pts_ = pkt->data.frame.pts;
- ++tot_frame_number_;
- }
-
- virtual void EndPassHook(void) {
- duration_ = (last_pts_ + 1) * timebase_;
- if (cfg_.ts_number_layers > 1) {
- for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
- ++layer) {
- if (bits_total_[layer]) {
- // Effective file datarate:
- effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_;
- }
- }
- }
- }
-
- double effective_datarate_[3];
- private:
- libvpx_test::TestMode encoding_mode_;
- vpx_codec_pts_t last_pts_;
- double timebase_;
- int64_t bits_total_[3];
- double duration_;
- int tot_frame_number_;
- };
-
-// Check two codec controls used for:
-// (1) for setting temporal layer id, and (2) for settings encoder flags.
-// This test invokes those controls for each frame, and verifies encoder/decoder
-// mismatch and basic rate control response.
-// TODO(marpan): Maybe move this test to datarate_test.cc.
-TEST_P(ErrorResilienceTestLargeCodecControls, CodecControl3TemporalLayers) {
- cfg_.rc_buf_initial_sz = 500;
- cfg_.rc_buf_optimal_sz = 500;
- cfg_.rc_buf_sz = 1000;
- cfg_.rc_dropframe_thresh = 1;
- cfg_.rc_min_quantizer = 2;
- cfg_.rc_max_quantizer = 56;
- cfg_.rc_end_usage = VPX_CBR;
- cfg_.rc_dropframe_thresh = 1;
- cfg_.g_lag_in_frames = 0;
- cfg_.kf_mode = VPX_KF_DISABLED;
- cfg_.g_error_resilient = 1;
-
- // 3 Temporal layers. Framerate decimation (4, 2, 1).
- cfg_.ts_number_layers = 3;
- cfg_.ts_rate_decimator[0] = 4;
- cfg_.ts_rate_decimator[1] = 2;
- cfg_.ts_rate_decimator[2] = 1;
- cfg_.ts_periodicity = 4;
- cfg_.ts_layer_id[0] = 0;
- cfg_.ts_layer_id[1] = 2;
- cfg_.ts_layer_id[2] = 1;
- cfg_.ts_layer_id[3] = 2;
-
- ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
- 30, 1, 0, 200);
- for (int i = 200; i <= 800; i += 200) {
- cfg_.rc_target_bitrate = i;
- Reset();
- // 40-20-40 bitrate allocation for 3 temporal layers.
- cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
- cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
- cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate;
- ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
- for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
- ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.75)
- << " The datarate for the file is lower than target by too much, "
- "for layer: " << j;
- ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.25)
- << " The datarate for the file is greater than target by too much, "
- "for layer: " << j;
- }
- }
-}
-
-// SVC-related tests don't run for VP10 since SVC is not supported.
-VP10_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
- ::testing::Values(false));
+VP10_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES);
} // namespace
diff --git a/test/spatial_svc_encoder.sh b/test/spatial_svc_encoder.sh
deleted file mode 100644
index 6503107..0000000
--- a/test/spatial_svc_encoder.sh
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/bin/sh
-##
-## Copyright (c) 2014 The WebM project authors. All Rights Reserved.
-##
-## Use of this source code is governed by a BSD-style license
-## that can be found in the LICENSE file in the root of the source
-## tree. An additional intellectual property rights grant can be found
-## in the file PATENTS. All contributing project authors may
-## be found in the AUTHORS file in the root of the source tree.
-##
-## This file tests the libvpx vp9_spatial_svc_encoder example. To add new
-## tests to to this file, do the following:
-## 1. Write a shell function (this is your test).
-## 2. Add the function to vp9_spatial_svc_tests (on a new line).
-##
-. $(dirname $0)/tools_common.sh
-
-# Environment check: $YUV_RAW_INPUT is required.
-vp9_spatial_svc_encoder_verify_environment() {
- if [ ! -e "${YUV_RAW_INPUT}" ]; then
- echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
- return 1
- fi
-}
-
-# Runs vp9_spatial_svc_encoder. $1 is the test name.
-vp9_spatial_svc_encoder() {
- local readonly \
- encoder="${LIBVPX_BIN_PATH}/vp9_spatial_svc_encoder${VPX_TEST_EXE_SUFFIX}"
- local readonly test_name="$1"
- local readonly \
- output_file="${VPX_TEST_OUTPUT_DIR}/vp9_ssvc_encoder${test_name}.ivf"
- local readonly frames_to_encode=10
- local readonly max_kf=9999
-
- shift
-
- if [ ! -x "${encoder}" ]; then
- elog "${encoder} does not exist or is not executable."
- return 1
- fi
-
- eval "${VPX_TEST_PREFIX}" "${encoder}" -w "${YUV_RAW_INPUT_WIDTH}" \
- -h "${YUV_RAW_INPUT_HEIGHT}" -k "${max_kf}" -f "${frames_to_encode}" \
- "$@" "${YUV_RAW_INPUT}" "${output_file}" ${devnull}
-
- [ -e "${output_file}" ] || return 1
-}
-
-# Each test is run with layer count 1-$vp9_ssvc_test_layers.
-vp9_ssvc_test_layers=5
-
-vp9_spatial_svc() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- local readonly test_name="vp9_spatial_svc"
- for layers in $(seq 1 ${vp9_ssvc_test_layers}); do
- vp9_spatial_svc_encoder "${test_name}" -sl ${layers}
- done
- fi
-}
-
-readonly vp9_spatial_svc_tests="DISABLED_vp9_spatial_svc_mode_i
- DISABLED_vp9_spatial_svc_mode_altip
- DISABLED_vp9_spatial_svc_mode_ip
- DISABLED_vp9_spatial_svc_mode_gf
- vp9_spatial_svc"
-
-if [ "$(vpx_config_option_enabled CONFIG_SPATIAL_SVC)" = "yes" ]; then
- run_tests \
- vp9_spatial_svc_encoder_verify_environment \
- "${vp9_spatial_svc_tests}"
-fi
diff --git a/test/svc_test.cc b/test/svc_test.cc
deleted file mode 100644
index 1ad17be..0000000
--- a/test/svc_test.cc
+++ /dev/null
@@ -1,803 +0,0 @@
-/*
- * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include <string>
-#include "third_party/googletest/src/include/gtest/gtest.h"
-#include "test/codec_factory.h"
-#include "test/decode_test_driver.h"
-#include "test/i420_video_source.h"
-
-#include "vp9/decoder/vp9_decoder.h"
-
-#include "vpx/svc_context.h"
-#include "vpx/vp8cx.h"
-#include "vpx/vpx_encoder.h"
-
-namespace {
-
-using libvpx_test::CodecFactory;
-using libvpx_test::Decoder;
-using libvpx_test::DxDataIterator;
-using libvpx_test::VP9CodecFactory;
-
-class SvcTest : public ::testing::Test {
- protected:
- static const uint32_t kWidth = 352;
- static const uint32_t kHeight = 288;
-
- SvcTest()
- : codec_iface_(0),
- test_file_name_("hantro_collage_w352h288.yuv"),
- codec_initialized_(false),
- decoder_(0) {
- memset(&svc_, 0, sizeof(svc_));
- memset(&codec_, 0, sizeof(codec_));
- memset(&codec_enc_, 0, sizeof(codec_enc_));
- }
-
- virtual ~SvcTest() {}
-
- virtual void SetUp() {
- svc_.log_level = SVC_LOG_DEBUG;
- svc_.log_print = 0;
-
- codec_iface_ = vpx_codec_vp9_cx();
- const vpx_codec_err_t res =
- vpx_codec_enc_config_default(codec_iface_, &codec_enc_, 0);
- EXPECT_EQ(VPX_CODEC_OK, res);
-
- codec_enc_.g_w = kWidth;
- codec_enc_.g_h = kHeight;
- codec_enc_.g_timebase.num = 1;
- codec_enc_.g_timebase.den = 60;
- codec_enc_.kf_min_dist = 100;
- codec_enc_.kf_max_dist = 100;
-
- vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
- VP9CodecFactory codec_factory;
- decoder_ = codec_factory.CreateDecoder(dec_cfg, 0);
-#if CONFIG_VP10 && CONFIG_EXT_TILE
- if (decoder_->IsVP10()) {
- decoder_->Control(VP10_SET_DECODE_TILE_ROW, -1);
- decoder_->Control(VP10_SET_DECODE_TILE_COL, -1);
- }
-#endif
-
- tile_columns_ = 0;
- tile_rows_ = 0;
- }
-
- virtual void TearDown() {
- ReleaseEncoder();
- delete(decoder_);
- }
-
- void InitializeEncoder() {
- const vpx_codec_err_t res =
- vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_OK, res);
- vpx_codec_control(&codec_, VP8E_SET_CPUUSED, 4); // Make the test faster
- vpx_codec_control(&codec_, VP9E_SET_TILE_COLUMNS, tile_columns_);
- vpx_codec_control(&codec_, VP9E_SET_TILE_ROWS, tile_rows_);
- codec_initialized_ = true;
- }
-
- void ReleaseEncoder() {
- vpx_svc_release(&svc_);
- if (codec_initialized_) vpx_codec_destroy(&codec_);
- codec_initialized_ = false;
- }
-
- void GetStatsData(std::string *const stats_buf) {
- vpx_codec_iter_t iter = NULL;
- const vpx_codec_cx_pkt_t *cx_pkt;
-
- while ((cx_pkt = vpx_codec_get_cx_data(&codec_, &iter)) != NULL) {
- if (cx_pkt->kind == VPX_CODEC_STATS_PKT) {
- EXPECT_GT(cx_pkt->data.twopass_stats.sz, 0U);
- ASSERT_TRUE(cx_pkt->data.twopass_stats.buf != NULL);
- stats_buf->append(static_cast<char*>(cx_pkt->data.twopass_stats.buf),
- cx_pkt->data.twopass_stats.sz);
- }
- }
- }
-
- void Pass1EncodeNFrames(const int n, const int layers,
- std::string *const stats_buf) {
- vpx_codec_err_t res;
-
- ASSERT_GT(n, 0);
- ASSERT_GT(layers, 0);
- svc_.spatial_layers = layers;
- codec_enc_.g_pass = VPX_RC_FIRST_PASS;
- InitializeEncoder();
-
- libvpx_test::I420VideoSource video(test_file_name_,
- codec_enc_.g_w, codec_enc_.g_h,
- codec_enc_.g_timebase.den,
- codec_enc_.g_timebase.num, 0, 30);
- video.Begin();
-
- for (int i = 0; i < n; ++i) {
- res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
- video.duration(), VPX_DL_GOOD_QUALITY);
- ASSERT_EQ(VPX_CODEC_OK, res);
- GetStatsData(stats_buf);
- video.Next();
- }
-
- // Flush encoder and test EOS packet.
- res = vpx_svc_encode(&svc_, &codec_, NULL, video.pts(),
- video.duration(), VPX_DL_GOOD_QUALITY);
- ASSERT_EQ(VPX_CODEC_OK, res);
- GetStatsData(stats_buf);
-
- ReleaseEncoder();
- }
-
- void StoreFrames(const size_t max_frame_received,
- struct vpx_fixed_buf *const outputs,
- size_t *const frame_received) {
- vpx_codec_iter_t iter = NULL;
- const vpx_codec_cx_pkt_t *cx_pkt;
-
- while ((cx_pkt = vpx_codec_get_cx_data(&codec_, &iter)) != NULL) {
- if (cx_pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
- const size_t frame_size = cx_pkt->data.frame.sz;
-
- EXPECT_GT(frame_size, 0U);
- ASSERT_TRUE(cx_pkt->data.frame.buf != NULL);
- ASSERT_LT(*frame_received, max_frame_received);
-
- if (*frame_received == 0)
- EXPECT_EQ(1, !!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY));
-
- outputs[*frame_received].buf = malloc(frame_size + 16);
- ASSERT_TRUE(outputs[*frame_received].buf != NULL);
- memcpy(outputs[*frame_received].buf, cx_pkt->data.frame.buf,
- frame_size);
- outputs[*frame_received].sz = frame_size;
- ++(*frame_received);
- }
- }
- }
-
- void Pass2EncodeNFrames(std::string *const stats_buf,
- const int n, const int layers,
- struct vpx_fixed_buf *const outputs) {
- vpx_codec_err_t res;
- size_t frame_received = 0;
-
- ASSERT_TRUE(outputs != NULL);
- ASSERT_GT(n, 0);
- ASSERT_GT(layers, 0);
- svc_.spatial_layers = layers;
- codec_enc_.rc_target_bitrate = 500;
- if (codec_enc_.g_pass == VPX_RC_LAST_PASS) {
- ASSERT_TRUE(stats_buf != NULL);
- ASSERT_GT(stats_buf->size(), 0U);
- codec_enc_.rc_twopass_stats_in.buf = &(*stats_buf)[0];
- codec_enc_.rc_twopass_stats_in.sz = stats_buf->size();
- }
- InitializeEncoder();
-
- libvpx_test::I420VideoSource video(test_file_name_,
- codec_enc_.g_w, codec_enc_.g_h,
- codec_enc_.g_timebase.den,
- codec_enc_.g_timebase.num, 0, 30);
- video.Begin();
-
- for (int i = 0; i < n; ++i) {
- res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
- video.duration(), VPX_DL_GOOD_QUALITY);
- ASSERT_EQ(VPX_CODEC_OK, res);
- StoreFrames(n, outputs, &frame_received);
- video.Next();
- }
-
- // Flush encoder.
- res = vpx_svc_encode(&svc_, &codec_, NULL, 0,
- video.duration(), VPX_DL_GOOD_QUALITY);
- EXPECT_EQ(VPX_CODEC_OK, res);
- StoreFrames(n, outputs, &frame_received);
-
- EXPECT_EQ(frame_received, static_cast<size_t>(n));
-
- ReleaseEncoder();
- }
-
- void DecodeNFrames(const struct vpx_fixed_buf *const inputs, const int n) {
- int decoded_frames = 0;
- int received_frames = 0;
-
- ASSERT_TRUE(inputs != NULL);
- ASSERT_GT(n, 0);
-
- for (int i = 0; i < n; ++i) {
- ASSERT_TRUE(inputs[i].buf != NULL);
- ASSERT_GT(inputs[i].sz, 0U);
- const vpx_codec_err_t res_dec =
- decoder_->DecodeFrame(static_cast<const uint8_t *>(inputs[i].buf),
- inputs[i].sz);
- ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
- ++decoded_frames;
-
- DxDataIterator dec_iter = decoder_->GetDxData();
- while (dec_iter.Next() != NULL) {
- ++received_frames;
- }
- }
- EXPECT_EQ(decoded_frames, n);
- EXPECT_EQ(received_frames, n);
- }
-
- void DropEnhancementLayers(struct vpx_fixed_buf *const inputs,
- const int num_super_frames,
- const int remained_spatial_layers) {
- ASSERT_TRUE(inputs != NULL);
- ASSERT_GT(num_super_frames, 0);
- ASSERT_GT(remained_spatial_layers, 0);
-
- for (int i = 0; i < num_super_frames; ++i) {
- uint32_t frame_sizes[8] = {0};
- int frame_count = 0;
- int frames_found = 0;
- int frame;
- ASSERT_TRUE(inputs[i].buf != NULL);
- ASSERT_GT(inputs[i].sz, 0U);
-
- vpx_codec_err_t res =
- vp9_parse_superframe_index(static_cast<const uint8_t*>(inputs[i].buf),
- inputs[i].sz, frame_sizes, &frame_count,
- NULL, NULL);
- ASSERT_EQ(VPX_CODEC_OK, res);
-
- if (frame_count == 0) {
- // There's no super frame but only a single frame.
- ASSERT_EQ(1, remained_spatial_layers);
- } else {
- // Found a super frame.
- uint8_t *frame_data = static_cast<uint8_t*>(inputs[i].buf);
- uint8_t *frame_start = frame_data;
- for (frame = 0; frame < frame_count; ++frame) {
- // Looking for a visible frame.
- if (frame_data[0] & 0x02) {
- ++frames_found;
- if (frames_found == remained_spatial_layers)
- break;
- }
- frame_data += frame_sizes[frame];
- }
- ASSERT_LT(frame, frame_count) << "Couldn't find a visible frame. "
- << "remained_spatial_layers: " << remained_spatial_layers
- << " super_frame: " << i;
- if (frame == frame_count - 1)
- continue;
-
- frame_data += frame_sizes[frame];
-
- // We need to add one more frame for multiple frame contexts.
- uint8_t marker =
- static_cast<const uint8_t*>(inputs[i].buf)[inputs[i].sz - 1];
- const uint32_t mag = ((marker >> 3) & 0x3) + 1;
- const size_t index_sz = 2 + mag * frame_count;
- const size_t new_index_sz = 2 + mag * (frame + 1);
- marker &= 0x0f8;
- marker |= frame;
-
- // Copy existing frame sizes.
- memmove(frame_data + 1, frame_start + inputs[i].sz - index_sz + 1,
- new_index_sz - 2);
- // New marker.
- frame_data[0] = marker;
- frame_data += (mag * (frame + 1) + 1);
-
- *frame_data++ = marker;
- inputs[i].sz = frame_data - frame_start;
- }
- }
- }
-
- void FreeBitstreamBuffers(struct vpx_fixed_buf *const inputs, const int n) {
- ASSERT_TRUE(inputs != NULL);
- ASSERT_GT(n, 0);
-
- for (int i = 0; i < n; ++i) {
- free(inputs[i].buf);
- inputs[i].buf = NULL;
- inputs[i].sz = 0;
- }
- }
-
- SvcContext svc_;
- vpx_codec_ctx_t codec_;
- struct vpx_codec_enc_cfg codec_enc_;
- vpx_codec_iface_t *codec_iface_;
- std::string test_file_name_;
- bool codec_initialized_;
- Decoder *decoder_;
- int tile_columns_;
- int tile_rows_;
-};
-
-TEST_F(SvcTest, SvcInit) {
- // test missing parameters
- vpx_codec_err_t res = vpx_svc_init(NULL, &codec_, codec_iface_, &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
- res = vpx_svc_init(&svc_, NULL, codec_iface_, &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
- res = vpx_svc_init(&svc_, &codec_, NULL, &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- res = vpx_svc_init(&svc_, &codec_, codec_iface_, NULL);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- svc_.spatial_layers = 6; // too many layers
- res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- svc_.spatial_layers = 0; // use default layers
- InitializeEncoder();
- EXPECT_EQ(VPX_SS_DEFAULT_LAYERS, svc_.spatial_layers);
-}
-
-TEST_F(SvcTest, InitTwoLayers) {
- svc_.spatial_layers = 2;
- InitializeEncoder();
-}
-
-TEST_F(SvcTest, InvalidOptions) {
- vpx_codec_err_t res = vpx_svc_set_options(&svc_, NULL);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- res = vpx_svc_set_options(&svc_, "not-an-option=1");
- EXPECT_EQ(VPX_CODEC_OK, res);
- res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-}
-
-TEST_F(SvcTest, SetLayersOption) {
- vpx_codec_err_t res = vpx_svc_set_options(&svc_, "spatial-layers=3");
- EXPECT_EQ(VPX_CODEC_OK, res);
- InitializeEncoder();
- EXPECT_EQ(3, svc_.spatial_layers);
-}
-
-TEST_F(SvcTest, SetMultipleOptions) {
- vpx_codec_err_t res =
- vpx_svc_set_options(&svc_, "spatial-layers=2 scale-factors=1/3,2/3");
- EXPECT_EQ(VPX_CODEC_OK, res);
- InitializeEncoder();
- EXPECT_EQ(2, svc_.spatial_layers);
-}
-
-TEST_F(SvcTest, SetScaleFactorsOption) {
- svc_.spatial_layers = 2;
- vpx_codec_err_t res =
- vpx_svc_set_options(&svc_, "scale-factors=not-scale-factors");
- EXPECT_EQ(VPX_CODEC_OK, res);
- res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- res = vpx_svc_set_options(&svc_, "scale-factors=1/3, 3*3");
- EXPECT_EQ(VPX_CODEC_OK, res);
- res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- res = vpx_svc_set_options(&svc_, "scale-factors=1/3");
- EXPECT_EQ(VPX_CODEC_OK, res);
- res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- res = vpx_svc_set_options(&svc_, "scale-factors=1/3,2/3");
- EXPECT_EQ(VPX_CODEC_OK, res);
- InitializeEncoder();
-}
-
-TEST_F(SvcTest, SetQuantizersOption) {
- svc_.spatial_layers = 2;
- vpx_codec_err_t res = vpx_svc_set_options(&svc_, "max-quantizers=nothing");
- EXPECT_EQ(VPX_CODEC_OK, res);
- res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- res = vpx_svc_set_options(&svc_, "min-quantizers=nothing");
- EXPECT_EQ(VPX_CODEC_OK, res);
- res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- res = vpx_svc_set_options(&svc_, "max-quantizers=40");
- EXPECT_EQ(VPX_CODEC_OK, res);
- res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- res = vpx_svc_set_options(&svc_, "min-quantizers=40");
- EXPECT_EQ(VPX_CODEC_OK, res);
- res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- res = vpx_svc_set_options(&svc_, "max-quantizers=30,30 min-quantizers=40,40");
- EXPECT_EQ(VPX_CODEC_OK, res);
- res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- res = vpx_svc_set_options(&svc_, "max-quantizers=40,40 min-quantizers=30,30");
- InitializeEncoder();
-}
-
-TEST_F(SvcTest, SetAutoAltRefOption) {
- svc_.spatial_layers = 5;
- vpx_codec_err_t res = vpx_svc_set_options(&svc_, "auto-alt-refs=none");
- EXPECT_EQ(VPX_CODEC_OK, res);
- res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- res = vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1,1,0");
- EXPECT_EQ(VPX_CODEC_OK, res);
- res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- vpx_svc_set_options(&svc_, "auto-alt-refs=0,1,1,1,0");
- InitializeEncoder();
-}
-
-// Test that decoder can handle an SVC frame as the first frame in a sequence.
-TEST_F(SvcTest, OnePassEncodeOneFrame) {
- codec_enc_.g_pass = VPX_RC_ONE_PASS;
- vpx_fixed_buf output = {0};
- Pass2EncodeNFrames(NULL, 1, 2, &output);
- DecodeNFrames(&output, 1);
- FreeBitstreamBuffers(&output, 1);
-}
-
-TEST_F(SvcTest, OnePassEncodeThreeFrames) {
- codec_enc_.g_pass = VPX_RC_ONE_PASS;
- codec_enc_.g_lag_in_frames = 0;
- vpx_fixed_buf outputs[3];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(NULL, 3, 2, &outputs[0]);
- DecodeNFrames(&outputs[0], 3);
- FreeBitstreamBuffers(&outputs[0], 3);
-}
-
-TEST_F(SvcTest, TwoPassEncode10Frames) {
- // First pass encode
- std::string stats_buf;
- Pass1EncodeNFrames(10, 2, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
- DecodeNFrames(&outputs[0], 10);
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-TEST_F(SvcTest, TwoPassEncode20FramesWithAltRef) {
- // First pass encode
- std::string stats_buf;
- Pass1EncodeNFrames(20, 2, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- vpx_svc_set_options(&svc_, "auto-alt-refs=1,1");
- vpx_fixed_buf outputs[20];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 20, 2, &outputs[0]);
- DecodeNFrames(&outputs[0], 20);
- FreeBitstreamBuffers(&outputs[0], 20);
-}
-
-TEST_F(SvcTest, TwoPassEncode2SpatialLayersDecodeBaseLayerOnly) {
- // First pass encode
- std::string stats_buf;
- Pass1EncodeNFrames(10, 2, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- vpx_svc_set_options(&svc_, "auto-alt-refs=1,1");
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
- DropEnhancementLayers(&outputs[0], 10, 1);
- DecodeNFrames(&outputs[0], 10);
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-TEST_F(SvcTest, TwoPassEncode5SpatialLayersDecode54321Layers) {
- // First pass encode
- std::string stats_buf;
- Pass1EncodeNFrames(10, 5, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- vpx_svc_set_options(&svc_, "auto-alt-refs=0,1,1,1,0");
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 5, &outputs[0]);
-
- DecodeNFrames(&outputs[0], 10);
- DropEnhancementLayers(&outputs[0], 10, 4);
- DecodeNFrames(&outputs[0], 10);
- DropEnhancementLayers(&outputs[0], 10, 3);
- DecodeNFrames(&outputs[0], 10);
- DropEnhancementLayers(&outputs[0], 10, 2);
- DecodeNFrames(&outputs[0], 10);
- DropEnhancementLayers(&outputs[0], 10, 1);
- DecodeNFrames(&outputs[0], 10);
-
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-TEST_F(SvcTest, TwoPassEncode2SNRLayers) {
- // First pass encode
- std::string stats_buf;
- vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1");
- Pass1EncodeNFrames(20, 2, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- vpx_svc_set_options(&svc_,
- "auto-alt-refs=1,1 scale-factors=1/1,1/1");
- vpx_fixed_buf outputs[20];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 20, 2, &outputs[0]);
- DecodeNFrames(&outputs[0], 20);
- FreeBitstreamBuffers(&outputs[0], 20);
-}
-
-TEST_F(SvcTest, TwoPassEncode3SNRLayersDecode321Layers) {
- // First pass encode
- std::string stats_buf;
- vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1");
- Pass1EncodeNFrames(20, 3, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- vpx_svc_set_options(&svc_,
- "auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1");
- vpx_fixed_buf outputs[20];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 20, 3, &outputs[0]);
- DecodeNFrames(&outputs[0], 20);
- DropEnhancementLayers(&outputs[0], 20, 2);
- DecodeNFrames(&outputs[0], 20);
- DropEnhancementLayers(&outputs[0], 20, 1);
- DecodeNFrames(&outputs[0], 20);
-
- FreeBitstreamBuffers(&outputs[0], 20);
-}
-
-TEST_F(SvcTest, SetMultipleFrameContextsOption) {
- svc_.spatial_layers = 5;
- vpx_codec_err_t res =
- vpx_svc_set_options(&svc_, "multi-frame-contexts=1");
- EXPECT_EQ(VPX_CODEC_OK, res);
- res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
- EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
-
- svc_.spatial_layers = 2;
- res = vpx_svc_set_options(&svc_, "multi-frame-contexts=1");
- InitializeEncoder();
-}
-
-TEST_F(SvcTest, TwoPassEncode2SpatialLayersWithMultipleFrameContexts) {
- // First pass encode
- std::string stats_buf;
- Pass1EncodeNFrames(10, 2, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- codec_enc_.g_error_resilient = 0;
- vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1");
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
- DecodeNFrames(&outputs[0], 10);
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-TEST_F(SvcTest,
- TwoPassEncode2SpatialLayersWithMultipleFrameContextsDecodeBaselayer) {
- // First pass encode
- std::string stats_buf;
- Pass1EncodeNFrames(10, 2, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- codec_enc_.g_error_resilient = 0;
- vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1");
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
- DropEnhancementLayers(&outputs[0], 10, 1);
- DecodeNFrames(&outputs[0], 10);
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-TEST_F(SvcTest, TwoPassEncode2SNRLayersWithMultipleFrameContexts) {
- // First pass encode
- std::string stats_buf;
- vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1");
- Pass1EncodeNFrames(10, 2, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- codec_enc_.g_error_resilient = 0;
- vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 scale-factors=1/1,1/1 "
- "multi-frame-contexts=1");
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
- DecodeNFrames(&outputs[0], 10);
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-TEST_F(SvcTest,
- TwoPassEncode3SNRLayersWithMultipleFrameContextsDecode321Layer) {
- // First pass encode
- std::string stats_buf;
- vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1");
- Pass1EncodeNFrames(10, 3, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- codec_enc_.g_error_resilient = 0;
- vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1 "
- "multi-frame-contexts=1");
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 3, &outputs[0]);
-
- DecodeNFrames(&outputs[0], 10);
- DropEnhancementLayers(&outputs[0], 10, 2);
- DecodeNFrames(&outputs[0], 10);
- DropEnhancementLayers(&outputs[0], 10, 1);
- DecodeNFrames(&outputs[0], 10);
-
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-TEST_F(SvcTest, TwoPassEncode2TemporalLayers) {
- // First pass encode
- std::string stats_buf;
- vpx_svc_set_options(&svc_, "scale-factors=1/1");
- svc_.temporal_layers = 2;
- Pass1EncodeNFrames(10, 1, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- svc_.temporal_layers = 2;
- vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
- DecodeNFrames(&outputs[0], 10);
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithMultipleFrameContexts) {
- // First pass encode
- std::string stats_buf;
- vpx_svc_set_options(&svc_, "scale-factors=1/1");
- svc_.temporal_layers = 2;
- Pass1EncodeNFrames(10, 1, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- svc_.temporal_layers = 2;
- codec_enc_.g_error_resilient = 0;
- vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1 "
- "multi-frame-contexts=1");
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
- DecodeNFrames(&outputs[0], 10);
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-TEST_F(SvcTest, TwoPassEncode2TemporalLayersDecodeBaseLayer) {
- // First pass encode
- std::string stats_buf;
- vpx_svc_set_options(&svc_, "scale-factors=1/1");
- svc_.temporal_layers = 2;
- Pass1EncodeNFrames(10, 1, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- svc_.temporal_layers = 2;
- vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
-
- vpx_fixed_buf base_layer[5];
- for (int i = 0; i < 5; ++i)
- base_layer[i] = outputs[i * 2];
-
- DecodeNFrames(&base_layer[0], 5);
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-TEST_F(SvcTest,
- TwoPassEncode2TemporalLayersWithMultipleFrameContextsDecodeBaseLayer) {
- // First pass encode
- std::string stats_buf;
- vpx_svc_set_options(&svc_, "scale-factors=1/1");
- svc_.temporal_layers = 2;
- Pass1EncodeNFrames(10, 1, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- svc_.temporal_layers = 2;
- codec_enc_.g_error_resilient = 0;
- vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1 "
- "multi-frame-contexts=1");
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
-
- vpx_fixed_buf base_layer[5];
- for (int i = 0; i < 5; ++i)
- base_layer[i] = outputs[i * 2];
-
- DecodeNFrames(&base_layer[0], 5);
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithTiles) {
- // First pass encode
- std::string stats_buf;
- vpx_svc_set_options(&svc_, "scale-factors=1/1");
- svc_.temporal_layers = 2;
- Pass1EncodeNFrames(10, 1, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- svc_.temporal_layers = 2;
- vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
- codec_enc_.g_w = 704;
- codec_enc_.g_h = 144;
- tile_columns_ = 1;
- tile_rows_ = 1;
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
- DecodeNFrames(&outputs[0], 10);
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-TEST_F(SvcTest,
- TwoPassEncode2TemporalLayersWithMultipleFrameContextsAndTiles) {
- // First pass encode
- std::string stats_buf;
- vpx_svc_set_options(&svc_, "scale-factors=1/1");
- svc_.temporal_layers = 2;
- Pass1EncodeNFrames(10, 1, &stats_buf);
-
- // Second pass encode
- codec_enc_.g_pass = VPX_RC_LAST_PASS;
- svc_.temporal_layers = 2;
- codec_enc_.g_error_resilient = 0;
- codec_enc_.g_w = 704;
- codec_enc_.g_h = 144;
- tile_columns_ = 1;
- tile_rows_ = 1;
- vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1 "
- "multi-frame-contexts=1");
- vpx_fixed_buf outputs[10];
- memset(&outputs[0], 0, sizeof(outputs));
- Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
- DecodeNFrames(&outputs[0], 10);
- FreeBitstreamBuffers(&outputs[0], 10);
-}
-
-} // namespace
diff --git a/test/test.mk b/test/test.mk
index 346a9ba..bc8424c 100644
--- a/test/test.mk
+++ b/test/test.mk
@@ -120,10 +120,6 @@
#LIBVPX_TEST_SRCS-$(CONFIG_VP10_ENCODER) += vp9_quantize_test.cc
LIBVPX_TEST_SRCS-$(CONFIG_VP10_ENCODER) += subtract_test.cc
-ifeq ($(CONFIG_VP10_ENCODER),yes)
-LIBVPX_TEST_SRCS-$(CONFIG_SPATIAL_SVC) += svc_test.cc
-endif
-
ifeq ($(CONFIG_VP10_ENCODER)$(CONFIG_VP10_TEMPORAL_DENOISING),yesyes)
LIBVPX_TEST_SRCS-$(HAVE_SSE2) += denoiser_sse2_test.cc
endif
diff --git a/test/vpx_temporal_svc_encoder.sh b/test/vpx_temporal_svc_encoder.sh
deleted file mode 100755
index fcc8cb4..0000000
--- a/test/vpx_temporal_svc_encoder.sh
+++ /dev/null
@@ -1,290 +0,0 @@
-#!/bin/sh
-##
-## Copyright (c) 2014 The WebM project authors. All Rights Reserved.
-##
-## Use of this source code is governed by a BSD-style license
-## that can be found in the LICENSE file in the root of the source
-## tree. An additional intellectual property rights grant can be found
-## in the file PATENTS. All contributing project authors may
-## be found in the AUTHORS file in the root of the source tree.
-##
-## This file tests the libvpx vpx_temporal_svc_encoder example. To add new
-## tests to this file, do the following:
-## 1. Write a shell function (this is your test).
-## 2. Add the function to vpx_tsvc_encoder_tests (on a new line).
-##
-. $(dirname $0)/tools_common.sh
-
-# Environment check: $YUV_RAW_INPUT is required.
-vpx_tsvc_encoder_verify_environment() {
- if [ ! -e "${YUV_RAW_INPUT}" ]; then
- echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
- return 1
- fi
- if [ "$(vpx_config_option_enabled CONFIG_TEMPORAL_DENOISING)" != "yes" ]; then
- elog "Warning: Temporal denoising is disabled! Spatial denoising will be " \
- "used instead, which is probably not what you want for this test."
- fi
-}
-
-# Runs vpx_temporal_svc_encoder using the codec specified by $1 and output file
-# name by $2. Additional positional parameters are passed directly to
-# vpx_temporal_svc_encoder.
-vpx_tsvc_encoder() {
- local encoder="${LIBVPX_BIN_PATH}/vpx_temporal_svc_encoder"
- encoder="${encoder}${VPX_TEST_EXE_SUFFIX}"
- local codec="$1"
- local output_file_base="$2"
- local output_file="${VPX_TEST_OUTPUT_DIR}/${output_file_base}"
- local timebase_num="1"
- local timebase_den="1000"
- local speed="6"
- local frame_drop_thresh="30"
-
- shift 2
-
- if [ ! -x "${encoder}" ]; then
- elog "${encoder} does not exist or is not executable."
- return 1
- fi
-
- eval "${VPX_TEST_PREFIX}" "${encoder}" "${YUV_RAW_INPUT}" "${output_file}" \
- "${codec}" "${YUV_RAW_INPUT_WIDTH}" "${YUV_RAW_INPUT_HEIGHT}" \
- "${timebase_num}" "${timebase_den}" "${speed}" "${frame_drop_thresh}" \
- "$@" \
- ${devnull}
-}
-
-# Confirms that all expected output files exist given the output file name
-# passed to vpx_temporal_svc_encoder.
-# The file name passed to vpx_temporal_svc_encoder is joined with the stream
-# number and the extension .ivf to produce per stream output files. Here $1 is
-# file name, and $2 is expected number of files.
-files_exist() {
- local file_name="${VPX_TEST_OUTPUT_DIR}/$1"
- local num_files="$(($2 - 1))"
- for stream_num in $(seq 0 ${num_files}); do
- [ -e "${file_name}_${stream_num}.ivf" ] || return 1
- done
-}
-
-# Run vpx_temporal_svc_encoder in all supported modes for vp8 and vp9.
-
-vpx_tsvc_encoder_vp8_mode_0() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp8 "${FUNCNAME}" 0 200 || return 1
- # Mode 0 produces 1 stream
- files_exist "${FUNCNAME}" 1 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp8_mode_1() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp8 "${FUNCNAME}" 1 200 400 || return 1
- # Mode 1 produces 2 streams
- files_exist "${FUNCNAME}" 2 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp8_mode_2() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp8 "${FUNCNAME}" 2 200 400 || return 1
- # Mode 2 produces 2 streams
- files_exist "${FUNCNAME}" 2 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp8_mode_3() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp8 "${FUNCNAME}" 3 200 400 600 || return 1
- # Mode 3 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp8_mode_4() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp8 "${FUNCNAME}" 4 200 400 600 || return 1
- # Mode 4 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp8_mode_5() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp8 "${FUNCNAME}" 5 200 400 600 || return 1
- # Mode 5 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp8_mode_6() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp8 "${FUNCNAME}" 6 200 400 600 || return 1
- # Mode 6 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp8_mode_7() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp8 "${FUNCNAME}" 7 200 400 600 800 1000 || return 1
- # Mode 7 produces 5 streams
- files_exist "${FUNCNAME}" 5 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp8_mode_8() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp8 "${FUNCNAME}" 8 200 400 || return 1
- # Mode 8 produces 2 streams
- files_exist "${FUNCNAME}" 2 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp8_mode_9() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp8 "${FUNCNAME}" 9 200 400 600 || return 1
- # Mode 9 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp8_mode_10() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp8 "${FUNCNAME}" 10 200 400 600 || return 1
- # Mode 10 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp8_mode_11() {
- if [ "$(vp8_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp8 "${FUNCNAME}" 11 200 400 600 || return 1
- # Mode 11 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp9_mode_0() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp9 "${FUNCNAME}" 0 200 || return 1
- # Mode 0 produces 1 stream
- files_exist "${FUNCNAME}" 1 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp9_mode_1() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp9 "${FUNCNAME}" 1 200 400 || return 1
- # Mode 1 produces 2 streams
- files_exist "${FUNCNAME}" 2 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp9_mode_2() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp9 "${FUNCNAME}" 2 200 400 || return 1
- # Mode 2 produces 2 streams
- files_exist "${FUNCNAME}" 2 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp9_mode_3() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp9 "${FUNCNAME}" 3 200 400 600 || return 1
- # Mode 3 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp9_mode_4() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp9 "${FUNCNAME}" 4 200 400 600 || return 1
- # Mode 4 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp9_mode_5() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp9 "${FUNCNAME}" 5 200 400 600 || return 1
- # Mode 5 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp9_mode_6() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp9 "${FUNCNAME}" 6 200 400 600 || return 1
- # Mode 6 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp9_mode_7() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp9 "${FUNCNAME}" 7 200 400 600 800 1000 || return 1
- # Mode 7 produces 5 streams
- files_exist "${FUNCNAME}" 5 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp9_mode_8() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp9 "${FUNCNAME}" 8 200 400 || return 1
- # Mode 8 produces 2 streams
- files_exist "${FUNCNAME}" 2 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp9_mode_9() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp9 "${FUNCNAME}" 9 200 400 600 || return 1
- # Mode 9 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp9_mode_10() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp9 "${FUNCNAME}" 10 200 400 600 || return 1
- # Mode 10 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_vp9_mode_11() {
- if [ "$(vp9_encode_available)" = "yes" ]; then
- vpx_tsvc_encoder vp9 "${FUNCNAME}" 11 200 400 600 || return 1
- # Mode 11 produces 3 streams
- files_exist "${FUNCNAME}" 3 || return 1
- fi
-}
-
-vpx_tsvc_encoder_tests="vpx_tsvc_encoder_vp8_mode_0
- vpx_tsvc_encoder_vp8_mode_1
- vpx_tsvc_encoder_vp8_mode_2
- vpx_tsvc_encoder_vp8_mode_3
- vpx_tsvc_encoder_vp8_mode_4
- vpx_tsvc_encoder_vp8_mode_5
- vpx_tsvc_encoder_vp8_mode_6
- vpx_tsvc_encoder_vp8_mode_7
- vpx_tsvc_encoder_vp8_mode_8
- vpx_tsvc_encoder_vp8_mode_9
- vpx_tsvc_encoder_vp8_mode_10
- vpx_tsvc_encoder_vp8_mode_11
- vpx_tsvc_encoder_vp9_mode_0
- vpx_tsvc_encoder_vp9_mode_1
- vpx_tsvc_encoder_vp9_mode_2
- vpx_tsvc_encoder_vp9_mode_3
- vpx_tsvc_encoder_vp9_mode_4
- vpx_tsvc_encoder_vp9_mode_5
- vpx_tsvc_encoder_vp9_mode_6
- vpx_tsvc_encoder_vp9_mode_7
- vpx_tsvc_encoder_vp9_mode_8
- vpx_tsvc_encoder_vp9_mode_9
- vpx_tsvc_encoder_vp9_mode_10
- vpx_tsvc_encoder_vp9_mode_11"
-
-run_tests vpx_tsvc_encoder_verify_environment "${vpx_tsvc_encoder_tests}"
diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c
index 2e92f0d..88200c8 100644
--- a/vp10/encoder/encodeframe.c
+++ b/vp10/encoder/encodeframe.c
@@ -39,6 +39,9 @@
#if CONFIG_SUPERTX
#include "vp10/encoder/cost.h"
#endif
+#if CONFIG_GLOBAL_MOTION
+#include "vp10/encoder/global_motion.h"
+#endif
#include "vp10/encoder/encodeframe.h"
#include "vp10/encoder/encodemb.h"
#include "vp10/encoder/encodemv.h"
@@ -1084,6 +1087,17 @@
}
}
#endif
+#if CONFIG_GLOBAL_MOTION
+static void update_global_motion_used(PREDICTION_MODE mode,
+ const MB_MODE_INFO *mbmi,
+ VP10_COMP *cpi) {
+ if (mode == ZEROMV) {
+ ++cpi->global_motion_used[mbmi->ref_frame[0]];
+ if (has_second_ref(mbmi))
+ ++cpi->global_motion_used[mbmi->ref_frame[1]];
+ }
+}
+#endif // CONFIG_GLOBAL_MOTION
static void update_state(VP10_COMP *cpi, ThreadData *td,
PICK_MODE_CONTEXT *ctx,
@@ -1231,6 +1245,21 @@
if (!frame_is_intra_only(cm)) {
if (is_inter_block(mbmi)) {
vp10_update_mv_count(td);
+#if CONFIG_GLOBAL_MOTION
+ if (bsize >= BLOCK_8X8) {
+ update_global_motion_used(mbmi->mode, mbmi, cpi);
+ } else {
+ const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
+ const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
+ int idx, idy;
+ for (idy = 0; idy < 2; idy += num_4x4_h) {
+ for (idx = 0; idx < 2; idx += num_4x4_w) {
+ const int j = idy * 2 + idx;
+ update_global_motion_used(mi->bmi[j].as_mode, mbmi, cpi);
+ }
+ }
+ }
+#endif // CONFIG_GLOBAL_MOTION
if (cm->interp_filter == SWITCHABLE
#if CONFIG_EXT_INTERP
&& vp10_is_interp_needed(xd)
@@ -4538,6 +4567,7 @@
#if CONFIG_GLOBAL_MOTION
#define MIN_TRANS_THRESH 8
+#define GLOBAL_MOTION_MODEL ROTZOOM
static void convert_to_params(double *H, TransformationType type,
Global_Motion_Params *model) {
int i;
@@ -4610,10 +4640,19 @@
vpx_clear_system_state();
vp10_zero(cpi->global_motion_used);
if (cpi->common.frame_type == INTER_FRAME && cpi->Source) {
+ YV12_BUFFER_CONFIG *ref_buf;
int frame;
double H[9] = {0, 0, 0, 0, 0, 0, 0, 0, 1};
- for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame)
- convert_model_to_params(H, AFFINE, &cm->global_motion[frame]);
+ for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) {
+ ref_buf = get_ref_frame_buffer(cpi, frame);
+ if (ref_buf) {
+ if (compute_global_motion_feature_based(
+ cpi, GLOBAL_MOTION_MODEL, cpi->Source, ref_buf,
+ 0.5, H))
+ convert_model_to_params(H, GLOBAL_MOTION_MODEL,
+ &cm->global_motion[frame]);
+ }
+ }
}
#endif // CONFIG_GLOBAL_MOTION
diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c
index efb042a..4b8dbc3 100644
--- a/vp10/encoder/encoder.c
+++ b/vp10/encoder/encoder.c
@@ -43,7 +43,6 @@
#include "vp10/encoder/rd.h"
#include "vp10/encoder/resize.h"
#include "vp10/encoder/segmentation.h"
-#include "vp10/encoder/skin_detection.h"
#include "vp10/encoder/speed_features.h"
#include "vp10/encoder/temporal_filter.h"
@@ -3507,7 +3506,7 @@
&cm->ref_frame_map[arf_idx], cm->new_fb_idx);
if (use_upsampled_ref)
uref_cnt_fb(cpi->upsampled_ref_bufs,
- &cpi->upsampled_ref_idx[cpi->alt_fb_idx], new_uidx);
+ &cpi->upsampled_ref_idx[arf_idx], new_uidx);
memcpy(cpi->interp_filter_selected[ALTREF_FRAME],
cpi->interp_filter_selected[0],
diff --git a/vp10/encoder/global_motion.c b/vp10/encoder/global_motion.c
new file mode 100644
index 0000000..387a40b
--- /dev/null
+++ b/vp10/encoder/global_motion.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <math.h>
+#include <assert.h>
+
+#include "vp10/common/warped_motion.h"
+
+#include "vp10/encoder/segmentation.h"
+#include "vp10/encoder/global_motion.h"
+
+int compute_global_motion_feature_based(struct VP10_COMP *cpi,
+ TransformationType type,
+ YV12_BUFFER_CONFIG *frm,
+ YV12_BUFFER_CONFIG *ref,
+ double inlier_prob, double *H) {
+ (void) cpi;
+ (void) type;
+ (void) frm;
+ (void) ref;
+ (void) inlier_prob;
+ (void) H;
+ return 0;
+}
diff --git a/vp10/encoder/global_motion.h b/vp10/encoder/global_motion.h
new file mode 100644
index 0000000..35deb13
--- /dev/null
+++ b/vp10/encoder/global_motion.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef VP10_ENCODER_GLOBAL_MOTION_H_
+#define VP10_ENCODER_GLOBAL_MOTION_H_
+
+#include "vpx/vpx_integer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int compute_global_motion_feature_based(struct VP10_COMP *cpi,
+ TransformationType type,
+ YV12_BUFFER_CONFIG *frm,
+ YV12_BUFFER_CONFIG *ref,
+ double inlier_prob, double *H);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+#endif // VP10_ENCODER_GLOBAL_MOTION_H_
+
diff --git a/vp10/encoder/quantize.c b/vp10/encoder/quantize.c
index a55c812..22863e2 100644
--- a/vp10/encoder/quantize.c
+++ b/vp10/encoder/quantize.c
@@ -982,7 +982,7 @@
const int16_t *dequant_ptr,
uint16_t *eob_ptr,
const int16_t *scan,
- const int16_t *iscan, const int log_scale) {
+ const int16_t *iscan, int log_scale) {
int i;
int eob = -1;
const int scale = 1 << log_scale;
@@ -1069,7 +1069,7 @@
tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr,
const int16_t *dequant_ptr,
uint16_t *eob_ptr, const int16_t *scan,
- const int16_t *iscan, const int log_scale) {
+ const int16_t *iscan, int log_scale) {
int i, non_zero_count = (int)n_coeffs, eob = -1;
int zbins[2] = {zbin_ptr[0], zbin_ptr[1]};
int round[2] = {round_ptr[0], round_ptr[1]};
diff --git a/vp10/encoder/rd.c b/vp10/encoder/rd.c
index cbdcc94..4d2380b 100644
--- a/vp10/encoder/rd.c
+++ b/vp10/encoder/rd.c
@@ -558,9 +558,9 @@
*d_q10 = (dist_tab_q10[xq] * b_q10 + dist_tab_q10[xq + 1] * a_q10) >> 10;
}
-void vp10_model_rd_from_var_lapndz(unsigned int var, unsigned int n_log2,
- unsigned int qstep, int *rate,
- int64_t *dist) {
+void vp10_model_rd_from_var_lapndz(int64_t var, unsigned int n_log2,
+ unsigned int qstep, int *rate,
+ int64_t *dist) {
// This function models the rate and distortion for a Laplacian
// source with given variance when quantized with a uniform quantizer
// with given stepsize. The closed form expressions are in:
diff --git a/vp10/encoder/rd.h b/vp10/encoder/rd.h
index 8f7aecf..b668f10 100644
--- a/vp10/encoder/rd.h
+++ b/vp10/encoder/rd.h
@@ -394,21 +394,21 @@
void vp10_initialize_me_consts(const struct VP10_COMP *cpi,
MACROBLOCK *x, int qindex);
-void vp10_model_rd_from_var_lapndz(unsigned int var, unsigned int n,
- unsigned int qstep, int *rate,
- int64_t *dist);
+void vp10_model_rd_from_var_lapndz(int64_t var, unsigned int n,
+ unsigned int qstep, int *rate,
+ int64_t *dist);
int vp10_get_switchable_rate(const struct VP10_COMP *cpi,
- const MACROBLOCKD *const xd);
+ const MACROBLOCKD *const xd);
int vp10_raster_block_offset(BLOCK_SIZE plane_bsize,
- int raster_block, int stride);
+ int raster_block, int stride);
int16_t* vp10_raster_block_offset_int16(BLOCK_SIZE plane_bsize,
- int raster_block, int16_t *base);
+ int raster_block, int16_t *base);
YV12_BUFFER_CONFIG *vp10_get_scaled_ref_frame(const struct VP10_COMP *cpi,
- int ref_frame);
+ int ref_frame);
void vp10_init_me_luts(void);
@@ -417,9 +417,9 @@
#endif
void vp10_get_entropy_contexts(BLOCK_SIZE bsize, TX_SIZE tx_size,
- const struct macroblockd_plane *pd,
- ENTROPY_CONTEXT t_above[2 * MAX_MIB_SIZE],
- ENTROPY_CONTEXT t_left[2 * MAX_MIB_SIZE]);
+ const struct macroblockd_plane *pd,
+ ENTROPY_CONTEXT t_above[2 * MAX_MIB_SIZE],
+ ENTROPY_CONTEXT t_left[2 * MAX_MIB_SIZE]);
void vp10_set_rd_speed_thresholds(struct VP10_COMP *cpi);
@@ -441,8 +441,8 @@
}
void vp10_mv_pred(struct VP10_COMP *cpi, MACROBLOCK *x,
- uint8_t *ref_y_buffer, int ref_y_stride,
- int ref_frame, BLOCK_SIZE block_size);
+ uint8_t *ref_y_buffer, int ref_y_stride,
+ int ref_frame, BLOCK_SIZE block_size);
static INLINE void set_error_per_bit(MACROBLOCK *x, int rdmult) {
x->errorperbit = rdmult >> RD_EPB_SHIFT;
@@ -450,14 +450,14 @@
}
void vp10_setup_pred_block(const MACROBLOCKD *xd,
- struct buf_2d dst[MAX_MB_PLANE],
- const YV12_BUFFER_CONFIG *src,
- int mi_row, int mi_col,
- const struct scale_factors *scale,
- const struct scale_factors *scale_uv);
+ struct buf_2d dst[MAX_MB_PLANE],
+ const YV12_BUFFER_CONFIG *src,
+ int mi_row, int mi_col,
+ const struct scale_factors *scale,
+ const struct scale_factors *scale_uv);
int vp10_get_intra_cost_penalty(int qindex, int qdelta,
- vpx_bit_depth_t bit_depth);
+ vpx_bit_depth_t bit_depth);
#ifdef __cplusplus
} // extern "C"
diff --git a/vp10/encoder/rdopt.c b/vp10/encoder/rdopt.c
index 3516593..ea2e821 100644
--- a/vp10/encoder/rdopt.c
+++ b/vp10/encoder/rdopt.c
@@ -792,7 +792,7 @@
const MACROBLOCKD *const xd,
BLOCK_SIZE bsize,
int plane,
- uint64_t sse,
+ int64_t sse,
int *rate,
int64_t *dist) {
const struct macroblockd_plane *const pd = &xd->plane[plane];
@@ -809,7 +809,8 @@
int quantizer = (pd->dequant[1] >> dequant_shift);
if (quantizer < 120)
- *rate = (square_error * (280 - quantizer)) >> (16 - VP9_PROB_COST_SHIFT);
+ *rate = (int)((square_error * (280 - quantizer)) >>
+ (16 - VP9_PROB_COST_SHIFT));
else
*rate = 0;
*dist = (square_error * quantizer) >> 8;
@@ -4467,7 +4468,8 @@
k = i;
for (idy = 0; idy < height / 4; idy += num_4x4_h) {
for (idx = 0; idx < width / 4; idx += num_4x4_w) {
- int64_t dist, ssz, rd, rd1, rd2, block;
+ int64_t dist, ssz, rd, rd1, rd2;
+ int block;
int coeff_ctx;
k += (idy * 2 + idx);
if (tx_size == TX_4X4)
diff --git a/vp10/encoder/skin_detection.c b/vp10/encoder/skin_detection.c
deleted file mode 100644
index 1714cd3..0000000
--- a/vp10/encoder/skin_detection.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2015 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include <limits.h>
-#include <math.h>
-
-#include "vp10/common/blockd.h"
-#include "vp10/encoder/encoder.h"
-#include "vp10/encoder/skin_detection.h"
-
-// Fixed-point skin color model parameters.
-static const int skin_mean[2] = {7463, 9614}; // q6
-static const int skin_inv_cov[4] = {4107, 1663, 1663, 2157}; // q16
-static const int skin_threshold = 1570636; // q18
-
-// Thresholds on luminance.
-static const int y_low = 20;
-static const int y_high = 220;
-
-// Evaluates the Mahalanobis distance measure for the input CbCr values.
-static int evaluate_skin_color_difference(int cb, int cr) {
- const int cb_q6 = cb << 6;
- const int cr_q6 = cr << 6;
- const int cb_diff_q12 = (cb_q6 - skin_mean[0]) * (cb_q6 - skin_mean[0]);
- const int cbcr_diff_q12 = (cb_q6 - skin_mean[0]) * (cr_q6 - skin_mean[1]);
- const int cr_diff_q12 = (cr_q6 - skin_mean[1]) * (cr_q6 - skin_mean[1]);
- const int cb_diff_q2 = (cb_diff_q12 + (1 << 9)) >> 10;
- const int cbcr_diff_q2 = (cbcr_diff_q12 + (1 << 9)) >> 10;
- const int cr_diff_q2 = (cr_diff_q12 + (1 << 9)) >> 10;
- const int skin_diff = skin_inv_cov[0] * cb_diff_q2 +
- skin_inv_cov[1] * cbcr_diff_q2 +
- skin_inv_cov[2] * cbcr_diff_q2 +
- skin_inv_cov[3] * cr_diff_q2;
- return skin_diff;
-}
-
-int vp10_skin_pixel(const uint8_t y, const uint8_t cb, const uint8_t cr) {
- if (y < y_low || y > y_high)
- return 0;
- else
- return (evaluate_skin_color_difference(cb, cr) < skin_threshold);
-}
-
-#ifdef OUTPUT_YUV_SKINMAP
-// For viewing skin map on input source.
-void vp10_compute_skin_map(VP10_COMP *const cpi, FILE *yuv_skinmap_file) {
- int i, j, mi_row, mi_col;
- VP10_COMMON *const cm = &cpi->common;
- uint8_t *y;
- const uint8_t *src_y = cpi->Source->y_buffer;
- const uint8_t *src_u = cpi->Source->u_buffer;
- const uint8_t *src_v = cpi->Source->v_buffer;
- const int src_ystride = cpi->Source->y_stride;
- const int src_uvstride = cpi->Source->uv_stride;
- YV12_BUFFER_CONFIG skinmap;
- memset(&skinmap, 0, sizeof(YV12_BUFFER_CONFIG));
- if (vpx_alloc_frame_buffer(&skinmap, cm->width, cm->height,
- cm->subsampling_x, cm->subsampling_y,
- VPX_ENC_BORDER_IN_PIXELS, cm->byte_alignment)) {
- vpx_free_frame_buffer(&skinmap);
- return;
- }
- memset(skinmap.buffer_alloc, 128, skinmap.frame_size);
- y = skinmap.y_buffer;
- // Loop through 8x8 blocks and set skin map based on center pixel of block.
- // Set y to white for skin block, otherwise set to source with gray scale.
- // Ignore rightmost/bottom boundary blocks.
- for (mi_row = 0; mi_row < cm->mi_rows - 1; ++mi_row) {
- for (mi_col = 0; mi_col < cm->mi_cols - 1; ++mi_col) {
- // Use middle pixel for each 8x8 block for skin detection.
- // If middle pixel is skin, assign whole 8x8 block to skin.
- const uint8_t ysource = src_y[4 * src_ystride + 4];
- const uint8_t usource = src_u[2 * src_uvstride + 2];
- const uint8_t vsource = src_v[2 * src_uvstride + 2];
- const int is_skin = vp10_skin_pixel(ysource, usource, vsource);
- for (i = 0; i < 8; i++) {
- for (j = 0; j < 8; j++) {
- if (is_skin)
- y[i * src_ystride + j] = 255;
- else
- y[i * src_ystride + j] = src_y[i * src_ystride + j];
- }
- }
- y += 8;
- src_y += 8;
- src_u += 4;
- src_v += 4;
- }
- y += (src_ystride << 3) - ((cm->mi_cols - 1) << 3);
- src_y += (src_ystride << 3) - ((cm->mi_cols - 1) << 3);
- src_u += (src_uvstride << 2) - ((cm->mi_cols - 1) << 2);
- src_v += (src_uvstride << 2) - ((cm->mi_cols - 1) << 2);
- }
- vp10_write_yuv_frame_420(&skinmap, yuv_skinmap_file);
- vpx_free_frame_buffer(&skinmap);
-}
-#endif
diff --git a/vp10/encoder/skin_detection.h b/vp10/encoder/skin_detection.h
deleted file mode 100644
index 26b7d5e..0000000
--- a/vp10/encoder/skin_detection.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2015 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef VP10_ENCODER_SKIN_MAP_H_
-#define VP10_ENCODER_SKIN_MAP_H_
-
-#include "vp10/common/blockd.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct VP10_COMP;
-
-// #define OUTPUT_YUV_SKINMAP
-
-int vp10_skin_pixel(const uint8_t y, const uint8_t cb, const uint8_t cr);
-
-#ifdef OUTPUT_YUV_SKINMAP
-// For viewing skin map on input source.
-void vp10_compute_skin_map(VP10_COMP *const cpi, FILE *yuv_skinmap_file);
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // VP10_ENCODER_SKIN_MAP_H_
diff --git a/vp10/encoder/x86/vp10_highbd_quantize_sse4.c b/vp10/encoder/x86/vp10_highbd_quantize_sse4.c
index a2ed7a9..c9ad5d0 100644
--- a/vp10/encoder/x86/vp10_highbd_quantize_sse4.c
+++ b/vp10/encoder/x86/vp10_highbd_quantize_sse4.c
@@ -119,7 +119,7 @@
uint16_t *eob_ptr,
const int16_t *scan,
const int16_t *iscan,
- const int log_scale) {
+ int log_scale) {
__m128i coeff[2], qcoeff[2], dequant[2], qparam[3], coeff_sign;
__m128i eob = _mm_setzero_si128();
const tran_low_t *src = coeff_ptr;
diff --git a/vp10/vp10_cx_iface.c b/vp10/vp10_cx_iface.c
index 4b6f75f..6a9b9e4 100644
--- a/vp10/vp10_cx_iface.c
+++ b/vp10/vp10_cx_iface.c
@@ -110,7 +110,6 @@
vp8_postproc_cfg_t preview_ppcfg;
vpx_codec_pkt_list_decl(256) pkt_list;
unsigned int fixed_kf_cntr;
- vpx_codec_priv_output_cx_pkt_cb_pair_t output_cx_pkt_cb;
// BufferPool that holds all reference frames.
BufferPool *buffer_pool;
};
@@ -192,10 +191,6 @@
RANGE_CHECK(cfg, rc_scaled_height, 0, cfg->g_h);
}
- // Spatial/temporal scalability are not yet supported in VP10.
- // Only accept the default value for range checking.
- RANGE_CHECK(cfg, ss_number_layers, 1, 1);
- RANGE_CHECK(cfg, ts_number_layers, 1, 1);
// VP9 does not support a lower bound on the keyframe interval in
// automatic keyframe placement mode.
if (cfg->kf_mode != VPX_KF_DISABLED &&
@@ -1054,22 +1049,6 @@
cx_data += size;
cx_data_sz -= size;
- if (ctx->output_cx_pkt_cb.output_cx_pkt) {
- pkt.kind = VPX_CODEC_CX_FRAME_PKT;
- pkt.data.frame.pts = ticks_to_timebase_units(timebase,
- dst_time_stamp);
- pkt.data.frame.duration =
- (unsigned long)ticks_to_timebase_units(timebase,
- dst_end_time_stamp - dst_time_stamp);
- pkt.data.frame.flags = get_frame_pkt_flags(cpi, lib_flags);
- pkt.data.frame.buf = ctx->pending_cx_data;
- pkt.data.frame.sz = size;
- ctx->pending_cx_data = NULL;
- ctx->pending_cx_data_sz = 0;
- ctx->pending_frame_count = 0;
- ctx->output_cx_pkt_cb.output_cx_pkt(
- &pkt, ctx->output_cx_pkt_cb.user_priv);
- }
continue;
}
@@ -1084,9 +1063,7 @@
if (ctx->pending_cx_data) {
ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
ctx->pending_cx_data_sz += size;
- // write the superframe only for the case when
- if (!ctx->output_cx_pkt_cb.output_cx_pkt)
- size += write_superframe_index(ctx);
+ size += write_superframe_index(ctx);
pkt.data.frame.buf = ctx->pending_cx_data;
pkt.data.frame.sz = ctx->pending_cx_data_sz;
ctx->pending_cx_data = NULL;
@@ -1098,11 +1075,7 @@
}
pkt.data.frame.partition_id = -1;
- if(ctx->output_cx_pkt_cb.output_cx_pkt)
- ctx->output_cx_pkt_cb.output_cx_pkt(&pkt,
- ctx->output_cx_pkt_cb.user_priv);
- else
- vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
+ vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
cx_data += size;
cx_data_sz -= size;
@@ -1265,16 +1238,6 @@
}
}
-static vpx_codec_err_t ctrl_register_cx_callback(vpx_codec_alg_priv_t *ctx,
- va_list args) {
- vpx_codec_priv_output_cx_pkt_cb_pair_t *cbp =
- (vpx_codec_priv_output_cx_pkt_cb_pair_t *)va_arg(args, void *);
- ctx->output_cx_pkt_cb.output_cx_pkt = cbp->output_cx_pkt;
- ctx->output_cx_pkt_cb.user_priv = cbp->user_priv;
-
- return VPX_CODEC_OK;
-}
-
static vpx_codec_err_t ctrl_set_tune_content(vpx_codec_alg_priv_t *ctx,
va_list args) {
struct vp10_extracfg extra_cfg = ctx->extra_cfg;
@@ -1343,7 +1306,6 @@
{VP9E_SET_FRAME_PARALLEL_DECODING, ctrl_set_frame_parallel_decoding_mode},
{VP9E_SET_AQ_MODE, ctrl_set_aq_mode},
{VP9E_SET_FRAME_PERIODIC_BOOST, ctrl_set_frame_periodic_boost},
- {VP9E_REGISTER_CX_CALLBACK, ctrl_register_cx_callback},
{VP9E_SET_TUNE_CONTENT, ctrl_set_tune_content},
{VP9E_SET_COLOR_SPACE, ctrl_set_color_space},
{VP9E_SET_COLOR_RANGE, ctrl_set_color_range},
@@ -1412,20 +1374,6 @@
VPX_KF_AUTO, // g_kfmode
0, // kf_min_dist
9999, // kf_max_dist
-
- // TODO(yunqingwang): Spatial/temporal scalability are not supported
- // in VP10. The following 10 parameters are not used, which should
- // be removed later.
- 1, // ss_number_layers
- {0},
- {0}, // ss_target_bitrate
- 1, // ts_number_layers
- {0}, // ts_target_bitrate
- {0}, // ts_rate_decimator
- 0, // ts_periodicity
- {0}, // ts_layer_id
- {0}, // layer_taget_bitrate
- 0 // temporal_layering_mode
}
},
};
diff --git a/vp10/vp10cx.mk b/vp10/vp10cx.mk
index 735ec5b..cb9e108 100644
--- a/vp10/vp10cx.mk
+++ b/vp10/vp10cx.mk
@@ -36,6 +36,8 @@
VP10_CX_SRCS-yes += encoder/ethread.c
VP10_CX_SRCS-yes += encoder/extend.c
VP10_CX_SRCS-yes += encoder/firstpass.c
+VP10_CX_SRCS-$(CONFIG_GLOBAL_MOTION) += encoder/global_motion.c
+VP10_CX_SRCS-$(CONFIG_GLOBAL_MOTION) += encoder/global_motion.h
VP10_CX_SRCS-yes += encoder/block.h
VP10_CX_SRCS-yes += encoder/bitstream.h
VP10_CX_SRCS-yes += encoder/encodemb.h
@@ -84,8 +86,6 @@
VP10_CX_SRCS-yes += encoder/aq_cyclicrefresh.h
VP10_CX_SRCS-yes += encoder/aq_complexity.c
VP10_CX_SRCS-yes += encoder/aq_complexity.h
-VP10_CX_SRCS-yes += encoder/skin_detection.c
-VP10_CX_SRCS-yes += encoder/skin_detection.h
VP10_CX_SRCS-yes += encoder/temporal_filter.c
VP10_CX_SRCS-yes += encoder/temporal_filter.h
VP10_CX_SRCS-yes += encoder/mbgraph.c
diff --git a/vpx/exports_spatial_svc b/vpx/exports_spatial_svc
deleted file mode 100644
index d258a1d..0000000
--- a/vpx/exports_spatial_svc
+++ /dev/null
@@ -1,6 +0,0 @@
-text vpx_svc_dump_statistics
-text vpx_svc_encode
-text vpx_svc_get_message
-text vpx_svc_init
-text vpx_svc_release
-text vpx_svc_set_options
diff --git a/vpx/src/svc_encodeframe.c b/vpx/src/svc_encodeframe.c
deleted file mode 100644
index ef9b352..0000000
--- a/vpx/src/svc_encodeframe.c
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-/**
- * @file
- * VP9 SVC encoding support via libvpx
- */
-
-#include <assert.h>
-#include <math.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#define VPX_DISABLE_CTRL_TYPECHECKS 1
-#include "./vpx_config.h"
-#include "vpx/svc_context.h"
-#include "vpx/vp8cx.h"
-#include "vpx/vpx_encoder.h"
-#include "vpx_mem/vpx_mem.h"
-#include "vp9/common/vp9_onyxc_int.h"
-
-#ifdef __MINGW32__
-#define strtok_r strtok_s
-#ifndef MINGW_HAS_SECURE_API
-// proto from /usr/x86_64-w64-mingw32/include/sec_api/string_s.h
-_CRTIMP char *__cdecl strtok_s(char *str, const char *delim, char **context);
-#endif /* MINGW_HAS_SECURE_API */
-#endif /* __MINGW32__ */
-
-#ifdef _MSC_VER
-#define strdup _strdup
-#define strtok_r strtok_s
-#endif
-
-#define SVC_REFERENCE_FRAMES 8
-#define SUPERFRAME_SLOTS (8)
-#define SUPERFRAME_BUFFER_SIZE (SUPERFRAME_SLOTS * sizeof(uint32_t) + 2)
-
-#define MAX_QUANTIZER 63
-
-static const int DEFAULT_SCALE_FACTORS_NUM[VPX_SS_MAX_LAYERS] = {
- 4, 5, 7, 11, 16
-};
-
-static const int DEFAULT_SCALE_FACTORS_DEN[VPX_SS_MAX_LAYERS] = {
- 16, 16, 16, 16, 16
-};
-
-typedef enum {
- QUANTIZER = 0,
- BITRATE,
- SCALE_FACTOR,
- AUTO_ALT_REF,
- ALL_OPTION_TYPES
-} LAYER_OPTION_TYPE;
-
-static const int option_max_values[ALL_OPTION_TYPES] = {
- 63, INT_MAX, INT_MAX, 1
-};
-
-static const int option_min_values[ALL_OPTION_TYPES] = {
- 0, 0, 1, 0
-};
-
-// One encoded frame
-typedef struct FrameData {
- void *buf; // compressed data buffer
- size_t size; // length of compressed data
- vpx_codec_frame_flags_t flags; /**< flags for this frame */
- struct FrameData *next;
-} FrameData;
-
-static SvcInternal_t *get_svc_internal(SvcContext *svc_ctx) {
- if (svc_ctx == NULL) return NULL;
- if (svc_ctx->internal == NULL) {
- SvcInternal_t *const si = (SvcInternal_t *)malloc(sizeof(*si));
- if (si != NULL) {
- memset(si, 0, sizeof(*si));
- }
- svc_ctx->internal = si;
- }
- return (SvcInternal_t *)svc_ctx->internal;
-}
-
-static const SvcInternal_t *get_const_svc_internal(
- const SvcContext *svc_ctx) {
- if (svc_ctx == NULL) return NULL;
- return (const SvcInternal_t *)svc_ctx->internal;
-}
-
-static void svc_log_reset(SvcContext *svc_ctx) {
- SvcInternal_t *const si = (SvcInternal_t *)svc_ctx->internal;
- si->message_buffer[0] = '\0';
-}
-
-static int svc_log(SvcContext *svc_ctx, SVC_LOG_LEVEL level,
- const char *fmt, ...) {
- char buf[512];
- int retval = 0;
- va_list ap;
- SvcInternal_t *const si = get_svc_internal(svc_ctx);
-
- if (level > svc_ctx->log_level) {
- return retval;
- }
-
- va_start(ap, fmt);
- retval = vsnprintf(buf, sizeof(buf), fmt, ap);
- va_end(ap);
-
- if (svc_ctx->log_print) {
- printf("%s", buf);
- } else {
- strncat(si->message_buffer, buf,
- sizeof(si->message_buffer) - strlen(si->message_buffer) - 1);
- }
-
- if (level == SVC_LOG_ERROR) {
- si->codec_ctx->err_detail = si->message_buffer;
- }
- return retval;
-}
-
-static vpx_codec_err_t extract_option(LAYER_OPTION_TYPE type,
- char *input,
- int *value0,
- int *value1) {
- if (type == SCALE_FACTOR) {
- *value0 = strtol(input, &input, 10);
- if (*input++ != '/')
- return VPX_CODEC_INVALID_PARAM;
- *value1 = strtol(input, &input, 10);
-
- if (*value0 < option_min_values[SCALE_FACTOR] ||
- *value1 < option_min_values[SCALE_FACTOR] ||
- *value0 > option_max_values[SCALE_FACTOR] ||
- *value1 > option_max_values[SCALE_FACTOR] ||
- *value0 > *value1) // num shouldn't be greater than den
- return VPX_CODEC_INVALID_PARAM;
- } else {
- *value0 = atoi(input);
- if (*value0 < option_min_values[type] ||
- *value0 > option_max_values[type])
- return VPX_CODEC_INVALID_PARAM;
- }
- return VPX_CODEC_OK;
-}
-
-static vpx_codec_err_t parse_layer_options_from_string(SvcContext *svc_ctx,
- LAYER_OPTION_TYPE type,
- const char *input,
- int *option0,
- int *option1) {
- int i;
- vpx_codec_err_t res = VPX_CODEC_OK;
- char *input_string;
- char *token;
- const char *delim = ",";
- char *save_ptr;
-
- if (input == NULL || option0 == NULL ||
- (option1 == NULL && type == SCALE_FACTOR))
- return VPX_CODEC_INVALID_PARAM;
-
- input_string = strdup(input);
- token = strtok_r(input_string, delim, &save_ptr);
- for (i = 0; i < svc_ctx->spatial_layers; ++i) {
- if (token != NULL) {
- res = extract_option(type, token, option0 + i, option1 + i);
- if (res != VPX_CODEC_OK)
- break;
- token = strtok_r(NULL, delim, &save_ptr);
- } else {
- break;
- }
- }
- if (res == VPX_CODEC_OK && i != svc_ctx->spatial_layers) {
- svc_log(svc_ctx, SVC_LOG_ERROR,
- "svc: layer params type: %d %d values required, "
- "but only %d specified\n", type, svc_ctx->spatial_layers, i);
- res = VPX_CODEC_INVALID_PARAM;
- }
- free(input_string);
- return res;
-}
-
-/**
- * Parse SVC encoding options
- * Format: encoding-mode=<svc_mode>,layers=<layer_count>
- * scale-factors=<n1>/<d1>,<n2>/<d2>,...
- * quantizers=<q1>,<q2>,...
- * svc_mode = [i|ip|alt_ip|gf]
- */
-static vpx_codec_err_t parse_options(SvcContext *svc_ctx, const char *options) {
- char *input_string;
- char *option_name;
- char *option_value;
- char *input_ptr;
- SvcInternal_t *const si = get_svc_internal(svc_ctx);
- vpx_codec_err_t res = VPX_CODEC_OK;
- int i, alt_ref_enabled = 0;
-
- if (options == NULL) return VPX_CODEC_OK;
- input_string = strdup(options);
-
- // parse option name
- option_name = strtok_r(input_string, "=", &input_ptr);
- while (option_name != NULL) {
- // parse option value
- option_value = strtok_r(NULL, " ", &input_ptr);
- if (option_value == NULL) {
- svc_log(svc_ctx, SVC_LOG_ERROR, "option missing value: %s\n",
- option_name);
- res = VPX_CODEC_INVALID_PARAM;
- break;
- }
- if (strcmp("spatial-layers", option_name) == 0) {
- svc_ctx->spatial_layers = atoi(option_value);
- } else if (strcmp("temporal-layers", option_name) == 0) {
- svc_ctx->temporal_layers = atoi(option_value);
- } else if (strcmp("scale-factors", option_name) == 0) {
- res = parse_layer_options_from_string(svc_ctx, SCALE_FACTOR, option_value,
- si->svc_params.scaling_factor_num,
- si->svc_params.scaling_factor_den);
- if (res != VPX_CODEC_OK) break;
- } else if (strcmp("max-quantizers", option_name) == 0) {
- res = parse_layer_options_from_string(svc_ctx, QUANTIZER, option_value,
- si->svc_params.max_quantizers,
- NULL);
- if (res != VPX_CODEC_OK) break;
- } else if (strcmp("min-quantizers", option_name) == 0) {
- res = parse_layer_options_from_string(svc_ctx, QUANTIZER, option_value,
- si->svc_params.min_quantizers,
- NULL);
- if (res != VPX_CODEC_OK) break;
- } else if (strcmp("auto-alt-refs", option_name) == 0) {
- res = parse_layer_options_from_string(svc_ctx, AUTO_ALT_REF, option_value,
- si->enable_auto_alt_ref, NULL);
- if (res != VPX_CODEC_OK) break;
- } else if (strcmp("bitrates", option_name) == 0) {
- res = parse_layer_options_from_string(svc_ctx, BITRATE, option_value,
- si->bitrates, NULL);
- if (res != VPX_CODEC_OK) break;
- } else if (strcmp("multi-frame-contexts", option_name) == 0) {
- si->use_multiple_frame_contexts = atoi(option_value);
- } else {
- svc_log(svc_ctx, SVC_LOG_ERROR, "invalid option: %s\n", option_name);
- res = VPX_CODEC_INVALID_PARAM;
- break;
- }
- option_name = strtok_r(NULL, "=", &input_ptr);
- }
- free(input_string);
-
- for (i = 0; i < svc_ctx->spatial_layers; ++i) {
- if (si->svc_params.max_quantizers[i] > MAX_QUANTIZER ||
- si->svc_params.max_quantizers[i] < 0 ||
- si->svc_params.min_quantizers[i] > si->svc_params.max_quantizers[i] ||
- si->svc_params.min_quantizers[i] < 0)
- res = VPX_CODEC_INVALID_PARAM;
- }
-
- if (si->use_multiple_frame_contexts &&
- (svc_ctx->spatial_layers > 3 ||
- svc_ctx->spatial_layers * svc_ctx->temporal_layers > 4))
- res = VPX_CODEC_INVALID_PARAM;
-
- for (i = 0; i < svc_ctx->spatial_layers; ++i)
- alt_ref_enabled += si->enable_auto_alt_ref[i];
- if (alt_ref_enabled > REF_FRAMES - svc_ctx->spatial_layers) {
- svc_log(svc_ctx, SVC_LOG_ERROR,
- "svc: auto alt ref: Maxinum %d(REF_FRAMES - layers) layers could"
- "enabled auto alt reference frame, but % layers are enabled\n",
- REF_FRAMES - svc_ctx->spatial_layers, alt_ref_enabled);
- res = VPX_CODEC_INVALID_PARAM;
- }
-
- return res;
-}
-
-vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx,
- const char *options) {
- SvcInternal_t *const si = get_svc_internal(svc_ctx);
- if (svc_ctx == NULL || options == NULL || si == NULL) {
- return VPX_CODEC_INVALID_PARAM;
- }
- strncpy(si->options, options, sizeof(si->options));
- si->options[sizeof(si->options) - 1] = '\0';
- return VPX_CODEC_OK;
-}
-
-void assign_layer_bitrates(const SvcContext *svc_ctx,
- vpx_codec_enc_cfg_t *const enc_cfg) {
- int i;
- const SvcInternal_t *const si = get_const_svc_internal(svc_ctx);
- int sl, tl, spatial_layer_target;
-
- if (svc_ctx->temporal_layering_mode != 0) {
- if (si->bitrates[0] != 0) {
- enc_cfg->rc_target_bitrate = 0;
- for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) {
- enc_cfg->ss_target_bitrate[sl*svc_ctx->temporal_layers] = 0;
- for (tl = 0; tl < svc_ctx->temporal_layers; ++tl) {
- enc_cfg->ss_target_bitrate[sl*svc_ctx->temporal_layers]
- += (unsigned int)si->bitrates[sl * svc_ctx->temporal_layers + tl];
- enc_cfg->layer_target_bitrate[sl*svc_ctx->temporal_layers + tl]
- = si->bitrates[sl * svc_ctx->temporal_layers + tl];
- }
- }
- } else {
- float total = 0;
- float alloc_ratio[VPX_MAX_LAYERS] = {0};
-
- for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) {
- if (si->svc_params.scaling_factor_den[sl] > 0) {
- alloc_ratio[sl] = (float)( pow(2, sl) );
- total += alloc_ratio[sl];
- }
- }
-
- for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) {
- enc_cfg->ss_target_bitrate[sl] = spatial_layer_target =
- (unsigned int)(enc_cfg->rc_target_bitrate *
- alloc_ratio[sl] / total);
- if (svc_ctx->temporal_layering_mode == 3) {
- enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers] =
- (spatial_layer_target*6)/10; // 60%
- enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 1] =
- (spatial_layer_target*8)/10; // 80%
- enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 2] =
- spatial_layer_target;
- } else if (svc_ctx->temporal_layering_mode == 2 ||
- svc_ctx->temporal_layering_mode == 1) {
- enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers] =
- spatial_layer_target * 2 / 3;
- enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 1] =
- spatial_layer_target;
- } else {
- // User should explicitly assign bitrates in this case.
- assert(0);
- }
- }
- }
- } else {
- if (si->bitrates[0] != 0) {
- enc_cfg->rc_target_bitrate = 0;
- for (i = 0; i < svc_ctx->spatial_layers; ++i) {
- enc_cfg->ss_target_bitrate[i] = (unsigned int)si->bitrates[i];
- enc_cfg->rc_target_bitrate += si->bitrates[i];
- }
- } else {
- float total = 0;
- float alloc_ratio[VPX_MAX_LAYERS] = {0};
-
- for (i = 0; i < svc_ctx->spatial_layers; ++i) {
- if (si->svc_params.scaling_factor_den[i] > 0) {
- alloc_ratio[i] = (float)(si->svc_params.scaling_factor_num[i] * 1.0 /
- si->svc_params.scaling_factor_den[i]);
-
- alloc_ratio[i] *= alloc_ratio[i];
- total += alloc_ratio[i];
- }
- }
- for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
- if (total > 0) {
- enc_cfg->layer_target_bitrate[i] = (unsigned int)
- (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total);
- }
- }
- }
- }
-}
-
-vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
- vpx_codec_iface_t *iface,
- vpx_codec_enc_cfg_t *enc_cfg) {
- vpx_codec_err_t res;
- int i, sl , tl;
- SvcInternal_t *const si = get_svc_internal(svc_ctx);
- if (svc_ctx == NULL || codec_ctx == NULL || iface == NULL ||
- enc_cfg == NULL) {
- return VPX_CODEC_INVALID_PARAM;
- }
- if (si == NULL) return VPX_CODEC_MEM_ERROR;
-
- si->codec_ctx = codec_ctx;
-
- si->width = enc_cfg->g_w;
- si->height = enc_cfg->g_h;
-
- si->kf_dist = enc_cfg->kf_max_dist;
-
- if (svc_ctx->spatial_layers == 0)
- svc_ctx->spatial_layers = VPX_SS_DEFAULT_LAYERS;
- if (svc_ctx->spatial_layers < 1 ||
- svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS) {
- svc_log(svc_ctx, SVC_LOG_ERROR, "spatial layers: invalid value: %d\n",
- svc_ctx->spatial_layers);
- return VPX_CODEC_INVALID_PARAM;
- }
-
- // Note: temporal_layering_mode only applies to one-pass CBR
- // si->svc_params.temporal_layering_mode = svc_ctx->temporal_layering_mode;
- if (svc_ctx->temporal_layering_mode == 3) {
- svc_ctx->temporal_layers = 3;
- } else if (svc_ctx->temporal_layering_mode == 2 ||
- svc_ctx->temporal_layering_mode == 1) {
- svc_ctx->temporal_layers = 2;
- }
-
- for (sl = 0; sl < VPX_SS_MAX_LAYERS; ++sl) {
- si->svc_params.scaling_factor_num[sl] = DEFAULT_SCALE_FACTORS_NUM[sl];
- si->svc_params.scaling_factor_den[sl] = DEFAULT_SCALE_FACTORS_DEN[sl];
- }
- for (tl = 0; tl < svc_ctx->temporal_layers; ++tl) {
- for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) {
- i = sl * svc_ctx->temporal_layers + tl;
- si->svc_params.max_quantizers[i] = MAX_QUANTIZER;
- si->svc_params.min_quantizers[i] = 0;
- }
- }
-
- // Parse aggregate command line options. Options must start with
- // "layers=xx" then followed by other options
- res = parse_options(svc_ctx, si->options);
- if (res != VPX_CODEC_OK) return res;
-
- if (svc_ctx->spatial_layers < 1)
- svc_ctx->spatial_layers = 1;
- if (svc_ctx->spatial_layers > VPX_SS_MAX_LAYERS)
- svc_ctx->spatial_layers = VPX_SS_MAX_LAYERS;
-
- if (svc_ctx->temporal_layers < 1)
- svc_ctx->temporal_layers = 1;
- if (svc_ctx->temporal_layers > VPX_TS_MAX_LAYERS)
- svc_ctx->temporal_layers = VPX_TS_MAX_LAYERS;
-
- if (svc_ctx->temporal_layers * svc_ctx->spatial_layers > VPX_MAX_LAYERS) {
- svc_log(svc_ctx, SVC_LOG_ERROR,
- "spatial layers * temporal layers exceeds the maximum number of "
- "allowed layers of %d\n",
- svc_ctx->spatial_layers * svc_ctx->temporal_layers,
- (int) VPX_MAX_LAYERS);
- return VPX_CODEC_INVALID_PARAM;
- }
- assign_layer_bitrates(svc_ctx, enc_cfg);
-
-#if CONFIG_SPATIAL_SVC
- for (i = 0; i < svc_ctx->spatial_layers; ++i)
- enc_cfg->ss_enable_auto_alt_ref[i] = si->enable_auto_alt_ref[i];
-#endif
-
- if (svc_ctx->temporal_layers > 1) {
- int i;
- for (i = 0; i < svc_ctx->temporal_layers; ++i) {
- enc_cfg->ts_target_bitrate[i] = enc_cfg->rc_target_bitrate /
- svc_ctx->temporal_layers;
- enc_cfg->ts_rate_decimator[i] = 1 << (svc_ctx->temporal_layers - 1 - i);
- }
- }
-
- if (svc_ctx->threads)
- enc_cfg->g_threads = svc_ctx->threads;
-
- // Modify encoder configuration
- enc_cfg->ss_number_layers = svc_ctx->spatial_layers;
- enc_cfg->ts_number_layers = svc_ctx->temporal_layers;
-
- if (enc_cfg->rc_end_usage == VPX_CBR) {
- enc_cfg->rc_resize_allowed = 0;
- enc_cfg->rc_min_quantizer = 2;
- enc_cfg->rc_max_quantizer = 56;
- enc_cfg->rc_undershoot_pct = 50;
- enc_cfg->rc_overshoot_pct = 50;
- enc_cfg->rc_buf_initial_sz = 500;
- enc_cfg->rc_buf_optimal_sz = 600;
- enc_cfg->rc_buf_sz = 1000;
- enc_cfg->rc_dropframe_thresh = 0;
- }
-
- if (enc_cfg->g_error_resilient == 0 && si->use_multiple_frame_contexts == 0)
- enc_cfg->g_error_resilient = 1;
-
- // Initialize codec
- res = vpx_codec_enc_init(codec_ctx, iface, enc_cfg, VPX_CODEC_USE_PSNR);
- if (res != VPX_CODEC_OK) {
- svc_log(svc_ctx, SVC_LOG_ERROR, "svc_enc_init error\n");
- return res;
- }
- if (svc_ctx->spatial_layers > 1 || svc_ctx->temporal_layers > 1) {
- vpx_codec_control(codec_ctx, VP9E_SET_SVC, 1);
- vpx_codec_control(codec_ctx, VP9E_SET_SVC_PARAMETERS, &si->svc_params);
- }
- return VPX_CODEC_OK;
-}
-
-/**
- * Encode a frame into multiple layers
- * Create a superframe containing the individual layers
- */
-vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx,
- vpx_codec_ctx_t *codec_ctx,
- struct vpx_image *rawimg,
- vpx_codec_pts_t pts,
- int64_t duration, int deadline) {
- vpx_codec_err_t res;
- vpx_codec_iter_t iter;
- const vpx_codec_cx_pkt_t *cx_pkt;
- SvcInternal_t *const si = get_svc_internal(svc_ctx);
- if (svc_ctx == NULL || codec_ctx == NULL || si == NULL) {
- return VPX_CODEC_INVALID_PARAM;
- }
-
- svc_log_reset(svc_ctx);
-
- res = vpx_codec_encode(codec_ctx, rawimg, pts, (uint32_t)duration, 0,
- deadline);
- if (res != VPX_CODEC_OK) {
- return res;
- }
- // save compressed data
- iter = NULL;
- while ((cx_pkt = vpx_codec_get_cx_data(codec_ctx, &iter))) {
- switch (cx_pkt->kind) {
-#if VPX_ENCODER_ABI_VERSION > (5 + VPX_CODEC_ABI_VERSION)
-#if CONFIG_SPATIAL_SVC
- case VPX_CODEC_SPATIAL_SVC_LAYER_PSNR: {
- int i;
- for (i = 0; i < svc_ctx->spatial_layers; ++i) {
- int j;
- svc_log(svc_ctx, SVC_LOG_DEBUG,
- "SVC frame: %d, layer: %d, PSNR(Total/Y/U/V): "
- "%2.3f %2.3f %2.3f %2.3f \n",
- si->psnr_pkt_received, i,
- cx_pkt->data.layer_psnr[i].psnr[0],
- cx_pkt->data.layer_psnr[i].psnr[1],
- cx_pkt->data.layer_psnr[i].psnr[2],
- cx_pkt->data.layer_psnr[i].psnr[3]);
- svc_log(svc_ctx, SVC_LOG_DEBUG,
- "SVC frame: %d, layer: %d, SSE(Total/Y/U/V): "
- "%2.3f %2.3f %2.3f %2.3f \n",
- si->psnr_pkt_received, i,
- cx_pkt->data.layer_psnr[i].sse[0],
- cx_pkt->data.layer_psnr[i].sse[1],
- cx_pkt->data.layer_psnr[i].sse[2],
- cx_pkt->data.layer_psnr[i].sse[3]);
-
- for (j = 0; j < COMPONENTS; ++j) {
- si->psnr_sum[i][j] +=
- cx_pkt->data.layer_psnr[i].psnr[j];
- si->sse_sum[i][j] += cx_pkt->data.layer_psnr[i].sse[j];
- }
- }
- ++si->psnr_pkt_received;
- break;
- }
- case VPX_CODEC_SPATIAL_SVC_LAYER_SIZES: {
- int i;
- for (i = 0; i < svc_ctx->spatial_layers; ++i)
- si->bytes_sum[i] += cx_pkt->data.layer_sizes[i];
- break;
- }
-#endif
-#endif
- case VPX_CODEC_PSNR_PKT:
- {
-#if VPX_ENCODER_ABI_VERSION > (5 + VPX_CODEC_ABI_VERSION)
- int j;
- svc_log(svc_ctx, SVC_LOG_DEBUG,
- "frame: %d, layer: %d, PSNR(Total/Y/U/V): "
- "%2.3f %2.3f %2.3f %2.3f \n",
- si->psnr_pkt_received, 0,
- cx_pkt->data.layer_psnr[0].psnr[0],
- cx_pkt->data.layer_psnr[0].psnr[1],
- cx_pkt->data.layer_psnr[0].psnr[2],
- cx_pkt->data.layer_psnr[0].psnr[3]);
- for (j = 0; j < COMPONENTS; ++j) {
- si->psnr_sum[0][j] +=
- cx_pkt->data.layer_psnr[0].psnr[j];
- si->sse_sum[0][j] += cx_pkt->data.layer_psnr[0].sse[j];
- }
-#endif
- }
- ++si->psnr_pkt_received;
- break;
- default: {
- break;
- }
- }
- }
-
- return VPX_CODEC_OK;
-}
-
-const char *vpx_svc_get_message(const SvcContext *svc_ctx) {
- const SvcInternal_t *const si = get_const_svc_internal(svc_ctx);
- if (svc_ctx == NULL || si == NULL) return NULL;
- return si->message_buffer;
-}
-
-static double calc_psnr(double d) {
- if (d == 0) return 100;
- return -10.0 * log(d) / log(10.0);
-}
-
-// dump accumulated statistics and reset accumulated values
-const char *vpx_svc_dump_statistics(SvcContext *svc_ctx) {
- int number_of_frames;
- int i, j;
- uint32_t bytes_total = 0;
- double scale[COMPONENTS];
- double psnr[COMPONENTS];
- double mse[COMPONENTS];
- double y_scale;
-
- SvcInternal_t *const si = get_svc_internal(svc_ctx);
- if (svc_ctx == NULL || si == NULL) return NULL;
-
- svc_log_reset(svc_ctx);
-
- number_of_frames = si->psnr_pkt_received;
- if (number_of_frames <= 0) return vpx_svc_get_message(svc_ctx);
-
- svc_log(svc_ctx, SVC_LOG_INFO, "\n");
- for (i = 0; i < svc_ctx->spatial_layers; ++i) {
-
- svc_log(svc_ctx, SVC_LOG_INFO,
- "Layer %d Average PSNR=[%2.3f, %2.3f, %2.3f, %2.3f], Bytes=[%u]\n",
- i, (double)si->psnr_sum[i][0] / number_of_frames,
- (double)si->psnr_sum[i][1] / number_of_frames,
- (double)si->psnr_sum[i][2] / number_of_frames,
- (double)si->psnr_sum[i][3] / number_of_frames, si->bytes_sum[i]);
- // the following psnr calculation is deduced from ffmpeg.c#print_report
- y_scale = si->width * si->height * 255.0 * 255.0 * number_of_frames;
- scale[1] = y_scale;
- scale[2] = scale[3] = y_scale / 4; // U or V
- scale[0] = y_scale * 1.5; // total
-
- for (j = 0; j < COMPONENTS; j++) {
- psnr[j] = calc_psnr(si->sse_sum[i][j] / scale[j]);
- mse[j] = si->sse_sum[i][j] * 255.0 * 255.0 / scale[j];
- }
- svc_log(svc_ctx, SVC_LOG_INFO,
- "Layer %d Overall PSNR=[%2.3f, %2.3f, %2.3f, %2.3f]\n", i, psnr[0],
- psnr[1], psnr[2], psnr[3]);
- svc_log(svc_ctx, SVC_LOG_INFO,
- "Layer %d Overall MSE=[%2.3f, %2.3f, %2.3f, %2.3f]\n", i, mse[0],
- mse[1], mse[2], mse[3]);
-
- bytes_total += si->bytes_sum[i];
- // Clear sums for next time.
- si->bytes_sum[i] = 0;
- for (j = 0; j < COMPONENTS; ++j) {
- si->psnr_sum[i][j] = 0;
- si->sse_sum[i][j] = 0;
- }
- }
-
- // only display statistics once
- si->psnr_pkt_received = 0;
-
- svc_log(svc_ctx, SVC_LOG_INFO, "Total Bytes=[%u]\n", bytes_total);
- return vpx_svc_get_message(svc_ctx);
-}
-
-void vpx_svc_release(SvcContext *svc_ctx) {
- SvcInternal_t *si;
- if (svc_ctx == NULL) return;
- // do not use get_svc_internal as it will unnecessarily allocate an
- // SvcInternal_t if it was not already allocated
- si = (SvcInternal_t *)svc_ctx->internal;
- if (si != NULL) {
- free(si);
- svc_ctx->internal = NULL;
- }
-}
-
diff --git a/vpx/svc_context.h b/vpx/svc_context.h
deleted file mode 100644
index 5bc2518..0000000
--- a/vpx/svc_context.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-/**
- * SvcContext - input parameters and state to encode a multi-layered
- * spatial SVC frame
- */
-
-#ifndef VPX_SVC_CONTEXT_H_
-#define VPX_SVC_CONTEXT_H_
-
-#include "./vp8cx.h"
-#include "./vpx_encoder.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef enum SVC_LOG_LEVEL {
- SVC_LOG_ERROR,
- SVC_LOG_INFO,
- SVC_LOG_DEBUG
-} SVC_LOG_LEVEL;
-
-typedef struct {
- // public interface to svc_command options
- int spatial_layers; // number of spatial layers
- int temporal_layers; // number of temporal layers
- int temporal_layering_mode;
- SVC_LOG_LEVEL log_level; // amount of information to display
- int log_print; // when set, printf log messages instead of returning the
- // message with svc_get_message
- int output_rc_stat; // for outputting rc stats
- int speed; // speed setting for codec
- int threads;
- int aqmode; // turns on aq-mode=3 (cyclic_refresh): 0=off, 1=on.
- // private storage for vpx_svc_encode
- void *internal;
-} SvcContext;
-
-#define OPTION_BUFFER_SIZE 1024
-#define COMPONENTS 4 // psnr & sse statistics maintained for total, y, u, v
-
-typedef struct SvcInternal {
- char options[OPTION_BUFFER_SIZE]; // set by vpx_svc_set_options
-
- // values extracted from option, quantizers
- vpx_svc_extra_cfg_t svc_params;
- int enable_auto_alt_ref[VPX_SS_MAX_LAYERS];
- int bitrates[VPX_SS_MAX_LAYERS];
-
- // accumulated statistics
- double psnr_sum[VPX_SS_MAX_LAYERS][COMPONENTS]; // total/Y/U/V
- uint64_t sse_sum[VPX_SS_MAX_LAYERS][COMPONENTS];
- uint32_t bytes_sum[VPX_SS_MAX_LAYERS];
-
- // codec encoding values
- int width; // width of highest layer
- int height; // height of highest layer
- int kf_dist; // distance between keyframes
-
- // state variables
- int psnr_pkt_received;
- int layer;
- int use_multiple_frame_contexts;
-
- char message_buffer[2048];
- vpx_codec_ctx_t *codec_ctx;
-} SvcInternal_t;
-
-/**
- * Set SVC options
- * options are supplied as a single string separated by spaces
- * Format: encoding-mode=<i|ip|alt-ip|gf>
- * layers=<layer_count>
- * scaling-factors=<n1>/<d1>,<n2>/<d2>,...
- * quantizers=<q1>,<q2>,...
- */
-vpx_codec_err_t vpx_svc_set_options(SvcContext *svc_ctx, const char *options);
-
-/**
- * initialize SVC encoding
- */
-vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx,
- vpx_codec_ctx_t *codec_ctx,
- vpx_codec_iface_t *iface,
- vpx_codec_enc_cfg_t *cfg);
-/**
- * encode a frame of video with multiple layers
- */
-vpx_codec_err_t vpx_svc_encode(SvcContext *svc_ctx,
- vpx_codec_ctx_t *codec_ctx,
- struct vpx_image *rawimg,
- vpx_codec_pts_t pts,
- int64_t duration, int deadline);
-
-/**
- * finished with svc encoding, release allocated resources
- */
-void vpx_svc_release(SvcContext *svc_ctx);
-
-/**
- * dump accumulated statistics and reset accumulated values
- */
-const char *vpx_svc_dump_statistics(SvcContext *svc_ctx);
-
-/**
- * get status message from previous encode
- */
-const char *vpx_svc_get_message(const SvcContext *svc_ctx);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif // VPX_SVC_CONTEXT_H_
diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h
index 8e9b7b7..954ad32 100644
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -301,17 +301,6 @@
*/
VP9E_SET_GF_CBR_BOOST_PCT,
- /*!\brief Codec control function to set the temporal layer id.
- *
- * For temporal scalability: this control allows the application to set the
- * layer id for each frame to be encoded. Note that this control must be set
- * for every frame prior to encoding. The usage of this control function
- * supersedes the internal temporal pattern counter, which is now deprecated.
- *
- * Supported in codecs: VP8
- */
- VP8E_SET_TEMPORAL_LAYER_ID,
-
/*!\brief Codec control function to set encoder screen content mode.
*
* 0: off, 1: On, 2: On with more aggressive rate control.
@@ -428,32 +417,6 @@
*/
VP9E_SET_NOISE_SENSITIVITY,
- /*!\brief Codec control function to turn on/off SVC in encoder.
- * \note Return value is VPX_CODEC_INVALID_PARAM if the encoder does not
- * support SVC in its current encoding mode
- * 0: off, 1: on
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_SVC,
-
- /*!\brief Codec control function to set parameters for SVC.
- * \note Parameters contain min_q, max_q, scaling factor for each of the
- * SVC layers.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_SVC_PARAMETERS,
-
- /*!\brief Codec control function to set svc layer for spatial and temporal.
- * \note Valid ranges: 0..#vpx_codec_enc_cfg::ss_number_layers for spatial
- * layer and 0..#vpx_codec_enc_cfg::ts_number_layers for
- * temporal layer.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_SVC_LAYER_ID,
-
/*!\brief Codec control function to set content type.
* \note Valid parameter range:
* VPX_CONTENT_DEFAULT = Regular video content (Default)
@@ -463,22 +426,6 @@
*/
VP9E_SET_TUNE_CONTENT,
- /*!\brief Codec control function to get svc layer ID.
- * \note The layer ID returned is for the data packet from the registered
- * callback function.
- *
- * Supported in codecs: VP9
- */
- VP9E_GET_SVC_LAYER_ID,
-
- /*!\brief Codec control function to register callback to get per layer packet.
- * \note Parameter for this control function is a structure with a callback
- * function and a pointer to private data used by the callback.
- *
- * Supported in codecs: VP9
- */
- VP9E_REGISTER_CX_CALLBACK,
-
/*!\brief Codec control function to set color space info.
* \note Valid ranges: 0..7, default is "UNKNOWN".
* 0 = UNKNOWN,
@@ -494,17 +441,6 @@
*/
VP9E_SET_COLOR_SPACE,
- /*!\brief Codec control function to set temporal layering mode.
- * \note Valid ranges: 0..3, default is "0" (VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING).
- * 0 = VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING
- * 1 = VP9E_TEMPORAL_LAYERING_MODE_BYPASS
- * 2 = VP9E_TEMPORAL_LAYERING_MODE_0101
- * 3 = VP9E_TEMPORAL_LAYERING_MODE_0212
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_TEMPORAL_LAYERING_MODE,
-
/*!\brief Codec control function to set minimum interval between GF/ARF frames
*
* By default the value is set as 4.
@@ -536,14 +472,6 @@
*/
VP9E_SET_COLOR_RANGE,
- /*!\brief Codec control function to set the frame flags and buffer indices
- * for spatial layers. The frame flags and buffer indices are set using the
- * struct #vpx_svc_ref_frame_config defined below.
- *
- * Supported in codecs: VP9
- */
- VP9E_SET_SVC_REF_FRAME_CONFIG,
-
/*!\brief Codec control function to set intended rendering image size.
*
* By default, this is identical to the image size in pixels.
@@ -588,33 +516,6 @@
VP8E_ONETWO = 3
} VPX_SCALING_MODE;
-/*!\brief Temporal layering mode enum for VP9 SVC.
- *
- * This set of macros define the different temporal layering modes.
- * Supported codecs: VP9 (in SVC mode)
- *
- */
-typedef enum vp9e_temporal_layering_mode {
- /*!\brief No temporal layering.
- * Used when only spatial layering is used.
- */
- VP9E_TEMPORAL_LAYERING_MODE_NOLAYERING = 0,
-
- /*!\brief Bypass mode.
- * Used when application needs to control temporal layering.
- * This will only work when the number of spatial layers equals 1.
- */
- VP9E_TEMPORAL_LAYERING_MODE_BYPASS = 1,
-
- /*!\brief 0-1-0-1... temporal layering scheme with two temporal layers.
- */
- VP9E_TEMPORAL_LAYERING_MODE_0101 = 2,
-
- /*!\brief 0-2-1-2... temporal layering scheme with three temporal layers.
- */
- VP9E_TEMPORAL_LAYERING_MODE_0212 = 3
-} VP9E_TEMPORAL_LAYERING_MODE;
-
/*!\brief vpx region of interest map
*
* These defines the data structures for the region of interest map
@@ -689,33 +590,6 @@
VPX_TUNE_SSIM
} vpx_tune_metric;
-/*!\brief vp9 svc layer parameters
- *
- * This defines the spatial and temporal layer id numbers for svc encoding.
- * This is used with the #VP9E_SET_SVC_LAYER_ID control to set the spatial and
- * temporal layer id for the current frame.
- *
- */
-typedef struct vpx_svc_layer_id {
- int spatial_layer_id; /**< Spatial layer id number. */
- int temporal_layer_id; /**< Temporal layer id number. */
-} vpx_svc_layer_id_t;
-
-/*!\brief vp9 svc frame flag parameters.
- *
- * This defines the frame flags and buffer indices for each spatial layer for
- * svc encoding.
- * This is used with the #VP9E_SET_SVC_REF_FRAME_CONFIG control to set frame
- * flags and buffer indices for each spatial layer for the current (super)frame.
- *
- */
-typedef struct vpx_svc_ref_frame_config {
- int frame_flags[VPX_TS_MAX_LAYERS]; /**< Frame flags. */
- int lst_fb_idx[VPX_TS_MAX_LAYERS]; /**< Last buffer index. */
- int gld_fb_idx[VPX_TS_MAX_LAYERS]; /**< Golden buffer index. */
- int alt_fb_idx[VPX_TS_MAX_LAYERS]; /**< Altref buffer index. */
-} vpx_svc_ref_frame_config_t;
-
/*!\cond */
/*!\brief VP8 encoder control function parameter type
*
@@ -728,8 +602,6 @@
#define VPX_CTRL_VP8E_USE_REFERENCE
VPX_CTRL_USE_TYPE(VP8E_SET_FRAME_FLAGS, int)
#define VPX_CTRL_VP8E_SET_FRAME_FLAGS
-VPX_CTRL_USE_TYPE(VP8E_SET_TEMPORAL_LAYER_ID, int)
-#define VPX_CTRL_VP8E_SET_TEMPORAL_LAYER_ID
VPX_CTRL_USE_TYPE(VP8E_SET_ROI_MAP, vpx_roi_map_t *)
#define VPX_CTRL_VP8E_SET_ROI_MAP
VPX_CTRL_USE_TYPE(VP8E_SET_ACTIVEMAP, vpx_active_map_t *)
@@ -737,15 +609,6 @@
VPX_CTRL_USE_TYPE(VP8E_SET_SCALEMODE, vpx_scaling_mode_t *)
#define VPX_CTRL_VP8E_SET_SCALEMODE
-VPX_CTRL_USE_TYPE(VP9E_SET_SVC, int)
-#define VPX_CTRL_VP9E_SET_SVC
-VPX_CTRL_USE_TYPE(VP9E_SET_SVC_PARAMETERS, void *)
-#define VPX_CTRL_VP9E_SET_SVC_PARAMETERS
-VPX_CTRL_USE_TYPE(VP9E_REGISTER_CX_CALLBACK, void *)
-#define VPX_CTRL_VP9E_REGISTER_CX_CALLBACK
-VPX_CTRL_USE_TYPE(VP9E_SET_SVC_LAYER_ID, vpx_svc_layer_id_t *)
-#define VPX_CTRL_VP9E_SET_SVC_LAYER_ID
-
VPX_CTRL_USE_TYPE(VP8E_SET_CPUUSED, int)
#define VPX_CTRL_VP8E_SET_CPUUSED
VPX_CTRL_USE_TYPE(VP8E_SET_ENABLEAUTOALTREF, unsigned int)
@@ -785,8 +648,6 @@
#define VPX_CTRL_VP8E_GET_LAST_QUANTIZER
VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER_64, int *)
#define VPX_CTRL_VP8E_GET_LAST_QUANTIZER_64
-VPX_CTRL_USE_TYPE(VP9E_GET_SVC_LAYER_ID, vpx_svc_layer_id_t *)
-#define VPX_CTRL_VP9E_GET_SVC_LAYER_ID
VPX_CTRL_USE_TYPE(VP8E_SET_MAX_INTRA_BITRATE_PCT, unsigned int)
#define VPX_CTRL_VP8E_SET_MAX_INTRA_BITRATE_PCT
@@ -832,9 +693,6 @@
VPX_CTRL_USE_TYPE(VP9E_SET_COLOR_RANGE, int)
#define VPX_CTRL_VP9E_SET_COLOR_RANGE
-VPX_CTRL_USE_TYPE(VP9E_SET_SVC_REF_FRAME_CONFIG, vpx_svc_ref_frame_config_t *)
-#define VPX_CTRL_VP9E_SET_SVC_REF_FRAME_CONFIG
-
/*!\brief
*
* TODO(rbultje) : add support of the control in ffmpeg
diff --git a/vpx/vpx_encoder.h b/vpx/vpx_encoder.h
index 955e873..9a0f48e 100644
--- a/vpx/vpx_encoder.h
+++ b/vpx/vpx_encoder.h
@@ -31,29 +31,6 @@
#include "./vpx_codec.h"
- /*! Temporal Scalability: Maximum length of the sequence defining frame
- * layer membership
- */
-#define VPX_TS_MAX_PERIODICITY 16
-
- /*! Temporal Scalability: Maximum number of coding layers */
-#define VPX_TS_MAX_LAYERS 5
-
- /*!\deprecated Use #VPX_TS_MAX_PERIODICITY instead. */
-#define MAX_PERIODICITY VPX_TS_MAX_PERIODICITY
-
-/*! Temporal+Spatial Scalability: Maximum number of coding layers */
-#define VPX_MAX_LAYERS 12 // 3 temporal + 4 spatial layers are allowed.
-
-/*!\deprecated Use #VPX_MAX_LAYERS instead. */
-#define MAX_LAYERS VPX_MAX_LAYERS // 3 temporal + 4 spatial layers allowed.
-
-/*! Spatial Scalability: Maximum number of coding layers */
-#define VPX_SS_MAX_LAYERS 5
-
-/*! Spatial Scalability: Default number of coding layers */
-#define VPX_SS_DEFAULT_LAYERS 1
-
/*!\brief Current ABI version number
*
* \internal
@@ -164,12 +141,6 @@
VPX_CODEC_STATS_PKT, /**< Two-pass statistics for this frame */
VPX_CODEC_FPMB_STATS_PKT, /**< first pass mb statistics for this frame */
VPX_CODEC_PSNR_PKT, /**< PSNR statistics for this frame */
- // Spatial SVC is still experimental and may be removed before the next ABI
- // bump.
-#if VPX_ENCODER_ABI_VERSION > (5 + VPX_CODEC_ABI_VERSION)
- VPX_CODEC_SPATIAL_SVC_LAYER_SIZES, /**< Sizes for each layer in this frame*/
- VPX_CODEC_SPATIAL_SVC_LAYER_PSNR, /**< PSNR for each layer in this frame*/
-#endif
VPX_CODEC_CUSTOM_PKT = 256 /**< Algorithm extensions */
};
@@ -206,12 +177,6 @@
double psnr[4]; /**< PSNR, total/y/u/v */
} psnr; /**< data for PSNR packet */
vpx_fixed_buf_t raw; /**< data for arbitrary packets */
- // Spatial SVC is still experimental and may be removed before the next
- // ABI bump.
-#if VPX_ENCODER_ABI_VERSION > (5 + VPX_CODEC_ABI_VERSION)
- size_t layer_sizes[VPX_SS_MAX_LAYERS];
- struct vpx_psnr_pkt layer_psnr[VPX_SS_MAX_LAYERS];
-#endif
/* This packet size is fixed to allow codecs to extend this
* interface without having to manage storage for raw packets,
@@ -222,23 +187,6 @@
} data; /**< packet data */
} vpx_codec_cx_pkt_t; /**< alias for struct vpx_codec_cx_pkt */
-
- /*!\brief Encoder return output buffer callback
- *
- * This callback function, when registered, returns with packets when each
- * spatial layer is encoded.
- */
- // putting the definitions here for now. (agrange: find if there
- // is a better place for this)
- typedef void (* vpx_codec_enc_output_cx_pkt_cb_fn_t)(vpx_codec_cx_pkt_t *pkt,
- void *user_data);
-
- /*!\brief Callback function pointer / user data pair storage */
- typedef struct vpx_codec_enc_output_cx_cb_pair {
- vpx_codec_enc_output_cx_pkt_cb_fn_t output_cx_pkt; /**< Callback function */
- void *user_priv; /**< Pointer to private data */
- } vpx_codec_priv_output_cx_pkt_cb_pair_t;
-
/*!\brief Rational Number
*
* This structure holds a fractional value.
@@ -670,100 +618,8 @@
* equal to kf_max_dist for a fixed interval.
*/
unsigned int kf_max_dist;
-
- /*
- * Spatial scalability settings (ss)
- */
-
- /*!\brief Number of spatial coding layers.
- *
- * This value specifies the number of spatial coding layers to be used.
- */
- unsigned int ss_number_layers;
-
- /*!\brief Enable auto alt reference flags for each spatial layer.
- *
- * These values specify if auto alt reference frame is enabled for each
- * spatial layer.
- */
- int ss_enable_auto_alt_ref[VPX_SS_MAX_LAYERS];
-
- /*!\brief Target bitrate for each spatial layer.
- *
- * These values specify the target coding bitrate to be used for each
- * spatial layer.
- */
- unsigned int ss_target_bitrate[VPX_SS_MAX_LAYERS];
-
- /*!\brief Number of temporal coding layers.
- *
- * This value specifies the number of temporal layers to be used.
- */
- unsigned int ts_number_layers;
-
- /*!\brief Target bitrate for each temporal layer.
- *
- * These values specify the target coding bitrate to be used for each
- * temporal layer.
- */
- unsigned int ts_target_bitrate[VPX_TS_MAX_LAYERS];
-
- /*!\brief Frame rate decimation factor for each temporal layer.
- *
- * These values specify the frame rate decimation factors to apply
- * to each temporal layer.
- */
- unsigned int ts_rate_decimator[VPX_TS_MAX_LAYERS];
-
- /*!\brief Length of the sequence defining frame temporal layer membership.
- *
- * This value specifies the length of the sequence that defines the
- * membership of frames to temporal layers. For example, if the
- * ts_periodicity = 8, then the frames are assigned to coding layers with a
- * repeated sequence of length 8.
- */
- unsigned int ts_periodicity;
-
- /*!\brief Template defining the membership of frames to temporal layers.
- *
- * This array defines the membership of frames to temporal coding layers.
- * For a 2-layer encoding that assigns even numbered frames to one temporal
- * layer (0) and odd numbered frames to a second temporal layer (1) with
- * ts_periodicity=8, then ts_layer_id = (0,1,0,1,0,1,0,1).
- */
- unsigned int ts_layer_id[VPX_TS_MAX_PERIODICITY];
-
- /*!\brief Target bitrate for each spatial/temporal layer.
- *
- * These values specify the target coding bitrate to be used for each
- * spatial/temporal layer.
- *
- */
- unsigned int layer_target_bitrate[VPX_MAX_LAYERS];
-
- /*!\brief Temporal layering mode indicating which temporal layering scheme to use.
- *
- * The value (refer to VP9E_TEMPORAL_LAYERING_MODE) specifies the
- * temporal layering mode to use.
- *
- */
- int temporal_layering_mode;
} vpx_codec_enc_cfg_t; /**< alias for struct vpx_codec_enc_cfg */
- /*!\brief vp9 svc extra configure parameters
- *
- * This defines max/min quantizers and scale factors for each layer
- *
- */
- typedef struct vpx_svc_parameters {
- int max_quantizers[VPX_MAX_LAYERS]; /**< Max Q for each layer */
- int min_quantizers[VPX_MAX_LAYERS]; /**< Min Q for each layer */
- int scaling_factor_num[VPX_MAX_LAYERS]; /**< Scaling factor-numerator */
- int scaling_factor_den[VPX_MAX_LAYERS]; /**< Scaling factor-denominator */
- int temporal_layering_mode; /**< Temporal layering mode */
- } vpx_svc_extra_cfg_t;
-
-
/*!\brief Initialize an encoder instance
*
* Initializes a encoder context using the given interface. Applications