shithub: libvpx

Download patch

ref: bc9670eee0c2a8731cca5e967d8e90a3a13911c3
parent: 5338d983d655664614fffc29142331a928ce018f
author: Vignesh Venkatasubramanian <vigneshv@google.com>
date: Mon Oct 29 11:57:44 EDT 2012

Packing Altref along with succeeding frame and length encoding frames

The altref frame is packed along with the next P frame. So that
outside of the codec there are now only two types of frames P and I.
Also, now it is one frame in and one frame out with respect to the
codec. Apart from that, all the frames are length encoded with the
length of each frame appended to the frame itself. There are
two categories of frames and each of them will look as follows:

  - Packed frames (an altref along with the succeeding p frame)
    - altref_frame_data | altref_lenngth | frame_data | length
  - Unpacked frames (all frames other than the above)
    - frame_data | length

Change-Id: If1eabf5c473f7d46b3f2d026bd30c803588c5330

--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -79,6 +79,8 @@
   VP9_PTR             cpi;
   unsigned char          *cx_data;
   unsigned int            cx_data_sz;
+  unsigned char           *altref_cx_data;
+  unsigned int            altref_size;
   vpx_image_t             preview_img;
   unsigned int            next_frame_flag;
   vp8_postproc_cfg_t      preview_ppcfg;
@@ -568,6 +570,19 @@
   }
 }
 
+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,
@@ -671,10 +686,16 @@
       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;
+    }
+
     while (cx_data_sz >= ctx->cx_data_sz / 2 &&
            -1 != vp9_get_compressed_data(ctx->cpi, &lib_flags, &size,
                                          cx_data, &dst_time_stamp,
@@ -684,6 +705,18 @@
         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);
+
+        if (!cpi->common.show_frame) {
+          ctx->altref_cx_data = cx_data;
+          ctx->altref_size = size;
+          cx_data += size;
+          cx_data_sz -= size;
+          continue;
+        }
+
         /* Add the frame packet to the list of returned packets. */
         round = 1000000 * ctx->cfg.g_timebase.num / 2 - 1;
         delta = (dst_end_time_stamp - dst_time_stamp);
@@ -737,8 +770,15 @@
         }
         else*/
         {
-          pkt.data.frame.buf = cx_data;
-          pkt.data.frame.sz  = size;
+          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;
+          } else {
+            pkt.data.frame.buf = cx_data;
+            pkt.data.frame.sz = size;
+          }
           pkt.data.frame.partition_id = -1;
           vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
           cx_data += size;
--- a/vpx/src/vpx_decoder.c
+++ b/vpx/src/vpx_decoder.c
@@ -106,7 +106,30 @@
   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,
@@ -113,6 +136,11 @@
                                  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 */
@@ -121,8 +149,18 @@
   else if (!ctx->iface || !ctx->priv)
     res = VPX_CODEC_ERROR;
   else {
-    res = ctx->iface->dec.decode(ctx->priv->alg_priv, data, data_sz,
-                                 user_priv, deadline);
+    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);
   }
 
   return SAVE_STATUS(ctx, res);