summaryrefslogtreecommitdiffstats
path: root/third_party/aom/examples
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/aom/examples')
-rw-r--r--third_party/aom/examples/analyzer.cc58
-rw-r--r--third_party/aom/examples/aom_cx_set_ref.c119
-rw-r--r--third_party/aom/examples/decode_to_md5.c12
-rw-r--r--third_party/aom/examples/decode_with_drops.c13
-rw-r--r--third_party/aom/examples/encoder_util.c45
-rw-r--r--third_party/aom/examples/encoder_util.h3
-rw-r--r--third_party/aom/examples/inspect.c260
-rw-r--r--third_party/aom/examples/lightfield_bitstream_parsing.c343
-rw-r--r--third_party/aom/examples/lightfield_decoder.c233
-rw-r--r--third_party/aom/examples/lightfield_encoder.c323
-rw-r--r--third_party/aom/examples/lightfield_tile_list_decoder.c172
-rw-r--r--third_party/aom/examples/lossless_encoder.c7
-rw-r--r--third_party/aom/examples/noise_model.c426
-rw-r--r--third_party/aom/examples/resize_util.c4
-rw-r--r--third_party/aom/examples/scalable_decoder.c185
-rw-r--r--third_party/aom/examples/scalable_encoder.c289
-rw-r--r--third_party/aom/examples/set_maps.c10
-rw-r--r--third_party/aom/examples/simple_decoder.c12
-rw-r--r--third_party/aom/examples/simple_encoder.c7
-rw-r--r--third_party/aom/examples/twopass_encoder.c26
20 files changed, 2041 insertions, 506 deletions
diff --git a/third_party/aom/examples/analyzer.cc b/third_party/aom/examples/analyzer.cc
index ae0801964..6a42eca24 100644
--- a/third_party/aom/examples/analyzer.cc
+++ b/third_party/aom/examples/analyzer.cc
@@ -12,13 +12,14 @@
#include <wx/aboutdlg.h>
#include <wx/cmdline.h>
#include <wx/dcbuffer.h>
-#include "./tools_common.h"
-#include "./video_reader.h"
+
#include "aom/aom_decoder.h"
#include "aom/aomdx.h"
-#include "av1/decoder/accounting.h"
#include "av1/common/onyxc_int.h"
+#include "av1/decoder/accounting.h"
#include "av1/decoder/inspection.h"
+#include "common/tools_common.h"
+#include "common/video_reader.h"
#define OD_SIGNMASK(a) (-((a) < 0))
#define OD_FLIPSIGNI(a, b) (((a) + OD_SIGNMASK(b)) ^ OD_SIGNMASK(b))
@@ -108,7 +109,7 @@ bool AV1Decoder::step() {
size_t frame_size;
const unsigned char *frame_data;
frame_data = aom_video_reader_get_frame(reader, &frame_size);
- if (aom_codec_decode(&codec, frame_data, frame_size, NULL, 0)) {
+ if (aom_codec_decode(&codec, frame_data, frame_size, NULL)) {
fprintf(stderr, "Failed to decode frame.");
return false;
} else {
@@ -129,11 +130,10 @@ int AV1Decoder::getWidth() const {
}
int AV1Decoder::getWidthPadding() const {
- return show_padding
- ? AOMMAX(info->frame_width + 16,
- ALIGN_POWER_OF_TWO(info->frame_width, 6)) -
- info->frame_width
- : 0;
+ return show_padding ? AOMMAX(info->frame_width + 16,
+ ALIGN_POWER_OF_TWO(info->frame_width, 6)) -
+ info->frame_width
+ : 0;
}
int AV1Decoder::getHeight() const {
@@ -141,11 +141,10 @@ int AV1Decoder::getHeight() const {
}
int AV1Decoder::getHeightPadding() const {
- return show_padding
- ? AOMMAX(info->frame_height + 16,
- ALIGN_POWER_OF_TWO(info->frame_height, 6)) -
- info->frame_height
- : 0;
+ return show_padding ? AOMMAX(info->frame_height + 16,
+ ALIGN_POWER_OF_TWO(info->frame_height, 6)) -
+ info->frame_height
+ : 0;
}
bool AV1Decoder::getAccountingStruct(Accounting **accounting) {
@@ -285,19 +284,22 @@ void AnalyzerPanel::render() {
cbval = ((pmask & OD_CB_MASK) >> 1) * (cbval - 128);
crval = ((pmask & OD_CR_MASK) >> 2) * (crval - 128);
/*This is intentionally slow and very accurate.*/
- rval = OD_CLAMPI(0, (int32_t)OD_DIV_ROUND(
- 2916394880000LL * yval + 4490222169144LL * crval,
- 9745792000LL),
- 65535);
- gval = OD_CLAMPI(0, (int32_t)OD_DIV_ROUND(2916394880000LL * yval -
- 534117096223LL * cbval -
- 1334761232047LL * crval,
- 9745792000LL),
- 65535);
- bval = OD_CLAMPI(0, (int32_t)OD_DIV_ROUND(
- 2916394880000LL * yval + 5290866304968LL * cbval,
- 9745792000LL),
+ rval = OD_CLAMPI(
+ 0,
+ (int32_t)OD_DIV_ROUND(
+ 2916394880000LL * yval + 4490222169144LL * crval, 9745792000LL),
+ 65535);
+ gval = OD_CLAMPI(0,
+ (int32_t)OD_DIV_ROUND(2916394880000LL * yval -
+ 534117096223LL * cbval -
+ 1334761232047LL * crval,
+ 9745792000LL),
65535);
+ bval = OD_CLAMPI(
+ 0,
+ (int32_t)OD_DIV_ROUND(
+ 2916394880000LL * yval + 5290866304968LL * cbval, 9745792000LL),
+ 65535);
unsigned char *px_row = p;
for (int v = 0; v < zoom; v++) {
unsigned char *px = px_row;
@@ -701,8 +703,8 @@ bool Analyzer::OnCmdLineParsed(wxCmdLineParser &parser) { // NOLINT
bool bit_accounting = parser.Found(_("a"));
if (bit_accounting && !CONFIG_ACCOUNTING) {
fprintf(stderr,
- "Bit accounting support not found. "
- "Recompile with:\n./configure --enable-accounting\n");
+ "Bit accounting support not found. "
+ "Recompile with:\n./cmake -DCONFIG_ACCOUNTING=1\n");
return false;
}
frame = new AnalyzerFrame(parser.Found(_("a")));
diff --git a/third_party/aom/examples/aom_cx_set_ref.c b/third_party/aom/examples/aom_cx_set_ref.c
index 456e81300..e02e94c07 100644
--- a/third_party/aom/examples/aom_cx_set_ref.c
+++ b/third_party/aom/examples/aom_cx_set_ref.c
@@ -51,12 +51,14 @@
#include <stdlib.h>
#include <string.h>
-#include "aom/aomcx.h"
#include "aom/aom_decoder.h"
#include "aom/aom_encoder.h"
+#include "aom/aomcx.h"
+#include "common/tools_common.h"
+#include "common/video_writer.h"
#include "examples/encoder_util.h"
-#include "./tools_common.h"
-#include "./video_writer.h"
+
+#define AOM_BORDER_IN_PIXELS 288
static const char *exec_name;
@@ -71,25 +73,41 @@ void usage_exit() {
static void testing_decode(aom_codec_ctx_t *encoder, aom_codec_ctx_t *decoder,
unsigned int frame_out, int *mismatch_seen) {
aom_image_t enc_img, dec_img;
- struct av1_ref_frame ref_enc, ref_dec;
if (*mismatch_seen) return;
- ref_enc.idx = 0;
- ref_dec.idx = 0;
- if (aom_codec_control(encoder, AV1_GET_REFERENCE, &ref_enc))
+ /* Get the internal reference frame */
+ if (aom_codec_control(encoder, AV1_GET_NEW_FRAME_IMAGE, &enc_img))
die_codec(encoder, "Failed to get encoder reference frame");
- enc_img = ref_enc.img;
- if (aom_codec_control(decoder, AV1_GET_REFERENCE, &ref_dec))
+ if (aom_codec_control(decoder, AV1_GET_NEW_FRAME_IMAGE, &dec_img))
die_codec(decoder, "Failed to get decoder reference frame");
- dec_img = ref_dec.img;
+
+ if ((enc_img.fmt & AOM_IMG_FMT_HIGHBITDEPTH) !=
+ (dec_img.fmt & AOM_IMG_FMT_HIGHBITDEPTH)) {
+ if (enc_img.fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
+ aom_image_t enc_hbd_img;
+ aom_img_alloc(&enc_hbd_img, enc_img.fmt - AOM_IMG_FMT_HIGHBITDEPTH,
+ enc_img.d_w, enc_img.d_h, 16);
+ aom_img_truncate_16_to_8(&enc_hbd_img, &enc_img);
+ enc_img = enc_hbd_img;
+ }
+ if (dec_img.fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
+ aom_image_t dec_hbd_img;
+ aom_img_alloc(&dec_hbd_img, dec_img.fmt - AOM_IMG_FMT_HIGHBITDEPTH,
+ dec_img.d_w, dec_img.d_h, 16);
+ aom_img_truncate_16_to_8(&dec_hbd_img, &dec_img);
+ dec_img = dec_hbd_img;
+ }
+ }
if (!aom_compare_img(&enc_img, &dec_img)) {
int y[4], u[4], v[4];
+ if (enc_img.fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
+ aom_find_mismatch_high(&enc_img, &dec_img, y, u, v);
+ } else {
+ aom_find_mismatch(&enc_img, &dec_img, y, u, v);
+ }
- *mismatch_seen = 1;
-
- aom_find_mismatch(&enc_img, &dec_img, y, u, v);
printf(
"Encode/decode mismatch on frame %d at"
" Y[%d, %d] {%d/%d},"
@@ -97,6 +115,7 @@ static void testing_decode(aom_codec_ctx_t *encoder, aom_codec_ctx_t *decoder,
" V[%d, %d] {%d/%d}",
frame_out, y[0], y[1], y[2], y[3], u[0], u[1], u[2], u[3], v[0], v[1],
v[2], v[3]);
+ *mismatch_seen = 1;
}
aom_img_free(&enc_img);
@@ -106,13 +125,13 @@ static void testing_decode(aom_codec_ctx_t *encoder, aom_codec_ctx_t *decoder,
static int encode_frame(aom_codec_ctx_t *ecodec, aom_image_t *img,
unsigned int frame_in, AvxVideoWriter *writer,
int test_decode, aom_codec_ctx_t *dcodec,
- unsigned int *frame_out, int *mismatch_seen) {
+ unsigned int *frame_out, int *mismatch_seen,
+ aom_image_t *ext_ref) {
int got_pkts = 0;
aom_codec_iter_t iter = NULL;
const aom_codec_cx_pkt_t *pkt = NULL;
int got_data;
- const aom_codec_err_t res =
- aom_codec_encode(ecodec, img, frame_in, 1, 0, AOM_DL_GOOD_QUALITY);
+ const aom_codec_err_t res = aom_codec_encode(ecodec, img, frame_in, 1, 0);
if (res != AOM_CODEC_OK) die_codec(ecodec, "Failed to encode frame");
got_data = 0;
@@ -139,8 +158,13 @@ static int encode_frame(aom_codec_ctx_t *ecodec, aom_image_t *img,
// Decode 1 frame.
if (test_decode) {
if (aom_codec_decode(dcodec, pkt->data.frame.buf,
- (unsigned int)pkt->data.frame.sz, NULL, 0))
+ (unsigned int)pkt->data.frame.sz, NULL))
die_codec(dcodec, "Failed to decode frame.");
+
+ // Copy out first decoded frame, and use it as reference later.
+ if (*frame_out == 1 && ext_ref != NULL)
+ if (aom_codec_control(dcodec, AV1_GET_NEW_FRAME_IMAGE, ext_ref))
+ die_codec(dcodec, "Failed to get decoder new frame");
}
}
}
@@ -160,10 +184,16 @@ int main(int argc, char **argv) {
aom_codec_enc_cfg_t cfg;
unsigned int frame_in = 0;
aom_image_t raw;
+ aom_image_t raw_shift;
+ aom_image_t ext_ref;
aom_codec_err_t res;
AvxVideoInfo info;
AvxVideoWriter *writer = NULL;
const AvxInterface *encoder = NULL;
+ int flags = 0;
+ int allocated_raw_shift = 0;
+ aom_img_fmt_t raw_fmt = AOM_IMG_FMT_I420;
+ aom_img_fmt_t ref_fmt = AOM_IMG_FMT_I420;
// Test encoder/decoder mismatch.
int test_decode = 1;
@@ -225,13 +255,21 @@ int main(int argc, char **argv) {
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) {
+ if (info.frame_width <= 0 || info.frame_height <= 0) {
die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
}
- if (!aom_img_alloc(&raw, AOM_IMG_FMT_I420, info.frame_width,
- info.frame_height, 1)) {
+ // In this test, the bit depth of input video is 8-bit, and the input format
+ // is AOM_IMG_FMT_I420.
+ if (!aom_img_alloc(&raw, raw_fmt, info.frame_width, info.frame_height, 32)) {
+ die("Failed to allocate image.");
+ }
+
+ if (!CONFIG_LOWBITDEPTH) ref_fmt |= AOM_IMG_FMT_HIGHBITDEPTH;
+ // Allocate memory with the border so that it can be used as a reference.
+ if (!aom_img_alloc_with_border(&ext_ref, ref_fmt, info.frame_width,
+ info.frame_height, 32, 8,
+ AOM_BORDER_IN_PIXELS)) {
die("Failed to allocate image.");
}
@@ -246,6 +284,11 @@ int main(int argc, char **argv) {
cfg.g_timebase.den = info.time_base.denominator;
cfg.rc_target_bitrate = bitrate;
cfg.g_lag_in_frames = 3;
+ cfg.g_bit_depth = AOM_BITS_8;
+
+ flags |= (cfg.g_bit_depth > AOM_BITS_8 || !CONFIG_LOWBITDEPTH)
+ ? AOM_CODEC_USE_HIGHBITDEPTH
+ : 0;
writer = aom_video_writer_open(outfile_arg, kContainerIVF, &info);
if (!writer) die("Failed to open %s for writing.", outfile_arg);
@@ -253,7 +296,7 @@ int main(int argc, char **argv) {
if (!(infile = fopen(infile_arg, "rb")))
die("Failed to open %s for reading.", infile_arg);
- if (aom_codec_enc_init(&ecodec, encoder->codec_interface(), &cfg, 0))
+ if (aom_codec_enc_init(&ecodec, encoder->codec_interface(), &cfg, flags))
die_codec(&ecodec, "Failed to initialize encoder");
// Disable alt_ref.
@@ -269,25 +312,43 @@ int main(int argc, char **argv) {
// Encode frames.
while (aom_img_read(&raw, infile)) {
if (limit && frame_in >= limit) break;
+ aom_image_t *frame_to_encode;
+
+ if (!CONFIG_LOWBITDEPTH) {
+ // Need to allocate larger buffer to use hbd internal.
+ int input_shift = 0;
+ if (!allocated_raw_shift) {
+ aom_img_alloc(&raw_shift, raw_fmt | AOM_IMG_FMT_HIGHBITDEPTH,
+ info.frame_width, info.frame_height, 32);
+ allocated_raw_shift = 1;
+ }
+ aom_img_upshift(&raw_shift, &raw, input_shift);
+ frame_to_encode = &raw_shift;
+ } else {
+ frame_to_encode = &raw;
+ }
+
if (update_frame_num > 1 && frame_out + 1 == update_frame_num) {
av1_ref_frame_t ref;
ref.idx = 0;
- ref.img = raw;
+ ref.use_external_ref = 0;
+ ref.img = ext_ref;
// Set reference frame in encoder.
if (aom_codec_control(&ecodec, AV1_SET_REFERENCE, &ref))
- die_codec(&ecodec, "Failed to set reference frame");
+ die_codec(&ecodec, "Failed to set encoder reference frame");
printf(" <SET_REF>");
// If set_reference in decoder is commented out, the enc/dec mismatch
// would be seen.
if (test_decode) {
+ ref.use_external_ref = 1;
if (aom_codec_control(&dcodec, AV1_SET_REFERENCE, &ref))
- die_codec(&dcodec, "Failed to set reference frame");
+ die_codec(&dcodec, "Failed to set decoder reference frame");
}
}
- encode_frame(&ecodec, &raw, frame_in, writer, test_decode, &dcodec,
- &frame_out, &mismatch_seen);
+ encode_frame(&ecodec, frame_to_encode, frame_in, writer, test_decode,
+ &dcodec, &frame_out, &mismatch_seen, &ext_ref);
frame_in++;
if (mismatch_seen) break;
}
@@ -295,7 +356,7 @@ int main(int argc, char **argv) {
// Flush encoder.
if (!mismatch_seen)
while (encode_frame(&ecodec, NULL, frame_in, writer, test_decode, &dcodec,
- &frame_out, &mismatch_seen)) {
+ &frame_out, &mismatch_seen, NULL)) {
}
printf("\n");
@@ -313,6 +374,8 @@ int main(int argc, char **argv) {
if (aom_codec_destroy(&dcodec))
die_codec(&dcodec, "Failed to destroy decoder");
+ if (allocated_raw_shift) aom_img_free(&raw_shift);
+ aom_img_free(&ext_ref);
aom_img_free(&raw);
if (aom_codec_destroy(&ecodec))
die_codec(&ecodec, "Failed to destroy encoder.");
diff --git a/third_party/aom/examples/decode_to_md5.c b/third_party/aom/examples/decode_to_md5.c
index 5ab253209..bc127b78d 100644
--- a/third_party/aom/examples/decode_to_md5.c
+++ b/third_party/aom/examples/decode_to_md5.c
@@ -34,13 +34,11 @@
#include <stdlib.h>
#include <string.h>
-#include "aom/aomdx.h"
#include "aom/aom_decoder.h"
-
-#include "../md5_utils.h"
-#include "../tools_common.h"
-#include "../video_reader.h"
-#include "./aom_config.h"
+#include "aom/aomdx.h"
+#include "common/md5_utils.h"
+#include "common/tools_common.h"
+#include "common/video_reader.h"
static void get_image_md5(const aom_image_t *img, unsigned char digest[16]) {
int plane, y;
@@ -110,7 +108,7 @@ int main(int argc, char **argv) {
size_t frame_size = 0;
const unsigned char *frame =
aom_video_reader_get_frame(reader, &frame_size);
- if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
+ if (aom_codec_decode(&codec, frame, frame_size, NULL))
die_codec(&codec, "Failed to decode frame");
while ((img = aom_codec_get_frame(&codec, &iter)) != NULL) {
diff --git a/third_party/aom/examples/decode_with_drops.c b/third_party/aom/examples/decode_with_drops.c
index 45e0fb027..214401958 100644
--- a/third_party/aom/examples/decode_with_drops.c
+++ b/third_party/aom/examples/decode_with_drops.c
@@ -57,12 +57,10 @@
#include <stdlib.h>
#include <string.h>
-#include "aom/aomdx.h"
#include "aom/aom_decoder.h"
-
-#include "../tools_common.h"
-#include "../video_reader.h"
-#include "./aom_config.h"
+#include "aom/aomdx.h"
+#include "common/tools_common.h"
+#include "common/video_reader.h"
static const char *exec_name;
@@ -116,9 +114,6 @@ int main(int argc, char **argv) {
int skip;
const unsigned char *frame =
aom_video_reader_get_frame(reader, &frame_size);
- if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
- die_codec(&codec, "Failed to decode frame.");
-
++frame_cnt;
skip = (is_range && frame_cnt >= n && frame_cnt <= m) ||
@@ -126,6 +121,8 @@ int main(int argc, char **argv) {
if (!skip) {
putc('.', stdout);
+ if (aom_codec_decode(&codec, frame, frame_size, NULL))
+ die_codec(&codec, "Failed to decode frame.");
while ((img = aom_codec_get_frame(&codec, &iter)) != NULL)
aom_img_write(img, outfile);
diff --git a/third_party/aom/examples/encoder_util.c b/third_party/aom/examples/encoder_util.c
index 1aa3a7eef..e43b37250 100644
--- a/third_party/aom/examples/encoder_util.c
+++ b/third_party/aom/examples/encoder_util.c
@@ -11,10 +11,11 @@
// Utility functions used by encoder binaries.
+#include "examples/encoder_util.h"
+
#include <assert.h>
#include <string.h>
-#include "./encoder_util.h"
#include "aom/aom_integer.h"
#define mmin(a, b) ((a) < (b) ? (a) : (b))
@@ -40,6 +41,7 @@ static void find_mismatch_plane(const aom_image_t *const img1,
assert(img1->x_chroma_shift == img2->x_chroma_shift &&
img1->y_chroma_shift == img2->y_chroma_shift);
loc[0] = loc[1] = loc[2] = loc[3] = -1;
+ if (img1->monochrome && img2->monochrome && plane) return;
int match = 1;
uint32_t i, j;
for (i = 0; match && i < c_h; i += bsizey) {
@@ -79,21 +81,16 @@ static void find_mismatch_helper(const aom_image_t *const img1,
const aom_image_t *const img2,
int use_highbitdepth, int yloc[4], int uloc[4],
int vloc[4]) {
-#if !CONFIG_HIGHBITDEPTH
- assert(!use_highbitdepth);
-#endif // !CONFIG_HIGHBITDEPTH
find_mismatch_plane(img1, img2, AOM_PLANE_Y, use_highbitdepth, yloc);
find_mismatch_plane(img1, img2, AOM_PLANE_U, use_highbitdepth, uloc);
find_mismatch_plane(img1, img2, AOM_PLANE_V, use_highbitdepth, vloc);
}
-#if CONFIG_HIGHBITDEPTH
void aom_find_mismatch_high(const aom_image_t *const img1,
const aom_image_t *const img2, int yloc[4],
int uloc[4], int vloc[4]) {
find_mismatch_helper(img1, img2, 1, yloc, uloc, vloc);
}
-#endif
void aom_find_mismatch(const aom_image_t *const img1,
const aom_image_t *const img2, int yloc[4], int uloc[4],
@@ -103,37 +100,37 @@ void aom_find_mismatch(const aom_image_t *const img1,
int aom_compare_img(const aom_image_t *const img1,
const aom_image_t *const img2) {
+ assert(img1->cp == img2->cp);
+ assert(img1->tc == img2->tc);
+ assert(img1->mc == img2->mc);
+ assert(img1->monochrome == img2->monochrome);
+
+ int num_planes = img1->monochrome ? 1 : 3;
+
uint32_t l_w = img1->d_w;
uint32_t c_w = (img1->d_w + img1->x_chroma_shift) >> img1->x_chroma_shift;
const uint32_t c_h =
(img1->d_h + img1->y_chroma_shift) >> img1->y_chroma_shift;
- uint32_t i;
int match = 1;
match &= (img1->fmt == img2->fmt);
match &= (img1->d_w == img2->d_w);
match &= (img1->d_h == img2->d_h);
-#if CONFIG_HIGHBITDEPTH
if (img1->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
l_w *= 2;
c_w *= 2;
}
-#endif
-
- for (i = 0; i < img1->d_h; ++i)
- match &= (memcmp(img1->planes[AOM_PLANE_Y] + i * img1->stride[AOM_PLANE_Y],
- img2->planes[AOM_PLANE_Y] + i * img2->stride[AOM_PLANE_Y],
- l_w) == 0);
-
- for (i = 0; i < c_h; ++i)
- match &= (memcmp(img1->planes[AOM_PLANE_U] + i * img1->stride[AOM_PLANE_U],
- img2->planes[AOM_PLANE_U] + i * img2->stride[AOM_PLANE_U],
- c_w) == 0);
-
- for (i = 0; i < c_h; ++i)
- match &= (memcmp(img1->planes[AOM_PLANE_V] + i * img1->stride[AOM_PLANE_V],
- img2->planes[AOM_PLANE_V] + i * img2->stride[AOM_PLANE_V],
- c_w) == 0);
+
+ for (int plane = 0; plane < num_planes; ++plane) {
+ uint32_t height = plane ? c_h : img1->d_h;
+ uint32_t width = plane ? c_w : l_w;
+
+ for (uint32_t i = 0; i < height; ++i) {
+ match &=
+ (memcmp(img1->planes[plane] + i * img1->stride[plane],
+ img2->planes[plane] + i * img2->stride[plane], width) == 0);
+ }
+ }
return match;
}
diff --git a/third_party/aom/examples/encoder_util.h b/third_party/aom/examples/encoder_util.h
index 38deef03d..966f5e004 100644
--- a/third_party/aom/examples/encoder_util.h
+++ b/third_party/aom/examples/encoder_util.h
@@ -14,16 +14,13 @@
#ifndef EXAMPLES_ENCODER_UTIL_H_
#define EXAMPLES_ENCODER_UTIL_H_
-#include "./aom_config.h"
#include "aom/aom_image.h"
// Returns mismatch location (?loc[0],?loc[1]) and the values at that location
// in img1 (?loc[2]) and img2 (?loc[3]).
-#if CONFIG_HIGHBITDEPTH
void aom_find_mismatch_high(const aom_image_t *const img1,
const aom_image_t *const img2, int yloc[4],
int uloc[4], int vloc[4]);
-#endif // CONFIG_HIGHBITDEPTH
void aom_find_mismatch(const aom_image_t *const img1,
const aom_image_t *const img2, int yloc[4], int uloc[4],
diff --git a/third_party/aom/examples/inspect.c b/third_party/aom/examples/inspect.c
index 74e770b84..4887fc4a3 100644
--- a/third_party/aom/examples/inspect.c
+++ b/third_party/aom/examples/inspect.c
@@ -19,27 +19,27 @@
#include <stdlib.h>
#include <string.h>
-#include "./args.h"
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#else
#define EMSCRIPTEN_KEEPALIVE
#endif
+#include "config/aom_config.h"
+
#include "aom/aom_decoder.h"
-#include "./aom_config.h"
-#if CONFIG_ACCOUNTING
-#include "../av1/decoder/accounting.h"
-#endif
-#include "../av1/decoder/inspection.h"
#include "aom/aomdx.h"
+#include "av1/common/onyxc_int.h"
-#include "../tools_common.h"
-#include "../video_reader.h"
-// #include "av1/av1_dx_iface.c"
-#include "../av1/common/onyxc_int.h"
+#if CONFIG_ACCOUNTING
+#include "av1/decoder/accounting.h"
+#endif
-#include "../video_common.h"
+#include "av1/decoder/inspection.h"
+#include "common/args.h"
+#include "common/tools_common.h"
+#include "common/video_common.h"
+#include "common/video_reader.h"
// Max JSON buffer size.
const int MAX_BUFFER = 1024 * 1024 * 32;
@@ -57,7 +57,10 @@ typedef enum {
MOTION_VECTORS_LAYER = 1 << 9,
UV_MODE_LAYER = 1 << 10,
CFL_LAYER = 1 << 11,
- ALL_LAYERS = (1 << 12) - 1
+ DUAL_FILTER_LAYER = 1 << 12,
+ Q_INDEX_LAYER = 1 << 13,
+ SEGMENT_ID_LAYER = 1 << 14,
+ ALL_LAYERS = (1 << 15) - 1
} LayerType;
static LayerType layers = 0;
@@ -87,12 +90,16 @@ static const arg_def_t dump_skip_arg = ARG_DEF("s", "skip", 0, "Dump Skip");
static const arg_def_t dump_filter_arg =
ARG_DEF("f", "filter", 0, "Dump Filter");
static const arg_def_t dump_cdef_arg = ARG_DEF("c", "cdef", 0, "Dump CDEF");
-#if CONFIG_CFL
static const arg_def_t dump_cfl_arg =
ARG_DEF("cfl", "chroma_from_luma", 0, "Dump Chroma from Luma Alphas");
-#endif
+static const arg_def_t dump_dual_filter_type_arg =
+ ARG_DEF("df", "dualFilterType", 0, "Dump Dual Filter Type");
static const arg_def_t dump_reference_frame_arg =
ARG_DEF("r", "referenceFrame", 0, "Dump Reference Frame");
+static const arg_def_t dump_delta_q_arg =
+ ARG_DEF("dq", "delta_q", 0, "Dump QIndex");
+static const arg_def_t dump_seg_id_arg =
+ ARG_DEF("si", "seg_id", 0, "Dump Segment ID");
static const arg_def_t usage_arg = ARG_DEF("h", "help", 0, "Help");
static const arg_def_t *main_args[] = { &limit_arg,
@@ -108,14 +115,13 @@ static const arg_def_t *main_args[] = { &limit_arg,
&dump_uv_mode_arg,
&dump_skip_arg,
&dump_filter_arg,
-#if CONFIG_CDEF
&dump_cdef_arg,
-#endif
-#if CONFIG_CFL
+ &dump_dual_filter_type_arg,
&dump_cfl_arg,
-#endif
&dump_reference_frame_arg,
&dump_motion_vectors_arg,
+ &dump_delta_q_arg,
+ &dump_seg_id_arg,
&usage_arg,
NULL };
#define ENUM(name) \
@@ -127,58 +133,35 @@ typedef struct map_entry {
int value;
} map_entry;
-const map_entry refs_map[] = { ENUM(INTRA_FRAME), ENUM(LAST_FRAME),
-#if CONFIG_EXT_REFS
- ENUM(LAST2_FRAME), ENUM(LAST3_FRAME),
- ENUM(GOLDEN_FRAME), ENUM(BWDREF_FRAME),
- ENUM(ALTREF_FRAME),
-#else
- ENUM(GOLDEN_FRAME), ENUM(ALTREF_FRAME),
-#endif
- LAST_ENUM };
+const map_entry refs_map[] = {
+ ENUM(INTRA_FRAME), ENUM(LAST_FRAME), ENUM(LAST2_FRAME),
+ ENUM(LAST3_FRAME), ENUM(GOLDEN_FRAME), ENUM(BWDREF_FRAME),
+ ENUM(ALTREF2_FRAME), ENUM(ALTREF_FRAME), LAST_ENUM
+};
const map_entry block_size_map[] = {
-#if CONFIG_CHROMA_2X2 || CONFIG_CHROMA_SUB8X8
- ENUM(BLOCK_2X2), ENUM(BLOCK_2X4), ENUM(BLOCK_4X2),
-#endif
- ENUM(BLOCK_4X4), ENUM(BLOCK_4X8), ENUM(BLOCK_8X4),
- ENUM(BLOCK_8X8), ENUM(BLOCK_8X16), ENUM(BLOCK_16X8),
- ENUM(BLOCK_16X16), ENUM(BLOCK_16X32), ENUM(BLOCK_32X16),
- ENUM(BLOCK_32X32), ENUM(BLOCK_32X64), ENUM(BLOCK_64X32),
- ENUM(BLOCK_64X64),
-#if CONFIG_EXT_PARTITION
- ENUM(BLOCK_64X128), ENUM(BLOCK_128X64), ENUM(BLOCK_128X128),
-#endif
- ENUM(BLOCK_4X16), ENUM(BLOCK_16X4), ENUM(BLOCK_8X32),
- ENUM(BLOCK_32X8), ENUM(BLOCK_16X64), ENUM(BLOCK_64X16),
-#if CONFIG_EXT_PARTITION
- ENUM(BLOCK_32X128), ENUM(BLOCK_128X32),
-#endif
- LAST_ENUM
+ ENUM(BLOCK_4X4), ENUM(BLOCK_4X8), ENUM(BLOCK_8X4),
+ ENUM(BLOCK_8X8), ENUM(BLOCK_8X16), ENUM(BLOCK_16X8),
+ ENUM(BLOCK_16X16), ENUM(BLOCK_16X32), ENUM(BLOCK_32X16),
+ ENUM(BLOCK_32X32), ENUM(BLOCK_32X64), ENUM(BLOCK_64X32),
+ ENUM(BLOCK_64X64), ENUM(BLOCK_64X128), ENUM(BLOCK_128X64),
+ ENUM(BLOCK_128X128), ENUM(BLOCK_4X16), ENUM(BLOCK_16X4),
+ ENUM(BLOCK_8X32), ENUM(BLOCK_32X8), ENUM(BLOCK_16X64),
+ ENUM(BLOCK_64X16), LAST_ENUM
};
const map_entry tx_size_map[] = {
-#if CONFIG_CHROMA_2X2
- ENUM(TX_2X2),
-#endif
ENUM(TX_4X4), ENUM(TX_8X8), ENUM(TX_16X16), ENUM(TX_32X32),
-#if CONFIG_TX64X64
- ENUM(TX_64X64),
-#endif
- ENUM(TX_4X8), ENUM(TX_8X4), ENUM(TX_8X16), ENUM(TX_16X8),
- ENUM(TX_16X32), ENUM(TX_32X16),
-#if CONFIG_TX64X64
- ENUM(TX_32X64), ENUM(TX_64X32),
-#endif // CONFIG_TX64X64
- ENUM(TX_4X16), ENUM(TX_16X4), ENUM(TX_8X32), ENUM(TX_32X8),
- LAST_ENUM
+ ENUM(TX_64X64), ENUM(TX_4X8), ENUM(TX_8X4), ENUM(TX_8X16),
+ ENUM(TX_16X8), ENUM(TX_16X32), ENUM(TX_32X16), ENUM(TX_32X64),
+ ENUM(TX_64X32), ENUM(TX_4X16), ENUM(TX_16X4), ENUM(TX_8X32),
+ ENUM(TX_32X8), LAST_ENUM
};
const map_entry tx_type_map[] = { ENUM(DCT_DCT),
ENUM(ADST_DCT),
ENUM(DCT_ADST),
ENUM(ADST_ADST),
-#if CONFIG_EXT_TX
ENUM(FLIPADST_DCT),
ENUM(DCT_FLIPADST),
ENUM(FLIPADST_FLIPADST),
@@ -191,43 +174,35 @@ const map_entry tx_type_map[] = { ENUM(DCT_DCT),
ENUM(H_ADST),
ENUM(V_FLIPADST),
ENUM(H_FLIPADST),
-#endif
LAST_ENUM };
+const map_entry dual_filter_map[] = { ENUM(REG_REG), ENUM(REG_SMOOTH),
+ ENUM(REG_SHARP), ENUM(SMOOTH_REG),
+ ENUM(SMOOTH_SMOOTH), ENUM(SMOOTH_SHARP),
+ ENUM(SHARP_REG), ENUM(SHARP_SMOOTH),
+ ENUM(SHARP_SHARP), LAST_ENUM };
const map_entry prediction_mode_map[] = {
- ENUM(DC_PRED), ENUM(V_PRED), ENUM(H_PRED),
- ENUM(D45_PRED), ENUM(D135_PRED), ENUM(D117_PRED),
- ENUM(D153_PRED), ENUM(D207_PRED), ENUM(D63_PRED),
- ENUM(SMOOTH_PRED),
-#if CONFIG_SMOOTH_HV
- ENUM(SMOOTH_V_PRED), ENUM(SMOOTH_H_PRED),
-#endif // CONFIG_SMOOTH_HV
- ENUM(TM_PRED), ENUM(NEARESTMV), ENUM(NEARMV),
- ENUM(ZEROMV), ENUM(NEWMV), ENUM(NEAREST_NEARESTMV),
- ENUM(NEAR_NEARMV), ENUM(NEAREST_NEWMV), ENUM(NEW_NEARESTMV),
- ENUM(NEAR_NEWMV), ENUM(NEW_NEARMV), ENUM(ZERO_ZEROMV),
- ENUM(NEW_NEWMV), ENUM(INTRA_INVALID), LAST_ENUM
+ ENUM(DC_PRED), ENUM(V_PRED), ENUM(H_PRED),
+ ENUM(D45_PRED), ENUM(D135_PRED), ENUM(D113_PRED),
+ ENUM(D157_PRED), ENUM(D203_PRED), ENUM(D67_PRED),
+ ENUM(SMOOTH_PRED), ENUM(SMOOTH_V_PRED), ENUM(SMOOTH_H_PRED),
+ ENUM(PAETH_PRED), ENUM(NEARESTMV), ENUM(NEARMV),
+ ENUM(GLOBALMV), ENUM(NEWMV), ENUM(NEAREST_NEARESTMV),
+ ENUM(NEAR_NEARMV), ENUM(NEAREST_NEWMV), ENUM(NEW_NEARESTMV),
+ ENUM(NEAR_NEWMV), ENUM(NEW_NEARMV), ENUM(GLOBAL_GLOBALMV),
+ ENUM(NEW_NEWMV), ENUM(INTRA_INVALID), LAST_ENUM
};
-#if CONFIG_CFL
const map_entry uv_prediction_mode_map[] = {
ENUM(UV_DC_PRED), ENUM(UV_V_PRED),
ENUM(UV_H_PRED), ENUM(UV_D45_PRED),
- ENUM(UV_D135_PRED), ENUM(UV_D117_PRED),
- ENUM(UV_D153_PRED), ENUM(UV_D207_PRED),
- ENUM(UV_D63_PRED), ENUM(UV_SMOOTH_PRED),
-#if CONFIG_SMOOTH_HV
+ ENUM(UV_D135_PRED), ENUM(UV_D113_PRED),
+ ENUM(UV_D157_PRED), ENUM(UV_D203_PRED),
+ ENUM(UV_D67_PRED), ENUM(UV_SMOOTH_PRED),
ENUM(UV_SMOOTH_V_PRED), ENUM(UV_SMOOTH_H_PRED),
-#endif // CONFIG_SMOOTH_HV
- ENUM(UV_TM_PRED),
-#if CONFIG_CFL
- ENUM(UV_CFL_PRED),
-#endif
+ ENUM(UV_PAETH_PRED), ENUM(UV_CFL_PRED),
ENUM(UV_MODE_INVALID), LAST_ENUM
};
-#else
-#define uv_prediction_mode_map prediction_mode_map
-#endif
#define NO_SKIP 0
#define SKIP 1
@@ -327,7 +302,7 @@ int put_map(char *buffer, const map_entry *map) {
*(buf++) = ',';
}
}
- return buf - buffer;
+ return (int)(buf - buffer);
}
int put_reference_frame(char *buffer) {
@@ -365,7 +340,7 @@ int put_reference_frame(char *buffer) {
if (r < mi_rows - 1) *(buf++) = ',';
}
buf += put_str(buf, "],\n");
- return buf - buffer;
+ return (int)(buf - buffer);
}
int put_motion_vectors(char *buffer) {
@@ -404,15 +379,19 @@ int put_motion_vectors(char *buffer) {
if (r < mi_rows - 1) *(buf++) = ',';
}
buf += put_str(buf, "],\n");
- return buf - buffer;
+ return (int)(buf - buffer);
}
int put_block_info(char *buffer, const map_entry *map, const char *name,
- size_t offset) {
+ size_t offset, int len) {
const int mi_rows = frame_data.mi_rows;
const int mi_cols = frame_data.mi_cols;
char *buf = buffer;
- int r, c, t, v;
+ int r, c, t, i;
+ if (compress && len == 1) {
+ die("Can't encode scalars as arrays when RLE compression is enabled.");
+ return -1;
+ }
if (map) {
buf += snprintf(buf, MAX_BUFFER, " \"%sMap\": {", name);
buf += put_map(buf, map);
@@ -422,13 +401,36 @@ int put_block_info(char *buffer, const map_entry *map, const char *name,
for (r = 0; r < mi_rows; ++r) {
*(buf++) = '[';
for (c = 0; c < mi_cols; ++c) {
- insp_mi_data *curr_mi = &frame_data.mi_grid[r * mi_cols + c];
- v = *(((int8_t *)curr_mi) + offset);
- buf += put_num(buf, 0, v, 0);
+ insp_mi_data *mi = &frame_data.mi_grid[r * mi_cols + c];
+ int16_t *v = (int16_t *)(((int8_t *)mi) + offset);
+ if (len == 0) {
+ buf += put_num(buf, 0, v[0], 0);
+ } else {
+ buf += put_str(buf, "[");
+ for (i = 0; i < len; i++) {
+ buf += put_num(buf, 0, v[i], 0);
+ if (i < len - 1) {
+ buf += put_str(buf, ",");
+ }
+ }
+ buf += put_str(buf, "]");
+ }
if (compress) { // RLE
for (t = c + 1; t < mi_cols; ++t) {
insp_mi_data *next_mi = &frame_data.mi_grid[r * mi_cols + t];
- if (v != *(((int8_t *)next_mi) + offset)) {
+ int16_t *nv = (int16_t *)(((int8_t *)next_mi) + offset);
+ int same = 0;
+ if (len == 0) {
+ same = v[0] == nv[0];
+ } else {
+ for (i = 0; i < len; i++) {
+ same = v[i] == nv[i];
+ if (!same) {
+ break;
+ }
+ }
+ }
+ if (!same) {
break;
}
}
@@ -444,7 +446,7 @@ int put_block_info(char *buffer, const map_entry *map, const char *name,
if (r < mi_rows - 1) *(buf++) = ',';
}
buf += put_str(buf, "],\n");
- return buf - buffer;
+ return (int)(buf - buffer);
}
#if CONFIG_ACCOUNTING
@@ -484,7 +486,7 @@ int put_accounting(char *buffer) {
if (i < num_syms - 1) *(buf++) = ',';
}
buf += put_str(buf, "],\n");
- return buf - buffer;
+ return (int)(buf - buffer);
}
#endif
@@ -499,51 +501,62 @@ void inspect(void *pbi, void *data) {
buf += put_str(buf, "{\n");
if (layers & BLOCK_SIZE_LAYER) {
buf += put_block_info(buf, block_size_map, "blockSize",
- offsetof(insp_mi_data, sb_type));
+ offsetof(insp_mi_data, sb_type), 0);
}
if (layers & TRANSFORM_SIZE_LAYER) {
buf += put_block_info(buf, tx_size_map, "transformSize",
- offsetof(insp_mi_data, tx_size));
+ offsetof(insp_mi_data, tx_size), 0);
}
if (layers & TRANSFORM_TYPE_LAYER) {
buf += put_block_info(buf, tx_type_map, "transformType",
- offsetof(insp_mi_data, tx_type));
+ offsetof(insp_mi_data, tx_type), 0);
+ }
+ if (layers & DUAL_FILTER_LAYER) {
+ buf += put_block_info(buf, dual_filter_map, "dualFilterType",
+ offsetof(insp_mi_data, dual_filter_type), 0);
}
if (layers & MODE_LAYER) {
buf += put_block_info(buf, prediction_mode_map, "mode",
- offsetof(insp_mi_data, mode));
+ offsetof(insp_mi_data, mode), 0);
}
if (layers & UV_MODE_LAYER) {
buf += put_block_info(buf, uv_prediction_mode_map, "uv_mode",
- offsetof(insp_mi_data, uv_mode));
+ offsetof(insp_mi_data, uv_mode), 0);
}
if (layers & SKIP_LAYER) {
- buf += put_block_info(buf, skip_map, "skip", offsetof(insp_mi_data, skip));
+ buf +=
+ put_block_info(buf, skip_map, "skip", offsetof(insp_mi_data, skip), 0);
}
if (layers & FILTER_LAYER) {
- buf += put_block_info(buf, NULL, "filter", offsetof(insp_mi_data, filter));
+ buf +=
+ put_block_info(buf, NULL, "filter", offsetof(insp_mi_data, filter), 2);
}
-#if CONFIG_CDEF
if (layers & CDEF_LAYER) {
buf += put_block_info(buf, NULL, "cdef_level",
- offsetof(insp_mi_data, cdef_level));
+ offsetof(insp_mi_data, cdef_level), 0);
buf += put_block_info(buf, NULL, "cdef_strength",
- offsetof(insp_mi_data, cdef_strength));
+ offsetof(insp_mi_data, cdef_strength), 0);
}
-#endif
-#if CONFIG_CFL
if (layers & CFL_LAYER) {
buf += put_block_info(buf, NULL, "cfl_alpha_idx",
- offsetof(insp_mi_data, cfl_alpha_idx));
+ offsetof(insp_mi_data, cfl_alpha_idx), 0);
buf += put_block_info(buf, NULL, "cfl_alpha_sign",
- offsetof(insp_mi_data, cfl_alpha_sign));
+ offsetof(insp_mi_data, cfl_alpha_sign), 0);
+ }
+ if (layers & Q_INDEX_LAYER) {
+ buf += put_block_info(buf, NULL, "delta_q",
+ offsetof(insp_mi_data, current_qindex), 0);
+ }
+ if (layers & SEGMENT_ID_LAYER) {
+ buf += put_block_info(buf, NULL, "seg_id",
+ offsetof(insp_mi_data, segment_id), 0);
}
-#endif
if (layers & MOTION_VECTORS_LAYER) {
buf += put_motion_vectors(buf);
}
if (layers & REFERENCE_FRAME_LAYER) {
- buf += put_reference_frame(buf);
+ buf += put_block_info(buf, refs_map, "referenceFrame",
+ offsetof(insp_mi_data, ref_frame), 2);
}
#if CONFIG_ACCOUNTING
if (layers & ACCOUNTING_LAYER) {
@@ -561,6 +574,10 @@ void inspect(void *pbi, void *data) {
frame_data.tile_mi_cols);
buf += snprintf(buf, MAX_BUFFER, " \"tileRows\": %d,\n",
frame_data.tile_mi_rows);
+ buf += snprintf(buf, MAX_BUFFER, " \"deltaQPresentFlag\": %d,\n",
+ frame_data.delta_q_present_flag);
+ buf += snprintf(buf, MAX_BUFFER, " \"deltaQRes\": %d,\n",
+ frame_data.delta_q_res);
buf += put_str(buf, " \"config\": {");
buf += put_map(buf, config_map);
buf += put_str(buf, "},\n");
@@ -608,15 +625,18 @@ int read_frame() {
aom_codec_iter_t iter = NULL;
size_t frame_size = 0;
const unsigned char *frame = aom_video_reader_get_frame(reader, &frame_size);
- if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0) !=
+ if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, NULL) !=
AOM_CODEC_OK) {
die_codec(&codec, "Failed to decode frame.");
}
- img = aom_codec_get_frame(&codec, &iter);
- if (img == NULL) {
+ int got_any_frames = 0;
+ while ((img = aom_codec_get_frame(&codec, &iter))) {
+ ++frame_count;
+ got_any_frames = 1;
+ }
+ if (!got_any_frames) {
return EXIT_FAILURE;
}
- ++frame_count;
return EXIT_SUCCESS;
}
@@ -674,18 +694,20 @@ static void parse_args(char **argv) {
layers |= SKIP_LAYER;
else if (arg_match(&arg, &dump_filter_arg, argi))
layers |= FILTER_LAYER;
-#if CONFIG_CDEF
else if (arg_match(&arg, &dump_cdef_arg, argi))
layers |= CDEF_LAYER;
-#endif
-#if CONFIG_CFL
else if (arg_match(&arg, &dump_cfl_arg, argi))
layers |= CFL_LAYER;
-#endif
else if (arg_match(&arg, &dump_reference_frame_arg, argi))
layers |= REFERENCE_FRAME_LAYER;
else if (arg_match(&arg, &dump_motion_vectors_arg, argi))
layers |= MOTION_VECTORS_LAYER;
+ else if (arg_match(&arg, &dump_dual_filter_type_arg, argi))
+ layers |= DUAL_FILTER_LAYER;
+ else if (arg_match(&arg, &dump_delta_q_arg, argi))
+ layers |= Q_INDEX_LAYER;
+ else if (arg_match(&arg, &dump_seg_id_arg, argi))
+ layers |= SEGMENT_ID_LAYER;
else if (arg_match(&arg, &dump_all_arg, argi))
layers |= ALL_LAYERS;
else if (arg_match(&arg, &compress_arg, argi))
diff --git a/third_party/aom/examples/lightfield_bitstream_parsing.c b/third_party/aom/examples/lightfield_bitstream_parsing.c
new file mode 100644
index 000000000..d13f3f172
--- /dev/null
+++ b/third_party/aom/examples/lightfield_bitstream_parsing.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// Lightfield Bitstream Parsing
+// ============================
+//
+// This is an lightfield bitstream parsing example. It takes an input file
+// containing the whole compressed lightfield bitstream(ivf file), and parses it
+// and constructs and outputs a new bitstream that can be decoded by an AV1
+// decoder. The output bitstream contains tile list OBUs. The lf_width and
+// lf_height arguments are the number of lightfield images in each dimension.
+// The lf_blocksize determines the number of reference images used.
+// After running the lightfield encoder, run lightfield bitstream parsing:
+// examples/lightfield_bitstream_parsing vase10x10.ivf vase_tile_list.ivf 10 10
+// 5
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "aom/aom_decoder.h"
+#include "aom/aom_encoder.h"
+#include "aom/aom_integer.h"
+#include "aom/aomdx.h"
+#include "aom_dsp/bitwriter_buffer.h"
+#include "common/tools_common.h"
+#include "common/video_reader.h"
+#include "common/video_writer.h"
+
+static const char *exec_name;
+
+void usage_exit(void) {
+ fprintf(
+ stderr,
+ "Usage: %s <infile> <outfile> <lf_width> <lf_height> <lf_blocksize> \n",
+ exec_name);
+ exit(EXIT_FAILURE);
+}
+
+#define ALIGN_POWER_OF_TWO(value, n) \
+ (((value) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1))
+
+// SB size: 64x64
+const uint8_t output_frame_width_in_tiles_minus_1 = 512 / 64 - 1;
+const uint8_t output_frame_height_in_tiles_minus_1 = 512 / 64 - 1;
+
+// Spec:
+// typedef struct {
+// uint8_t anchor_frame_idx;
+// uint8_t tile_row;
+// uint8_t tile_col;
+// uint16_t coded_tile_data_size_minus_1;
+// uint8_t *coded_tile_data;
+// } TILE_LIST_ENTRY;
+
+// Tile list entry provided by the application
+typedef struct {
+ int image_idx;
+ int reference_idx;
+ int tile_col;
+ int tile_row;
+} TILE_LIST_INFO;
+
+// M references: 0 - M-1; N images(including references): 0 - N-1;
+// Note: order the image index incrementally, so that we only go through the
+// bitstream once to construct the tile list.
+const int num_tile_lists = 2;
+const uint16_t tile_count_minus_1 = 9 - 1;
+const TILE_LIST_INFO tile_list[2][9] = {
+ { { 16, 0, 4, 5 },
+ { 83, 3, 13, 2 },
+ { 57, 2, 2, 6 },
+ { 31, 1, 11, 5 },
+ { 2, 0, 7, 4 },
+ { 77, 3, 9, 9 },
+ { 49, 1, 0, 1 },
+ { 6, 0, 3, 10 },
+ { 63, 2, 5, 8 } },
+ { { 65, 2, 11, 1 },
+ { 42, 1, 3, 7 },
+ { 88, 3, 8, 4 },
+ { 76, 3, 1, 15 },
+ { 1, 0, 2, 2 },
+ { 19, 0, 5, 6 },
+ { 60, 2, 4, 0 },
+ { 25, 1, 11, 15 },
+ { 50, 2, 5, 4 } },
+};
+
+int main(int argc, char **argv) {
+ aom_codec_ctx_t codec;
+ AvxVideoReader *reader = NULL;
+ AvxVideoWriter *writer = NULL;
+ const AvxInterface *decoder = NULL;
+ const AvxVideoInfo *info = NULL;
+ const char *lf_width_arg;
+ const char *lf_height_arg;
+ const char *lf_blocksize_arg;
+ int width, height;
+ int lf_width, lf_height;
+ int lf_blocksize;
+ int u_blocks, v_blocks;
+ int n, i;
+ aom_codec_pts_t pts;
+
+ exec_name = argv[0];
+ if (argc != 6) die("Invalid number of arguments.");
+
+ reader = aom_video_reader_open(argv[1]);
+ if (!reader) die("Failed to open %s for reading.", argv[1]);
+
+ lf_width_arg = argv[3];
+ lf_height_arg = argv[4];
+ lf_blocksize_arg = argv[5];
+
+ lf_width = (int)strtol(lf_width_arg, NULL, 0);
+ lf_height = (int)strtol(lf_height_arg, NULL, 0);
+ lf_blocksize = (int)strtol(lf_blocksize_arg, NULL, 0);
+
+ info = aom_video_reader_get_info(reader);
+ width = info->frame_width;
+ height = info->frame_height;
+
+ // The writer to write out ivf file in tile list OBU, which can be decoded by
+ // AV1 decoder.
+ writer = aom_video_writer_open(argv[2], kContainerIVF, info);
+ if (!writer) die("Failed to open %s for writing", argv[2]);
+
+ decoder = get_aom_decoder_by_fourcc(info->codec_fourcc);
+ if (!decoder) die("Unknown input codec.");
+ printf("Using %s\n", aom_codec_iface_name(decoder->codec_interface()));
+
+ if (aom_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
+ die_codec(&codec, "Failed to initialize decoder.");
+
+ // Decode anchor frames.
+ aom_codec_control_(&codec, AV1_SET_TILE_MODE, 0);
+
+ // How many anchor frames we have.
+ u_blocks = (lf_width + lf_blocksize - 1) / lf_blocksize;
+ v_blocks = (lf_height + lf_blocksize - 1) / lf_blocksize;
+
+ int num_references = v_blocks * u_blocks;
+ for (i = 0; i < num_references; ++i) {
+ aom_video_reader_read_frame(reader);
+
+ size_t frame_size = 0;
+ const unsigned char *frame =
+ aom_video_reader_get_frame(reader, &frame_size);
+ pts = (aom_codec_pts_t)aom_video_reader_get_frame_pts(reader);
+
+ // Copy references bitstream directly.
+ if (!aom_video_writer_write_frame(writer, frame, frame_size, pts))
+ die_codec(&codec, "Failed to copy compressed anchor frame.");
+
+ if (aom_codec_decode(&codec, frame, frame_size, NULL))
+ die_codec(&codec, "Failed to decode frame.");
+ }
+
+ // Decode camera frames.
+ aom_codec_control_(&codec, AV1_SET_TILE_MODE, 1);
+ aom_codec_control_(&codec, AV1D_EXT_TILE_DEBUG, 1);
+
+ FILE *infile = aom_video_reader_get_file(reader);
+ // Record the offset of the first camera image.
+ const FileOffset camera_frame_pos = ftello(infile);
+
+ // Read out the first camera frame.
+ aom_video_reader_read_frame(reader);
+
+ // Copy first camera frame for getting camera frame header. This is done
+ // only once.
+ {
+ size_t frame_size = 0;
+ const unsigned char *frame =
+ aom_video_reader_get_frame(reader, &frame_size);
+ pts = (aom_codec_pts_t)aom_video_reader_get_frame_pts(reader);
+ aom_tile_data frame_header_info = { 0, NULL, 0 };
+
+ // Need to decode frame header to get camera frame header info. So, here
+ // decoding 1 tile is enough.
+ aom_codec_control_(&codec, AV1_SET_DECODE_TILE_ROW, 0);
+ aom_codec_control_(&codec, AV1_SET_DECODE_TILE_COL, 0);
+
+ aom_codec_err_t aom_status =
+ aom_codec_decode(&codec, frame, frame_size, NULL);
+ if (aom_status) die_codec(&codec, "Failed to decode tile.");
+
+ aom_codec_control_(&codec, AV1D_GET_FRAME_HEADER_INFO, &frame_header_info);
+
+ size_t obu_size_offset =
+ (uint8_t *)frame_header_info.coded_tile_data - frame;
+ size_t length_field_size = frame_header_info.coded_tile_data_size;
+ // Remove ext-tile tile info.
+ uint32_t frame_header_size = (uint32_t)frame_header_info.extra_size - 1;
+ size_t bytes_to_copy =
+ obu_size_offset + length_field_size + frame_header_size;
+
+ unsigned char *frame_hdr_buf = (unsigned char *)malloc(bytes_to_copy);
+ if (frame_hdr_buf == NULL)
+ die_codec(&codec, "Failed to allocate frame header buffer.");
+
+ memcpy(frame_hdr_buf, frame, bytes_to_copy);
+
+ // Update frame header OBU size.
+ size_t bytes_written = 0;
+ if (aom_uleb_encode_fixed_size(
+ frame_header_size, length_field_size, length_field_size,
+ frame_hdr_buf + obu_size_offset, &bytes_written))
+ die_codec(&codec, "Failed to encode the tile list obu size.");
+
+ // Copy camera frame header bitstream.
+ if (!aom_video_writer_write_frame(writer, frame_hdr_buf, bytes_to_copy,
+ pts))
+ die_codec(&codec, "Failed to copy compressed camera frame header.");
+ }
+
+ // Allocate a buffer to store tile list bitstream. Image format
+ // AOM_IMG_FMT_I420.
+ size_t data_sz =
+ ALIGN_POWER_OF_TWO(width, 5) * ALIGN_POWER_OF_TWO(height, 5) * 12 / 8;
+ unsigned char *tl_buf = (unsigned char *)malloc(data_sz);
+ if (tl_buf == NULL) die_codec(&codec, "Failed to allocate tile list buffer.");
+
+ aom_codec_pts_t tl_pts = pts;
+
+ // Process 1 tile list.
+ for (n = 0; n < num_tile_lists; n++) {
+ unsigned char *tl = tl_buf;
+ struct aom_write_bit_buffer wb = { tl, 0 };
+ unsigned char *saved_obu_size_loc = NULL;
+ uint32_t tile_list_obu_header_size = 0;
+ uint32_t tile_list_obu_size = 0;
+
+ // Write the tile list OBU header that is 1 byte long.
+ aom_wb_write_literal(&wb, 0, 1); // forbidden bit.
+ aom_wb_write_literal(&wb, 8, 4); // tile list OBU: "1000"
+ aom_wb_write_literal(&wb, 0, 1); // obu_extension = 0
+ aom_wb_write_literal(&wb, 1, 1); // obu_has_size_field
+ aom_wb_write_literal(&wb, 0, 1); // reserved
+ tl++;
+ tile_list_obu_header_size++;
+
+ // Write the OBU size using a fixed length_field_size of 4 bytes.
+ saved_obu_size_loc = tl;
+ aom_wb_write_literal(&wb, 0, 32);
+ tl += 4;
+ tile_list_obu_header_size += 4;
+
+ // write_tile_list_obu()
+ aom_wb_write_literal(&wb, output_frame_width_in_tiles_minus_1, 8);
+ aom_wb_write_literal(&wb, output_frame_height_in_tiles_minus_1, 8);
+ aom_wb_write_literal(&wb, tile_count_minus_1, 16);
+ tl += 4;
+ tile_list_obu_size += 4;
+
+ // Write each tile's data
+ for (i = 0; i <= tile_count_minus_1; i++) {
+ aom_tile_data tile_data = { 0, NULL, 0 };
+
+ int image_idx = tile_list[n][i].image_idx;
+ int ref_idx = tile_list[n][i].reference_idx;
+ int tc = tile_list[n][i].tile_col;
+ int tr = tile_list[n][i].tile_row;
+ int frame_cnt = -1;
+
+ // Reset bit writer to the right location.
+ wb.bit_buffer = tl;
+ wb.bit_offset = 0;
+
+ // Seek to the first camera image.
+ fseeko(infile, camera_frame_pos, SEEK_SET);
+
+ // Read out the camera image
+ while (frame_cnt != image_idx) {
+ aom_video_reader_read_frame(reader);
+ frame_cnt++;
+ }
+
+ size_t frame_size = 0;
+ const unsigned char *frame =
+ aom_video_reader_get_frame(reader, &frame_size);
+
+ aom_codec_control_(&codec, AV1_SET_DECODE_TILE_ROW, tr);
+ aom_codec_control_(&codec, AV1_SET_DECODE_TILE_COL, tc);
+
+ aom_codec_err_t aom_status =
+ aom_codec_decode(&codec, frame, frame_size, NULL);
+ if (aom_status) die_codec(&codec, "Failed to decode tile.");
+
+ aom_codec_control_(&codec, AV1D_GET_TILE_DATA, &tile_data);
+
+ // Copy over tile info.
+ // uint8_t anchor_frame_idx;
+ // uint8_t tile_row;
+ // uint8_t tile_col;
+ // uint16_t coded_tile_data_size_minus_1;
+ // uint8_t *coded_tile_data;
+ uint32_t tile_info_bytes = 5;
+ aom_wb_write_literal(&wb, ref_idx, 8);
+ aom_wb_write_literal(&wb, tr, 8);
+ aom_wb_write_literal(&wb, tc, 8);
+ aom_wb_write_literal(&wb, (int)tile_data.coded_tile_data_size - 1, 16);
+ tl += tile_info_bytes;
+
+ memcpy(tl, (uint8_t *)tile_data.coded_tile_data,
+ tile_data.coded_tile_data_size);
+ tl += tile_data.coded_tile_data_size;
+
+ tile_list_obu_size +=
+ tile_info_bytes + (uint32_t)tile_data.coded_tile_data_size;
+ }
+
+ // Write tile list OBU size.
+ size_t bytes_written = 0;
+ if (aom_uleb_encode_fixed_size(tile_list_obu_size, 4, 4, saved_obu_size_loc,
+ &bytes_written))
+ die_codec(&codec, "Failed to encode the tile list obu size.");
+
+ // Copy the tile list.
+ if (!aom_video_writer_write_frame(
+ writer, tl_buf, tile_list_obu_header_size + tile_list_obu_size,
+ tl_pts))
+ die_codec(&codec, "Failed to copy compressed tile list.");
+
+ tl_pts++;
+ }
+
+ free(tl_buf);
+ if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
+ aom_video_writer_close(writer);
+ aom_video_reader_close(reader);
+
+ return EXIT_SUCCESS;
+}
diff --git a/third_party/aom/examples/lightfield_decoder.c b/third_party/aom/examples/lightfield_decoder.c
index 8743df9bc..625cddcac 100644
--- a/third_party/aom/examples/lightfield_decoder.c
+++ b/third_party/aom/examples/lightfield_decoder.c
@@ -14,14 +14,14 @@
//
// This is an example of a simple lightfield decoder. It builds upon the
// simple_decoder.c example. It takes an input file containing the compressed
-// data (in webm format), treating it as a lightfield instead of a video and
+// data (in ivf format), treating it as a lightfield instead of a video and
// will decode a single lightfield tile. The lf_width and lf_height arguments
// are the number of lightfield images in each dimension. The tile to decode
// is specified by the tile_u, tile_v, tile_s, tile_t arguments. The tile_u,
// tile_v specify the image and tile_s, tile_t specify the tile in the image.
// After running the lightfield encoder, run lightfield decoder to decode a
// single tile:
-// examples/lightfield_decoder vase10x10.webm vase_tile.yuv 10 10 3 4 5 10 5
+// examples/lightfield_decoder vase10x10.ivf vase_reference.yuv 10 10 5
#include <stdio.h>
#include <stdlib.h>
@@ -29,47 +29,57 @@
#include "aom/aom_decoder.h"
#include "aom/aomdx.h"
+#include "common/tools_common.h"
+#include "common/video_reader.h"
-#include "../tools_common.h"
-#include "../video_reader.h"
-#include "./aom_config.h"
+#define MAX_EXTERNAL_REFERENCES 128
+#define AOM_BORDER_IN_PIXELS 288
static const char *exec_name;
void usage_exit(void) {
- fprintf(stderr,
- "Usage: %s <infile> <outfile> <lf_width> <lf_height> <tlie_u>"
- " <tile_v> <tile_s> <tile_t> <lf_blocksize>\n",
- exec_name);
+ fprintf(
+ stderr,
+ "Usage: %s <infile> <outfile> <lf_width> <lf_height> <lf_blocksize>\n",
+ exec_name);
exit(EXIT_FAILURE);
}
-aom_image_t *aom_img_copy(aom_image_t *src, aom_image_t *dst) {
- dst = aom_img_alloc(dst, src->fmt, src->d_w, src->d_h, 16);
-
- int plane;
-
- for (plane = 0; plane < 3; ++plane) {
- uint8_t *src_buf = src->planes[plane];
- const int src_stride = src->stride[plane];
- const int src_w = plane == 0 ? src->d_w : src->d_w >> 1;
- const int src_h = plane == 0 ? src->d_h : src->d_h >> 1;
-
- uint8_t *dst_buf = dst->planes[plane];
- const int dst_stride = dst->stride[plane];
- int y;
-
- for (y = 0; y < src_h; ++y) {
- memcpy(dst_buf, src_buf, src_w);
- src_buf += src_stride;
- dst_buf += dst_stride;
- }
- }
- return dst;
-}
+// Tile list entry provided by the application
+typedef struct {
+ int image_idx;
+ int reference_idx;
+ int tile_col;
+ int tile_row;
+} TILE_LIST_INFO;
+
+// M references: 0 - M-1; N images(including references): 0 - N-1;
+// Note: order the image index incrementally, so that we only go through the
+// bitstream once to construct the tile list.
+const int num_tile_lists = 2;
+const uint16_t tile_count_minus_1 = 9 - 1;
+const TILE_LIST_INFO tile_list[2][9] = {
+ { { 16, 0, 4, 5 },
+ { 83, 3, 13, 2 },
+ { 57, 2, 2, 6 },
+ { 31, 1, 11, 5 },
+ { 2, 0, 7, 4 },
+ { 77, 3, 9, 9 },
+ { 49, 1, 0, 1 },
+ { 6, 0, 3, 10 },
+ { 63, 2, 5, 8 } },
+ { { 65, 2, 11, 1 },
+ { 42, 1, 3, 7 },
+ { 88, 3, 8, 4 },
+ { 76, 3, 1, 15 },
+ { 1, 0, 2, 2 },
+ { 19, 0, 5, 6 },
+ { 60, 2, 4, 0 },
+ { 25, 1, 11, 15 },
+ { 50, 2, 5, 4 } },
+};
int main(int argc, char **argv) {
- int frame_cnt = 0;
FILE *outfile = NULL;
aom_codec_ctx_t codec;
AvxVideoReader *reader = NULL;
@@ -77,20 +87,20 @@ int main(int argc, char **argv) {
const AvxVideoInfo *info = NULL;
const char *lf_width_arg;
const char *lf_height_arg;
- const char *tile_u_arg;
- const char *tile_v_arg;
- const char *tile_s_arg;
- const char *tile_t_arg;
const char *lf_blocksize_arg;
+ int width, height;
int lf_width, lf_height;
- int tile_u, tile_v, tile_s, tile_t;
int lf_blocksize;
int u_blocks;
int v_blocks;
+ aom_image_t reference_images[MAX_EXTERNAL_REFERENCES];
+ size_t frame_size = 0;
+ const unsigned char *frame = NULL;
+ int n, i;
exec_name = argv[0];
- if (argc != 10) die("Invalid number of arguments.");
+ if (argc != 6) die("Invalid number of arguments.");
reader = aom_video_reader_open(argv[1]);
if (!reader) die("Failed to open %s for reading.", argv[1]);
@@ -100,86 +110,113 @@ int main(int argc, char **argv) {
lf_width_arg = argv[3];
lf_height_arg = argv[4];
- tile_u_arg = argv[5];
- tile_v_arg = argv[6];
- tile_s_arg = argv[7];
- tile_t_arg = argv[8];
- lf_blocksize_arg = argv[9];
+ lf_blocksize_arg = argv[5];
lf_width = (int)strtol(lf_width_arg, NULL, 0);
lf_height = (int)strtol(lf_height_arg, NULL, 0);
- tile_u = (int)strtol(tile_u_arg, NULL, 0);
- tile_v = (int)strtol(tile_v_arg, NULL, 0);
- tile_s = (int)strtol(tile_s_arg, NULL, 0);
- tile_t = (int)strtol(tile_t_arg, NULL, 0);
lf_blocksize = (int)strtol(lf_blocksize_arg, NULL, 0);
info = aom_video_reader_get_info(reader);
+ width = info->frame_width;
+ height = info->frame_height;
decoder = get_aom_decoder_by_fourcc(info->codec_fourcc);
if (!decoder) die("Unknown input codec.");
-
printf("Using %s\n", aom_codec_iface_name(decoder->codec_interface()));
if (aom_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
die_codec(&codec, "Failed to initialize decoder.");
- // How many reference images we need to encode.
+ // How many anchor frames we have.
u_blocks = (lf_width + lf_blocksize - 1) / lf_blocksize;
v_blocks = (lf_height + lf_blocksize - 1) / lf_blocksize;
- aom_image_t *reference_images =
- (aom_image_t *)malloc(u_blocks * v_blocks * sizeof(aom_image_t));
- for (int bv = 0; bv < v_blocks; ++bv) {
- for (int bu = 0; bu < u_blocks; ++bu) {
- aom_video_reader_read_frame(reader);
- aom_codec_iter_t iter = NULL;
- aom_image_t *img = NULL;
- size_t frame_size = 0;
- const unsigned char *frame =
- aom_video_reader_get_frame(reader, &frame_size);
- if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
- die_codec(&codec, "Failed to decode frame.");
-
- while ((img = aom_codec_get_frame(&codec, &iter)) != NULL) {
- aom_img_copy(img, &reference_images[bu + bv * u_blocks]);
- char name[1024];
- snprintf(name, sizeof(name), "ref_%d_%d.yuv", bu, bv);
- printf("writing ref image to %s, %d, %d\n", name, img->d_w, img->d_h);
- FILE *ref_file = fopen(name, "wb");
- aom_img_write(img, ref_file);
- fclose(ref_file);
- ++frame_cnt;
- }
+
+ int num_references = v_blocks * u_blocks;
+
+ // Allocate memory to store decoded references.
+ aom_img_fmt_t ref_fmt = AOM_IMG_FMT_I420;
+ if (!CONFIG_LOWBITDEPTH) ref_fmt |= AOM_IMG_FMT_HIGHBITDEPTH;
+ // Allocate memory with the border so that it can be used as a reference.
+ for (i = 0; i < num_references; i++) {
+ unsigned int border = AOM_BORDER_IN_PIXELS;
+ if (!aom_img_alloc_with_border(&reference_images[i], ref_fmt, width, height,
+ 32, 8, border)) {
+ die("Failed to allocate references.");
}
}
- int decode_frame_index = tile_v * lf_width + tile_u;
- do {
+ // Decode anchor frames.
+ aom_codec_control_(&codec, AV1_SET_TILE_MODE, 0);
+
+ for (i = 0; i < num_references; ++i) {
aom_video_reader_read_frame(reader);
- } while (frame_cnt++ != decode_frame_index);
- size_t frame_size = 0;
- const unsigned char *frame = aom_video_reader_get_frame(reader, &frame_size);
-
- int ref_bu = tile_u / lf_blocksize;
- int ref_bv = tile_v / lf_blocksize;
- int ref_bi = ref_bu + ref_bv * u_blocks;
- av1_ref_frame_t ref;
- ref.idx = 0;
- ref.img = reference_images[ref_bi];
- // This is too slow for real lightfield rendering. This copies the
- // reference image bytes. We need a way to just set a pointer
- // in order to make this fast enough.
- if (aom_codec_control(&codec, AV1_SET_REFERENCE, &ref)) {
- die_codec(&codec, "Failed to set reference image.");
+ frame = aom_video_reader_get_frame(reader, &frame_size);
+ if (aom_codec_decode(&codec, frame, frame_size, NULL))
+ die_codec(&codec, "Failed to decode frame.");
+
+ if (aom_codec_control(&codec, AV1_COPY_NEW_FRAME_IMAGE,
+ &reference_images[i]))
+ die_codec(&codec, "Failed to copy decoded reference frame");
+
+ aom_codec_iter_t iter = NULL;
+ aom_image_t *img = NULL;
+ while ((img = aom_codec_get_frame(&codec, &iter)) != NULL) {
+ char name[1024];
+ snprintf(name, sizeof(name), "ref_%d.yuv", i);
+ printf("writing ref image to %s, %d, %d\n", name, img->d_w, img->d_h);
+ FILE *ref_file = fopen(name, "wb");
+ aom_img_write(img, ref_file);
+ fclose(ref_file);
+ }
+ }
+
+ FILE *infile = aom_video_reader_get_file(reader);
+ // Record the offset of the first camera image.
+ const FileOffset camera_frame_pos = ftello(infile);
+
+ // Process 1 tile.
+ for (n = 0; n < num_tile_lists; n++) {
+ for (i = 0; i <= tile_count_minus_1; i++) {
+ int image_idx = tile_list[n][i].image_idx;
+ int ref_idx = tile_list[n][i].reference_idx;
+ int tc = tile_list[n][i].tile_col;
+ int tr = tile_list[n][i].tile_row;
+ int frame_cnt = -1;
+
+ // Seek to the first camera image.
+ fseeko(infile, camera_frame_pos, SEEK_SET);
+
+ // Read out the camera image
+ while (frame_cnt != image_idx) {
+ aom_video_reader_read_frame(reader);
+ frame_cnt++;
+ }
+
+ frame = aom_video_reader_get_frame(reader, &frame_size);
+
+ aom_codec_control_(&codec, AV1_SET_TILE_MODE, 1);
+ aom_codec_control_(&codec, AV1D_EXT_TILE_DEBUG, 1);
+ aom_codec_control_(&codec, AV1_SET_DECODE_TILE_ROW, tr);
+ aom_codec_control_(&codec, AV1_SET_DECODE_TILE_COL, tc);
+
+ av1_ref_frame_t ref;
+ ref.idx = 0;
+ ref.use_external_ref = 1;
+ ref.img = reference_images[ref_idx];
+ if (aom_codec_control(&codec, AV1_SET_REFERENCE, &ref)) {
+ die_codec(&codec, "Failed to set reference frame.");
+ }
+
+ aom_codec_err_t aom_status =
+ aom_codec_decode(&codec, frame, frame_size, NULL);
+ if (aom_status) die_codec(&codec, "Failed to decode tile.");
+
+ aom_codec_iter_t iter = NULL;
+ aom_image_t *img = aom_codec_get_frame(&codec, &iter);
+ aom_img_write(img, outfile);
+ }
}
- aom_codec_control_(&codec, AV1_SET_DECODE_TILE_ROW, tile_t);
- aom_codec_control_(&codec, AV1_SET_DECODE_TILE_COL, tile_s);
- aom_codec_err_t aom_status =
- aom_codec_decode(&codec, frame, frame_size, NULL, 0);
- if (aom_status) die_codec(&codec, "Failed to decode tile.");
- aom_codec_iter_t iter = NULL;
- aom_image_t *img = aom_codec_get_frame(&codec, &iter);
- aom_img_write(img, outfile);
+ for (i = 0; i < num_references; i++) aom_img_free(&reference_images[i]);
if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
aom_video_reader_close(reader);
fclose(outfile);
diff --git a/third_party/aom/examples/lightfield_encoder.c b/third_party/aom/examples/lightfield_encoder.c
index 0a424db8c..22daf622c 100644
--- a/third_party/aom/examples/lightfield_encoder.c
+++ b/third_party/aom/examples/lightfield_encoder.c
@@ -24,7 +24,12 @@
// image for MCP.
// Run "make test" to download lightfield test data: vase10x10.yuv.
// Run lightfield encoder to encode whole lightfield:
-// examples/lightfield_encoder 1024 1024 vase10x10.yuv vase10x10.webm 10 10 5
+// examples/lightfield_encoder 1024 1024 vase10x10.yuv vase10x10.ivf 10 10 5
+
+// Note: In bitstream.c and encoder.c, define EXT_TILE_DEBUG as 1 will print
+// out the uncompressed header and the frame contexts, which can be used to
+// test the bit exactness of the headers and the frame contexts for large scale
+// tile coded frames.
#include <stdio.h>
#include <stdlib.h>
@@ -34,11 +39,13 @@
#include "aom/aomcx.h"
#include "av1/common/enums.h"
-#include "../tools_common.h"
-#include "../video_writer.h"
+#include "common/tools_common.h"
+#include "common/video_writer.h"
+
+#define MAX_EXTERNAL_REFERENCES 128
+#define AOM_BORDER_IN_PIXELS 288
static const char *exec_name;
-static const unsigned int deadline = AOM_DL_GOOD_QUALITY;
void usage_exit(void) {
fprintf(stderr,
@@ -48,52 +55,26 @@ void usage_exit(void) {
exit(EXIT_FAILURE);
}
-static aom_image_t *aom_img_copy(aom_image_t *src, aom_image_t *dst) {
- dst = aom_img_alloc(dst, src->fmt, src->d_w, src->d_h, 16);
-
- int plane;
-
- for (plane = 0; plane < 3; ++plane) {
- unsigned char *src_buf = src->planes[plane];
- const int src_stride = src->stride[plane];
- const int src_w = plane == 0 ? src->d_w : src->d_w >> 1;
- const int src_h = plane == 0 ? src->d_h : src->d_h >> 1;
-
- unsigned char *dst_buf = dst->planes[plane];
- const int dst_stride = dst->stride[plane];
- int y;
-
- for (y = 0; y < src_h; ++y) {
- memcpy(dst_buf, src_buf, src_w);
- src_buf += src_stride;
- dst_buf += dst_stride;
- }
- }
- return dst;
-}
-
static int aom_img_size_bytes(aom_image_t *img) {
int image_size_bytes = 0;
int plane;
for (plane = 0; plane < 3; ++plane) {
- const int stride = img->stride[plane];
const int w = aom_img_plane_width(img, plane) *
((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
const int h = aom_img_plane_height(img, plane);
- image_size_bytes += (w + stride) * h;
+ image_size_bytes += w * h;
}
return image_size_bytes;
}
static int get_frame_stats(aom_codec_ctx_t *ctx, const aom_image_t *img,
aom_codec_pts_t pts, unsigned int duration,
- aom_enc_frame_flags_t flags, unsigned int dl,
+ aom_enc_frame_flags_t flags,
aom_fixed_buf_t *stats) {
int got_pkts = 0;
aom_codec_iter_t iter = NULL;
const aom_codec_cx_pkt_t *pkt = NULL;
- const aom_codec_err_t res =
- aom_codec_encode(ctx, img, pts, duration, flags, dl);
+ const aom_codec_err_t res = aom_codec_encode(ctx, img, pts, duration, flags);
if (res != AOM_CODEC_OK) die_codec(ctx, "Failed to get frame stats.");
while ((pkt = aom_codec_get_cx_data(ctx, &iter)) != NULL) {
@@ -113,13 +94,11 @@ static int get_frame_stats(aom_codec_ctx_t *ctx, const aom_image_t *img,
static int encode_frame(aom_codec_ctx_t *ctx, const aom_image_t *img,
aom_codec_pts_t pts, unsigned int duration,
- aom_enc_frame_flags_t flags, unsigned int dl,
- AvxVideoWriter *writer) {
+ aom_enc_frame_flags_t flags, AvxVideoWriter *writer) {
int got_pkts = 0;
aom_codec_iter_t iter = NULL;
const aom_codec_cx_pkt_t *pkt = NULL;
- const aom_codec_err_t res =
- aom_codec_encode(ctx, img, pts, duration, flags, dl);
+ const aom_codec_err_t res = aom_codec_encode(ctx, img, pts, duration, flags);
if (res != AOM_CODEC_OK) die_codec(ctx, "Failed to encode frame.");
while ((pkt = aom_codec_get_cx_data(ctx, &iter)) != NULL) {
@@ -139,33 +118,44 @@ static int encode_frame(aom_codec_ctx_t *ctx, const aom_image_t *img,
return got_pkts;
}
+static void get_raw_image(aom_image_t **frame_to_encode, aom_image_t *raw,
+ aom_image_t *raw_shift) {
+ if (!CONFIG_LOWBITDEPTH) {
+ // Need to allocate larger buffer to use hbd internal.
+ int input_shift = 0;
+ aom_img_upshift(raw_shift, raw, input_shift);
+ *frame_to_encode = raw_shift;
+ } else {
+ *frame_to_encode = raw;
+ }
+}
+
static aom_fixed_buf_t pass0(aom_image_t *raw, FILE *infile,
const AvxInterface *encoder,
const aom_codec_enc_cfg_t *cfg, int lf_width,
- int lf_height, int lf_blocksize) {
+ int lf_height, int lf_blocksize, int flags,
+ aom_image_t *raw_shift) {
aom_codec_ctx_t codec;
int frame_count = 0;
- int image_size_bytes = 0;
+ int image_size_bytes = aom_img_size_bytes(raw);
int u_blocks, v_blocks;
int bu, bv;
aom_fixed_buf_t stats = { NULL, 0 };
+ aom_image_t *frame_to_encode;
- if (aom_codec_enc_init(&codec, encoder->codec_interface(), cfg, 0))
+ if (aom_codec_enc_init(&codec, encoder->codec_interface(), cfg, flags))
die_codec(&codec, "Failed to initialize encoder");
- if (aom_codec_control(&codec, AV1E_SET_FRAME_PARALLEL_DECODING, 1))
- die_codec(&codec, "Failed to set frame parallel decoding");
if (aom_codec_control(&codec, AOME_SET_ENABLEAUTOALTREF, 0))
die_codec(&codec, "Failed to turn off auto altref");
- if (aom_codec_control(&codec, AV1E_SET_SINGLE_TILE_DECODING, 1))
- die_codec(&codec, "Failed to turn on single tile decoding");
-
- image_size_bytes = aom_img_size_bytes(raw);
+ if (aom_codec_control(&codec, AV1E_SET_FRAME_PARALLEL_DECODING, 0))
+ die_codec(&codec, "Failed to set frame parallel decoding");
// How many reference images we need to encode.
u_blocks = (lf_width + lf_blocksize - 1) / lf_blocksize;
v_blocks = (lf_height + lf_blocksize - 1) / lf_blocksize;
- aom_image_t *reference_images =
- (aom_image_t *)malloc(u_blocks * v_blocks * sizeof(aom_image_t));
+
+ printf("\n First pass: ");
+
for (bv = 0; bv < v_blocks; ++bv) {
for (bu = 0; bu < u_blocks; ++bu) {
const int block_u_min = bu * lf_blocksize;
@@ -174,7 +164,6 @@ static aom_fixed_buf_t pass0(aom_image_t *raw, FILE *infile,
int block_v_end = (bv + 1) * lf_blocksize;
int u_block_size, v_block_size;
int block_ref_u, block_ref_v;
- struct av1_ref_frame ref_frame;
block_u_end = block_u_end < lf_width ? block_u_end : lf_width;
block_v_end = block_v_end < lf_height ? block_v_end : lf_height;
@@ -182,22 +171,28 @@ static aom_fixed_buf_t pass0(aom_image_t *raw, FILE *infile,
v_block_size = block_v_end - block_v_min;
block_ref_u = block_u_min + u_block_size / 2;
block_ref_v = block_v_min + v_block_size / 2;
+
+ printf("A%d, ", (block_ref_u + block_ref_v * lf_width));
fseek(infile, (block_ref_u + block_ref_v * lf_width) * image_size_bytes,
SEEK_SET);
aom_img_read(raw, infile);
- if (aom_codec_control(&codec, AOME_USE_REFERENCE,
- AOM_LAST_FLAG | AOM_GOLD_FLAG | AOM_ALT_FLAG))
- die_codec(&codec, "Failed to set reference flags");
+ get_raw_image(&frame_to_encode, raw, raw_shift);
+
// Reference frames can be encoded encoded without tiles.
++frame_count;
- get_frame_stats(&codec, raw, frame_count, 1,
- AOM_EFLAG_FORCE_GF | AOM_EFLAG_NO_UPD_ENTROPY, deadline,
+ get_frame_stats(&codec, frame_to_encode, frame_count, 1,
+ AOM_EFLAG_NO_REF_LAST2 | AOM_EFLAG_NO_REF_LAST3 |
+ AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF |
+ AOM_EFLAG_NO_REF_BWD | AOM_EFLAG_NO_REF_ARF2 |
+ AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
+ AOM_EFLAG_NO_UPD_ARF,
&stats);
- ref_frame.idx = 0;
- aom_codec_control(&codec, AV1_GET_REFERENCE, &ref_frame);
- aom_img_copy(&ref_frame.img, &reference_images[frame_count - 1]);
}
}
+
+ if (aom_codec_control(&codec, AV1E_SET_FRAME_PARALLEL_DECODING, 1))
+ die_codec(&codec, "Failed to set frame parallel decoding");
+
for (bv = 0; bv < v_blocks; ++bv) {
for (bu = 0; bu < u_blocks; ++bu) {
const int block_u_min = bu * lf_blocksize;
@@ -209,58 +204,39 @@ static aom_fixed_buf_t pass0(aom_image_t *raw, FILE *infile,
block_v_end = block_v_end < lf_height ? block_v_end : lf_height;
for (v = block_v_min; v < block_v_end; ++v) {
for (u = block_u_min; u < block_u_end; ++u) {
- // This was a work around for a bug in libvpx. I'm not sure if this
- // same bug exists in current version of av1. Need to call this,
- // otherwise the default is to not use any reference frames. Then
- // if you don't have at least one AOM_EFLAG_NO_REF_* flag, all frames
- // will be intra encoded. I'm not sure why the default is not to use
- // any reference frames. It looks like there is something about the
- // way I encode the reference frames above that sets that as
- // default...
- if (aom_codec_control(&codec, AOME_USE_REFERENCE,
- AOM_LAST_FLAG | AOM_GOLD_FLAG | AOM_ALT_FLAG))
- die_codec(&codec, "Failed to set reference flags");
-
- // Set tile size to 64 pixels. The tile_columns and
- // tile_rows in the tile coding are overloaded to represent
- // tile_width and tile_height, that range from 1 to 64, in the unit
- // of 64 pixels.
- if (aom_codec_control(&codec, AV1E_SET_TILE_COLUMNS, 1))
- die_codec(&codec, "Failed to set tile width");
- if (aom_codec_control(&codec, AV1E_SET_TILE_ROWS, 1))
- die_codec(&codec, "Failed to set tile height");
-
- av1_ref_frame_t ref;
- ref.idx = 0;
- ref.img = reference_images[bv * u_blocks + bu];
- if (aom_codec_control(&codec, AV1_SET_REFERENCE, &ref))
- die_codec(&codec, "Failed to set reference frame");
-
+ printf("C%d, ", (u + v * lf_width));
fseek(infile, (u + v * lf_width) * image_size_bytes, SEEK_SET);
aom_img_read(raw, infile);
+ get_raw_image(&frame_to_encode, raw, raw_shift);
+
++frame_count;
- get_frame_stats(&codec, raw, frame_count, 1,
- AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
- AOM_EFLAG_NO_UPD_ARF | AOM_EFLAG_NO_UPD_ENTROPY |
- AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF,
- deadline, &stats);
+ get_frame_stats(&codec, frame_to_encode, frame_count, 1,
+ AOM_EFLAG_NO_REF_LAST2 | AOM_EFLAG_NO_REF_LAST3 |
+ AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF |
+ AOM_EFLAG_NO_REF_BWD | AOM_EFLAG_NO_REF_ARF2 |
+ AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
+ AOM_EFLAG_NO_UPD_ARF | AOM_EFLAG_NO_UPD_ENTROPY,
+ &stats);
}
}
}
}
// Flush encoder.
- while (get_frame_stats(&codec, NULL, frame_count, 1, 0, deadline, &stats)) {
+ // No ARF, this should not be needed.
+ while (get_frame_stats(&codec, NULL, frame_count, 1, 0, &stats)) {
}
- printf("Pass 0 complete. Processed %d frames.\n", frame_count);
if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
+ printf("\nFirst pass complete. Processed %d frames.\n", frame_count);
+
return stats;
}
static void pass1(aom_image_t *raw, FILE *infile, const char *outfile_name,
- const AvxInterface *encoder, const aom_codec_enc_cfg_t *cfg,
- int lf_width, int lf_height, int lf_blocksize) {
+ const AvxInterface *encoder, aom_codec_enc_cfg_t *cfg,
+ int lf_width, int lf_height, int lf_blocksize, int flags,
+ aom_image_t *raw_shift) {
AvxVideoInfo info = { encoder->fourcc,
cfg->g_w,
cfg->g_h,
@@ -268,27 +244,48 @@ static void pass1(aom_image_t *raw, FILE *infile, const char *outfile_name,
AvxVideoWriter *writer = NULL;
aom_codec_ctx_t codec;
int frame_count = 0;
- int image_size_bytes;
+ int image_size_bytes = aom_img_size_bytes(raw);
int bu, bv;
int u_blocks, v_blocks;
+ aom_image_t *frame_to_encode;
+ aom_image_t reference_images[MAX_EXTERNAL_REFERENCES];
+ int reference_image_num = 0;
+ int i;
writer = aom_video_writer_open(outfile_name, kContainerIVF, &info);
if (!writer) die("Failed to open %s for writing", outfile_name);
- if (aom_codec_enc_init(&codec, encoder->codec_interface(), cfg, 0))
+ if (aom_codec_enc_init(&codec, encoder->codec_interface(), cfg, flags))
die_codec(&codec, "Failed to initialize encoder");
- if (aom_codec_control(&codec, AV1E_SET_FRAME_PARALLEL_DECODING, 1))
- die_codec(&codec, "Failed to set frame parallel decoding");
if (aom_codec_control(&codec, AOME_SET_ENABLEAUTOALTREF, 0))
die_codec(&codec, "Failed to turn off auto altref");
- if (aom_codec_control(&codec, AV1E_SET_SINGLE_TILE_DECODING, 1))
- die_codec(&codec, "Failed to turn on single tile decoding");
+ if (aom_codec_control(&codec, AV1E_SET_FRAME_PARALLEL_DECODING, 0))
+ die_codec(&codec, "Failed to set frame parallel decoding");
+ // Note: The superblock is a sequence parameter and has to be the same for 1
+ // sequence. In lightfield application, must choose the superblock size(either
+ // 64x64 or 128x128) before the encoding starts. Otherwise, the default is
+ // AOM_SUPERBLOCK_SIZE_DYNAMIC, and the superblock size will be set to 64x64
+ // internally.
+ if (aom_codec_control(&codec, AV1E_SET_SUPERBLOCK_SIZE,
+ AOM_SUPERBLOCK_SIZE_64X64))
+ die_codec(&codec, "Failed to set SB size");
- image_size_bytes = aom_img_size_bytes(raw);
u_blocks = (lf_width + lf_blocksize - 1) / lf_blocksize;
v_blocks = (lf_height + lf_blocksize - 1) / lf_blocksize;
- aom_image_t *reference_images =
- (aom_image_t *)malloc(u_blocks * v_blocks * sizeof(aom_image_t));
+
+ reference_image_num = u_blocks * v_blocks;
+ aom_img_fmt_t ref_fmt = AOM_IMG_FMT_I420;
+ if (!CONFIG_LOWBITDEPTH) ref_fmt |= AOM_IMG_FMT_HIGHBITDEPTH;
+ // Allocate memory with the border so that it can be used as a reference.
+ for (i = 0; i < reference_image_num; i++) {
+ if (!aom_img_alloc_with_border(&reference_images[i], ref_fmt, cfg->g_w,
+ cfg->g_h, 32, 8, AOM_BORDER_IN_PIXELS)) {
+ die("Failed to allocate image.");
+ }
+ }
+
+ printf("\n Second pass: ");
+
// Encode reference images first.
printf("Encoding Reference Images\n");
for (bv = 0; bv < v_blocks; ++bv) {
@@ -299,7 +296,6 @@ static void pass1(aom_image_t *raw, FILE *infile, const char *outfile_name,
int block_v_end = (bv + 1) * lf_blocksize;
int u_block_size, v_block_size;
int block_ref_u, block_ref_v;
- struct av1_ref_frame ref_frame;
block_u_end = block_u_end < lf_width ? block_u_end : lf_width;
block_v_end = block_v_end < lf_height ? block_v_end : lf_height;
@@ -307,25 +303,52 @@ static void pass1(aom_image_t *raw, FILE *infile, const char *outfile_name,
v_block_size = block_v_end - block_v_min;
block_ref_u = block_u_min + u_block_size / 2;
block_ref_v = block_v_min + v_block_size / 2;
+
+ printf("A%d, ", (block_ref_u + block_ref_v * lf_width));
fseek(infile, (block_ref_u + block_ref_v * lf_width) * image_size_bytes,
SEEK_SET);
aom_img_read(raw, infile);
- if (aom_codec_control(&codec, AOME_USE_REFERENCE,
- AOM_LAST_FLAG | AOM_GOLD_FLAG | AOM_ALT_FLAG))
- die_codec(&codec, "Failed to set reference flags");
+
+ get_raw_image(&frame_to_encode, raw, raw_shift);
+
// Reference frames may be encoded without tiles.
++frame_count;
printf("Encoding reference image %d of %d\n", bv * u_blocks + bu,
u_blocks * v_blocks);
- encode_frame(&codec, raw, frame_count, 1,
- AOM_EFLAG_FORCE_GF | AOM_EFLAG_NO_UPD_ENTROPY, deadline,
+ encode_frame(&codec, frame_to_encode, frame_count, 1,
+ AOM_EFLAG_NO_REF_LAST2 | AOM_EFLAG_NO_REF_LAST3 |
+ AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF |
+ AOM_EFLAG_NO_REF_BWD | AOM_EFLAG_NO_REF_ARF2 |
+ AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
+ AOM_EFLAG_NO_UPD_ARF | AOM_EFLAG_NO_UPD_ENTROPY,
writer);
- ref_frame.idx = 0;
- aom_codec_control(&codec, AV1_GET_REFERENCE, &ref_frame);
- aom_img_copy(&ref_frame.img, &reference_images[frame_count - 1]);
+
+ if (aom_codec_control(&codec, AV1_COPY_NEW_FRAME_IMAGE,
+ &reference_images[frame_count - 1]))
+ die_codec(&codec, "Failed to copy decoder reference frame");
}
}
+ cfg->large_scale_tile = 1;
+ // Fixed q encoding for camera frames.
+ cfg->rc_end_usage = AOM_Q;
+ if (aom_codec_enc_config_set(&codec, cfg))
+ die_codec(&codec, "Failed to configure encoder");
+
+ // The fixed q value used in encoding.
+ if (aom_codec_control(&codec, AOME_SET_CQ_LEVEL, 36))
+ die_codec(&codec, "Failed to set cq level");
+ if (aom_codec_control(&codec, AV1E_SET_FRAME_PARALLEL_DECODING, 1))
+ die_codec(&codec, "Failed to set frame parallel decoding");
+ if (aom_codec_control(&codec, AV1E_SET_SINGLE_TILE_DECODING, 1))
+ die_codec(&codec, "Failed to turn on single tile decoding");
+ // Set tile_columns and tile_rows to MAX values, which guarantees the tile
+ // size of 64 x 64 pixels(i.e. 1 SB) for <= 4k resolution.
+ if (aom_codec_control(&codec, AV1E_SET_TILE_COLUMNS, 6))
+ die_codec(&codec, "Failed to set tile width");
+ if (aom_codec_control(&codec, AV1E_SET_TILE_ROWS, 6))
+ die_codec(&codec, "Failed to set tile height");
+
for (bv = 0; bv < v_blocks; ++bv) {
for (bu = 0; bu < u_blocks; ++bu) {
const int block_u_min = bu * lf_blocksize;
@@ -337,56 +360,44 @@ static void pass1(aom_image_t *raw, FILE *infile, const char *outfile_name,
block_v_end = block_v_end < lf_height ? block_v_end : lf_height;
for (v = block_v_min; v < block_v_end; ++v) {
for (u = block_u_min; u < block_u_end; ++u) {
- // This was a work around for a bug in libvpx. I'm not sure if this
- // same bug exists in current version of av1. Need to call this,
- // otherwise the default is to not use any reference frames. Then
- // if you don't have at least one AOM_EFLAG_NO_REF_* flag, all frames
- // will be intra encoded. I'm not sure why the default is not to use
- // any reference frames. It looks like there is something about the
- // way I encode the reference frames above that sets that as
- // default...
- if (aom_codec_control(&codec, AOME_USE_REFERENCE,
- AOM_LAST_FLAG | AOM_GOLD_FLAG | AOM_ALT_FLAG))
- die_codec(&codec, "Failed to set reference flags");
-
- // Set tile size to 64 pixels. The tile_columns and
- // tile_rows in the tile coding are overloaded to represent tile_width
- // and tile_height, that range from 1 to 64, in the unit of 64 pixels.
- if (aom_codec_control(&codec, AV1E_SET_TILE_COLUMNS, 1))
- die_codec(&codec, "Failed to set tile width");
- if (aom_codec_control(&codec, AV1E_SET_TILE_ROWS, 1))
- die_codec(&codec, "Failed to set tile height");
-
av1_ref_frame_t ref;
ref.idx = 0;
+ ref.use_external_ref = 1;
ref.img = reference_images[bv * u_blocks + bu];
if (aom_codec_control(&codec, AV1_SET_REFERENCE, &ref))
die_codec(&codec, "Failed to set reference frame");
+
+ printf("C%d, ", (u + v * lf_width));
fseek(infile, (u + v * lf_width) * image_size_bytes, SEEK_SET);
aom_img_read(raw, infile);
- ++frame_count;
+ get_raw_image(&frame_to_encode, raw, raw_shift);
+ ++frame_count;
printf("Encoding image %d of %d\n",
frame_count - (u_blocks * v_blocks), lf_width * lf_height);
- encode_frame(&codec, raw, frame_count, 1,
- AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
- AOM_EFLAG_NO_UPD_ARF | AOM_EFLAG_NO_UPD_ENTROPY |
- AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF,
- deadline, writer);
+ encode_frame(&codec, frame_to_encode, frame_count, 1,
+ AOM_EFLAG_NO_REF_LAST2 | AOM_EFLAG_NO_REF_LAST3 |
+ AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF |
+ AOM_EFLAG_NO_REF_BWD | AOM_EFLAG_NO_REF_ARF2 |
+ AOM_EFLAG_NO_UPD_LAST | AOM_EFLAG_NO_UPD_GF |
+ AOM_EFLAG_NO_UPD_ARF | AOM_EFLAG_NO_UPD_ENTROPY,
+ writer);
}
}
}
}
// Flush encoder.
- while (encode_frame(&codec, NULL, -1, 1, 0, deadline, writer)) {
+ // No ARF, this should not be needed.
+ while (encode_frame(&codec, NULL, -1, 1, 0, writer)) {
}
- if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
+ for (i = 0; i < reference_image_num; i++) aom_img_free(&reference_images[i]);
+ if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
aom_video_writer_close(writer);
- printf("Pass 1 complete. Processed %d frames.\n", frame_count);
+ printf("\nSecond pass complete. Processed %d frames.\n", frame_count);
}
int main(int argc, char **argv) {
@@ -401,8 +412,10 @@ int main(int argc, char **argv) {
aom_codec_ctx_t codec;
aom_codec_enc_cfg_t cfg;
aom_image_t raw;
+ aom_image_t raw_shift;
aom_codec_err_t res;
aom_fixed_buf_t stats;
+ int flags = 0;
const AvxInterface *encoder = NULL;
const int fps = 30;
@@ -435,14 +448,19 @@ int main(int argc, char **argv) {
die("Invalid lf_width and/or lf_height: %dx%d", lf_width, lf_height);
if (lf_blocksize <= 0) die("Invalid lf_blocksize: %d", lf_blocksize);
- if (!aom_img_alloc(&raw, AOM_IMG_FMT_I420, w, h, 1))
- die("Failed to allocate image", w, h);
+ if (!aom_img_alloc(&raw, AOM_IMG_FMT_I420, w, h, 32)) {
+ die("Failed to allocate image.");
+ }
+ if (!CONFIG_LOWBITDEPTH) {
+ // Need to allocate larger buffer to use hbd internal.
+ aom_img_alloc(&raw_shift, AOM_IMG_FMT_I420 | AOM_IMG_FMT_HIGHBITDEPTH, w, h,
+ 32);
+ }
printf("Using %s\n", aom_codec_iface_name(encoder->codec_interface()));
// Configuration
res = aom_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
-
if (res) die_codec(&codec, "Failed to get default codec config.");
cfg.g_w = w;
@@ -450,29 +468,32 @@ int main(int argc, char **argv) {
cfg.g_timebase.num = 1;
cfg.g_timebase.den = fps;
cfg.rc_target_bitrate = bitrate;
- cfg.g_error_resilient = AOM_ERROR_RESILIENT_DEFAULT;
- // Need to set lag_in_frames to 1 or 0. Otherwise the frame flags get
- // overridden after the first frame in encode_frame_to_data_rate() (see where
- // get_frame_flags() is called).
- cfg.g_lag_in_frames = 0;
+ cfg.g_error_resilient = 0; // This is required.
+ cfg.g_lag_in_frames = 0; // need to set this since default is 19.
cfg.kf_mode = AOM_KF_DISABLED;
- cfg.large_scale_tile = 1;
+ cfg.large_scale_tile = 0; // Only set it to 1 for camera frame encoding.
+ cfg.g_bit_depth = AOM_BITS_8;
+ flags |= (cfg.g_bit_depth > AOM_BITS_8 || !CONFIG_LOWBITDEPTH)
+ ? AOM_CODEC_USE_HIGHBITDEPTH
+ : 0;
if (!(infile = fopen(infile_arg, "rb")))
die("Failed to open %s for reading", infile_arg);
// Pass 0
cfg.g_pass = AOM_RC_FIRST_PASS;
- stats = pass0(&raw, infile, encoder, &cfg, lf_width, lf_height, lf_blocksize);
+ stats = pass0(&raw, infile, encoder, &cfg, lf_width, lf_height, lf_blocksize,
+ flags, &raw_shift);
// Pass 1
rewind(infile);
cfg.g_pass = AOM_RC_LAST_PASS;
cfg.rc_twopass_stats_in = stats;
pass1(&raw, infile, outfile_arg, encoder, &cfg, lf_width, lf_height,
- lf_blocksize);
+ lf_blocksize, flags, &raw_shift);
free(stats.buf);
+ if (!CONFIG_LOWBITDEPTH) aom_img_free(&raw_shift);
aom_img_free(&raw);
fclose(infile);
diff --git a/third_party/aom/examples/lightfield_tile_list_decoder.c b/third_party/aom/examples/lightfield_tile_list_decoder.c
new file mode 100644
index 000000000..cec6baa2c
--- /dev/null
+++ b/third_party/aom/examples/lightfield_tile_list_decoder.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// Lightfield Tile List Decoder
+// ============================
+//
+// This is a lightfield tile list decoder example. It takes an input file that
+// contains the anchor frames that are references of the coded tiles, the camera
+// frame header, and tile list OBUs that include the tile information and the
+// compressed tile data. This input file is reconstructed from the encoded
+// lightfield ivf file, and is decodable by AV1 decoder. The lf_width and
+// lf_height arguments are the number of lightfield images in each dimension.
+// The lf_blocksize determines the number of reference images used.
+// Run lightfield tile list decoder to decode an AV1 tile list file:
+// examples/lightfield_tile_list_decoder vase_tile_list.ivf vase_tile_list.yuv
+// 10 10 5 2
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "aom/aom_decoder.h"
+#include "aom/aomdx.h"
+#include "common/tools_common.h"
+#include "common/video_reader.h"
+
+#define MAX_EXTERNAL_REFERENCES 128
+#define AOM_BORDER_IN_PIXELS 288
+
+static const char *exec_name;
+
+void usage_exit(void) {
+ fprintf(stderr,
+ "Usage: %s <infile> <outfile> <lf_width> <lf_height> <lf_blocksize> "
+ "<num_tile_lists>\n",
+ exec_name);
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv) {
+ FILE *outfile = NULL;
+ aom_codec_ctx_t codec;
+ AvxVideoReader *reader = NULL;
+ const AvxInterface *decoder = NULL;
+ const AvxVideoInfo *info = NULL;
+ const char *lf_width_arg;
+ const char *lf_height_arg;
+ const char *lf_blocksize_arg;
+ int width, height;
+ int lf_width, lf_height, lf_blocksize;
+ int u_blocks, v_blocks;
+ int num_tile_lists;
+ aom_image_t reference_images[MAX_EXTERNAL_REFERENCES];
+ size_t frame_size = 0;
+ const unsigned char *frame = NULL;
+ int i, n;
+
+ exec_name = argv[0];
+
+ if (argc != 7) die("Invalid number of arguments.");
+
+ reader = aom_video_reader_open(argv[1]);
+ if (!reader) die("Failed to open %s for reading.", argv[1]);
+
+ if (!(outfile = fopen(argv[2], "wb")))
+ die("Failed to open %s for writing.", argv[2]);
+
+ lf_width_arg = argv[3];
+ lf_height_arg = argv[4];
+ lf_blocksize_arg = argv[5];
+ lf_width = (int)strtol(lf_width_arg, NULL, 0);
+ lf_height = (int)strtol(lf_height_arg, NULL, 0);
+ lf_blocksize = (int)strtol(lf_blocksize_arg, NULL, 0);
+ num_tile_lists = (int)strtol(argv[6], NULL, 0);
+
+ info = aom_video_reader_get_info(reader);
+ width = info->frame_width;
+ height = info->frame_height;
+
+ decoder = get_aom_decoder_by_fourcc(info->codec_fourcc);
+ if (!decoder) die("Unknown input codec.");
+ printf("Using %s\n", aom_codec_iface_name(decoder->codec_interface()));
+
+ if (aom_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
+ die_codec(&codec, "Failed to initialize decoder.");
+
+ // How many anchor frames we have.
+ u_blocks = (lf_width + lf_blocksize - 1) / lf_blocksize;
+ v_blocks = (lf_height + lf_blocksize - 1) / lf_blocksize;
+
+ int num_references = v_blocks * u_blocks;
+
+ // Allocate memory to store decoded references.
+ aom_img_fmt_t ref_fmt = AOM_IMG_FMT_I420;
+ if (!CONFIG_LOWBITDEPTH) ref_fmt |= AOM_IMG_FMT_HIGHBITDEPTH;
+ // Allocate memory with the border so that it can be used as a reference.
+ for (i = 0; i < num_references; i++) {
+ unsigned int border = AOM_BORDER_IN_PIXELS;
+ if (!aom_img_alloc_with_border(&reference_images[i], ref_fmt, width, height,
+ 32, 8, border)) {
+ die("Failed to allocate references.");
+ }
+ }
+
+ // Decode anchor frames.
+ aom_codec_control_(&codec, AV1_SET_TILE_MODE, 0);
+
+ for (i = 0; i < num_references; ++i) {
+ aom_video_reader_read_frame(reader);
+ frame = aom_video_reader_get_frame(reader, &frame_size);
+ if (aom_codec_decode(&codec, frame, frame_size, NULL))
+ die_codec(&codec, "Failed to decode frame.");
+
+ if (aom_codec_control(&codec, AV1_COPY_NEW_FRAME_IMAGE,
+ &reference_images[i]))
+ die_codec(&codec, "Failed to copy decoded reference frame");
+
+ aom_codec_iter_t iter = NULL;
+ aom_image_t *img = NULL;
+ while ((img = aom_codec_get_frame(&codec, &iter)) != NULL) {
+ char name[1024];
+ snprintf(name, sizeof(name), "ref_%d.yuv", i);
+ printf("writing ref image to %s, %d, %d\n", name, img->d_w, img->d_h);
+ FILE *ref_file = fopen(name, "wb");
+ aom_img_write(img, ref_file);
+ fclose(ref_file);
+ }
+ }
+
+ // Decode the lightfield.
+ aom_codec_control_(&codec, AV1_SET_TILE_MODE, 1);
+
+ // Set external references.
+ av1_ext_ref_frame_t set_ext_ref = { &reference_images[0], num_references };
+ aom_codec_control_(&codec, AV1D_SET_EXT_REF_PTR, &set_ext_ref);
+
+ // Must decode the camera frame header first.
+ aom_video_reader_read_frame(reader);
+ frame = aom_video_reader_get_frame(reader, &frame_size);
+ if (aom_codec_decode(&codec, frame, frame_size, NULL))
+ die_codec(&codec, "Failed to decode the frame.");
+
+ // Decode tile lists one by one.
+ for (n = 0; n < num_tile_lists; n++) {
+ aom_video_reader_read_frame(reader);
+ frame = aom_video_reader_get_frame(reader, &frame_size);
+
+ if (aom_codec_decode(&codec, frame, frame_size, NULL))
+ die_codec(&codec, "Failed to decode the tile list.");
+
+ aom_codec_iter_t iter = NULL;
+ aom_image_t *img;
+ while ((img = aom_codec_get_frame(&codec, &iter)))
+ fwrite(img->img_data, 1, img->sz, outfile);
+ }
+
+ for (i = 0; i < num_references; i++) aom_img_free(&reference_images[i]);
+ if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
+ aom_video_reader_close(reader);
+ fclose(outfile);
+
+ return EXIT_SUCCESS;
+}
diff --git a/third_party/aom/examples/lossless_encoder.c b/third_party/aom/examples/lossless_encoder.c
index 32ab18a16..438ff21c6 100644
--- a/third_party/aom/examples/lossless_encoder.c
+++ b/third_party/aom/examples/lossless_encoder.c
@@ -15,9 +15,8 @@
#include "aom/aom_encoder.h"
#include "aom/aomcx.h"
-
-#include "../tools_common.h"
-#include "../video_writer.h"
+#include "common/tools_common.h"
+#include "common/video_writer.h"
static const char *exec_name;
@@ -35,7 +34,7 @@ static int encode_frame(aom_codec_ctx_t *codec, aom_image_t *img,
aom_codec_iter_t iter = NULL;
const aom_codec_cx_pkt_t *pkt = NULL;
const aom_codec_err_t res =
- aom_codec_encode(codec, img, frame_index, 1, flags, AOM_DL_GOOD_QUALITY);
+ aom_codec_encode(codec, img, frame_index, 1, flags);
if (res != AOM_CODEC_OK) die_codec(codec, "Failed to encode frame");
while ((pkt = aom_codec_get_cx_data(codec, &iter)) != NULL) {
diff --git a/third_party/aom/examples/noise_model.c b/third_party/aom/examples/noise_model.c
new file mode 100644
index 000000000..5a5b4d40d
--- /dev/null
+++ b/third_party/aom/examples/noise_model.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*!\file
+ * \brief This is an sample binary to create noise params from input video.
+ *
+ * To allow for external denoising applications, this sample binary illustrates
+ * how to create a film grain table (film grain params as a function of time)
+ * from an input video and its corresponding denoised source.
+ *
+ * The --output-grain-table file can be passed as input to the encoder (in
+ * aomenc this is done through the "--film-grain-table" parameter).
+ *
+ * As an example, where the input source is an 854x480 yuv420p 8-bit video
+ * named "input.854_480.yuv" you would use steps similar to the following:
+ *
+ * # Run your denoiser (e.g, using hqdn3d filter):
+ * ffmpeg -vcodec rawvideo -video_size 854x480 -i input.854_480.yuv \
+ * -vf hqdn3d=5:5:5:5 -vcodec rawvideo -an -f rawvideo \
+ * denoised.854_480.yuv
+ *
+ * # Model the noise between the denoised version and original source:
+ * ./examples/noise_model --fps=25/1 --width=854 --height=480 --i420 \
+ * --input-denoised=denoised.854_480.yuv --input=original.854_480.yuv \
+ * --output-grain-table=film_grain.tbl
+ *
+ * # Encode with your favorite settings (including the grain table):
+ * aomenc --limit=100 --cpu-used=4 --input-bit-depth=8 \
+ * --i420 -w 854 -h 480 --end-usage=q --cq-level=25 --lag-in-frames=25 \
+ * --auto-alt-ref=2 --bit-depth=8 --film-grain-table=film_grain.tbl \
+ * -o denoised_with_grain_params.ivf denoised.854_480.yuv
+ */
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "aom/aom_encoder.h"
+#include "aom_dsp/aom_dsp_common.h"
+
+#if CONFIG_AV1_DECODER
+#include "aom_dsp/grain_synthesis.h"
+#endif
+
+#include "aom_dsp/grain_table.h"
+#include "aom_dsp/noise_model.h"
+#include "aom_dsp/noise_util.h"
+#include "aom_mem/aom_mem.h"
+#include "common/args.h"
+#include "common/tools_common.h"
+#include "common/video_writer.h"
+
+static const char *exec_name;
+
+void usage_exit(void) {
+ fprintf(stderr,
+ "Usage: %s --input=<input> --input-denoised=<denoised> "
+ "--output-grain-table=<outfile> "
+ "See comments in noise_model.c for more information.\n",
+ exec_name);
+ exit(EXIT_FAILURE);
+}
+
+static const arg_def_t help =
+ ARG_DEF(NULL, "help", 0, "Show usage options and exit");
+static const arg_def_t width_arg =
+ ARG_DEF("w", "width", 1, "Input width (if rawvideo)");
+static const arg_def_t height_arg =
+ ARG_DEF("h", "height", 1, "Input height (if rawvideo)");
+static const arg_def_t skip_frames_arg =
+ ARG_DEF("s", "skip-frames", 1, "Number of frames to skip (default = 1)");
+static const arg_def_t fps_arg = ARG_DEF(NULL, "fps", 1, "Frame rate");
+static const arg_def_t input_arg = ARG_DEF("-i", "input", 1, "Input filename");
+static const arg_def_t output_grain_table_arg =
+ ARG_DEF("n", "output-grain-table", 1, "Output noise file");
+static const arg_def_t input_denoised_arg =
+ ARG_DEF("d", "input-denoised", 1, "Input denoised filename (YUV) only");
+static const arg_def_t flat_block_finder_arg =
+ ARG_DEF("b", "flat-block-finder", 1, "Run the flat block finder");
+static const arg_def_t block_size_arg =
+ ARG_DEF("b", "block-size", 1, "Block size");
+static const arg_def_t bit_depth_arg =
+ ARG_DEF(NULL, "bit-depth", 1, "Bit depth of input");
+static const arg_def_t use_i420 =
+ ARG_DEF(NULL, "i420", 0, "Input file (and denoised) is I420 (default)");
+static const arg_def_t use_i422 =
+ ARG_DEF(NULL, "i422", 0, "Input file (and denoised) is I422");
+static const arg_def_t use_i444 =
+ ARG_DEF(NULL, "i444", 0, "Input file (and denoised) is I444");
+static const arg_def_t debug_file_arg =
+ ARG_DEF(NULL, "debug-file", 1, "File to output debug info");
+
+typedef struct {
+ int width;
+ int height;
+ struct aom_rational fps;
+ const char *input;
+ const char *input_denoised;
+ const char *output_grain_table;
+ int img_fmt;
+ int block_size;
+ int bit_depth;
+ int run_flat_block_finder;
+ int force_flat_psd;
+ int skip_frames;
+ const char *debug_file;
+} noise_model_args_t;
+
+void parse_args(noise_model_args_t *noise_args, int *argc, char **argv) {
+ struct arg arg;
+ static const arg_def_t *main_args[] = { &help,
+ &input_arg,
+ &fps_arg,
+ &width_arg,
+ &height_arg,
+ &block_size_arg,
+ &output_grain_table_arg,
+ &input_denoised_arg,
+ &use_i420,
+ &use_i422,
+ &use_i444,
+ &debug_file_arg,
+ NULL };
+ for (int argi = *argc + 1; *argv; argi++, argv++) {
+ if (arg_match(&arg, &help, argv)) {
+ fprintf(stdout, "\nOptions:\n");
+ arg_show_usage(stdout, main_args);
+ exit(0);
+ } else if (arg_match(&arg, &width_arg, argv)) {
+ noise_args->width = atoi(arg.val);
+ } else if (arg_match(&arg, &height_arg, argv)) {
+ noise_args->height = atoi(arg.val);
+ } else if (arg_match(&arg, &input_arg, argv)) {
+ noise_args->input = arg.val;
+ } else if (arg_match(&arg, &input_denoised_arg, argv)) {
+ noise_args->input_denoised = arg.val;
+ } else if (arg_match(&arg, &output_grain_table_arg, argv)) {
+ noise_args->output_grain_table = arg.val;
+ } else if (arg_match(&arg, &block_size_arg, argv)) {
+ noise_args->block_size = atoi(arg.val);
+ } else if (arg_match(&arg, &bit_depth_arg, argv)) {
+ noise_args->bit_depth = atoi(arg.val);
+ } else if (arg_match(&arg, &flat_block_finder_arg, argv)) {
+ noise_args->run_flat_block_finder = atoi(arg.val);
+ } else if (arg_match(&arg, &fps_arg, argv)) {
+ noise_args->fps = arg_parse_rational(&arg);
+ } else if (arg_match(&arg, &use_i420, argv)) {
+ noise_args->img_fmt = AOM_IMG_FMT_I420;
+ } else if (arg_match(&arg, &use_i422, argv)) {
+ noise_args->img_fmt = AOM_IMG_FMT_I422;
+ } else if (arg_match(&arg, &use_i444, argv)) {
+ noise_args->img_fmt = AOM_IMG_FMT_I444;
+ } else if (arg_match(&arg, &skip_frames_arg, argv)) {
+ noise_args->skip_frames = atoi(arg.val);
+ } else if (arg_match(&arg, &debug_file_arg, argv)) {
+ noise_args->debug_file = arg.val;
+ } else {
+ fprintf(stdout, "Unknown arg: %s\n\nUsage:\n", *argv);
+ arg_show_usage(stdout, main_args);
+ exit(0);
+ }
+ }
+ if (noise_args->bit_depth > 8) {
+ noise_args->img_fmt |= AOM_IMG_FMT_HIGHBITDEPTH;
+ }
+}
+
+#if CONFIG_AV1_DECODER
+static void print_variance_y(FILE *debug_file, aom_image_t *raw,
+ aom_image_t *denoised, const uint8_t *flat_blocks,
+ int block_size, aom_film_grain_t *grain) {
+ aom_image_t renoised;
+ grain->apply_grain = 1;
+ grain->random_seed = 1071;
+ aom_img_alloc(&renoised, raw->fmt, raw->w, raw->h, 1);
+ av1_add_film_grain(grain, denoised, &renoised);
+
+ const int num_blocks_w = (raw->w + block_size - 1) / block_size;
+ const int num_blocks_h = (raw->h + block_size - 1) / block_size;
+ fprintf(debug_file, "x = [");
+ for (int by = 0; by < num_blocks_h; by++) {
+ for (int bx = 0; bx < num_blocks_w; bx++) {
+ double block_mean = 0;
+ double noise_std = 0, noise_mean = 0;
+ double renoise_std = 0, renoise_mean = 0;
+ for (int yi = 0; yi < block_size; ++yi) {
+ const int y = by * block_size + yi;
+ for (int xi = 0; xi < block_size; ++xi) {
+ const int x = bx * block_size + xi;
+ const double noise_v = (raw->planes[0][y * raw->stride[0] + x] -
+ denoised->planes[0][y * raw->stride[0] + x]);
+ noise_mean += noise_v;
+ noise_std += noise_v * noise_v;
+
+ block_mean += raw->planes[0][y * raw->stride[0] + x];
+
+ const double renoise_v =
+ (renoised.planes[0][y * raw->stride[0] + x] -
+ denoised->planes[0][y * raw->stride[0] + x]);
+ renoise_mean += renoise_v;
+ renoise_std += renoise_v * renoise_v;
+ }
+ }
+ int n = (block_size * block_size);
+ block_mean /= n;
+ noise_mean /= n;
+ renoise_mean /= n;
+ noise_std = sqrt(noise_std / n - noise_mean * noise_mean);
+ renoise_std = sqrt(renoise_std / n - renoise_mean * renoise_mean);
+ fprintf(debug_file, "%d %3.2lf %3.2lf %3.2lf ",
+ flat_blocks[by * num_blocks_w + bx], block_mean, noise_std,
+ renoise_std);
+ }
+ fprintf(debug_file, "\n");
+ }
+ fprintf(debug_file, "];\n");
+
+ if (raw->fmt & AOM_IMG_FMT_HIGHBITDEPTH) {
+ fprintf(stderr,
+ "Detailed debug info not supported for high bit"
+ "depth formats\n");
+ } else {
+ fprintf(debug_file, "figure(2); clf;\n");
+ fprintf(debug_file,
+ "scatter(x(:, 2:4:end), x(:, 3:4:end), 'r'); hold on;\n");
+ fprintf(debug_file, "scatter(x(:, 2:4:end), x(:, 4:4:end), 'b');\n");
+ fprintf(debug_file,
+ "plot(linspace(0, 255, length(noise_strength_0)), "
+ "noise_strength_0, 'b');\n");
+ fprintf(debug_file,
+ "title('Scatter plot of intensity vs noise strength');\n");
+ fprintf(debug_file,
+ "legend('Actual', 'Estimated', 'Estimated strength');\n");
+ fprintf(debug_file, "figure(3); clf;\n");
+ fprintf(debug_file, "scatter(x(:, 3:4:end), x(:, 4:4:end), 'k');\n");
+ fprintf(debug_file, "title('Actual vs Estimated');\n");
+ fprintf(debug_file, "pause(3);\n");
+ }
+ aom_img_free(&renoised);
+}
+#endif
+
+static void print_debug_info(FILE *debug_file, aom_image_t *raw,
+ aom_image_t *denoised, uint8_t *flat_blocks,
+ int block_size, aom_noise_model_t *noise_model) {
+ (void)raw;
+ (void)denoised;
+ (void)flat_blocks;
+ (void)block_size;
+ fprintf(debug_file, "figure(3); clf;\n");
+ fprintf(debug_file, "figure(2); clf;\n");
+ fprintf(debug_file, "figure(1); clf;\n");
+ for (int c = 0; c < 3; ++c) {
+ fprintf(debug_file, "noise_strength_%d = [\n", c);
+ const aom_equation_system_t *eqns =
+ &noise_model->combined_state[c].strength_solver.eqns;
+ for (int k = 0; k < eqns->n; ++k) {
+ fprintf(debug_file, "%lf ", eqns->x[k]);
+ }
+ fprintf(debug_file, "];\n");
+ fprintf(debug_file, "plot(noise_strength_%d); hold on;\n", c);
+ }
+ fprintf(debug_file, "legend('Y', 'cb', 'cr');\n");
+ fprintf(debug_file, "title('Noise strength function');\n");
+
+#if CONFIG_AV1_DECODER
+ aom_film_grain_t grain;
+ aom_noise_model_get_grain_parameters(noise_model, &grain);
+ print_variance_y(debug_file, raw, denoised, flat_blocks, block_size, &grain);
+#endif
+ fflush(debug_file);
+}
+
+int main(int argc, char *argv[]) {
+ noise_model_args_t args = { 0, 0, { 25, 1 }, 0, 0, 0, AOM_IMG_FMT_I420,
+ 32, 8, 1, 0, 1, NULL };
+ aom_image_t raw, denoised;
+ FILE *infile = NULL;
+ AvxVideoInfo info;
+
+ memset(&info, 0, sizeof(info));
+
+ exec_name = argv[0];
+ parse_args(&args, &argc, argv + 1);
+
+ info.frame_width = args.width;
+ info.frame_height = args.height;
+ info.time_base.numerator = args.fps.den;
+ info.time_base.denominator = args.fps.num;
+
+ 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 (!aom_img_alloc(&raw, args.img_fmt, info.frame_width, info.frame_height,
+ 1)) {
+ die("Failed to allocate image.");
+ }
+ if (!aom_img_alloc(&denoised, args.img_fmt, info.frame_width,
+ info.frame_height, 1)) {
+ die("Failed to allocate image.");
+ }
+ infile = fopen(args.input, "r");
+ if (!infile) {
+ die("Failed to open input file:", args.input);
+ }
+ fprintf(stderr, "Bit depth: %d stride:%d\n", args.bit_depth, raw.stride[0]);
+
+ const int high_bd = args.bit_depth > 8;
+ const int block_size = args.block_size;
+ aom_flat_block_finder_t block_finder;
+ aom_flat_block_finder_init(&block_finder, block_size, args.bit_depth,
+ high_bd);
+
+ const int num_blocks_w = (info.frame_width + block_size - 1) / block_size;
+ const int num_blocks_h = (info.frame_height + block_size - 1) / block_size;
+ uint8_t *flat_blocks = (uint8_t *)aom_malloc(num_blocks_w * num_blocks_h);
+ // Sets the random seed on the first entry in the output table
+ int16_t random_seed = 1071;
+ aom_noise_model_t noise_model;
+ aom_noise_model_params_t params = { AOM_NOISE_SHAPE_SQUARE, 3, args.bit_depth,
+ high_bd };
+ aom_noise_model_init(&noise_model, params);
+
+ FILE *denoised_file = 0;
+ if (args.input_denoised) {
+ denoised_file = fopen(args.input_denoised, "rb");
+ if (!denoised_file)
+ die("Unable to open input_denoised: %s", args.input_denoised);
+ } else {
+ die("--input-denoised file must be specified");
+ }
+ FILE *debug_file = 0;
+ if (args.debug_file) {
+ debug_file = fopen(args.debug_file, "w");
+ }
+ aom_film_grain_table_t grain_table = { 0, 0 };
+
+ int64_t prev_timestamp = 0;
+ int frame_count = 0;
+ while (aom_img_read(&raw, infile)) {
+ if (args.input_denoised) {
+ if (!aom_img_read(&denoised, denoised_file)) {
+ die("Unable to read input denoised file");
+ }
+ }
+ if (frame_count % args.skip_frames == 0) {
+ int num_flat_blocks = num_blocks_w * num_blocks_h;
+ memset(flat_blocks, 1, num_flat_blocks);
+ if (args.run_flat_block_finder) {
+ memset(flat_blocks, 0, num_flat_blocks);
+ num_flat_blocks = aom_flat_block_finder_run(
+ &block_finder, raw.planes[0], info.frame_width, info.frame_height,
+ info.frame_width, flat_blocks);
+ fprintf(stdout, "Num flat blocks %d\n", num_flat_blocks);
+ }
+
+ const uint8_t *planes[3] = { raw.planes[0], raw.planes[1],
+ raw.planes[2] };
+ uint8_t *denoised_planes[3] = { denoised.planes[0], denoised.planes[1],
+ denoised.planes[2] };
+ int strides[3] = { raw.stride[0] >> high_bd, raw.stride[1] >> high_bd,
+ raw.stride[2] >> high_bd };
+ int chroma_sub[3] = { raw.x_chroma_shift, raw.y_chroma_shift, 0 };
+
+ fprintf(stdout, "Updating noise model...\n");
+ aom_noise_status_t status = aom_noise_model_update(
+ &noise_model, (const uint8_t *const *)planes,
+ (const uint8_t *const *)denoised_planes, info.frame_width,
+ info.frame_height, strides, chroma_sub, flat_blocks, block_size);
+
+ int64_t cur_timestamp =
+ frame_count * 10000000ULL * args.fps.den / args.fps.num;
+ if (status == AOM_NOISE_STATUS_DIFFERENT_NOISE_TYPE) {
+ fprintf(stdout,
+ "Noise type is different, updating parameters for time "
+ "[ %" PRId64 ", %" PRId64 ")\n",
+ prev_timestamp, cur_timestamp);
+ aom_film_grain_t grain;
+ aom_noise_model_get_grain_parameters(&noise_model, &grain);
+ grain.random_seed = random_seed;
+ random_seed = 0;
+ aom_film_grain_table_append(&grain_table, prev_timestamp, cur_timestamp,
+ &grain);
+ aom_noise_model_save_latest(&noise_model);
+ prev_timestamp = cur_timestamp;
+ }
+ if (debug_file) {
+ print_debug_info(debug_file, &raw, &denoised, flat_blocks, block_size,
+ &noise_model);
+ }
+ fprintf(stdout, "Done noise model update, status = %d\n", status);
+ }
+ frame_count++;
+ }
+
+ aom_film_grain_t grain;
+ aom_noise_model_get_grain_parameters(&noise_model, &grain);
+ grain.random_seed = random_seed;
+ aom_film_grain_table_append(&grain_table, prev_timestamp, INT64_MAX, &grain);
+ if (args.output_grain_table) {
+ struct aom_internal_error_info error_info;
+ if (AOM_CODEC_OK != aom_film_grain_table_write(&grain_table,
+ args.output_grain_table,
+ &error_info)) {
+ die("Unable to write output film grain table");
+ }
+ }
+ aom_film_grain_table_free(&grain_table);
+
+ if (infile) fclose(infile);
+ if (denoised_file) fclose(denoised_file);
+ if (debug_file) fclose(debug_file);
+ aom_img_free(&raw);
+ aom_img_free(&denoised);
+
+ return EXIT_SUCCESS;
+}
diff --git a/third_party/aom/examples/resize_util.c b/third_party/aom/examples/resize_util.c
index 5485691a8..6a84d5740 100644
--- a/third_party/aom/examples/resize_util.c
+++ b/third_party/aom/examples/resize_util.c
@@ -16,8 +16,8 @@
#include <stdlib.h>
#include <string.h>
-#include "../tools_common.h"
-#include "../av1/encoder/av1_resize.h"
+#include "av1/common/resize.h"
+#include "common/tools_common.h"
static const char *exec_name = NULL;
diff --git a/third_party/aom/examples/scalable_decoder.c b/third_party/aom/examples/scalable_decoder.c
new file mode 100644
index 000000000..c22924223
--- /dev/null
+++ b/third_party/aom/examples/scalable_decoder.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// Scalable Decoder
+// ==============
+//
+// This is an example of a scalable decoder loop. It takes a 2-spatial-layer
+// input file
+// containing the compressed data (in OBU format), passes it through the
+// decoder, and writes the decompressed frames to disk. The base layer and
+// enhancement layers are stored as separate files, out_lyr0.yuv and
+// out_lyr1.yuv, respectively.
+//
+// Standard Includes
+// -----------------
+// For decoders, you only have to include `aom_decoder.h` and then any
+// header files for the specific codecs you use. In this case, we're using
+// av1.
+//
+// Initializing The Codec
+// ----------------------
+// The libaom decoder is initialized by the call to aom_codec_dec_init().
+// Determining the codec interface to use is handled by AvxVideoReader and the
+// functions prefixed with aom_video_reader_. Discussion of those functions is
+// beyond the scope of this example, but the main gist is to open the input file
+// and parse just enough of it to determine if it's a AVx file and which AVx
+// codec is contained within the file.
+// Note the NULL pointer passed to aom_codec_dec_init(). We do that in this
+// example because we want the algorithm to determine the stream configuration
+// (width/height) and allocate memory automatically.
+//
+// Decoding A Frame
+// ----------------
+// Once the frame has been read into memory, it is decoded using the
+// `aom_codec_decode` function. The call takes a pointer to the data
+// (`frame`) and the length of the data (`frame_size`). No application data
+// is associated with the frame in this example, so the `user_priv`
+// parameter is NULL. The `deadline` parameter is left at zero for this
+// example. This parameter is generally only used when doing adaptive post
+// processing.
+//
+// Codecs may produce a variable number of output frames for every call to
+// `aom_codec_decode`. These frames are retrieved by the
+// `aom_codec_get_frame` iterator function. The iterator variable `iter` is
+// initialized to NULL each time `aom_codec_decode` is called.
+// `aom_codec_get_frame` is called in a loop, returning a pointer to a
+// decoded image or NULL to indicate the end of list.
+//
+// Processing The Decoded Data
+// ---------------------------
+// In this example, we simply write the encoded data to disk. It is
+// important to honor the image's `stride` values.
+//
+// Cleanup
+// -------
+// The `aom_codec_destroy` call frees any memory allocated by the codec.
+//
+// Error Handling
+// --------------
+// This example does not special case any error return codes. If there was
+// an error, a descriptive message is printed and the program exits. With
+// few exceptions, aom_codec functions return an enumerated error status,
+// with the value `0` indicating success.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "aom/aom_decoder.h"
+#include "aom/aomdx.h"
+#include "common/obudec.h"
+#include "common/tools_common.h"
+#include "common/video_reader.h"
+
+static const char *exec_name;
+
+#define MAX_LAYERS 5
+
+void usage_exit(void) {
+ fprintf(stderr, "Usage: %s <infile>\n", exec_name);
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv) {
+ int frame_cnt = 0;
+ FILE *outfile[MAX_LAYERS];
+ char filename[80];
+ aom_codec_ctx_t codec;
+ const AvxInterface *decoder = NULL;
+ FILE *inputfile = NULL;
+ uint8_t *buf = NULL;
+ size_t bytes_in_buffer = 0;
+ size_t buffer_size = 0;
+ struct AvxInputContext aom_input_ctx;
+ struct ObuDecInputContext obu_ctx = { &aom_input_ctx, NULL, 0, 0, 0 };
+ aom_codec_stream_info_t si;
+ uint8_t tmpbuf[32];
+ unsigned int i;
+
+ exec_name = argv[0];
+
+ if (argc != 2) die("Invalid number of arguments.");
+
+ if (!(inputfile = fopen(argv[1], "rb")))
+ die("Failed to open %s for read.", argv[1]);
+ obu_ctx.avx_ctx->file = inputfile;
+ obu_ctx.avx_ctx->filename = argv[1];
+
+ decoder = get_aom_decoder_by_index(0);
+ printf("Using %s\n", aom_codec_iface_name(decoder->codec_interface()));
+
+ if (aom_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
+ die_codec(&codec, "Failed to initialize decoder.");
+
+ if (aom_codec_control(&codec, AV1D_SET_OUTPUT_ALL_LAYERS, 1)) {
+ die_codec(&codec, "Failed to set output_all_layers control.");
+ }
+
+ // peak sequence header OBU to get number of spatial layers
+ const size_t ret = fread(tmpbuf, 1, 32, inputfile);
+ if (ret != 32) die_codec(&codec, "Input is not a valid obu file");
+ si.is_annexb = 0;
+ if (aom_codec_peek_stream_info(decoder->codec_interface(), tmpbuf, 32, &si)) {
+ die_codec(&codec, "Input is not a valid obu file");
+ }
+ fseek(inputfile, -32, SEEK_CUR);
+
+ if (!file_is_obu(&obu_ctx))
+ die_codec(&codec, "Input is not a valid obu file");
+
+ // open base layer output yuv file
+ snprintf(filename, sizeof(filename), "out_lyr%d.yuv", 0);
+ if (!(outfile[0] = fopen(filename, "wb")))
+ die("Failed top open output for writing.");
+
+ // open any enhancement layer output yuv files
+ for (i = 1; i < si.number_spatial_layers; i++) {
+ snprintf(filename, sizeof(filename), "out_lyr%d.yuv", i);
+ if (!(outfile[i] = fopen(filename, "wb")))
+ die("Failed to open output for writing.");
+ }
+
+ while (!obudec_read_temporal_unit(&obu_ctx, &buf, &bytes_in_buffer,
+ &buffer_size)) {
+ aom_codec_iter_t iter = NULL;
+ aom_image_t *img = NULL;
+ if (aom_codec_decode(&codec, buf, bytes_in_buffer, NULL))
+ die_codec(&codec, "Failed to decode frame.");
+
+ while ((img = aom_codec_get_frame(&codec, &iter)) != NULL) {
+ aom_image_t *img_shifted =
+ aom_img_alloc(NULL, AOM_IMG_FMT_I420, img->d_w, img->d_h, 16);
+ img_shifted->bit_depth = 8;
+ aom_img_downshift(img_shifted, img,
+ img->bit_depth - img_shifted->bit_depth);
+ if (img->spatial_id == 0) {
+ printf("Writing base layer 0 %d\n", frame_cnt);
+ aom_img_write(img_shifted, outfile[0]);
+ } else if (img->spatial_id <= (int)(si.number_spatial_layers - 1)) {
+ printf("Writing enhancement layer %d %d\n", img->spatial_id, frame_cnt);
+ aom_img_write(img_shifted, outfile[img->spatial_id]);
+ } else {
+ die_codec(&codec, "Invalid bitstream. Layer id exceeds layer count");
+ }
+ if (img->spatial_id == (int)(si.number_spatial_layers - 1)) ++frame_cnt;
+ }
+ }
+
+ printf("Processed %d frames.\n", frame_cnt);
+ if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
+
+ for (i = 0; i < si.number_spatial_layers; i++) fclose(outfile[i]);
+
+ fclose(inputfile);
+
+ return EXIT_SUCCESS;
+}
diff --git a/third_party/aom/examples/scalable_encoder.c b/third_party/aom/examples/scalable_encoder.c
new file mode 100644
index 000000000..7af03e29f
--- /dev/null
+++ b/third_party/aom/examples/scalable_encoder.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// Scalable Encoder
+// ==============
+//
+// This is an example of a scalable encoder loop. It takes two input files in
+// YV12 format, passes it through the encoder, and writes the compressed
+// frames to disk in OBU format.
+//
+// Getting The Default Configuration
+// ---------------------------------
+// Encoders have the notion of "usage profiles." For example, an encoder
+// may want to publish default configurations for both a video
+// conferencing application and a best quality offline encoder. These
+// obviously have very different default settings. Consult the
+// documentation for your codec to see if it provides any default
+// configurations. All codecs provide a default configuration, number 0,
+// which is valid for material in the vacinity of QCIF/QVGA.
+//
+// Updating The Configuration
+// ---------------------------------
+// Almost all applications will want to update the default configuration
+// with settings specific to their usage. Here we set the width and height
+// of the video file to that specified on the command line. We also scale
+// the default bitrate based on the ratio between the default resolution
+// and the resolution specified on the command line.
+//
+// Encoding A Frame
+// ----------------
+// The frame is read as a continuous block (size = width * height * 3 / 2)
+// from the input file. If a frame was read (the input file has not hit
+// EOF) then the frame is passed to the encoder. Otherwise, a NULL
+// is passed, indicating the End-Of-Stream condition to the encoder. The
+// `frame_cnt` is reused as the presentation time stamp (PTS) and each
+// frame is shown for one frame-time in duration. The flags parameter is
+// unused in this example.
+
+// Forced Keyframes
+// ----------------
+// Keyframes can be forced by setting the AOM_EFLAG_FORCE_KF bit of the
+// flags passed to `aom_codec_control()`. In this example, we force a
+// keyframe every <keyframe-interval> frames. Note, the output stream can
+// contain additional keyframes beyond those that have been forced using the
+// AOM_EFLAG_FORCE_KF flag because of automatic keyframe placement by the
+// encoder.
+//
+// Processing The Encoded Data
+// ---------------------------
+// Each packet of type `AOM_CODEC_CX_FRAME_PKT` contains the encoded data
+// for this frame. We write a IVF frame header, followed by the raw data.
+//
+// Cleanup
+// -------
+// The `aom_codec_destroy` call frees any memory allocated by the codec.
+//
+// Error Handling
+// --------------
+// This example does not special case any error return codes. If there was
+// an error, a descriptive message is printed and the program exits. With
+// few exeptions, aom_codec functions return an enumerated error status,
+// with the value `0` indicating success.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "aom/aom_encoder.h"
+#include "aom/aomcx.h"
+#include "av1/common/enums.h"
+#include "common/tools_common.h"
+#include "common/video_writer.h"
+
+static const char *exec_name;
+
+void usage_exit(void) {
+ fprintf(stderr,
+ "Usage: %s <codec> <width> <height> <infile0> <infile1> "
+ "<outfile> <frames to encode>\n"
+ "See comments in scalable_encoder.c for more information.\n",
+ exec_name);
+ exit(EXIT_FAILURE);
+}
+
+static int encode_frame(aom_codec_ctx_t *codec, aom_image_t *img,
+ int frame_index, int flags, FILE *outfile) {
+ int got_pkts = 0;
+ aom_codec_iter_t iter = NULL;
+ const aom_codec_cx_pkt_t *pkt = NULL;
+ const aom_codec_err_t res =
+ aom_codec_encode(codec, img, frame_index, 1, flags);
+ if (res != AOM_CODEC_OK) die_codec(codec, "Failed to encode frame");
+
+ while ((pkt = aom_codec_get_cx_data(codec, &iter)) != NULL) {
+ got_pkts = 1;
+
+ if (pkt->kind == AOM_CODEC_CX_FRAME_PKT) {
+ const int keyframe = (pkt->data.frame.flags & AOM_FRAME_IS_KEY) != 0;
+ if (fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile) !=
+ pkt->data.frame.sz) {
+ die_codec(codec, "Failed to write compressed frame");
+ }
+ printf(keyframe ? "K" : ".");
+ printf(" %6d\n", (int)pkt->data.frame.sz);
+ fflush(stdout);
+ }
+ }
+
+ return got_pkts;
+}
+
+int main(int argc, char **argv) {
+ FILE *infile0 = NULL;
+ FILE *infile1 = NULL;
+ aom_codec_ctx_t codec;
+ aom_codec_enc_cfg_t cfg;
+ int frame_count = 0;
+ aom_image_t raw0, raw1;
+ aom_codec_err_t res;
+ AvxVideoInfo info;
+ const AvxInterface *encoder = NULL;
+ const int fps = 30;
+ const int bitrate = 200;
+ int keyframe_interval = 0;
+ int max_frames = 0;
+ int frames_encoded = 0;
+ const char *codec_arg = NULL;
+ const char *width_arg = NULL;
+ const char *height_arg = NULL;
+ const char *infile0_arg = NULL;
+ const char *infile1_arg = NULL;
+ const char *outfile_arg = NULL;
+ // const char *keyframe_interval_arg = NULL;
+ FILE *outfile = NULL;
+
+ exec_name = argv[0];
+
+ // Clear explicitly, as simply assigning "{ 0 }" generates
+ // "missing-field-initializers" warning in some compilers.
+ memset(&info, 0, sizeof(info));
+
+ if (argc != 8) die("Invalid number of arguments");
+
+ codec_arg = argv[1];
+ width_arg = argv[2];
+ height_arg = argv[3];
+ infile0_arg = argv[4];
+ infile1_arg = argv[5];
+ outfile_arg = argv[6];
+ max_frames = (int)strtol(argv[7], NULL, 0);
+
+ encoder = get_aom_encoder_by_name(codec_arg);
+ if (!encoder) die("Unsupported codec.");
+
+ info.codec_fourcc = encoder->fourcc;
+ info.frame_width = (int)strtol(width_arg, NULL, 0);
+ info.frame_height = (int)strtol(height_arg, 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 (!aom_img_alloc(&raw0, AOM_IMG_FMT_I420, info.frame_width,
+ info.frame_height, 1)) {
+ die("Failed to allocate image for layer 0.");
+ }
+ if (!aom_img_alloc(&raw1, AOM_IMG_FMT_I420, info.frame_width,
+ info.frame_height, 1)) {
+ die("Failed to allocate image for layer 1.");
+ }
+
+ // keyframe_interval = (int)strtol(keyframe_interval_arg, NULL, 0);
+ keyframe_interval = 100;
+ if (keyframe_interval < 0) die("Invalid keyframe interval value.");
+
+ printf("Using %s\n", aom_codec_iface_name(encoder->codec_interface()));
+
+ res = aom_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;
+ cfg.g_error_resilient = 0;
+ cfg.g_lag_in_frames = 0;
+ cfg.rc_end_usage = AOM_Q;
+ cfg.save_as_annexb = 0;
+
+ outfile = fopen(outfile_arg, "wb");
+ if (!outfile) die("Failed to open %s for writing.", outfile_arg);
+
+ if (!(infile0 = fopen(infile0_arg, "rb")))
+ die("Failed to open %s for reading.", infile0_arg);
+ if (!(infile1 = fopen(infile1_arg, "rb")))
+ die("Failed to open %s for reading.", infile0_arg);
+
+ if (aom_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
+ die_codec(&codec, "Failed to initialize encoder");
+ if (aom_codec_control(&codec, AOME_SET_CPUUSED, 8))
+ die_codec(&codec, "Failed to set cpu to 8");
+
+ if (aom_codec_control(&codec, AV1E_SET_TILE_COLUMNS, 2))
+ die_codec(&codec, "Failed to set tile columns to 2");
+ if (aom_codec_control(&codec, AV1E_SET_NUM_TG, 3))
+ die_codec(&codec, "Failed to set num of tile groups to 3");
+
+ if (aom_codec_control(&codec, AOME_SET_NUMBER_SPATIAL_LAYERS, 2))
+ die_codec(&codec, "Failed to set number of spatial layers to 2");
+
+ // Encode frames.
+ while (aom_img_read(&raw0, infile0)) {
+ int flags = 0;
+
+ // configure and encode base layer
+
+ if (keyframe_interval > 0 && frames_encoded % keyframe_interval == 0)
+ flags |= AOM_EFLAG_FORCE_KF;
+ else
+ // use previous base layer (LAST) as sole reference
+ // save this frame as LAST to be used as reference by enhanmcent layer
+ // and next base layer
+ flags |= AOM_EFLAG_NO_REF_LAST2 | AOM_EFLAG_NO_REF_LAST3 |
+ AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF |
+ AOM_EFLAG_NO_REF_BWD | AOM_EFLAG_NO_REF_ARF2 |
+ AOM_EFLAG_NO_UPD_GF | AOM_EFLAG_NO_UPD_ARF |
+ AOM_EFLAG_NO_UPD_ENTROPY;
+ cfg.g_w = info.frame_width;
+ cfg.g_h = info.frame_height;
+ if (aom_codec_enc_config_set(&codec, &cfg))
+ die_codec(&codec, "Failed to set enc cfg for layer 0");
+ if (aom_codec_control(&codec, AOME_SET_SPATIAL_LAYER_ID, 0))
+ die_codec(&codec, "Failed to set layer id to 0");
+ if (aom_codec_control(&codec, AOME_SET_CQ_LEVEL, 62))
+ die_codec(&codec, "Failed to set cq level");
+ encode_frame(&codec, &raw0, frame_count++, flags, outfile);
+
+ // configure and encode enhancement layer
+
+ // use LAST (base layer) as sole reference
+ flags = AOM_EFLAG_NO_REF_LAST2 | AOM_EFLAG_NO_REF_LAST3 |
+ AOM_EFLAG_NO_REF_GF | AOM_EFLAG_NO_REF_ARF | AOM_EFLAG_NO_REF_BWD |
+ AOM_EFLAG_NO_REF_ARF2 | AOM_EFLAG_NO_UPD_LAST |
+ AOM_EFLAG_NO_UPD_GF | AOM_EFLAG_NO_UPD_ARF |
+ AOM_EFLAG_NO_UPD_ENTROPY;
+ cfg.g_w = info.frame_width;
+ cfg.g_h = info.frame_height;
+ aom_img_read(&raw1, infile1);
+ if (aom_codec_enc_config_set(&codec, &cfg))
+ die_codec(&codec, "Failed to set enc cfg for layer 1");
+ if (aom_codec_control(&codec, AOME_SET_SPATIAL_LAYER_ID, 1))
+ die_codec(&codec, "Failed to set layer id to 1");
+ if (aom_codec_control(&codec, AOME_SET_CQ_LEVEL, 10))
+ die_codec(&codec, "Failed to set cq level");
+ encode_frame(&codec, &raw1, frame_count++, flags, outfile);
+
+ frames_encoded++;
+
+ if (max_frames > 0 && frames_encoded >= max_frames) break;
+ }
+
+ // Flush encoder.
+ while (encode_frame(&codec, NULL, -1, 0, outfile)) continue;
+
+ printf("\n");
+ fclose(infile0);
+ fclose(infile1);
+ printf("Processed %d frames.\n", frame_count / 2);
+
+ aom_img_free(&raw0);
+ aom_img_free(&raw1);
+ if (aom_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
+
+ fclose(outfile);
+
+ return EXIT_SUCCESS;
+}
diff --git a/third_party/aom/examples/set_maps.c b/third_party/aom/examples/set_maps.c
index 3a54e5f96..9aeb96e43 100644
--- a/third_party/aom/examples/set_maps.c
+++ b/third_party/aom/examples/set_maps.c
@@ -47,11 +47,10 @@
#include <stdlib.h>
#include <string.h>
-#include "aom/aomcx.h"
#include "aom/aom_encoder.h"
-
-#include "../tools_common.h"
-#include "../video_writer.h"
+#include "aom/aomcx.h"
+#include "common/tools_common.h"
+#include "common/video_writer.h"
static const char *exec_name;
@@ -95,8 +94,7 @@ static int encode_frame(aom_codec_ctx_t *codec, aom_image_t *img,
int got_pkts = 0;
aom_codec_iter_t iter = NULL;
const aom_codec_cx_pkt_t *pkt = NULL;
- const aom_codec_err_t res =
- aom_codec_encode(codec, img, frame_index, 1, 0, AOM_DL_GOOD_QUALITY);
+ const aom_codec_err_t res = aom_codec_encode(codec, img, frame_index, 1, 0);
if (res != AOM_CODEC_OK) die_codec(codec, "Failed to encode frame");
while ((pkt = aom_codec_get_cx_data(codec, &iter)) != NULL) {
diff --git a/third_party/aom/examples/simple_decoder.c b/third_party/aom/examples/simple_decoder.c
index 33a894539..d098d1e0b 100644
--- a/third_party/aom/examples/simple_decoder.c
+++ b/third_party/aom/examples/simple_decoder.c
@@ -49,9 +49,7 @@
// `aom_codec_decode` function. The call takes a pointer to the data
// (`frame`) and the length of the data (`frame_size`). No application data
// is associated with the frame in this example, so the `user_priv`
-// parameter is NULL. The `deadline` parameter is left at zero for this
-// example. This parameter is generally only used when doing adaptive post
-// processing.
+// parameter is NULL.
//
// Codecs may produce a variable number of output frames for every call to
// `aom_codec_decode`. These frames are retrieved by the
@@ -81,10 +79,8 @@
#include <string.h>
#include "aom/aom_decoder.h"
-
-#include "../tools_common.h"
-#include "../video_reader.h"
-#include "./aom_config.h"
+#include "common/tools_common.h"
+#include "common/video_reader.h"
static const char *exec_name;
@@ -127,7 +123,7 @@ int main(int argc, char **argv) {
size_t frame_size = 0;
const unsigned char *frame =
aom_video_reader_get_frame(reader, &frame_size);
- if (aom_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
+ if (aom_codec_decode(&codec, frame, frame_size, NULL))
die_codec(&codec, "Failed to decode frame.");
while ((img = aom_codec_get_frame(&codec, &iter)) != NULL) {
diff --git a/third_party/aom/examples/simple_encoder.c b/third_party/aom/examples/simple_encoder.c
index 996f6dacf..01a37cf0c 100644
--- a/third_party/aom/examples/simple_encoder.c
+++ b/third_party/aom/examples/simple_encoder.c
@@ -100,9 +100,8 @@
#include <string.h>
#include "aom/aom_encoder.h"
-
-#include "../tools_common.h"
-#include "../video_writer.h"
+#include "common/tools_common.h"
+#include "common/video_writer.h"
static const char *exec_name;
@@ -121,7 +120,7 @@ static int encode_frame(aom_codec_ctx_t *codec, aom_image_t *img,
aom_codec_iter_t iter = NULL;
const aom_codec_cx_pkt_t *pkt = NULL;
const aom_codec_err_t res =
- aom_codec_encode(codec, img, frame_index, 1, flags, AOM_DL_GOOD_QUALITY);
+ aom_codec_encode(codec, img, frame_index, 1, flags);
if (res != AOM_CODEC_OK) die_codec(codec, "Failed to encode frame");
while ((pkt = aom_codec_get_cx_data(codec, &iter)) != NULL) {
diff --git a/third_party/aom/examples/twopass_encoder.c b/third_party/aom/examples/twopass_encoder.c
index e767bb5d7..1b134cce0 100644
--- a/third_party/aom/examples/twopass_encoder.c
+++ b/third_party/aom/examples/twopass_encoder.c
@@ -52,9 +52,8 @@
#include <string.h>
#include "aom/aom_encoder.h"
-
-#include "../tools_common.h"
-#include "../video_writer.h"
+#include "common/tools_common.h"
+#include "common/video_writer.h"
static const char *exec_name;
@@ -68,13 +67,12 @@ void usage_exit(void) {
static int get_frame_stats(aom_codec_ctx_t *ctx, const aom_image_t *img,
aom_codec_pts_t pts, unsigned int duration,
- aom_enc_frame_flags_t flags, unsigned int deadline,
+ aom_enc_frame_flags_t flags,
aom_fixed_buf_t *stats) {
int got_pkts = 0;
aom_codec_iter_t iter = NULL;
const aom_codec_cx_pkt_t *pkt = NULL;
- const aom_codec_err_t res =
- aom_codec_encode(ctx, img, pts, duration, flags, deadline);
+ const aom_codec_err_t res = aom_codec_encode(ctx, img, pts, duration, flags);
if (res != AOM_CODEC_OK) die_codec(ctx, "Failed to get frame stats.");
while ((pkt = aom_codec_get_cx_data(ctx, &iter)) != NULL) {
@@ -94,13 +92,11 @@ static int get_frame_stats(aom_codec_ctx_t *ctx, const aom_image_t *img,
static int encode_frame(aom_codec_ctx_t *ctx, const aom_image_t *img,
aom_codec_pts_t pts, unsigned int duration,
- aom_enc_frame_flags_t flags, unsigned int deadline,
- AvxVideoWriter *writer) {
+ aom_enc_frame_flags_t flags, AvxVideoWriter *writer) {
int got_pkts = 0;
aom_codec_iter_t iter = NULL;
const aom_codec_cx_pkt_t *pkt = NULL;
- const aom_codec_err_t res =
- aom_codec_encode(ctx, img, pts, duration, flags, deadline);
+ const aom_codec_err_t res = aom_codec_encode(ctx, img, pts, duration, flags);
if (res != AOM_CODEC_OK) die_codec(ctx, "Failed to encode frame.");
while ((pkt = aom_codec_get_cx_data(ctx, &iter)) != NULL) {
@@ -133,13 +129,11 @@ static aom_fixed_buf_t pass0(aom_image_t *raw, FILE *infile,
// Calculate frame statistics.
while (aom_img_read(raw, infile) && frame_count < limit) {
++frame_count;
- get_frame_stats(&codec, raw, frame_count, 1, 0, AOM_DL_GOOD_QUALITY,
- &stats);
+ get_frame_stats(&codec, raw, frame_count, 1, 0, &stats);
}
// Flush encoder.
- while (get_frame_stats(&codec, NULL, frame_count, 1, 0, AOM_DL_GOOD_QUALITY,
- &stats)) {
+ while (get_frame_stats(&codec, NULL, frame_count, 1, 0, &stats)) {
}
printf("Pass 0 complete. Processed %d frames.\n", frame_count);
@@ -168,11 +162,11 @@ static void pass1(aom_image_t *raw, FILE *infile, const char *outfile_name,
// Encode frames.
while (aom_img_read(raw, infile) && frame_count < limit) {
++frame_count;
- encode_frame(&codec, raw, frame_count, 1, 0, AOM_DL_GOOD_QUALITY, writer);
+ encode_frame(&codec, raw, frame_count, 1, 0, writer);
}
// Flush encoder.
- while (encode_frame(&codec, NULL, -1, 1, 0, AOM_DL_GOOD_QUALITY, writer)) {
+ while (encode_frame(&codec, NULL, -1, 1, 0, writer)) {
}
printf("\n");