diff --git a/src/bin/common.rs b/src/bin/common.rs
index 21cdc46e3c407c3f410ce02b7791fb761f7117c4..5a4507882d31833854de1e57dbd7ccde61ef7633 100644
--- a/src/bin/common.rs
+++ b/src/bin/common.rs
@@ -154,7 +154,7 @@ pub fn process_frame(sequence: &mut Sequence, fi: &mut FrameInvariants,
                     fs.rec.planes[1].cfg.stride,
                     fs.rec.planes[2].cfg.stride);
 
-                for (line, line_out) in fs.rec.planes[0].data.chunks(stride_y).zip(rec_y.chunks_mut(pitch_y)) {
+                for (line, line_out) in fs.rec.planes[0].data_origin().chunks(stride_y).zip(rec_y.chunks_mut(pitch_y)) {
                     if sequence.bit_depth > 8 {
                         unsafe {
                             line_out.copy_from_slice(
@@ -165,7 +165,7 @@ pub fn process_frame(sequence: &mut Sequence, fi: &mut FrameInvariants,
                             &line.iter().map(|&v| v as u8).collect::<Vec<u8>>()[..pitch_y]);
                     }
                 }
-                for (line, line_out) in fs.rec.planes[1].data.chunks(stride_u).zip(rec_u.chunks_mut(pitch_uv)) {
+                for (line, line_out) in fs.rec.planes[1].data_origin().chunks(stride_u).zip(rec_u.chunks_mut(pitch_uv)) {
                     if sequence.bit_depth > 8 {
                         unsafe {
                             line_out.copy_from_slice(
@@ -176,7 +176,7 @@ pub fn process_frame(sequence: &mut Sequence, fi: &mut FrameInvariants,
                             &line.iter().map(|&v| v as u8).collect::<Vec<u8>>()[..pitch_uv]);
                     }
                 }
-                for (line, line_out) in fs.rec.planes[2].data.chunks(stride_v).zip(rec_v.chunks_mut(pitch_uv)) {
+                for (line, line_out) in fs.rec.planes[2].data_origin().chunks(stride_v).zip(rec_v.chunks_mut(pitch_uv)) {
                     if sequence.bit_depth > 8 {
                         unsafe {
                             line_out.copy_from_slice(
@@ -192,6 +192,7 @@ pub fn process_frame(sequence: &mut Sequence, fi: &mut FrameInvariants,
                 y4m_enc.write_frame(&rec_frame).unwrap();
             }
 
+            fs.rec.pad();
             update_rec_buffer(fi, fs);
             true
         },
diff --git a/src/cdef.rs b/src/cdef.rs
index 253179fbb548c3f08459873c100d637cacb1007d..c8230b5deacb5510e67566678cbabaffb49795d0 100755
--- a/src/cdef.rs
+++ b/src/cdef.rs
@@ -339,9 +339,9 @@ pub fn cdef_filter_frame(fi: &FrameInvariants, rec: &mut Frame, bc: &mut BlockCo
     }
     let mut cdef_frame = Frame {
         planes: [
-            Plane::new(padded_px[0][0], padded_px[0][1], rec.planes[0].cfg.xdec, rec.planes[0].cfg.ydec),
-            Plane::new(padded_px[1][0], padded_px[1][1], rec.planes[1].cfg.xdec, rec.planes[1].cfg.ydec),
-            Plane::new(padded_px[2][0], padded_px[2][1], rec.planes[2].cfg.xdec, rec.planes[2].cfg.ydec)
+            Plane::new(padded_px[0][0], padded_px[0][1], rec.planes[0].cfg.xdec, rec.planes[0].cfg.ydec, 0, 0),
+            Plane::new(padded_px[1][0], padded_px[1][1], rec.planes[1].cfg.xdec, rec.planes[1].cfg.ydec, 0, 0),
+            Plane::new(padded_px[2][0], padded_px[2][1], rec.planes[2].cfg.xdec, rec.planes[2].cfg.ydec, 0, 0)
         ]
     };
     for p in 0..3 {
@@ -350,14 +350,14 @@ pub fn cdef_filter_frame(fi: &FrameInvariants, rec: &mut Frame, bc: &mut BlockCo
         for row in 0..padded_px[p][1] {
             // pad first two elements of current row
             {
-                let mut cdef_slice = cdef_frame.planes[p].mut_slice(&PlaneOffset { x: 0, y: row});
+                let mut cdef_slice = cdef_frame.planes[p].mut_slice(&PlaneOffset { x: 0, y: row as isize });
                 let mut cdef_row = &mut cdef_slice.as_mut_slice()[..2];
                 cdef_row[0] = CDEF_VERY_LARGE;
                 cdef_row[1] = CDEF_VERY_LARGE;
             }
             // pad out end of current row
             {
-                let mut cdef_slice = cdef_frame.planes[p].mut_slice(&PlaneOffset { x: rec_w+2, y: row });
+                let mut cdef_slice = cdef_frame.planes[p].mut_slice(&PlaneOffset { x: rec_w as isize + 2, y: row as isize });
                 let mut cdef_row = &mut cdef_slice.as_mut_slice()[..padded_px[p][0]-rec_w-2];
                 for x in cdef_row {
                     *x = CDEF_VERY_LARGE;
@@ -365,7 +365,7 @@ pub fn cdef_filter_frame(fi: &FrameInvariants, rec: &mut Frame, bc: &mut BlockCo
             }
             // copy current row from rec if we're in data, or pad if we're in first two rows/last N rows
             {
-                let mut cdef_slice = cdef_frame.planes[p].mut_slice(&PlaneOffset { x: 2, y: row });
+                let mut cdef_slice = cdef_frame.planes[p].mut_slice(&PlaneOffset { x: 2, y: row as isize });
                 let mut cdef_row = &mut cdef_slice.as_mut_slice()[..rec_w];
                 if row < 2 || row >= rec_h+2 {
                     for x in cdef_row {
@@ -373,7 +373,7 @@ pub fn cdef_filter_frame(fi: &FrameInvariants, rec: &mut Frame, bc: &mut BlockCo
                     }
                 } else {
                     let rec_stride = rec.planes[p].cfg.stride;
-                    cdef_row.copy_from_slice(&rec.planes[p].data[(row-2)*rec_stride..(row-1)*rec_stride][..rec_w]);
+                    cdef_row.copy_from_slice(&rec.planes[p].data_origin()[(row-2)*rec_stride..(row-1)*rec_stride][..rec_w]);
                 }
             }
         }
diff --git a/src/context.rs b/src/context.rs
index 71db3a61b35af5c0232eedfe37ce3553a76369a5..f85876de5319665aee3c7864c8bdcb96d6033951 100755
--- a/src/context.rs
+++ b/src/context.rs
@@ -1253,8 +1253,8 @@ impl SuperBlockOffset {
   /// Offset of the top-left pixel of this block.
   pub fn plane_offset(&self, plane: &PlaneConfig) -> PlaneOffset {
     PlaneOffset {
-      x: self.x << (SUPERBLOCK_TO_PLANE_SHIFT - plane.xdec),
-      y: self.y << (SUPERBLOCK_TO_PLANE_SHIFT - plane.ydec)
+      x: (self.x as isize) << (SUPERBLOCK_TO_PLANE_SHIFT - plane.xdec),
+      y: (self.y as isize) << (SUPERBLOCK_TO_PLANE_SHIFT - plane.ydec)
     }
   }
 }
@@ -1284,8 +1284,8 @@ impl BlockOffset {
     let y_offset = self.y & LOCAL_BLOCK_MASK;
 
     PlaneOffset {
-        x: po.x + (x_offset >> plane.xdec << BLOCK_TO_PLANE_SHIFT),
-        y: po.y + (y_offset >> plane.ydec << BLOCK_TO_PLANE_SHIFT)
+        x: po.x + (x_offset as isize >> plane.xdec << BLOCK_TO_PLANE_SHIFT),
+        y: po.y + (y_offset as isize >> plane.ydec << BLOCK_TO_PLANE_SHIFT)
     }
   }
 
diff --git a/src/encoder.rs b/src/encoder.rs
index 679b514fed7311d1a33242f3b06d3596166fff87..053fdf121342c207e9677d1b5cad236368662785 100644
--- a/src/encoder.rs
+++ b/src/encoder.rs
@@ -30,12 +30,18 @@ impl Frame {
     pub fn new(width: usize, height:usize) -> Frame {
         Frame {
             planes: [
-                Plane::new(width, height, 0, 0),
-                Plane::new(width/2, height/2, 1, 1),
-                Plane::new(width/2, height/2, 1, 1)
+                Plane::new(width, height, 0, 0, 128+8, 128+8),
+                Plane::new(width/2, height/2, 1, 1, 64+8, 64+8),
+                Plane::new(width/2, height/2, 1, 1, 64+8, 64+8)
             ]
         }
     }
+
+    pub fn pad(&mut self) {
+        for p in self.planes.iter_mut() {
+            p.pad();
+        }
+    }
 }
 
 #[derive(Debug, Clone)]
@@ -1507,8 +1513,8 @@ pub fn write_tx_blocks(fi: &FrameInvariants, fs: &mut FrameState,
                         };
 
                     let mut po = bo.plane_offset(&fs.input.planes[p].cfg);
-                    po.x += bx * uv_tx_size.width();
-                    po.y += by * uv_tx_size.height();
+                    po.x += (bx * uv_tx_size.width()) as isize;
+                    po.y += (by * uv_tx_size.height()) as isize;
 
                     encode_tx_block(fi, fs, cw, w, p, &tx_bo, chroma_mode, uv_tx_size, uv_tx_type,
                                     plane_bsize, &po, skip, bit_depth, ac, alpha);
diff --git a/src/me.rs b/src/me.rs
index 020cc3ba08db59a444b8e76c047e92f7d030e0b7..2c1b4c94682bf549d56738c598482f52f49832d7 100644
--- a/src/me.rs
+++ b/src/me.rs
@@ -7,7 +7,6 @@
 // Media Patent License 1.0 was not distributed with this source code in the
 // PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 
-use std::cmp;
 use FrameInvariants;
 use FrameState;
 use partition::*;
@@ -37,14 +36,14 @@ pub fn motion_estimation(fi: &FrameInvariants, fs: &mut FrameState, bsize: Block
 
   match fi.rec_buffer.frames[fi.ref_frames[ref_frame - LAST_FRAME]] {
     Some(ref rec) => {
-      let po = PlaneOffset { x: bo.x << BLOCK_TO_PLANE_SHIFT, y: bo.y << BLOCK_TO_PLANE_SHIFT };
-      let range = 16 as usize;
+      let po = PlaneOffset { x: (bo.x as isize) << BLOCK_TO_PLANE_SHIFT, y: (bo.y as isize) << BLOCK_TO_PLANE_SHIFT };
+      let range = 16 as isize;
       let blk_w = bsize.width();
       let blk_h = bsize.height();
-      let x_lo = cmp::max(0, po.x as isize - range as isize) as usize;
-      let x_hi = cmp::min(fs.input.planes[0].cfg.width - blk_w, po.x + range);
-      let y_lo = cmp::max(0, po.y as isize - range as isize) as usize;
-      let y_hi = cmp::min(fs.input.planes[0].cfg.height - blk_h, po.y + range);
+      let x_lo = po.x - range;
+      let x_hi = po.x + range;
+      let y_lo = po.y - range;
+      let y_hi = po.y + range;
 
       let mut lowest_sad = 128*128*4096 as u32;
       let mut best_mv = MotionVector { row: 0, col: 0 };
@@ -65,7 +64,7 @@ pub fn motion_estimation(fi: &FrameInvariants, fs: &mut FrameState, bsize: Block
       }
 
       let mode = PredictionMode::NEWMV;
-      let mut tmp_plane = Plane::new(blk_w, blk_h, 0, 0);
+      let mut tmp_plane = Plane::new(blk_w, blk_h, 0, 0, 0, 0);
 
       let mut steps = vec![4, 2];
       if fi.allow_high_precision_mv {
diff --git a/src/partition.rs b/src/partition.rs
index ff94e84962fbe23512af84b67a67d93a460e2a0f..2fbcefa76e5ec13bbc0ee181791ad5415a7c1cf4 100755
--- a/src/partition.rs
+++ b/src/partition.rs
@@ -10,7 +10,6 @@
 #![allow(non_camel_case_types)]
 #![allow(dead_code)]
 
-use std::cmp;
 use self::BlockSize::*;
 use self::TxSize::*;
 use encoder::FrameInvariants;
@@ -533,8 +532,6 @@ impl PredictionMode {
       } else if self == PredictionMode::V_PRED && y == 0 {
         for i in 0..B::H {
           left[i + 1] = dst.go_left(1).p(0, 0);
-          // FIXME(yushin): Figure out why below does not work??
-          //left[i + 1] = dst.go_left(1).plane.data[0];
         }
       }
     }
@@ -635,8 +632,7 @@ impl PredictionMode {
         let col_offset = mv.col as i32 >> shift_col;
         let row_frac = (mv.row as i32 - (row_offset << shift_row)) << (4 - shift_row);
         let col_frac = (mv.col as i32 - (col_offset << shift_col)) << (4 - shift_col);
-        let ref_width = rec_cfg.width;
-        let ref_height = rec_cfg.height;
+        let ref_stride = rec_cfg.stride;
 
         let stride = dst.plane.cfg.stride;
         let slice = dst.as_mut_slice();
@@ -647,23 +643,25 @@ impl PredictionMode {
 
         match (col_frac, row_frac) {
         (0,0) => {
+          let qo = PlaneOffset { x: po.x + col_offset as isize, y: po.y + row_offset as isize };
+          let ps = rec.frame.planes[p].slice(&qo);
+          let s = ps.as_slice_clamped();
           for r in 0..height {
             for c in 0..width {
-              let rs = cmp::min(ref_height as i32 - 1, cmp::max(0, po.y as i32 + row_offset + r as i32)) as usize;
-              let cs = cmp::min(ref_width as i32 - 1, cmp::max(0, po.x as i32 + col_offset + c as i32)) as usize;
               let output_index = r * stride + c;
-              slice[output_index] = rec.frame.planes[p].p(cs, rs);
+              slice[output_index] = s[r * ref_stride + c];
             }
           }
         }
         (0,_) => {
+          let qo = PlaneOffset { x: po.x + col_offset as isize, y: po.y + row_offset as isize - 3 };
+          let ps = rec.frame.planes[p].slice(&qo);
+          let s = ps.as_slice_clamped();
           for r in 0..height {
             for c in 0..width {
               let mut sum: i32 = 0;
               for k in 0..8 {
-                let rs = cmp::min(ref_height as i32 - 1, cmp::max(0, po.y as i32 + row_offset + r as i32 - 3 + k as i32)) as usize;
-                let cs = cmp::min(ref_width as i32 - 1, cmp::max(0, po.x as i32 + col_offset + c as i32)) as usize;
-                sum += rec.frame.planes[p].p(cs, rs) as i32 * SUBPEL_FILTERS[y_filter_idx][row_frac as usize][k];
+                sum += s[(r + k) * ref_stride + c] as i32 * SUBPEL_FILTERS[y_filter_idx][row_frac as usize][k];
               }
               let output_index = r * stride + c;
               let val = ((sum + 64) >> 7).max(0).min(max_sample_val);
@@ -672,13 +670,14 @@ impl PredictionMode {
           }
         }
         (_,0) => {
+          let qo = PlaneOffset { x: po.x + col_offset as isize - 3, y: po.y + row_offset as isize };
+          let ps = rec.frame.planes[p].slice(&qo);
+          let s = ps.as_slice_clamped();
           for r in 0..height {
             for c in 0..width {
             let mut sum: i32 = 0;
             for k in 0..8 {
-              let rs = cmp::min(ref_height as i32 - 1, cmp::max(0, po.y as i32 + row_offset + r as i32)) as usize;
-              let cs = cmp::min(ref_width as i32 - 1, cmp::max(0, po.x as i32 + col_offset + c as i32 - 3 + k as i32)) as usize;
-              sum += rec.frame.planes[p].p(cs, rs) as i32 * SUBPEL_FILTERS[x_filter_idx][col_frac as usize][k];
+              sum += s[r * ref_stride + (c + k)] as i32 * SUBPEL_FILTERS[x_filter_idx][col_frac as usize][k];
             }
             let output_index = r * stride + c;
             let val = ((((sum + 4) >> 3) + 8) >> 4).max(0).min(max_sample_val);
@@ -687,34 +686,37 @@ impl PredictionMode {
           }
         }
         (_,_) => {
-          let mut intermediate = [[0 as i16; 128]; 128+7];
-
-          for r in 0..height+7 {
-            for c in 0..width {
-              let mut sum: i32 = 0;
-              for k in 0..8 {
-                let rs = cmp::min(ref_height as i32 - 1, cmp::max(0, po.y as i32 + row_offset + r as i32 - 3)) as usize;
-                let cs = cmp::min(ref_width as i32 - 1, cmp::max(0, po.x as i32 + col_offset + c as i32 - 3 + k as i32)) as usize;
-                sum += rec.frame.planes[p].p(cs, rs) as i32 * SUBPEL_FILTERS[x_filter_idx][col_frac as usize][k];
+          let mut intermediate = [0 as i16; 8 * (128 + 7)];
+
+          let qo = PlaneOffset { x: po.x + col_offset as isize - 3, y: po.y + row_offset as isize - 3 };
+          let ps = rec.frame.planes[p].slice(&qo);
+          let s = ps.as_slice_clamped();
+          for cg in (0..width).step_by(8) {
+            for r in 0..height+7 {
+              for c in cg..(cg+8).min(width) {
+                let mut sum: i32 = 0;
+                for k in 0..8 {
+                  sum += s[r * ref_stride + (c + k)] as i32 * SUBPEL_FILTERS[x_filter_idx][col_frac as usize][k];
+                }
+                let val = (sum + 4) >> 3;
+                intermediate[8 * r + (c - cg)] = val as i16;
               }
-              let val = (sum + 4) >> 3;
-              intermediate[r][c] = val as i16;
             }
-          }
 
-          for r in 0..height {
-            for c in 0..width {
-              let mut sum: i32 = 0;
-              for k in 0..8 {
-                sum += intermediate[r + k][c] as i32 * SUBPEL_FILTERS[y_filter_idx][row_frac as usize][k];
-              }
-              let output_index = r * stride + c;
-              let val = ((sum + 1024) >> 11).max(0).min(max_sample_val);
-              slice[output_index] = val as u16;
+            for r in 0..height {
+              for c in cg..(cg+8).min(width) {
+                let mut sum: i32 = 0;
+                for k in 0..8 {
+                  sum += intermediate[8 * (r + k) + c - cg] as i32 * SUBPEL_FILTERS[y_filter_idx][row_frac as usize][k];
+                }
+                let output_index = r * stride + c;
+                let val = ((sum + 1024) >> 11).max(0).min(max_sample_val);
+                slice[output_index] = val as u16;
               }
             }
           }
         }
+      }
       },
       None => (),
     }
diff --git a/src/plane.rs b/src/plane.rs
index 65a3d41f3c81d83eed828c1a0547fcd342247869..5d4e6e53a6449555139db589c2f25df66554a710 100644
--- a/src/plane.rs
+++ b/src/plane.rs
@@ -15,17 +15,20 @@ use util::*;
 #[derive(Debug, Clone)]
 pub struct PlaneConfig {
   pub stride: usize,
+  pub alloc_height: usize,
   pub width: usize,
   pub height: usize,
   pub xdec: usize,
-  pub ydec: usize
+  pub ydec: usize,
+  pub xorigin: usize,
+  pub yorigin: usize
 }
 
 /// Absolute offset in pixels inside a plane
 #[derive(Debug)]
 pub struct PlaneOffset {
-  pub x: usize,
-  pub y: usize
+  pub x: isize,
+  pub y: isize
 }
 
 #[derive(Debug, Clone)]
@@ -41,11 +44,57 @@ impl Plane {
   /// Data alignment in bytes.
   const DATA_ALIGNMENT_LOG2: usize = 4;
 
-  pub fn new(width: usize, height: usize, xdec: usize, ydec: usize) -> Plane {
-    let stride = width.align_power_of_two(Plane::STRIDE_ALIGNMENT_LOG2 - 1);
-    let data = vec![128u16; stride * height];
+  pub fn new(width: usize, height: usize, xdec: usize, ydec: usize, xpad: usize, ypad: usize) -> Plane {
+    let xorigin = xpad.align_power_of_two(Plane::STRIDE_ALIGNMENT_LOG2 - 1);
+    let yorigin = ypad;
+    let stride = (xorigin + width + xpad).align_power_of_two(Plane::STRIDE_ALIGNMENT_LOG2 - 1);
+    let alloc_height = yorigin + height + ypad;
+    let data = vec![128u16; stride * alloc_height];
     assert!(is_aligned(data.as_ptr(), Plane::DATA_ALIGNMENT_LOG2));
-    Plane { data, cfg: PlaneConfig { stride, width, height, xdec, ydec } }
+    Plane { data, cfg: PlaneConfig { stride, alloc_height, width, height, xdec, ydec, xorigin, yorigin } }
+  }
+
+  pub fn pad(&mut self) {
+    let xorigin = self.cfg.xorigin;
+    let yorigin = self.cfg.yorigin;
+    let stride = self.cfg.stride;
+    let width = self.cfg.width;
+    let height = self.cfg.height;
+
+
+    if xorigin > 0 {
+      for y in 0..height {
+        let mut ps = self.mut_slice(&PlaneOffset { x: -(xorigin as isize), y: y as isize });
+        let s = ps.as_mut_slice_w_width(xorigin + 1);
+        let fill_val = s[xorigin];
+        for val in s[..xorigin].iter_mut() { *val = fill_val; }
+      }
+    }
+
+    if xorigin + width < stride {
+      for y in 0..height {
+        let mut ps = self.mut_slice(&PlaneOffset { x: width as isize - 1, y: y as isize });
+        let s = ps.as_mut_slice_w_width(stride - xorigin - width + 1);
+        let fill_val = s[0];
+        for val in s[1..].iter_mut() { *val = fill_val; }
+      }
+    }
+
+    if yorigin > 0 {
+      let mut ps = self.mut_slice(&PlaneOffset { x: -(xorigin as isize), y: -(yorigin as isize) });
+      let (s1, s2) = ps.as_mut_slice().split_at_mut(yorigin*stride);
+      for y in 0 .. yorigin {
+        s1[y*stride..y*stride+stride].copy_from_slice(&s2[..stride]);
+      }
+    }
+
+    if yorigin + height < self.cfg.alloc_height {
+      let mut ps = self.mut_slice(&PlaneOffset { x: -(xorigin as isize), y: height as isize - 1 });
+      let (s2, s1) = ps.as_mut_slice().split_at_mut(stride);
+      for y in 0 .. yorigin {
+        s1[y*stride..y*stride+stride].copy_from_slice(&s2[..stride]);
+      }
+    }
   }
 
   pub fn slice<'a>(&'a self, po: &PlaneOffset) -> PlaneSlice<'a> {
@@ -57,7 +106,15 @@ impl Plane {
   }
 
   pub fn p(&self, x: usize, y: usize) -> u16 {
-    self.data[y * self.cfg.stride + x]
+    self.data[(y + self.cfg.yorigin) * self.cfg.stride + (x + self.cfg.xorigin)]
+  }
+
+  pub fn data_origin(&self) -> &[u16] {
+    &self.data[self.cfg.yorigin * self.cfg.stride + self.cfg.xorigin..]
+  }
+
+  pub fn data_origin_mut(&mut self) -> &mut [u16] {
+    &mut self.data[self.cfg.yorigin * self.cfg.stride + self.cfg.xorigin..]
   }
 
   pub fn copy_from_raw_u8(
@@ -65,7 +122,7 @@ impl Plane {
   ) {
     let stride = self.cfg.stride;
     for (self_row, source_row) in
-      self.data.chunks_mut(stride).zip(source.chunks(source_stride))
+      self.data_origin_mut().chunks_mut(stride).zip(source.chunks(source_stride))
     {
       match source_bytewidth {
         1 => for (self_pixel, source_pixel) in
@@ -87,66 +144,86 @@ impl Plane {
 
 pub struct PlaneSlice<'a> {
   pub plane: &'a Plane,
-  pub x: usize,
-  pub y: usize
+  pub x: isize,
+  pub y: isize
 }
 
 impl<'a> PlaneSlice<'a> {
   pub fn as_slice(&'a self) -> &'a [u16] {
     let stride = self.plane.cfg.stride;
-    &self.plane.data[self.y * stride + self.x..]
+    let base = (self.y + self.plane.cfg.yorigin as isize) as usize * stride + (self.x + self.plane.cfg.xorigin as isize) as usize;
+    &self.plane.data[base..]
+  }
+
+  pub fn as_slice_clamped(&'a self) -> &'a [u16] {
+    let stride = self.plane.cfg.stride;
+    let y = (self.y.min(self.plane.cfg.height as isize) + self.plane.cfg.yorigin as isize).max(0) as usize;
+    let x = (self.x.min(self.plane.cfg.width as isize) + self.plane.cfg.xorigin as isize).max(0) as usize;
+    &self.plane.data[y * stride + x..]
   }
 
   pub fn as_slice_w_width(&'a self, width: usize) -> &'a [u16] {
     let stride = self.plane.cfg.stride;
-    let base = self.y * stride + self.x;
+    let base = (self.y + self.plane.cfg.yorigin as isize) as usize * stride + (self.x + self.plane.cfg.xorigin as isize) as usize;
     &self.plane.data[base .. base + width]
   }
 
   pub fn subslice(&'a self, xo: usize, yo: usize) -> PlaneSlice<'a> {
-    PlaneSlice { plane: self.plane, x: self.x + xo, y: self.y + yo }
+    PlaneSlice { plane: self.plane, x: self.x + xo as isize, y: self.y + yo as isize }
   }
 
   /// A slice starting i pixels above the current one.
   pub fn go_up(&'a self, i: usize) -> PlaneSlice<'a> {
-    PlaneSlice { plane: self.plane, x: self.x, y: self.y - i }
+    PlaneSlice { plane: self.plane, x: self.x, y: self.y - i as isize }
   }
 
   /// A slice starting i pixels to the left of the current one.
   pub fn go_left(&'a self, i: usize) -> PlaneSlice<'a> {
-    PlaneSlice { plane: self.plane, x: self.x - i, y: self.y }
+    PlaneSlice { plane: self.plane, x: self.x - i as isize, y: self.y }
   }
 
   pub fn p(&self, add_x: usize, add_y: usize) -> u16 {
-    let new_y = self.y + add_y;
-    let new_x = self.x + add_x;
+    let new_y = (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize;
+    let new_x = (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize;
     self.plane.data[new_y * self.plane.cfg.stride + new_x]
   }
 }
 
 pub struct PlaneMutSlice<'a> {
   pub plane: &'a mut Plane,
-  pub x: usize,
-  pub y: usize
+  pub x: isize,
+  pub y: isize
 }
 
 impl<'a> PlaneMutSlice<'a> {
   pub fn as_mut_slice(&'a mut self) -> &'a mut [u16] {
     let stride = self.plane.cfg.stride;
-    &mut self.plane.data[self.y * stride + self.x..]
+    let base = (self.y + self.plane.cfg.yorigin as isize) as usize * stride + (self.x + self.plane.cfg.xorigin as isize) as usize;
+    &mut self.plane.data[base..]
+  }
+
+  pub fn as_mut_slice_w_width(&'a mut self, width: usize) -> &'a mut [u16] {
+    let stride = self.plane.cfg.stride;
+    let y = self.y + self.plane.cfg.yorigin as isize;
+    let x = self.x + self.plane.cfg.xorigin as isize;
+    assert!(y >= 0);
+    assert!(x >= 0);
+    let base = y as usize * stride + x as usize;
+    &mut self.plane.data[base .. base + width]
   }
 
+
   pub fn offset(&self, add_x: usize, add_y: usize) -> &[u16] {
-    let new_y = self.y + add_y;
-    let new_x = self.x + add_x;
+    let new_y = (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize;
+    let new_x = (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize;
     &self.plane.data[new_y * self.plane.cfg.stride + new_x..]
   }
 
   pub fn offset_as_mutable(
     &'a mut self, add_x: usize, add_y: usize
   ) -> &'a mut [u16] {
-    let new_y = self.y + add_y;
-    let new_x = self.x + add_x;
+    let new_y = (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize;
+    let new_x = (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize;
     &mut self.plane.data[new_y * self.plane.cfg.stride + new_x..]
   }
 
@@ -154,17 +231,17 @@ impl<'a> PlaneMutSlice<'a> {
 
   /// A slice starting i pixels above the current one.
   pub fn go_up(&'a self, i: usize) -> PlaneSlice<'a> {
-    PlaneSlice { plane: self.plane, x: self.x, y: self.y - i }
+    PlaneSlice { plane: self.plane, x: self.x, y: self.y - i as isize }
   }
 
   /// A slice starting i pixels to the left of the current one.
   pub fn go_left(&'a self, i: usize) -> PlaneSlice<'a> {
-    PlaneSlice { plane: self.plane, x: self.x - i, y: self.y }
+    PlaneSlice { plane: self.plane, x: self.x - i as isize, y: self.y }
   }
 
   pub fn p(&self, add_x: usize, add_y: usize) -> u16 {
-    let new_y = self.y + add_y;
-    let new_x = self.x + add_x;
+    let new_y = (self.y + add_y as isize + self.plane.cfg.yorigin as isize) as usize;
+    let new_x = (self.x + add_x as isize + self.plane.cfg.xorigin as isize) as usize;
     self.plane.data[new_y * self.plane.cfg.stride + new_x]
   }
 }
diff --git a/src/rdo.rs b/src/rdo.rs
index d815c3a25873623fdb28bc9530c77c8826edddb3..e3e432abd87318a3cbf635045aaa856c1ee3f8ff 100755
--- a/src/rdo.rs
+++ b/src/rdo.rs
@@ -584,30 +584,30 @@ pub fn rdo_cdef_decision(sbo: &SuperBlockOffset, fi: &FrameInvariants,
     let mut cdef_output = Frame {
         planes: [
             Plane::new(64 >> fs.rec.planes[0].cfg.xdec, 64 >> fs.rec.planes[0].cfg.ydec,
-                       fs.rec.planes[0].cfg.xdec, fs.rec.planes[0].cfg.ydec),
+                       fs.rec.planes[0].cfg.xdec, fs.rec.planes[0].cfg.ydec, 0, 0),
             Plane::new(64 >> fs.rec.planes[1].cfg.xdec, 64 >> fs.rec.planes[1].cfg.ydec,
-                       fs.rec.planes[1].cfg.xdec, fs.rec.planes[1].cfg.ydec),
+                       fs.rec.planes[1].cfg.xdec, fs.rec.planes[1].cfg.ydec, 0, 0),
             Plane::new(64 >> fs.rec.planes[2].cfg.xdec, 64 >> fs.rec.planes[2].cfg.ydec,
-                       fs.rec.planes[2].cfg.xdec, fs.rec.planes[2].cfg.ydec),
+                       fs.rec.planes[2].cfg.xdec, fs.rec.planes[2].cfg.ydec, 0, 0),
         ]
     };
     // Construct a padded input
     let mut rec_input = Frame {
         planes: [
             Plane::new((64 >> fs.rec.planes[0].cfg.xdec)+4, (64 >> fs.rec.planes[0].cfg.ydec)+4,
-                       fs.rec.planes[0].cfg.xdec, fs.rec.planes[0].cfg.ydec),
+                       fs.rec.planes[0].cfg.xdec, fs.rec.planes[0].cfg.ydec, 0, 0),
             Plane::new((64 >> fs.rec.planes[1].cfg.xdec)+4, (64 >> fs.rec.planes[1].cfg.ydec)+4,
-                       fs.rec.planes[1].cfg.xdec, fs.rec.planes[1].cfg.ydec),
+                       fs.rec.planes[1].cfg.xdec, fs.rec.planes[1].cfg.ydec, 0, 0),
             Plane::new((64 >> fs.rec.planes[2].cfg.xdec)+4, (64 >> fs.rec.planes[2].cfg.ydec)+4,
-                       fs.rec.planes[2].cfg.xdec, fs.rec.planes[2].cfg.ydec),
+                       fs.rec.planes[2].cfg.xdec, fs.rec.planes[2].cfg.ydec, 0, 0),
         ]
     };
     // Copy reconstructed data into padded input
     for p in 0..3 {
         let xdec = fs.rec.planes[p].cfg.xdec;
         let ydec = fs.rec.planes[p].cfg.ydec;
-        let h = fi.padded_h >> ydec;
-        let w = fi.padded_w >> xdec;
+        let h = fi.padded_h as isize >> ydec;
+        let w = fi.padded_w as isize >> xdec;
         let offset = sbo.plane_offset(&fs.rec.planes[p].cfg);
         for y in 0..(64>>ydec)+4 {
             let mut rec_slice = rec_input.planes[p].mut_slice(&PlaneOffset {x:0, y:y});
@@ -623,14 +623,14 @@ pub fn rdo_cdef_decision(sbo: &SuperBlockOffset, fi: &FrameInvariants,
                     // No; do it the hard way.  off left or right edge, fill with flag.
                     for x in 0..(64>>xdec)+4 {
                         if offset.x+x >= 2 && offset.x+x < w+2 {
-                            rec_row[x] = in_row[offset.x+x-2]
+                            rec_row[x as usize] = in_row[(offset.x+x-2) as usize]
                         } else {
-                            rec_row[x] = CDEF_VERY_LARGE;
+                            rec_row[x as usize] = CDEF_VERY_LARGE;
                         }
                     }
                 }  else  {
                     // Yes, do it the easy way: just copy
-                    rec_row[0..(64>>xdec)+4].copy_from_slice(&in_row[offset.x-2..offset.x+(64>>xdec)+2]);
+                    rec_row[0..(64>>xdec)+4].copy_from_slice(&in_row[(offset.x-2) as usize..(offset.x+(64>>xdec)+2) as usize]);
                 }
             }
         }
diff --git a/src/test_encode_decode.rs b/src/test_encode_decode.rs
index c2b94ee7948abfaad5b77e09332fbfa7f626d604..ea4fcd73b39aa7658f133250934ec9f74b60e688 100644
--- a/src/test_encode_decode.rs
+++ b/src/test_encode_decode.rs
@@ -182,7 +182,7 @@ use std::collections::VecDeque;
                     slice::from_raw_parts(data, size)
                 };
 
-                let rec: Vec<u16> = frame_plane.data.iter().map(|&v| v).collect();
+                let rec: Vec<u16> = frame_plane.data_origin().iter().map(|&v| v).collect();
 
                 compare_plane::<u16>(&rec[..], rec_stride, dec, dec_stride, w, h);
             } else {
@@ -195,7 +195,7 @@ use std::collections::VecDeque;
                     slice::from_raw_parts(data, size)
                 };
 
-                let rec: Vec<u8> = frame_plane.data.iter().map(|&v| v as u8).collect();
+                let rec: Vec<u8> = frame_plane.data_origin().iter().map(|&v| v as u8).collect();
 
                 compare_plane::<u8>(&rec[..], rec_stride, dec, dec_stride, w, h);
             }
@@ -228,6 +228,8 @@ use std::collections::VecDeque;
             let packet = encode_frame(&mut seq, &mut fi, &mut fs);
             println!("Encoded.");
 
+            fs.rec.pad();
+
             rec_fifo.push_back(fs.rec.clone());
 
             update_rec_buffer(&mut fi, fs);