Merge "[spatial svc] Remove handling frame and stats packets in the codec"
diff --git a/examples.mk b/examples.mk
index bd38c41..d400fe0 100644
--- a/examples.mk
+++ b/examples.mk
@@ -149,6 +149,13 @@
simple_encoder.SRCS += video_writer.h video_writer.c
simple_encoder.GUID = 4607D299-8A71-4D2C-9B1D-071899B6FBFD
simple_encoder.DESCRIPTION = Simplified encoder loop
+EXAMPLES-$(CONFIG_VP9_ENCODER) += vp9_lossless_encoder.c
+vp9_lossless_encoder.SRCS += ivfenc.h ivfenc.c
+vp9_lossless_encoder.SRCS += tools_common.h tools_common.c
+vp9_lossless_encoder.SRCS += video_common.h
+vp9_lossless_encoder.SRCS += video_writer.h video_writer.c
+vp9_lossless_encoder.GUID = B63C7C88-5348-46DC-A5A6-CC151EF93366
+vp9_lossless_encoder.DESCRIPTION = Simplified lossless VP9 encoder
EXAMPLES-$(CONFIG_VP8_ENCODER) += twopass_encoder.c
twopass_encoder.SRCS += ivfenc.h ivfenc.c
twopass_encoder.SRCS += tools_common.h tools_common.c
diff --git a/examples/vp9_lossless_encoder.c b/examples/vp9_lossless_encoder.c
new file mode 100644
index 0000000..3fcda0c
--- /dev/null
+++ b/examples/vp9_lossless_encoder.c
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpx/vpx_encoder.h"
+#include "vpx/vp8cx.h"
+
+#include "./tools_common.h"
+#include "./video_writer.h"
+
+static const char *exec_name;
+
+void usage_exit() {
+ fprintf(stderr, "vp9_lossless_encoder: Example demonstrating VP9 lossless "
+ "encoding feature. Supports raw input only.\n");
+ fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile>\n", exec_name);
+ exit(EXIT_FAILURE);
+}
+
+static int encode_frame(vpx_codec_ctx_t *codec,
+ vpx_image_t *img,
+ int frame_index,
+ int flags,
+ 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,
+ flags, 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;
+ vpx_codec_enc_cfg_t cfg;
+ int frame_count = 0;
+ vpx_image_t raw;
+ vpx_codec_err_t res;
+ VpxVideoInfo info = {0};
+ VpxVideoWriter *writer = NULL;
+ const VpxInterface *encoder = NULL;
+ const int fps = 30;
+
+ exec_name = argv[0];
+
+ if (argc < 5)
+ die("Invalid number of arguments");
+
+ encoder = get_vpx_encoder_by_name("vp9");
+ if (!encoder)
+ die("Unsupported codec.");
+
+ 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;
+
+ 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");
+
+ if (vpx_codec_control_(&codec, VP9E_SET_LOSSLESS, 1))
+ die_codec(&codec, "Failed to use lossless mode");
+
+ // Encode frames.
+ while (vpx_img_read(&raw, infile)) {
+ encode_frame(&codec, &raw, frame_count++, 0, writer);
+ }
+
+ // Flush encoder.
+ while (encode_frame(&codec, NULL, -1, 0, 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/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 9096677..0804cb5 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -41,9 +41,14 @@
#define RD_THRESH_MAX_FACT 64
#define RD_THRESH_INC 1
-#define LAST_FRAME_MODE_MASK 0xFFEDCD60
-#define GOLDEN_FRAME_MODE_MASK 0xFFDA3BB0
-#define ALT_REF_MODE_MASK 0xFFC648D0
+#define LAST_FRAME_MODE_MASK ((1 << GOLDEN_FRAME) | (1 << ALTREF_FRAME) | \
+ (1 << INTRA_FRAME))
+#define GOLDEN_FRAME_MODE_MASK ((1 << LAST_FRAME) | (1 << ALTREF_FRAME) | \
+ (1 << INTRA_FRAME))
+#define ALT_REF_MODE_MASK ((1 << LAST_FRAME) | (1 << GOLDEN_FRAME) | \
+ (1 << INTRA_FRAME))
+
+#define SECOND_REF_FRAME_MASK ((1 << ALTREF_FRAME) | 0x01)
#define MIN_EARLY_TERM_INDEX 3
@@ -1224,11 +1229,9 @@
// TODO(aconverse): Find out if this is still productive then clean up or remove
static int check_best_zero_mv(
const VP9_COMP *cpi, const uint8_t mode_context[MAX_REF_FRAMES],
- int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES],
- int inter_mode_mask, int this_mode,
+ int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES], int this_mode,
const MV_REFERENCE_FRAME ref_frames[2]) {
- if ((inter_mode_mask & (1 << ZEROMV)) &&
- (this_mode == NEARMV || this_mode == NEARESTMV || this_mode == ZEROMV) &&
+ if ((this_mode == NEARMV || this_mode == NEARESTMV || this_mode == ZEROMV) &&
frame_mv[this_mode][ref_frames[0]].as_int == 0 &&
(ref_frames[1] == NONE ||
frame_mv[this_mode][ref_frames[1]].as_int == 0)) {
@@ -1346,7 +1349,6 @@
continue;
if (!check_best_zero_mv(cpi, mbmi->mode_context, frame_mv,
- inter_mode_mask,
this_mode, mbmi->ref_frame))
continue;
@@ -2584,14 +2586,14 @@
PREDICTION_MODE mode_uv[TX_SIZES];
int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
int best_skip2 = 0;
- int mode_skip_mask = 0;
+ uint8_t ref_frame_skip_mask[2] = { 0 };
+ uint16_t mode_skip_mask[MAX_REF_FRAMES] = { 0 };
int mode_skip_start = cpi->sf.mode_skip_start + 1;
const int *const rd_threshes = rd_opt->threshes[segment_id][bsize];
const int *const rd_thresh_freq_fact = rd_opt->thresh_freq_fact[bsize];
const int mode_search_skip_flags = cpi->sf.mode_search_skip_flags;
const int intra_y_mode_mask =
cpi->sf.intra_y_mode_mask[max_txsize_lookup[bsize]];
- int inter_mode_mask = cpi->sf.inter_mode_mask[bsize];
vp9_zero(best_mbmode);
x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
@@ -2628,23 +2630,17 @@
}
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
- // All modes from vp9_mode_order that use this frame as any ref
- static const int ref_frame_mask_all[] = {
- 0x0, 0x123291, 0x25c444, 0x39b722
- };
- // Fixed mv modes (NEARESTMV, NEARMV, ZEROMV) from vp9_mode_order that use
- // this frame as their primary ref
- static const int ref_frame_mask_fixedmv[] = {
- 0x0, 0x121281, 0x24c404, 0x080102
- };
if (!(cpi->ref_frame_flags & flag_list[ref_frame])) {
- // Skip modes for missing references
- mode_skip_mask |= ref_frame_mask_all[ref_frame];
+ // Skip checking missing references in both single and compound reference
+ // modes. Note that a mode will be skipped iff both reference frames
+ // are masked out.
+ ref_frame_skip_mask[0] |= (1 << ref_frame);
+ ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
} else if (cpi->sf.reference_masking) {
for (i = LAST_FRAME; i <= ALTREF_FRAME; ++i) {
// Skip fixed mv modes for poor references
if ((x->pred_mv_sad[ref_frame] >> 2) > x->pred_mv_sad[i]) {
- mode_skip_mask |= ref_frame_mask_fixedmv[ref_frame];
+ mode_skip_mask[ref_frame] |= INTER_NEAREST_NEAR_ZERO;
break;
}
}
@@ -2653,7 +2649,8 @@
// then do nothing if the current ref frame is not allowed..
if (vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) &&
vp9_get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) {
- mode_skip_mask |= ref_frame_mask_all[ref_frame];
+ ref_frame_skip_mask[0] |= (1 << ref_frame);
+ ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
}
}
@@ -2666,15 +2663,29 @@
// an unfiltered alternative. We allow near/nearest as well
// because they may result in zero-zero MVs but be cheaper.
if (cpi->rc.is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) {
- mode_skip_mask =
- ~((1 << THR_NEARESTA) | (1 << THR_NEARA) | (1 << THR_ZEROA));
+ ref_frame_skip_mask[0] = (1 << LAST_FRAME) | (1 << GOLDEN_FRAME);
+ ref_frame_skip_mask[1] = SECOND_REF_FRAME_MASK;
+ mode_skip_mask[ALTREF_FRAME] = ~INTER_NEAREST_NEAR_ZERO;
if (frame_mv[NEARMV][ALTREF_FRAME].as_int != 0)
- mode_skip_mask |= (1 << THR_NEARA);
+ mode_skip_mask[ALTREF_FRAME] |= (1 << NEARMV);
if (frame_mv[NEARESTMV][ALTREF_FRAME].as_int != 0)
- mode_skip_mask |= (1 << THR_NEARESTA);
+ mode_skip_mask[ALTREF_FRAME] |= (1 << NEARESTMV);
}
}
+ if (cpi->rc.is_src_frame_alt_ref) {
+ if (cpi->sf.alt_ref_search_fp) {
+ mode_skip_mask[ALTREF_FRAME] = 0;
+ ref_frame_skip_mask[0] = ~(1 << ALTREF_FRAME);
+ ref_frame_skip_mask[1] = SECOND_REF_FRAME_MASK;
+ }
+ }
+
+ if (bsize > cpi->sf.max_intra_bsize) {
+ ref_frame_skip_mask[0] |= (1 << INTRA_FRAME);
+ ref_frame_skip_mask[1] |= (1 << INTRA_FRAME);
+ }
+
for (mode_index = 0; mode_index < MAX_MODES; ++mode_index) {
int mode_excluded = 0;
int64_t this_rd = INT64_MAX;
@@ -2691,8 +2702,6 @@
this_mode = vp9_mode_order[mode_index].mode;
ref_frame = vp9_mode_order[mode_index].ref_frame[0];
- if (ref_frame != INTRA_FRAME && !(inter_mode_mask & (1 << this_mode)))
- continue;
second_ref_frame = vp9_mode_order[mode_index].ref_frame[1];
// Look at the reference frame of the best mode so far and set the
@@ -2702,13 +2711,15 @@
case INTRA_FRAME:
break;
case LAST_FRAME:
- mode_skip_mask |= LAST_FRAME_MODE_MASK;
+ ref_frame_skip_mask[0] |= LAST_FRAME_MODE_MASK;
+ ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
break;
case GOLDEN_FRAME:
- mode_skip_mask |= GOLDEN_FRAME_MODE_MASK;
+ ref_frame_skip_mask[0] |= GOLDEN_FRAME_MODE_MASK;
+ ref_frame_skip_mask[1] |= SECOND_REF_FRAME_MASK;
break;
case ALTREF_FRAME:
- mode_skip_mask |= ALT_REF_MODE_MASK;
+ ref_frame_skip_mask[0] |= ALT_REF_MODE_MASK;
break;
case NONE:
case MAX_REF_FRAMES:
@@ -2717,17 +2728,11 @@
}
}
- if (cpi->sf.alt_ref_search_fp && cpi->rc.is_src_frame_alt_ref) {
- mode_skip_mask = 0;
- if (!(ref_frame == ALTREF_FRAME && second_ref_frame == NONE))
- continue;
- }
+ if (ref_frame_skip_mask[0] & (1 << ref_frame) &&
+ ref_frame_skip_mask[1] & (1 << MAX(0, second_ref_frame)))
+ continue;
- if (bsize > cpi->sf.max_intra_bsize)
- if (ref_frame == INTRA_FRAME)
- continue;
-
- if (mode_skip_mask & (1 << mode_index))
+ if (mode_skip_mask[ref_frame] & (1 << this_mode))
continue;
// Test best rd so far against threshold for trying this mode.
@@ -2834,7 +2839,7 @@
} else {
const MV_REFERENCE_FRAME ref_frames[2] = {ref_frame, second_ref_frame};
if (!check_best_zero_mv(cpi, mbmi->mode_context, frame_mv,
- inter_mode_mask, this_mode, ref_frames))
+ this_mode, ref_frames))
continue;
}
@@ -3450,14 +3455,12 @@
// If the segment reference frame feature is enabled....
// then do nothing if the current ref frame is not allowed..
if (vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) &&
- vp9_get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) !=
- (int)ref_frame) {
+ vp9_get_segdata(seg, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) {
continue;
// Disable this drop out case if the ref frame
// segment level feature is enabled for this segment. This is to
// prevent the possibility that we end up unable to pick any mode.
- } else if (!vp9_segfeature_active(seg, segment_id,
- SEG_LVL_REF_FRAME)) {
+ } else if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) {
// Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
// unless ARNR filtering is enabled in which case we want
// an unfiltered alternative. We allow near/nearest as well
diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c
index 04f3cc2..75d86ce 100644
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -13,43 +13,6 @@
#include "vp9/encoder/vp9_encoder.h"
#include "vp9/encoder/vp9_speed_features.h"
-enum {
- INTRA_ALL = (1 << DC_PRED) |
- (1 << V_PRED) | (1 << H_PRED) |
- (1 << D45_PRED) | (1 << D135_PRED) |
- (1 << D117_PRED) | (1 << D153_PRED) |
- (1 << D207_PRED) | (1 << D63_PRED) |
- (1 << TM_PRED),
- INTRA_DC = (1 << DC_PRED),
- INTRA_DC_TM = (1 << DC_PRED) | (1 << TM_PRED),
- INTRA_DC_H_V = (1 << DC_PRED) | (1 << V_PRED) | (1 << H_PRED),
- INTRA_DC_TM_H_V = (1 << DC_PRED) | (1 << TM_PRED) | (1 << V_PRED) |
- (1 << H_PRED)
-};
-
-enum {
- INTER_ALL = (1 << NEARESTMV) | (1 << NEARMV) | (1 << ZEROMV) | (1 << NEWMV),
- INTER_NEAREST = (1 << NEARESTMV),
- INTER_NEAREST_NEAR_NEW = (1 << NEARESTMV) | (1 << NEARMV) | (1 << NEWMV)
-};
-
-enum {
- DISABLE_ALL_INTER_SPLIT = (1 << THR_COMP_GA) |
- (1 << THR_COMP_LA) |
- (1 << THR_ALTR) |
- (1 << THR_GOLD) |
- (1 << THR_LAST),
-
- DISABLE_ALL_SPLIT = (1 << THR_INTRA) | DISABLE_ALL_INTER_SPLIT,
-
- DISABLE_COMPOUND_SPLIT = (1 << THR_COMP_GA) | (1 << THR_COMP_LA),
-
- LAST_AND_INTRA_SPLIT_ONLY = (1 << THR_COMP_GA) |
- (1 << THR_COMP_LA) |
- (1 << THR_ALTR) |
- (1 << THR_GOLD)
-};
-
// Intra only frames, golden frames (except alt ref overlays) and
// alt ref frames tend to be coded at a higher than ambient quality
static int frame_is_boosted(const VP9_COMP *cpi) {
diff --git a/vp9/encoder/vp9_speed_features.h b/vp9/encoder/vp9_speed_features.h
index 33c441f..0f49154 100644
--- a/vp9/encoder/vp9_speed_features.h
+++ b/vp9/encoder/vp9_speed_features.h
@@ -17,6 +17,44 @@
extern "C" {
#endif
+enum {
+ INTRA_ALL = (1 << DC_PRED) |
+ (1 << V_PRED) | (1 << H_PRED) |
+ (1 << D45_PRED) | (1 << D135_PRED) |
+ (1 << D117_PRED) | (1 << D153_PRED) |
+ (1 << D207_PRED) | (1 << D63_PRED) |
+ (1 << TM_PRED),
+ INTRA_DC = (1 << DC_PRED),
+ INTRA_DC_TM = (1 << DC_PRED) | (1 << TM_PRED),
+ INTRA_DC_H_V = (1 << DC_PRED) | (1 << V_PRED) | (1 << H_PRED),
+ INTRA_DC_TM_H_V = (1 << DC_PRED) | (1 << TM_PRED) | (1 << V_PRED) |
+ (1 << H_PRED)
+};
+
+enum {
+ INTER_ALL = (1 << NEARESTMV) | (1 << NEARMV) | (1 << ZEROMV) | (1 << NEWMV),
+ INTER_NEAREST = (1 << NEARESTMV),
+ INTER_NEAREST_NEAR_NEW = (1 << NEARESTMV) | (1 << NEARMV) | (1 << NEWMV),
+ INTER_NEAREST_NEAR_ZERO = (1 << NEARESTMV) | (1 << NEARMV) | (1 << ZEROMV),
+};
+
+enum {
+ DISABLE_ALL_INTER_SPLIT = (1 << THR_COMP_GA) |
+ (1 << THR_COMP_LA) |
+ (1 << THR_ALTR) |
+ (1 << THR_GOLD) |
+ (1 << THR_LAST),
+
+ DISABLE_ALL_SPLIT = (1 << THR_INTRA) | DISABLE_ALL_INTER_SPLIT,
+
+ DISABLE_COMPOUND_SPLIT = (1 << THR_COMP_GA) | (1 << THR_COMP_LA),
+
+ LAST_AND_INTRA_SPLIT_ONLY = (1 << THR_COMP_GA) |
+ (1 << THR_COMP_LA) |
+ (1 << THR_ALTR) |
+ (1 << THR_GOLD)
+};
+
typedef enum {
DIAMOND = 0,
NSTEP = 1,