Introduce encode_strategy.c & av1_encode interface
* Add new files av1/encoder/encode_strategy.{c,h} containing
av1_encode_strategy(). High-level encoding strategy will be moved
to av1_encode_strategy from av1_get_compressed_data(),
Pass{0,2}Encode(), etc.
* Add new interface av1_encode() in encoder.{c,h} to form the boundary
between high-level encoding strategy and low-level frame encoding.
In this patch av1_encode_strategy() directly calls av1_encode().
High-level encoding strategy will be gradually moved into
av1_encode_strategy() and low-level housekeeping will be moved below
av1_encode(). The new boundary will make the parameters for
frame-encoding explicit and grouped together.
(Also, I remove the unused skip_adapt flag for convenience).
This forms part of wider restructuring and refactoring in order to
achieve a clean API separation at the entry to the low-level encoder.
BUG=aomedia:2244
Change-Id: Ia5e0e9ba56a26134fddf0fb82b5104bce60f2888
diff --git a/av1/av1.cmake b/av1/av1.cmake
index 19f639d..fadded7 100644
--- a/av1/av1.cmake
+++ b/av1/av1.cmake
@@ -137,6 +137,8 @@
"${AOM_ROOT}/av1/encoder/encodemb.h"
"${AOM_ROOT}/av1/encoder/encodemv.c"
"${AOM_ROOT}/av1/encoder/encodemv.h"
+ "${AOM_ROOT}/av1/encoder/encode_strategy.c"
+ "${AOM_ROOT}/av1/encoder/encode_strategy.h"
"${AOM_ROOT}/av1/encoder/encoder.c"
"${AOM_ROOT}/av1/encoder/encoder.h"
"${AOM_ROOT}/av1/encoder/encodetxb.c"
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
new file mode 100644
index 0000000..ca00a6e
--- /dev/null
+++ b/av1/encoder/encode_strategy.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2019, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+
+#include <stdint.h>
+
+#include "aom/aom_codec.h"
+
+#include "av1/encoder/encoder.h"
+#include "av1/encoder/encode_strategy.h"
+
+int av1_encode_strategy(AV1_COMP *const cpi, size_t *const size,
+ uint8_t *const dest, unsigned int *frame_flags) {
+ EncodeFrameParams frame_params = { 0 };
+ EncodeFrameResults frame_results = { 0 };
+
+ // TODO(david.turner@argondesign.com): Move all the encode strategy
+ // (largely near av1_get_compressed_data) in here
+
+ // TODO(david.turner@argondesign.com): Change all the encode strategy to
+ // modify frame_params instead of cm or cpi.
+
+ frame_params.frame_flags = frame_flags;
+
+ if (av1_encode(cpi, dest, &frame_params, &frame_results) != AOM_CODEC_OK) {
+ return AOM_CODEC_ERROR;
+ }
+
+ *size = frame_results.size;
+
+ return AOM_CODEC_OK;
+}
diff --git a/av1/encoder/encode_strategy.h b/av1/encoder/encode_strategy.h
new file mode 100644
index 0000000..89f2d34
--- /dev/null
+++ b/av1/encoder/encode_strategy.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2019, Alliance for Open Media. All rights reserved
+ *
+ * This source code is subject to the terms of the BSD 2 Clause License and
+ * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
+ * was not distributed with this source code in the LICENSE file, you can
+ * obtain it at www.aomedia.org/license/software. If the Alliance for Open
+ * Media Patent License 1.0 was not distributed with this source code in the
+ * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
+ */
+
+#ifndef AOM_AV1_ENCODE_STRATEGY_H_
+#define AOM_AV1_ENCODE_STRATEGY_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// This function will implement high-level encode strategy, choosing frame type,
+// frame placement, etc. It populates an EncodeFrameParams struct with the
+// results of these decisions and then calls av1_encode()
+int av1_encode_strategy(AV1_COMP *const cpi, size_t *const size,
+ uint8_t *const dest, unsigned int *frame_flags);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // AOM_AV1_ENCODE_STRATEGY_H_
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 4c0e13e..2352b15 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -54,6 +54,7 @@
#include "av1/encoder/context_tree.h"
#include "av1/encoder/encodeframe.h"
#include "av1/encoder/encodemv.h"
+#include "av1/encoder/encode_strategy.h"
#include "av1/encoder/encoder.h"
#include "av1/encoder/encodetxb.h"
#include "av1/encoder/ethread.h"
@@ -5173,7 +5174,6 @@
}
static int encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size, uint8_t *dest,
- int skip_adapt,
unsigned int *frame_flags) {
AV1_COMMON *const cm = &cpi->common;
SequenceHeader *const seq_params = &cm->seq_params;
@@ -5450,8 +5450,6 @@
cpi->seq_params_locked = 1;
- if (skip_adapt) return AOM_CODEC_OK;
-
// Update reference frame ids for reference frames this frame will overwrite
if (seq_params->frame_id_numbers_present_flag) {
for (int i = 0; i < REF_FRAMES; i++) {
@@ -5539,6 +5537,20 @@
return AOM_CODEC_OK;
}
+int av1_encode(AV1_COMP *const cpi, uint8_t *const dest,
+ const EncodeFrameParams *const frame_params,
+ EncodeFrameResults *const frame_results) {
+ // TODO(david.turner@argondesign.com): Copy data from frame_params to cpi and
+ // cm as appropriate
+
+ if (encode_frame_to_data_rate(cpi, &frame_results->size, dest,
+ frame_params->frame_flags) != AOM_CODEC_OK) {
+ return AOM_CODEC_ERROR;
+ }
+
+ return AOM_CODEC_OK;
+}
+
static INLINE void update_keyframe_counters(AV1_COMP *cpi) {
// TODO(zoeliu): To investigate whether we should treat BWDREF_FRAME
// differently here for rc->avg_frame_bandwidth.
@@ -5591,14 +5603,13 @@
}
static int Pass0Encode(AV1_COMP *cpi, size_t *size, uint8_t *dest,
- int skip_adapt, unsigned int *frame_flags) {
+ unsigned int *frame_flags) {
if (cpi->oxcf.rc_mode == AOM_CBR) {
av1_rc_get_one_pass_cbr_params(cpi);
} else {
av1_rc_get_one_pass_vbr_params(cpi);
}
- if (encode_frame_to_data_rate(cpi, size, dest, skip_adapt, frame_flags) !=
- AOM_CODEC_OK) {
+ if (av1_encode_strategy(cpi, size, dest, frame_flags) != AOM_CODEC_OK) {
return AOM_CODEC_ERROR;
}
set_additional_frame_flags(&cpi->common, frame_flags);
@@ -5619,8 +5630,7 @@
cm->txcoeff_cost_count = 0;
#endif
- if (encode_frame_to_data_rate(cpi, size, dest, 0, frame_flags) !=
- AOM_CODEC_OK) {
+ if (av1_encode_strategy(cpi, size, dest, frame_flags) != AOM_CODEC_OK) {
return AOM_CODEC_ERROR;
}
set_additional_frame_flags(&cpi->common, frame_flags);
@@ -7017,7 +7027,7 @@
return AOM_CODEC_ERROR;
} else {
// One pass encode
- if (Pass0Encode(cpi, size, dest, 0, frame_flags) != AOM_CODEC_OK)
+ if (Pass0Encode(cpi, size, dest, frame_flags) != AOM_CODEC_OK)
return AOM_CODEC_ERROR;
}
if (oxcf->pass != 1 && cpi->common.allow_screen_content_tools) {
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index af02e07..2c1c4db 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -867,6 +867,18 @@
int is_screen_content_type;
} AV1_COMP;
+// EncodeFrameParams contains per-frame encoding parameters decided upon by
+// av1_encode_strategy() and passed down to av1_encode()
+typedef struct {
+ unsigned int *frame_flags;
+} EncodeFrameParams;
+
+// EncodeFrameResults contains information about the result of encoding a
+// single frame
+typedef struct {
+ size_t size; // Size of resulting bitstream
+} EncodeFrameResults;
+
// Must not be called more than once.
void av1_initialize_enc(void);
@@ -887,6 +899,10 @@
int64_t *time_end, int flush,
const aom_rational_t *timebase);
+int av1_encode(AV1_COMP *const cpi, uint8_t *const dest,
+ const EncodeFrameParams *const frame_params,
+ EncodeFrameResults *const frame_results);
+
int av1_get_preview_raw_frame(AV1_COMP *cpi, YV12_BUFFER_CONFIG *dest);
int av1_get_last_show_frame(AV1_COMP *cpi, YV12_BUFFER_CONFIG *frame);