X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-core%2Fsrc%2Fscale%2Fmod.rs;h=ad96da95c4b1a85c15a8f47c6da45016c249ec89;hb=085742a39fdbc8560a2e67db6b2848ecac9a9e61;hp=9cd6b8d8cc40b2b8e0db9d8003a507802c1b29d5;hpb=e243ceb4d694cc08767ad70027bb6963f4cefea3;p=nihav.git diff --git a/nihav-core/src/scale/mod.rs b/nihav-core/src/scale/mod.rs index 9cd6b8d..ad96da9 100644 --- a/nihav-core/src/scale/mod.rs +++ b/nihav-core/src/scale/mod.rs @@ -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!(); } @@ -163,7 +192,7 @@ println!("convert {} -> {}", ifmt, ofmt); } else { !just_convert }; - let needs_unpack = needs_scale || !ifmt.fmt.is_unpacked(); + let needs_unpack = !ifmt.fmt.is_unpacked(); let needs_pack = !ofmt.fmt.is_unpacked(); let needs_convert = inname != outname; let scale_before_cvt = is_better_fmt(&ifmt, &ofmt) && needs_convert @@ -205,7 +234,6 @@ println!("[adding scale]"); cur_fmt = new_stage.fmt_out; add_stage!(stages, new_stage); } -//todo flip if needed if needs_pack { println!("[adding pack]"); let new_stage = Stage::new("pack", &cur_fmt, &ofmt)?; @@ -220,6 +248,74 @@ println!("[adding pack]"); Ok(stages) } +fn swap_plane(data: &mut [T], stride: usize, h: usize, line0: &mut [T], line1: &mut [T]) { + let mut doff0 = 0; + let mut doff1 = stride * (h - 1); + for _ in 0..h/2 { + line0.copy_from_slice(&data[doff0..][..stride]); + line1.copy_from_slice(&data[doff1..][..stride]); + (&mut data[doff1..][..stride]).copy_from_slice(line0); + (&mut data[doff0..][..stride]).copy_from_slice(line1); + doff0 += stride; + doff1 -= stride; + } +} + +pub fn flip_picture(pic: &mut NABufferType) -> ScaleResult<()> { + match pic { + NABufferType::Video(ref mut vb) => { + let ncomp = vb.get_num_components(); + for comp in 0..ncomp { + let off = vb.get_offset(comp); + let stride = vb.get_stride(comp); + let (_, h) = vb.get_dimensions(comp); + let data = vb.get_data_mut().unwrap(); + let mut line0 = vec![0; stride]; + let mut line1 = vec![0; stride]; + swap_plane(&mut data[off..], stride, h, line0.as_mut_slice(), line1.as_mut_slice()); + } + }, + NABufferType::Video16(ref mut vb) => { + let ncomp = vb.get_num_components(); + for comp in 0..ncomp { + let off = vb.get_offset(comp); + let stride = vb.get_stride(comp); + let (_, h) = vb.get_dimensions(comp); + let data = vb.get_data_mut().unwrap(); + let mut line0 = vec![0; stride]; + let mut line1 = vec![0; stride]; + swap_plane(&mut data[off..], stride, h, line0.as_mut_slice(), line1.as_mut_slice()); + } + }, + NABufferType::Video32(ref mut vb) => { + let ncomp = vb.get_num_components(); + for comp in 0..ncomp { + let off = vb.get_offset(comp); + let stride = vb.get_stride(comp); + let (_, h) = vb.get_dimensions(comp); + let data = vb.get_data_mut().unwrap(); + let mut line0 = vec![0; stride]; + let mut line1 = vec![0; stride]; + swap_plane(&mut data[off..], stride, h, line0.as_mut_slice(), line1.as_mut_slice()); + } + }, + NABufferType::VideoPacked(ref mut vb) => { + let ncomp = vb.get_num_components(); + for comp in 0..ncomp { + let off = vb.get_offset(comp); + let stride = vb.get_stride(comp); + let (_, h) = vb.get_dimensions(comp); + let data = vb.get_data_mut().unwrap(); + let mut line0 = vec![0; stride]; + let mut line1 = vec![0; stride]; + swap_plane(&mut data[off..], stride, h, line0.as_mut_slice(), line1.as_mut_slice()); + } + }, + _ => { return Err(ScaleError::InvalidArgument); }, + }; + Ok(()) +} + impl NAScale { pub fn new(fmt_in: ScaleInfo, fmt_out: ScaleInfo) -> ScaleResult { let pipeline; @@ -244,14 +340,19 @@ impl NAScale { (in_info.get_width() != out_info.get_width() || in_info.get_height() != out_info.get_height()) { return Err(ScaleError::InvalidArgument); } + let needs_flip = in_info.is_flipped() ^ out_info.is_flipped(); check_format(in_info, &self.fmt_in, self.just_convert)?; check_format(out_info, &self.fmt_out, self.just_convert)?; - if let Some(ref mut pipe) = self.pipeline { - pipe.process(pic_in, pic_out) - } else { - copy(pic_in, pic_out); - Ok(()) + let ret = if let Some(ref mut pipe) = self.pipeline { + pipe.process(pic_in, pic_out) + } else { + copy(pic_in, pic_out); + Ok(()) + }; + if ret.is_ok() && needs_flip { + flip_picture(pic_out)?; } + ret } }