shithub: libvpx

Download patch

ref: 414f68d2666ae150f727771180ee8bd2412640f9
parent: b551d82d9230c626fef700c9e7eeb8b497f248a1
parent: 64bcffc1ec56da76e4fe631cf31fbc091cc49392
author: John Koleszar <jkoleszar@google.com>
date: Tue Nov 20 12:22:50 EST 2012

Merge "Pack invisible frames without lengths" into experimental

--- a/vp9/common/onyxd.h
+++ b/vp9/common/onyxd.h
@@ -42,7 +42,7 @@
   void vp9_initialize_dec(void);
 
   int vp9_receive_compressed_data(VP9D_PTR comp, unsigned long size,
-                                  const unsigned char *dest,
+                                  const unsigned char **dest,
                                   int64_t time_stamp);
 
   int vp9_get_raw_frame(VP9D_PTR comp, YV12_BUFFER_CONFIG *sd,
--- a/vp9/decoder/decodframe.c
+++ b/vp9/decoder/decodframe.c
@@ -992,7 +992,7 @@
   }
 }
 
-int vp9_decode_frame(VP9D_COMP *pbi) {
+int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
   BOOL_DECODER header_bc, residual_bc;
   VP9_COMMON *const pc = &pbi->common;
   MACROBLOCKD *const xd  = &pbi->mb;
@@ -1456,5 +1456,12 @@
 #endif
   // printf("Frame %d Done\n", frame_count++);
 
+  /* Find the end of the coded buffer */
+  while (residual_bc.count > CHAR_BIT
+         && residual_bc.count < VP9_BD_VALUE_SIZE) {
+    residual_bc.count -= CHAR_BIT;
+    residual_bc.user_buffer--;
+  }
+  *p_data_end = residual_bc.user_buffer;
   return 0;
 }
--- a/vp9/decoder/onyxd_if.c
+++ b/vp9/decoder/onyxd_if.c
@@ -315,7 +315,7 @@
 }
 
 int vp9_receive_compressed_data(VP9D_PTR ptr, unsigned long size,
-                                const unsigned char *source,
+                                const unsigned char **psource,
                                 int64_t time_stamp) {
 #if HAVE_ARMV7
   int64_t dx_store_reg[8];
@@ -322,6 +322,7 @@
 #endif
   VP9D_COMP *pbi = (VP9D_COMP *) ptr;
   VP9_COMMON *cm = &pbi->common;
+  const unsigned char *source = *psource;
   int retcode = 0;
 
   /*if(pbi->ready_for_new_data == 0)
@@ -380,7 +381,7 @@
 
   pbi->common.error.setjmp = 1;
 
-  retcode = vp9_decode_frame(pbi);
+  retcode = vp9_decode_frame(pbi, psource);
 
   if (retcode < 0) {
 #if HAVE_ARMV7
--- a/vp9/decoder/onyxd_int.h
+++ b/vp9/decoder/onyxd_int.h
@@ -83,7 +83,7 @@
 
 } VP9D_COMP;
 
-int vp9_decode_frame(VP9D_COMP *cpi);
+int vp9_decode_frame(VP9D_COMP *cpi, const unsigned char **p_data_end);
 
 
 #if CONFIG_DEBUG
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -77,8 +77,8 @@
   VP9_PTR             cpi;
   unsigned char          *cx_data;
   unsigned int            cx_data_sz;
-  unsigned char           *altref_cx_data;
-  unsigned int            altref_size;
+  unsigned char          *pending_cx_data;
+  unsigned int            pending_cx_data_sz;
   vpx_image_t             preview_img;
   unsigned int            next_frame_flag;
   vp8_postproc_cfg_t      preview_ppcfg;
@@ -577,19 +577,6 @@
   }
 }
 
-static void append_length(unsigned char* cx_data, unsigned long int *cx_size) {
-  unsigned char chunk;
-  unsigned int offset = 0;
-  unsigned long int size = *cx_size;
-  do {
-    chunk = size & 0x7F;
-    size >>= 7;
-    chunk |= (offset == 0) << 7;
-    cx_data[offset] = chunk;
-    offset++;
-  } while (size);
-  *cx_size += offset;
-}
 
 static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t  *ctx,
                                    const vpx_image_t     *img,
@@ -693,14 +680,24 @@
       ctx->next_frame_flag = 0;
     }
 
+    cx_data = ctx->cx_data;
+    cx_data_sz = ctx->cx_data_sz;
     lib_flags = 0;
 
-    if (ctx->altref_size) {
-      cx_data = ctx->altref_cx_data + ctx->altref_size;
-      cx_data_sz = ctx->cx_data_sz - ctx->altref_size;
-    } else {
-      cx_data = ctx->cx_data;
-      cx_data_sz = ctx->cx_data_sz;
+    /* Any pending invisible frames? */
+    if (ctx->pending_cx_data) {
+      memmove(cx_data, ctx->pending_cx_data, ctx->pending_cx_data_sz);
+      ctx->pending_cx_data = cx_data;
+      cx_data += ctx->pending_cx_data_sz;
+      cx_data_sz -= ctx->pending_cx_data_sz;
+
+      /* TODO: this is a minimal check, the underlying codec doesn't respect
+       * the buffer size anyway.
+       */
+      if (cx_data_sz < ctx->cx_data_sz / 2) {
+        ctx->base.err_detail = "Compressed data buffer too small";
+        return VPX_CODEC_ERROR;
+      }
     }
 
     while (cx_data_sz >= ctx->cx_data_sz / 2 &&
@@ -712,13 +709,11 @@
         vpx_codec_cx_pkt_t pkt;
         VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
 
-        /* TODO(jkoleszar): for now we append lengths to all frames, revisit
-         * this later to ensure if this is necessary */
-        append_length(cx_data + size, &size);
-
+        /* Pack invisible frames with the next visisble frame */
         if (!cpi->common.show_frame) {
-          ctx->altref_cx_data = cx_data;
-          ctx->altref_size = size;
+          if (!ctx->pending_cx_data)
+            ctx->pending_cx_data = cx_data;
+          ctx->pending_cx_data_sz += size;
           cx_data += size;
           cx_data_sz -= size;
           continue;
@@ -777,14 +772,14 @@
         }
         else*/
         {
-          if (ctx->altref_size) {
-            pkt.data.frame.sz = ctx->altref_size + size;
-            pkt.data.frame.buf = ctx->altref_cx_data;
-            ctx->altref_size = 0;
-            ctx->altref_cx_data = NULL;
+          if (ctx->pending_cx_data) {
+            pkt.data.frame.buf = ctx->pending_cx_data;
+            pkt.data.frame.sz  = ctx->pending_cx_data_sz + size;
+            ctx->pending_cx_data = NULL;
+            ctx->pending_cx_data_sz = 0;
           } else {
             pkt.data.frame.buf = cx_data;
-            pkt.data.frame.sz = size;
+            pkt.data.frame.sz  = size;
           }
           pkt.data.frame.partition_id = -1;
           vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
--- a/vp9/vp9_dx_iface.c
+++ b/vp9/vp9_dx_iface.c
@@ -303,11 +303,11 @@
   img->self_allocd = 0;
 }
 
-static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t  *ctx,
-                                  const uint8_t         *data,
-                                  unsigned int            data_sz,
-                                  void                    *user_priv,
-                                  long                    deadline) {
+static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t  *ctx,
+                                  const uint8_t        **data,
+                                  unsigned int           data_sz,
+                                  void                  *user_priv,
+                                  long                   deadline) {
   vpx_codec_err_t res = VPX_CODEC_OK;
 
   ctx->img_avail = 0;
@@ -317,7 +317,7 @@
    * of the heap.
    */
   if (!ctx->si.h)
-    res = ctx->base.iface->dec.peek_si(data, data_sz, &ctx->si);
+    res = ctx->base.iface->dec.peek_si(*data, data_sz, &ctx->si);
 
 
   /* Perform deferred allocations, if required */
@@ -424,6 +424,33 @@
   return res;
 }
 
+static vpx_codec_err_t vp9_decode(vpx_codec_alg_priv_t  *ctx,
+                                  const uint8_t         *data,
+                                  unsigned int           data_sz,
+                                  void                  *user_priv,
+                                  long                   deadline) {
+  const uint8_t *data_start = data;
+  const uint8_t *data_end = data + data_sz;
+  vpx_codec_err_t res;
+
+  do {
+    res = decode_one(ctx, &data_start, data_sz, user_priv, deadline);
+    assert(data_start >= data);
+    assert(data_start <= data_end);
+
+    /* Early exit if there was a decode error */
+    if (res)
+      break;
+
+    /* Account for suboptimal termination by the encoder. */
+    while (data_start < data_end && *data_start == 0)
+      data_start++;
+
+    data_sz = data_end - data_start;
+  } while (data_start < data_end);
+  return res;
+}
+
 static vpx_image_t *vp8_get_frame(vpx_codec_alg_priv_t  *ctx,
                                   vpx_codec_iter_t      *iter) {
   vpx_image_t *img = NULL;
@@ -672,7 +699,7 @@
   {
     vp8_peek_si,      /* vpx_codec_peek_si_fn_t    peek_si; */
     vp8_get_si,       /* vpx_codec_get_si_fn_t     get_si; */
-    vp8_decode,       /* vpx_codec_decode_fn_t     decode; */
+    vp9_decode,       /* vpx_codec_decode_fn_t     decode; */
     vp8_get_frame,    /* vpx_codec_frame_get_fn_t  frame_get; */
   },
   {
--- a/vpx/src/vpx_decoder.c
+++ b/vpx/src/vpx_decoder.c
@@ -109,30 +109,7 @@
   return SAVE_STATUS(ctx, res);
 }
 
-static int read_frame_length(const uint8_t *data, uint64_t size,
-                             uint64_t *frame_length, int *size_length) {
-  uint64_t value = 0;
-  *size_length = 0;
-  do {
-    uint64_t index;
-    size -= value + *size_length;
-    index = size - 1;
-    value = 0;
-    do {
-      if (data + index < data) {
-          *frame_length = -1;
-          return -1;
-      }
-      value <<= 7;
-      value |= (data[index] & 0x7F);
-    } while (!(data[index--] >> 7));
-    *size_length = size - 1 - index;
-  } while (value + *size_length < size);
-  *frame_length = value;
-  return 0;
-}
 
-
 vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t    *ctx,
                                  const uint8_t        *data,
                                  unsigned int    data_sz,
@@ -139,11 +116,6 @@
                                  void       *user_priv,
                                  long        deadline) {
   vpx_codec_err_t res;
-  int offset = 0;
-  uint64_t length = 0;
-  unsigned char altref_frame;
-  unsigned int cx_size = data_sz;
-  uint8_t *cx_data = data;
 
   /* Sanity checks */
   /* NULL data ptr allowed if data_sz is 0 too */
@@ -152,18 +124,8 @@
   else if (!ctx->iface || !ctx->priv)
     res = VPX_CODEC_ERROR;
   else {
-    do {
-      altref_frame = !(*cx_data & 0x10);
-      res = read_frame_length(cx_data, cx_size, &length, &offset);
-      if (res != 0)
-        return SAVE_STATUS(ctx, VPX_CODEC_UNSUP_BITSTREAM);
-      res = ctx->iface->dec.decode(ctx->priv->alg_priv, cx_data,
-                                         length, user_priv, deadline);
-      if (res != 0)
-        return SAVE_STATUS(ctx, res);
-      cx_data += offset + length;
-      cx_size -= offset + length;
-    } while (cx_data - data <= data_sz && altref_frame);
+    res = ctx->iface->dec.decode(ctx->priv->alg_priv, data, data_sz,
+                                 user_priv, deadline);
   }
 
   return SAVE_STATUS(ctx, res);