WIP: CONFIG_INSPECTION: fix non show frames
This makes non showable frames - analyzeable and also fixes
display of motion vectors.
Change-Id: Ie286a3d2005a0c5e35d164ed62dd0fe2269b9be6
diff --git a/examples/inspect.c b/examples/inspect.c
index 8c132a6..3ccb6e6 100644
--- a/examples/inspect.c
+++ b/examples/inspect.c
@@ -548,22 +548,51 @@
return EXIT_SUCCESS;
}
+VpxDecodeReturn adr;
+int have_frame = 0;
+const unsigned char *frame;
+const unsigned char *end_frame;
+size_t frame_size = 0;
+vpx_codec_iter_t iter = NULL;
EMSCRIPTEN_KEEPALIVE
int read_frame() {
- if (!vpx_video_reader_read_frame(reader)) return EXIT_FAILURE;
+ int got_any_frames = 0;
+ struct vpx_ref_frame ref_dec;
img = NULL;
- vpx_codec_iter_t iter = NULL;
- size_t frame_size = 0;
- const unsigned char *frame = vpx_video_reader_get_frame(reader, &frame_size);
- if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0) !=
- VPX_CODEC_OK) {
- die_codec(&codec, "Failed to decode frame.");
+
+ // This loop skips over any frames that are show_existing_frames, as
+ // there is nothing to analyze.
+ do {
+ if (!have_frame) {
+ if (!vpx_video_reader_read_frame(reader)) return EXIT_FAILURE;
+ frame = vpx_video_reader_get_frame(reader, &frame_size);
+
+ have_frame = 1;
+ end_frame = frame + frame_size;
+ }
+
+ if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, &adr, 0) !=
+ VPX_CODEC_OK) {
+ die_codec(&codec, "Failed to decode frame.");
+ }
+
+ frame = adr.buf;
+ if (adr.finished_superframes) have_frame = 0;
+ } while (adr.show_existing);
+
+ // ref_dec.idx is the index to the reference buffer idx to VP9_GET_REFERENCE
+ // if its -1 the decoder didn't update any reference buffer and the only
+ // way to see the frame is aom_codec_get_frame.
+ ref_dec.frame_type = adr.idx;
+
+ if (!vpx_codec_control(&codec, VP9_GET_REFERENCE, &ref_dec)) {
+ img = &ref_dec.img;
+ ++frame_count;
+ got_any_frames = 1;
}
- img = vpx_codec_get_frame(&codec, &iter);
- if (img == NULL) {
+ if (!got_any_frames) {
return EXIT_FAILURE;
}
- ++frame_count;
return EXIT_SUCCESS;
}
diff --git a/tools/build_inspector.sh b/tools/build_inspector.sh
index 3cceb60..4619b34 100755
--- a/tools/build_inspector.sh
+++ b/tools/build_inspector.sh
@@ -32,7 +32,7 @@
--disable-docs \
--disable-unit-tests \
--enable-inspection \
- --extra-cflags="-D_POSIX_SOURCE"
+ --extra-cflags="-D_POSIX_SOURCE -s ALLOW_MEMORY_GROWTH=1"
cd ..
fi
@@ -43,6 +43,7 @@
-s TOTAL_MEMORY=134217728 \
-s MODULARIZE=1 \
-s EXPORT_NAME="'DecoderModule'" \
+ -s ALLOW_MEMORY_GROWTH=1 \
--post-js "../inspect-post.js" \
--memory-init-file 0
cp inspect.js ../inspect.js
diff --git a/vp9/decoder/inspection.c b/vp9/decoder/inspection.c
index b6b38a5..2be2569 100644
--- a/vp9/decoder/inspection.c
+++ b/vp9/decoder/inspection.c
@@ -43,6 +43,8 @@
fd->frame_type = cm->frame_type;
fd->base_qindex = cm->base_qindex;
// TODO(jimbankoski): copy tile data
+ fd->show_existing_frame = cm->show_existing_frame;
+
// fd->tile_mi_cols = cm->tile_width;
// fd->tile_mi_rows = cm->tile_height;
#if CONFIG_ACCOUNTING
@@ -64,8 +66,14 @@
// Motion Vectors
mi->mv[0].row = bmi->mv[0].as_mv.row;
mi->mv[0].col = bmi->mv[0].as_mv.col;
- mi->mv[1].row = bmi->mv[1].as_mv.row;
- mi->mv[1].col = bmi->mv[1].as_mv.col;
+
+ if (bmi->ref_frame[1] == -1) {
+ mi->mv[1].row = 0;
+ mi->mv[1].col = 0;
+ } else {
+ mi->mv[1].row = bmi->mv[1].as_mv.row;
+ mi->mv[1].col = bmi->mv[1].as_mv.col;
+ }
// Reference Frames
mi->ref_frame[0] = bmi->ref_frame[0];
mi->ref_frame[1] = bmi->ref_frame[1];
diff --git a/vp9/decoder/inspection.h b/vp9/decoder/inspection.h
index a3c9807..304e2ee 100644
--- a/vp9/decoder/inspection.h
+++ b/vp9/decoder/inspection.h
@@ -58,6 +58,7 @@
int show_frame;
int frame_type;
int base_qindex;
+ int show_existing_frame;
int mi_rows;
int mi_cols;
int tile_mi_rows;
diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c
index 2bf0d78..1f13d87 100644
--- a/vp9/vp9_dx_iface.c
+++ b/vp9/vp9_dx_iface.c
@@ -279,7 +279,10 @@
set_default_ppflags(&ctx->postproc_cfg);
init_buffer_callbacks(ctx);
-
+#if CONFIG_INSPECTION
+ ctx->frame_count = 0;
+ ctx->which_frame = 0;
+#endif
return VPX_CODEC_OK;
}
@@ -333,6 +336,68 @@
return VPX_CODEC_OK;
}
+#if CONFIG_INSPECTION
+// This function enables the inspector to inspect non visible frames.
+static vpx_codec_err_t decoder_inspect(vpx_codec_alg_priv_t *ctx,
+ const uint8_t *data, size_t data_sz,
+ void *user_priv, int64_t deadline) {
+ vpx_codec_err_t res = VPX_CODEC_OK;
+
+ if (ctx->pbi == NULL) {
+ const vpx_codec_err_t res = init_decoder(ctx);
+ if (res != VPX_CODEC_OK) return res;
+ }
+
+ if (ctx->which_frame >= ctx->frame_count) {
+ int i;
+ const uint8_t *data_start = data;
+ const uint8_t *const data_end = data + data_sz;
+ res = vp9_parse_superframe_index(data, data_sz, ctx->frame_sizes,
+ &ctx->frame_count, ctx->decrypt_cb,
+ ctx->decrypt_state);
+
+ if (res != VPX_CODEC_OK) return res;
+ if (ctx->svc_decoding && ctx->svc_spatial_layer < ctx->frame_count - 1)
+ ctx->frame_count = ctx->svc_spatial_layer + 1;
+
+ ctx->which_frame = 0;
+
+ // Double check that we don't have problems with the index;
+ for (i = 0; i < ctx->frame_count; ++i) {
+ const uint32_t frame_size = ctx->frame_sizes[i];
+ if (data_start < data || frame_size > (uint32_t)(data_end - data_start)) {
+ set_error_detail(ctx, "Invalid frame size in index");
+ return VPX_CODEC_CORRUPT_FRAME;
+ }
+ data_start += frame_size;
+ }
+ }
+ if (ctx->frame_count == 0) ctx->frame_sizes[0] = data_sz;
+
+ // Decode in serial mode.
+ if (ctx->frame_count >= 0) {
+ int i;
+ vpx_codec_err_t res;
+ VP9_COMMON *const cm = &ctx->pbi->common;
+ VpxDecodeReturn *data2 = (VpxDecodeReturn *)user_priv;
+ const uint8_t *data_start = data;
+
+ res =
+ decode_one(ctx, &data, ctx->frame_sizes[ctx->which_frame], 0, deadline);
+ if (res != VPX_CODEC_OK) return res;
+
+ data2->idx = cm->new_fb_idx;
+
+ data2->buf = data_start + ctx->frame_sizes[ctx->which_frame];
+ data2->show_existing = cm->show_existing_frame;
+ ctx->which_frame++;
+ data2->finished_superframes = (ctx->which_frame >= ctx->frame_count);
+ return res;
+ }
+ return VPX_CODEC_OK;
+}
+#endif
+
static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx,
const uint8_t *data, unsigned int data_sz,
void *user_priv, long deadline) {
@@ -341,7 +406,11 @@
vpx_codec_err_t res;
uint32_t frame_sizes[8];
int frame_count;
-
+#if CONFIG_INSPECTION
+ if (user_priv != 0) {
+ return decoder_inspect(ctx, data, data_sz, user_priv, deadline);
+ }
+#endif
if (data == NULL && data_sz == 0) {
ctx->flushed = 1;
return VPX_CODEC_OK;
@@ -479,7 +548,11 @@
vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);
if (data) {
+#if CONFIG_INSPECTION
+ const int fb_idx = data->idx;
+#else
const int fb_idx = ctx->pbi->common.cur_show_frame_fb_idx;
+#endif
YV12_BUFFER_CONFIG *fb = get_buf_frame(&ctx->pbi->common, fb_idx);
if (fb == NULL) return VPX_CODEC_ERROR;
yuvconfig2image(&data->img, fb, NULL);
diff --git a/vp9/vp9_dx_iface.h b/vp9/vp9_dx_iface.h
index 7229597..e20aed9 100644
--- a/vp9/vp9_dx_iface.h
+++ b/vp9/vp9_dx_iface.h
@@ -51,6 +51,9 @@
#if CONFIG_INSPECTION
vpx_inspect_cb inspect_cb;
void *inspect_ctx;
+ uint32_t frame_sizes[8];
+ int frame_count;
+ int which_frame;
#endif
};
diff --git a/vpx/vp8dx.h b/vpx/vp8dx.h
index 5d0e533..e9d479f 100644
--- a/vpx/vp8dx.h
+++ b/vpx/vp8dx.h
@@ -64,6 +64,23 @@
void *inspect_ctx;
} vpx_inspect_init;
+/*!\brief Structure to hold decoder return.
+ *
+ * Defines a structure to hold the buffer and return an index
+ * when calling decode from inspect. This enables us to decode
+ * non showable sub frames.
+ */
+typedef struct {
+ /*! Pointer for new position in compressed buffer after decoding 1 OBU. */
+ const unsigned char *buf;
+ /*! Index into reference buffer array to see result of decoding 1 OBU. */
+ int idx;
+ /*! Is a show existing frame. */
+ int show_existing;
+ /*! Whether we've decoded all the superframes. */
+ int finished_superframes;
+} VpxDecodeReturn;
+
/*!\enum vp8_dec_control_id
* \brief VP8 decoder control functions
*