test_encode_decode.rs 12.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright (c) 2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// 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 super::*;
11
use rand::{ChaChaRng, Rng, SeedableRng};
12 13 14 15 16 17
use std::sync::Arc;
use crate::util::Pixel;
#[cfg(feature="decode_test")]
use crate::test_encode_decode_aom::AomDecoder;
#[cfg(feature="decode_test_dav1d")]
use crate::test_encode_decode_dav1d::Dav1dDecoder;
18
use std::collections::VecDeque;
19
use interpolate_name::interpolate_test;
20 21 22 23 24 25 26 27 28 29 30 31 32

fn fill_frame<T: Pixel>(ra: &mut ChaChaRng, frame: &mut Frame<T>) {
  for plane in frame.planes.iter_mut() {
    let stride = plane.cfg.stride;
    for row in plane.data.chunks_mut(stride) {
      for pixel in row {
        let v: u8 = ra.gen();
        *pixel = T::cast_from(v);
      }
    }
  }
}

Luca Barbato's avatar
Luca Barbato committed
33 34
pub(crate) fn read_frame_batch<T: Pixel>(ctx: &mut Context<T>, ra: &mut ChaChaRng, limit: usize) {
  for _ in  0..limit {
35 36 37 38 39
    let mut input = ctx.new_frame();
    fill_frame(ra, Arc::get_mut(&mut input).unwrap());

    let _ = ctx.send_frame(Some(input));
  }
Luca Barbato's avatar
Luca Barbato committed
40 41

  ctx.flush();
42 43
}

44 45 46 47 48 49
pub(crate) enum DecodeResult {
  Done,
  NotDone,
  Corrupted(usize),
}

50
pub(crate) trait TestDecoder<T: Pixel> {
51 52 53 54
  fn setup_decoder(w: usize, h: usize) -> Self where Self: Sized;
  fn encode_decode(
    &mut self, w: usize, h: usize, speed: usize, quantizer: usize,
    limit: usize, bit_depth: usize, chroma_sampling: ChromaSampling,
55 56
    min_keyint: u64, max_keyint: u64, low_latency: bool, bitrate: i32,
    tile_cols_log2: usize, tile_rows_log2: usize,
57 58 59
  ) {
    let mut ra = ChaChaRng::from_seed([0; 32]);

60
    let mut ctx: Context<T> =
61
      setup_encoder(w, h, speed, quantizer, bit_depth, chroma_sampling,
62 63
                    min_keyint, max_keyint, low_latency, bitrate,
                    tile_cols_log2, tile_rows_log2);
64 65 66 67 68 69 70 71 72

    println!("Encoding {}x{} speed {} quantizer {} bit-depth {}", w, h, speed, quantizer, bit_depth);
    #[cfg(feature="dump_ivf")]
    let mut out = std::fs::File::create(&format!("out-{}x{}-s{}-q{}-{:?}.ivf",
                                                   w, h, speed, quantizer, chroma_sampling)).unwrap();
    #[cfg(feature="dump_ivf")]
    ivf::write_ivf_header(&mut out, w, h, 30, 1);

    let mut rec_fifo = VecDeque::new();
Luca Barbato's avatar
Luca Barbato committed
73 74
    read_frame_batch(&mut ctx, &mut ra, limit);

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
    for _ in 0..limit {

      let mut corrupted_count = 0;
      loop {
        let res = ctx.receive_packet();
        if let Ok(pkt) = res {
          println!("Encoded packet {}", pkt.number);

          #[cfg(feature="dump_ivf")]
          ivf::write_ivf_frame(&mut out, pkt.number, &pkt.data);

          if let Some(pkt_rec) = pkt.rec {
            rec_fifo.push_back(pkt_rec.clone());
          }
          let packet = pkt.data;
          println!("Decoding frame {}", pkt.number);
          match self.decode_packet(&packet, &mut rec_fifo, w, h, bit_depth) {
            DecodeResult::Done => { break; }
            DecodeResult::NotDone => {}
            DecodeResult::Corrupted(corrupted) => { corrupted_count += corrupted; }
          }
        } else {
          break;
        }
      }
      assert_eq!(corrupted_count, 0);
    }
  }
103
  fn decode_packet(&mut self, packet: &[u8], rec_fifo: &mut VecDeque<Frame<T>>, w: usize, h: usize, bit_depth: usize) -> DecodeResult;
104 105 106 107 108 109 110 111 112 113 114 115 116 117
}

pub(crate) fn compare_plane<T: Ord + std::fmt::Debug>(
  rec: &[T], rec_stride: usize, dec: &[T], dec_stride: usize, width: usize,
  height: usize
) {
  for line in rec.chunks(rec_stride).zip(dec.chunks(dec_stride)).take(height) {
    assert_eq!(&line.0[..width], &line.1[..width]);
  }
}

pub(crate) fn setup_encoder<T: Pixel>(
  w: usize, h: usize, speed: usize, quantizer: usize, bit_depth: usize,
  chroma_sampling: ChromaSampling, min_keyint: u64, max_keyint: u64,
118
  low_latency: bool, bitrate: i32, tile_cols_log2: usize, tile_rows_log2: usize,
119
) -> Context<T> {
120
  assert!(bit_depth == 8 || std::mem::size_of::<T>() > 1);
121 122 123 124 125 126 127 128 129 130
  let mut enc = EncoderConfig::with_speed_preset(speed);
  enc.quantizer = quantizer;
  enc.min_key_frame_interval = min_keyint;
  enc.max_key_frame_interval = max_keyint;
  enc.low_latency = low_latency;
  enc.width = w;
  enc.height = h;
  enc.bit_depth = bit_depth;
  enc.chroma_sampling = chroma_sampling;
  enc.bitrate = bitrate;
131 132
  enc.tile_cols_log2 = tile_cols_log2;
  enc.tile_rows_log2 = tile_rows_log2;
133 134

  let cfg = Config {
Luca Barbato's avatar
Luca Barbato committed
135 136
    enc,
    threads: 0,
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
  };

  cfg.new_context()
}

// TODO: support non-multiple-of-16 dimensions
static DIMENSION_OFFSETS: &[(usize, usize)] =
  &[(0, 0), (4, 4), (8, 8), (16, 16)];

fn speed(s: usize, decoder: &str) {
  let quantizer = 100;
  let limit = 5;
  let w = 64;
  let h = 80;

  for b in DIMENSION_OFFSETS.iter() {
      let w = w + b.0;
      let h = h + b.1;
155
      let mut dec = get_decoder::<u8>(decoder, w as usize, h as usize);
156
      dec.encode_decode(w, h, s, quantizer, limit, 8, Default::default(), 15, 15, true, 0, 0, 0);
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
  }
}

macro_rules! test_speeds {
  ($($S:expr),+) => {
    $(
        paste::item!{
            #[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))]
            #[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))]
            #[ignore]
            fn [<speed_ $S>](decoder: &str) {
                speed($S, decoder)
            }
        }
    )*
  }
}

test_speeds!{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }

macro_rules! test_dimensions {
  ($(($W:expr, $H:expr)),+) => {
    $(
        paste::item!{
181 182
            #[cfg_attr(feature = "decode_test", interpolate_name::interpolate_test(aom, "aom"))]
            #[cfg_attr(feature = "decode_test_dav1d", interpolate_name::interpolate_test(dav1d, "dav1d"))]
183
            fn [<dimension_ $W x $H>](decoder: &str) {
184
                super::dimension($W, $H, decoder)
185 186 187 188 189 190
            }
        }
    )*
  }
}

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
#[cfg(not(feature="quick_test"))]
mod large_dimension {
  test_dimensions!{
    (512, 512),
    (1024, 1024),
    (2048, 2048)
  }
}

mod small_dimension {
  test_dimensions!{
    (256, 256),
    (258, 258),
    (260, 260),
    (262, 262),
    (264, 264),
    (265, 265)
  }
}

mod tiny_dimension {
  test_dimensions!{
    (8, 8),
    (16, 16),
    (32, 32),
    (64, 64),
    (128, 128)
  }
219 220 221 222 223 224 225
}

fn dimension(w: usize, h: usize, decoder: &str) {
  let quantizer = 100;
  let limit = 1;
  let speed = 10;

226
  let mut dec = get_decoder::<u8>(decoder, w as usize, h as usize);
227
  dec.encode_decode(w, h, speed, quantizer, limit, 8, Default::default(), 15, 15, true, 0, 0, 0);
228 229
}

230
fn quantizer(decoder: &str, q: usize) {
231 232 233 234 235 236
  let limit = 5;
  let w = 64;
  let h = 80;
  let speed = 10;

  for b in DIMENSION_OFFSETS.iter() {
237
    let mut dec = get_decoder::<u8>(decoder, b.0, b.1);
238
    dec.encode_decode(w + b.0, h + b.1, speed, q, limit, 8, Default::default(), 15, 15, true, 0, 0, 0);
239 240 241
  }
}

242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
macro_rules! test_quantizer {
  ($($Q:expr),+) => {
    $(
      paste::item!{
        #[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))]
        #[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))]
        fn [<quantizer_ $Q>](decoder: &str) {
          quantizer(decoder, $Q);
        }
      }
    )*
  }
}

test_quantizer!{60, 80, 100, 120}

258 259 260 261 262 263 264 265 266 267
#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))]
#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))]
fn bitrate(decoder: &str) {
  let limit = 5;
  let w = 64;
  let h = 80;
  let speed = 10;

  for &q in [172, 220, 252, 255].iter() {
    for &r in [100, 1000, 10_000].iter() {
268
      let mut dec = get_decoder::<u8>(decoder, w as usize, h as usize);
269
      dec.encode_decode(w, h, speed, q, limit, 8, Default::default(), 15, 15, true, r, 0, 0);
270 271 272 273 274 275 276 277 278 279 280 281 282
    }
  }
}

#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))]
#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))]
fn keyframes(decoder: &str) {
  let limit = 12;
  let w = 64;
  let h = 80;
  let speed = 9;
  let q = 100;

283
  let mut dec = get_decoder::<u8>(decoder, w as usize, h as usize);
284
  dec.encode_decode(w, h, speed, q, limit, 8, Default::default(), 6, 6, true, 0, 0, 0);
285 286 287 288 289 290 291 292 293 294 295 296
}

#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))]
#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))]
fn reordering(decoder: &str) {
  let limit = 12;
  let w = 64;
  let h = 80;
  let speed = 10;
  let q = 100;

  for keyint in &[4, 5, 6] {
297
    let mut dec = get_decoder::<u8>(decoder, w as usize, h as usize);
298
    dec.encode_decode(w, h, speed, q, limit, 8, Default::default(), *keyint, *keyint, false, 0, 0, 0);
299 300 301 302 303 304 305 306 307 308 309 310 311 312
  }
}

#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))]
#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))]
fn reordering_short_video(decoder: &str) {
  // Regression test for https://github.com/xiph/rav1e/issues/890
  let limit = 2;
  let w = 64;
  let h = 80;
  let speed = 10;
  let q = 100;
  let keyint = 12;

313
  let mut dec = get_decoder::<u8>(decoder, w as usize, h as usize);
314
  dec.encode_decode(w, h, speed, q, limit, 8, Default::default(), keyint, keyint, false, 0, 0, 0);
315 316 317 318 319 320 321 322 323 324 325 326
}

#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))]
#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))]
#[ignore]
fn odd_size_frame_with_full_rdo(decoder: &str) {
  let limit = 3;
  let w = 512 + 32 + 16 + 5;
  let h = 512 + 16 + 5;
  let speed = 0;
  let qindex = 100;

327
  let mut dec = get_decoder::<u8>(decoder, w as usize, h as usize);
328
  dec.encode_decode(w, h, speed, qindex, limit, 8, Default::default(), 15, 15, true, 0, 0, 0);
329 330 331 332
}

#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))]
#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))]
333
fn low_bit_depth(decoder: &str) {
334 335 336 337 338 339 340
  let quantizer = 100;
  let limit = 3; // Include inter frames
  let speed = 0; // Test as many tools as possible
  let w = 64;
  let h = 80;

  // 8-bit
341
  let mut dec = get_decoder::<u8>(decoder, w as usize, h as usize);
342
  dec.encode_decode(w, h, speed, quantizer, limit, 8, Default::default(), 15, 15, true, 0, 0, 0);
343
}
344

345 346 347 348 349 350
fn high_bit_depth(decoder: &str, depth: usize) {
  let quantizer = 100;
  let limit = 3; // Include inter frames
  let speed = 0; // Test as many tools as possible
  let w = 64;
  let h = 80;
351

352
  let mut dec = get_decoder::<u16>(decoder, w as usize, h as usize);
353
  dec.encode_decode(w, h, speed, quantizer, limit, depth, Default::default(), 15, 15, true, 0, 0, 0);
354 355
}

356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
macro_rules! test_high_bit_depth {
  ($($B:expr),+) => {
    $(
      paste::item_with_macros!{
        #[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))]
        #[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))]
        fn [<high_bit_depth_ $B>](decoder: &str) {
          high_bit_depth(decoder, $B);
        }
      }
    )*
  }
}

test_high_bit_depth!{10, 12}

372
fn chroma_sampling(decoder: &str, cs: ChromaSampling) {
373 374 375 376 377 378 379 380
  let quantizer = 100;
  let limit = 3; // Include inter frames
  let speed = 0; // Test as many tools as possible
  let w = 64;
  let h = 80;

  // TODO: bump keyint when inter is supported

381
  let mut dec = get_decoder::<u8>(decoder, w as usize, h as usize);
382
  dec.encode_decode(w, h, speed, quantizer, limit, 8, cs, 1, 1, true, 0, 0, 0);
383 384
}

385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
macro_rules! test_chroma_sampling {
  ($(($S:expr, $I:expr)),+) => {
    $(
      paste::item_with_macros!{
        #[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))]
        #[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))]
        fn [<chroma_sampling_ $S>](decoder: &str) {
          chroma_sampling(decoder, $I);
        }
      }
    )*
  }
}

test_chroma_sampling!{(420, ChromaSampling::Cs420), (422, ChromaSampling::Cs422), (444, ChromaSampling::Cs444)}

Romain Vimont's avatar
Romain Vimont committed
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
#[cfg_attr(feature = "decode_test", interpolate_test(aom, "aom"))]
#[cfg_attr(feature = "decode_test_dav1d", interpolate_test(dav1d, "dav1d"))]
fn tile_encoding_with_stretched_restoration_units(decoder: &str) {
  let limit = 5;
  let w = 256;
  // the bottom tiles are small (their height is 140-128=12), so they will use stretched
  // restoration units from their above neighbours
  let h = 140;
  let speed = 10;
  let q = 100;

  let mut dec = get_decoder::<u8>(decoder, w as usize, h as usize);
  dec.encode_decode(w, h, speed, q, limit, 8, Default::default(), 15, 15, true, 0, 2, 2);
}

416
fn get_decoder<T: Pixel>(decoder: &str, w: usize, h: usize) -> Box<dyn TestDecoder<T>> {
417 418
  match decoder {
    #[cfg(feature="decode_test")]
419
    "aom" => Box::new(AomDecoder::<T>::setup_decoder(w, h)),
420
    #[cfg(feature="decode_test_dav1d")]
421
    "dav1d" => Box::new(Dav1dDecoder::<T>::setup_decoder(w, h)),
422 423
    _ => unimplemented!()
  }
Luca Barbato's avatar
Luca Barbato committed
424
}