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);