Initial support for resolution changes on P-frames
authorJohn Koleszar <jkoleszar@google.com>
Wed, 6 Feb 2013 23:54:52 +0000 (15:54 -0800)
committerJohn Koleszar <jkoleszar@google.com>
Fri, 8 Feb 2013 20:20:30 +0000 (12:20 -0800)
Allows inter-frames to change resolution. Currently these are
almost equivalent to keyframes, as only intra prediction modes
are allowed, but without the other context resets that occur on
keyframes.

Change-Id: Icd1a2a5af0d9462cc792588427b0a1f5b12e40d3

vp9/decoder/vp9_decodframe.c
vp9/encoder/vp9_bitstream.c
vp9/encoder/vp9_onyx_if.c
vp9/encoder/vp9_rdopt.c
vp9/vp9_cx_iface.c

index b9b62d5..7717980 100644 (file)
@@ -1367,9 +1367,6 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
     vp9_setup_version(pc);
 
     if (pc->frame_type == KEY_FRAME) {
-      const int Width = pc->Width;
-      const int Height = pc->Height;
-
       /* vet via sync code */
       /* When error concealment is enabled we should only check the sync
        * code if we have enough bits available
@@ -1379,18 +1376,23 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
           vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
                              "Invalid frame sync code");
       }
+      data += 3;
+    }
+    {
+      const int Width = pc->Width;
+      const int Height = pc->Height;
 
       /* If error concealment is enabled we should only parse the new size
        * if we have enough data. Otherwise we will end up with the wrong
        * size.
        */
-      if (data + 6 < data_end) {
-        pc->Width = (data[3] | (data[4] << 8)) & 0x3fff;
-        pc->horiz_scale = data[4] >> 6;
-        pc->Height = (data[5] | (data[6] << 8)) & 0x3fff;
-        pc->vert_scale = data[6] >> 6;
+      if (data + 4 < data_end) {
+        pc->Width = (data[0] | (data[1] << 8)) & 0x3fff;
+        pc->horiz_scale = data[1] >> 6;
+        pc->Height = (data[2] | (data[3] << 8)) & 0x3fff;
+        pc->vert_scale = data[3] >> 6;
       }
-      data += 7;
+      data += 4;
 
       if (Width != pc->Width  ||  Height != pc->Height) {
         if (pc->Width <= 0) {
@@ -1423,10 +1425,8 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
                        (unsigned int)first_partition_length_in_bytes))
     vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate bool decoder 0");
-  if (pc->frame_type == KEY_FRAME) {
-    pc->clr_type    = (YUV_TYPE)vp9_read_bit(&header_bc);
-    pc->clamp_type  = (CLAMP_TYPE)vp9_read_bit(&header_bc);
-  }
+  pc->clr_type    = (YUV_TYPE)vp9_read_bit(&header_bc);
+  pc->clamp_type  = (CLAMP_TYPE)vp9_read_bit(&header_bc);
 
   pc->error_resilient_mode = vp9_read_bit(&header_bc);
   /* Is segmentation enabled */
index 2e69b84..b2c5d72 100644 (file)
@@ -1526,33 +1526,34 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
    * and color type.
    */
   if (oh.type == KEY_FRAME) {
-    int v;
-
     // Start / synch code
     cx_data[0] = 0x9D;
     cx_data[1] = 0x01;
     cx_data[2] = 0x2a;
+    extra_bytes_packed = 3;
+    cx_data += extra_bytes_packed;
+  }
+  {
+    int v;
 
+    /* TODO(jkoleszar): support arbitrary resolutions */
     v = (pc->horiz_scale << 14) | pc->Width;
-    cx_data[3] = v;
-    cx_data[4] = v >> 8;
+    cx_data[0] = v;
+    cx_data[1] = v >> 8;
 
     v = (pc->vert_scale << 14) | pc->Height;
-    cx_data[5] = v;
-    cx_data[6] = v >> 8;
+    cx_data[2] = v;
+    cx_data[3] = v >> 8;
 
-    extra_bytes_packed = 7;
-    cx_data += extra_bytes_packed;
-
-    vp9_start_encode(&header_bc, cx_data);
+    extra_bytes_packed += 4;
+    cx_data += 4;
+  }
 
-    // signal clr type
-    vp9_write_bit(&header_bc, pc->clr_type);
-    vp9_write_bit(&header_bc, pc->clamp_type);
+  vp9_start_encode(&header_bc, cx_data);
 
-  } else {
-    vp9_start_encode(&header_bc, cx_data);
-  }
+  // TODO(jkoleszar): remove these two unused bits?
+  vp9_write_bit(&header_bc, pc->clr_type);
+  vp9_write_bit(&header_bc, pc->clamp_type);
 
   // error resilient mode
   vp9_write_bit(&header_bc, pc->error_resilient_mode);
index e6e9cdd..2ad0c04 100644 (file)
@@ -3995,6 +3995,23 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
                                 cm->mb_cols * 16, cm->mb_rows * 16,
                                 VP9BORDERINPIXELS);
 
+  /* Disable any references that have different size */
+  if ((cm->yv12_fb[cm->active_ref_idx[cpi->lst_fb_idx]].y_width !=
+       cm->yv12_fb[cm->new_fb_idx].y_width) ||
+      (cm->yv12_fb[cm->active_ref_idx[cpi->lst_fb_idx]].y_height !=
+       cm->yv12_fb[cm->new_fb_idx].y_height))
+    cpi->ref_frame_flags &= ~VP9_LAST_FLAG;
+  if ((cm->yv12_fb[cm->active_ref_idx[cpi->gld_fb_idx]].y_width !=
+       cm->yv12_fb[cm->new_fb_idx].y_width) ||
+      (cm->yv12_fb[cm->active_ref_idx[cpi->gld_fb_idx]].y_height !=
+       cm->yv12_fb[cm->new_fb_idx].y_height))
+    cpi->ref_frame_flags &= ~VP9_GOLD_FLAG;
+  if ((cm->yv12_fb[cm->active_ref_idx[cpi->alt_fb_idx]].y_width !=
+       cm->yv12_fb[cm->new_fb_idx].y_width) ||
+      (cm->yv12_fb[cm->active_ref_idx[cpi->alt_fb_idx]].y_height !=
+       cm->yv12_fb[cm->new_fb_idx].y_height))
+    cpi->ref_frame_flags &= ~VP9_ALT_FLAG;
+
   vp9_setup_interp_filters(&cpi->mb.e_mbd, DEFAULT_INTERP_FILTER, cm);
   if (cpi->pass == 1) {
     Pass1Encode(cpi, size, dest, frame_flags);
index 200a6a9..59d2309 100644 (file)
@@ -3510,6 +3510,8 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
                                int recon_yoffset, int recon_uvoffset,
                                int *returnrate, int *returndistortion,
                                int64_t *returnintra) {
+  static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
+                                    VP9_ALT_FLAG };
   VP9_COMMON *cm = &cpi->common;
   MACROBLOCKD *xd = &x->e_mbd;
   union b_mode_info best_bmodes[16];
@@ -3677,6 +3679,16 @@ static void rd_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
     if (best_rd <= cpi->rd_threshes[mode_index])
       continue;
 
+    // Ensure that the references used by this mode are available.
+    if (mbmi->ref_frame &&
+        !(cpi->ref_frame_flags & flag_list[mbmi->ref_frame]))
+      continue;
+
+    if (mbmi->second_ref_frame > 0 &&
+        !(cpi->ref_frame_flags & flag_list[mbmi->second_ref_frame]))
+      continue;
+
+
     // current coding mode under rate-distortion optimization test loop
 #if CONFIG_COMP_INTERINTRA_PRED
     mbmi->interintra_mode = (MB_PREDICTION_MODE)(DC_PRED - 1);
index 75df0e0..210792f 100644 (file)
@@ -80,7 +80,6 @@ struct vpx_codec_alg_priv {
   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;
   vpx_codec_pkt_list_decl(64) pkt_list;              // changed to accomendate the maximum number of lagged frames allowed
   unsigned int                fixed_kf_cntr;
@@ -675,14 +674,11 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t  *ctx,
     if (img != NULL) {
       res = image2yuvconfig(img, &sd);
 
-      if (vp9_receive_raw_frame(ctx->cpi, ctx->next_frame_flag | lib_flags,
+      if (vp9_receive_raw_frame(ctx->cpi, lib_flags,
                                 &sd, dst_time_stamp, dst_end_time_stamp)) {
         VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
         res = update_error_state(ctx, &cpi->common.error);
       }
-
-      /* reset for next frame */
-      ctx->next_frame_flag = 0;
     }
 
     cx_data = ctx->cx_data;
@@ -984,8 +980,6 @@ static vpx_codec_err_t vp8e_set_scalemode(vpx_codec_alg_priv_t *ctx,
                                 scalemode.v_scaling_mode);
 
     if (!res) {
-      /*force next frame a key frame to effect scaling mode */
-      ctx->next_frame_flag |= FRAMEFLAGS_KEY;
       return VPX_CODEC_OK;
     } else
       return VPX_CODEC_INVALID_PARAM;