core/scale: copy pictures with different strides too
[nihav.git] / nihav-core / src / scale / mod.rs
index e49fecb81052664351ef35b7d48a44e992458b57..13762bd01e4d65e16536fa2740004930411fd57f 100644 (file)
@@ -123,9 +123,38 @@ fn check_format(in_fmt: NAVideoInfo, ref_fmt: &ScaleInfo, just_convert: bool) ->
 fn copy(pic_in: &NABufferType, pic_out: &mut NABufferType)
 {
     if let (Some(ref sbuf), Some(ref mut dbuf)) = (pic_in.get_vbuf(), pic_out.get_vbuf()) {
-        let sdata = sbuf.get_data();
-        let ddata = dbuf.get_data_mut().unwrap();
-        ddata.copy_from_slice(&sdata[0..]);
+        let mut same = true;
+        let num_components = sbuf.get_info().get_format().get_num_comp();
+        for i in 0..num_components {
+            if sbuf.get_stride(i) != dbuf.get_stride(i) {
+                same = false;
+                break;
+            }
+            if sbuf.get_offset(i) != dbuf.get_offset(i) {
+                same = false;
+                break;
+            }
+        }
+        if same {
+            let sdata = sbuf.get_data();
+            let ddata = dbuf.get_data_mut().unwrap();
+            ddata.copy_from_slice(&sdata[0..]);
+        } else {
+            let sdata = sbuf.get_data();
+            for comp in 0..num_components {
+                let (_, h) = sbuf.get_dimensions(comp);
+                let src = &sdata[sbuf.get_offset(comp)..];
+                let sstride = sbuf.get_stride(comp);
+                let doff = dbuf.get_offset(comp);
+                let dstride = dbuf.get_stride(comp);
+                let ddata = dbuf.get_data_mut().unwrap();
+                let dst = &mut ddata[doff..];
+                let copy_size = sstride.min(dstride);
+                for (dline, sline) in dst.chunks_exact_mut(dstride).take(h).zip(src.chunks_exact(sstride)) {
+                    (&mut dline[..copy_size]).copy_from_slice(&sline[..copy_size]);
+                }
+            }
+        }
     } else {
         unimplemented!();
     }
@@ -157,17 +186,15 @@ fn build_pipeline(ifmt: &ScaleInfo, ofmt: &ScaleInfo, just_convert: bool) -> Sca
     let outname = ofmt.fmt.get_model().get_short_name();
 
 println!("convert {} -> {}", ifmt, ofmt);
-    let mut needs_scale  = !just_convert;
-    if (ofmt.fmt.get_max_subsampling() > 0) &&
+    let needs_scale = if (ofmt.fmt.get_max_subsampling() > 0) &&
         (ofmt.fmt.get_max_subsampling() != ifmt.fmt.get_max_subsampling()) {
-        needs_scale = true;
-    }
-    let needs_unpack = needs_scale || !ifmt.fmt.is_unpacked();
+            true
+        } else {
+            !just_convert
+        };
+    let needs_unpack = !ifmt.fmt.is_unpacked();
     let needs_pack = !ofmt.fmt.is_unpacked();
-    let mut needs_convert = false;
-    if inname != outname {
-        needs_convert = true;
-    }
+    let needs_convert = inname != outname;
     let scale_before_cvt = is_better_fmt(&ifmt, &ofmt) && needs_convert
                            && (ofmt.fmt.get_max_subsampling() == 0);
 //todo stages for model and gamma conversion
@@ -177,12 +204,11 @@ println!("convert {} -> {}", ifmt, ofmt);
 
     if needs_unpack {
 println!("[adding unpack]");
-        let new_stage;
-        if !cur_fmt.fmt.is_paletted() {
-            new_stage = Stage::new("unpack", &cur_fmt, &ofmt)?;
-        } else {
-            new_stage = Stage::new("depal", &cur_fmt, &ofmt)?;
-        }
+        let new_stage = if !cur_fmt.fmt.is_paletted() {
+                Stage::new("unpack", &cur_fmt, &ofmt)?
+            } else {
+                Stage::new("depal", &cur_fmt, &ofmt)?
+            };
         cur_fmt = new_stage.fmt_out;
         add_stage!(stages, new_stage);
     }