]> granicus.if.org Git - libvpx/commitdiff
WIP: CONFIG_INSPECTION: fix non show frames
authorJim Bankoski <jimbankoski@google.com>
Mon, 5 Nov 2018 22:57:11 +0000 (14:57 -0800)
committerJim Bankoski <jimbankoski@google.com>
Fri, 21 Dec 2018 17:34:11 +0000 (09:34 -0800)
This makes non showable frames - analyzeable and also fixes
display of motion vectors.

Change-Id: Ie286a3d2005a0c5e35d164ed62dd0fe2269b9be6

examples/inspect.c
tools/build_inspector.sh
vp9/decoder/inspection.c
vp9/decoder/inspection.h
vp9/vp9_dx_iface.c
vp9/vp9_dx_iface.h
vpx/vp8dx.h

index 8c132a6dad0152b0043a0e8356870c75ad6d4a6e..3ccb6e6b4d22a5ccab1db5ed5175dcecd33e2571 100644 (file)
@@ -548,22 +548,51 @@ int open_file(char *file) {
   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;
 }
 
index 3cceb60f3c3d645b81248df5c9fd814b3e5b1dc2..4619b34368e6ada64a853b03dbb4c635edaef33f 100755 (executable)
@@ -32,7 +32,7 @@ if [ ! -d ".inspect" ]; then
     --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 @@ emcc -O3 inspect.bc -o inspect.js \
   -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
index b6b38a5a08534d8f2db28ec94179a627254e93db..2be2569336582bb8140480c998a86f11d38b8fbd 100644 (file)
@@ -43,6 +43,8 @@ int ifd_inspect(insp_frame_data *fd, void *decoder) {
   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 @@ int ifd_inspect(insp_frame_data *fd, void *decoder) {
       // 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];
index a3c98076b7afb22a146398f90ec85508b4c96204..304e2eee7d2f9d3a5edad357edfaba3a9df737a7 100644 (file)
@@ -58,6 +58,7 @@ struct insp_frame_data {
   int show_frame;
   int frame_type;
   int base_qindex;
+  int show_existing_frame;
   int mi_rows;
   int mi_cols;
   int tile_mi_rows;
index 2bf0d78d23999847ab77fde41f89ab349616d794..1f13d872877a8a1f23d7199cbf13f4e12be77167 100644 (file)
@@ -279,7 +279,10 @@ static vpx_codec_err_t init_decoder(vpx_codec_alg_priv_t *ctx) {
     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 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx,
   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 @@ static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx,
   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 @@ static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
   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);
index 7229597376755601040b7bf9b622ac9d5e63a7c5..e20aed93ee8778a53d028f9a8cec8b2b00a75936 100644 (file)
@@ -51,6 +51,9 @@ struct vpx_codec_alg_priv {
 #if CONFIG_INSPECTION
   vpx_inspect_cb inspect_cb;
   void *inspect_ctx;
+  uint32_t frame_sizes[8];
+  int frame_count;
+  int which_frame;
 #endif
 };
 
index 5d0e533f133947be8c5a23714c51a69a34c84078..e9d479fae9e0928df1264f168c446d166f6a7a6b 100644 (file)
@@ -64,6 +64,23 @@ typedef struct vpx_inspect_init {
   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
  *