shithub: libvpx

Download patch

ref: 625fbb3068815aa47dd42df90b461a22d7a6ae4d
parent: b202e475e936e9b529975aa0dc72f6170699543b
parent: 1eb6e683f26b0ef060d3f78b32cbf5665531c76d
author: hkuang <[email protected]>
date: Thu Jun 19 08:16:37 EDT 2014

Merge "Add superframe support for frame parallel decoding."

--- a/vp9/vp9_dx_iface.c
+++ b/vp9/vp9_dx_iface.c
@@ -356,7 +356,8 @@
                                       const uint8_t *data, unsigned int data_sz,
                                       void *user_priv, long deadline) {
   const uint8_t *data_start = data;
-  const uint8_t *const data_end = data + data_sz;
+  const uint8_t * const data_end = data + data_sz;
+  vpx_codec_err_t res;
   uint32_t frame_sizes[8];
   int frame_count;
 
@@ -366,40 +367,80 @@
   parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
                          ctx->decrypt_cb, ctx->decrypt_state);
 
-  if (frame_count > 0) {
-    int i;
+  if (ctx->frame_parallel_decode) {
+    // Decode in frame parallel mode. When decoding in this mode, the frame
+    // passed to the decoder must be either a normal frame or a superframe with
+    // superframe index so the decoder could get each frame's start position
+    // in the superframe.
+    if (frame_count > 0) {
+      int i;
 
-    for (i = 0; i < frame_count; ++i) {
-      const uint8_t *data_start_copy = data_start;
-      const uint32_t frame_size = frame_sizes[i];
-      vpx_codec_err_t res;
-      if (data_start < data ||
-          frame_size > (uint32_t)(data_end - data_start)) {
-        ctx->base.err_detail = "Invalid frame size in index";
-        return VPX_CODEC_CORRUPT_FRAME;
-      }
+      for (i = 0; i < frame_count; ++i) {
+        const uint8_t *data_start_copy = data_start;
+        const uint32_t frame_size = frame_sizes[i];
+        vpx_codec_err_t res;
+        if (data_start < data
+            || frame_size > (uint32_t) (data_end - data_start)) {
+          ctx->base.err_detail = "Invalid frame size in index";
+          return VPX_CODEC_CORRUPT_FRAME;
+        }
 
-      res = decode_one(ctx, &data_start_copy, frame_size, user_priv, deadline);
+        res = decode_one(ctx, &data_start_copy, frame_size, user_priv,
+                         deadline);
+        if (res != VPX_CODEC_OK)
+          return res;
+
+        data_start += frame_size;
+      }
+    } else {
+      res = decode_one(ctx, &data_start, data_sz, user_priv, deadline);
       if (res != VPX_CODEC_OK)
         return res;
 
-      data_start += frame_size;
+      // Extra data detected after the frame.
+      if (data_start < data_end - 1) {
+        ctx->base.err_detail = "Fail to decode frame in parallel mode";
+        return VPX_CODEC_INCAPABLE;
+      }
     }
   } else {
-    while (data_start < data_end) {
-      const uint32_t frame_size = (uint32_t)(data_end - data_start);
-      const vpx_codec_err_t res = decode_one(ctx, &data_start, frame_size,
-                                             user_priv, deadline);
-      if (res != VPX_CODEC_OK)
-        return res;
+    // Decode in serial mode.
+    if (frame_count > 0) {
+      int i;
 
-      // Account for suboptimal termination by the encoder.
+      for (i = 0; i < frame_count; ++i) {
+        const uint8_t *data_start_copy = data_start;
+        const uint32_t frame_size = frame_sizes[i];
+        vpx_codec_err_t res;
+        if (data_start < data
+            || frame_size > (uint32_t) (data_end - data_start)) {
+          ctx->base.err_detail = "Invalid frame size in index";
+          return VPX_CODEC_CORRUPT_FRAME;
+        }
+
+        res = decode_one(ctx, &data_start_copy, frame_size, user_priv,
+                         deadline);
+        if (res != VPX_CODEC_OK)
+          return res;
+
+        data_start += frame_size;
+      }
+    } else {
       while (data_start < data_end) {
-        const uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state,
-                                           data_start);
-        if (marker)
-          break;
-        ++data_start;
+        const uint32_t frame_size = (uint32_t) (data_end - data_start);
+        const vpx_codec_err_t res = decode_one(ctx, &data_start, frame_size,
+                                               user_priv, deadline);
+        if (res != VPX_CODEC_OK)
+          return res;
+
+        // Account for suboptimal termination by the encoder.
+        while (data_start < data_end) {
+          const uint8_t marker = read_marker(ctx->decrypt_cb,
+                                             ctx->decrypt_state, data_start);
+          if (marker)
+            break;
+          ++data_start;
+        }
       }
     }
   }