11b362b15af34006e6a11974088a46d42b903418eJohann/*
2b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *
4b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  Use of this source code is governed by a BSD-style license
5b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  that can be found in the LICENSE file in the root of the source
6b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  tree. An additional intellectual property rights grant can be found
7b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  in the file PATENTS.  All contributing project authors may
8b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian *  be found in the AUTHORS file in the root of the source tree.
9b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian */
10ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
111b362b15af34006e6a11974088a46d42b903418eJohann#include "third_party/googletest/src/include/gtest/gtest.h"
12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "test/codec_factory.h"
131b362b15af34006e6a11974088a46d42b903418eJohann#include "test/encode_test_driver.h"
141b362b15af34006e6a11974088a46d42b903418eJohann#include "test/i420_video_source.h"
15ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "test/util.h"
161b362b15af34006e6a11974088a46d42b903418eJohann
171b362b15af34006e6a11974088a46d42b903418eJohannnamespace {
181b362b15af34006e6a11974088a46d42b903418eJohann
19b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianconst int kMaxErrorFrames = 12;
20b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianconst int kMaxDroppableFrames = 12;
21ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
227bc9febe8749e98a3812a0dc4380ceae75c29450Johannclass ErrorResilienceTestLarge
237bc9febe8749e98a3812a0dc4380ceae75c29450Johann    : public ::libvpx_test::EncoderTest,
247bc9febe8749e98a3812a0dc4380ceae75c29450Johann      public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, bool> {
251b362b15af34006e6a11974088a46d42b903418eJohann protected:
26a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  ErrorResilienceTestLarge()
277bc9febe8749e98a3812a0dc4380ceae75c29450Johann      : EncoderTest(GET_PARAM(0)), svc_support_(GET_PARAM(2)), psnr_(0.0),
287bc9febe8749e98a3812a0dc4380ceae75c29450Johann        nframes_(0), mismatch_psnr_(0.0), mismatch_nframes_(0),
29a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian        encoding_mode_(GET_PARAM(1)) {
30ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    Reset();
311b362b15af34006e6a11974088a46d42b903418eJohann  }
32ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
33a72801d7d92ababb50eecf27a36bd222d031d2feVignesh Venkatasubramanian  virtual ~ErrorResilienceTestLarge() {}
341b362b15af34006e6a11974088a46d42b903418eJohann
35ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  void Reset() {
36ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error_nframes_ = 0;
37ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    droppable_nframes_ = 0;
387ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    pattern_switch_ = 0;
39ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
40ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
411b362b15af34006e6a11974088a46d42b903418eJohann  virtual void SetUp() {
421b362b15af34006e6a11974088a46d42b903418eJohann    InitializeConfig();
431b362b15af34006e6a11974088a46d42b903418eJohann    SetMode(encoding_mode_);
441b362b15af34006e6a11974088a46d42b903418eJohann  }
451b362b15af34006e6a11974088a46d42b903418eJohann
461b362b15af34006e6a11974088a46d42b903418eJohann  virtual void BeginPassHook(unsigned int /*pass*/) {
471b362b15af34006e6a11974088a46d42b903418eJohann    psnr_ = 0.0;
481b362b15af34006e6a11974088a46d42b903418eJohann    nframes_ = 0;
49ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    mismatch_psnr_ = 0.0;
50ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    mismatch_nframes_ = 0;
511b362b15af34006e6a11974088a46d42b903418eJohann  }
521b362b15af34006e6a11974088a46d42b903418eJohann
531b362b15af34006e6a11974088a46d42b903418eJohann  virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
541b362b15af34006e6a11974088a46d42b903418eJohann    psnr_ += pkt->data.psnr.psnr[0];
551b362b15af34006e6a11974088a46d42b903418eJohann    nframes_++;
561b362b15af34006e6a11974088a46d42b903418eJohann  }
571b362b15af34006e6a11974088a46d42b903418eJohann
587ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  //
597ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // Frame flags and layer id for temporal layers.
607ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // For two layers, test pattern is:
617ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  //   1     3
627ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // 0    2     .....
637ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // LAST is updated on base/layer 0, GOLDEN  updated on layer 1.
647ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // Non-zero pattern_switch parameter means pattern will switch to
657ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // not using LAST for frame_num >= pattern_switch.
667bc9febe8749e98a3812a0dc4380ceae75c29450Johann  int SetFrameFlags(int frame_num, int num_temp_layers, int pattern_switch) {
677ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    int frame_flags = 0;
687ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    if (num_temp_layers == 2) {
697bc9febe8749e98a3812a0dc4380ceae75c29450Johann      if (frame_num % 2 == 0) {
707bc9febe8749e98a3812a0dc4380ceae75c29450Johann        if (frame_num < pattern_switch || pattern_switch == 0) {
717bc9febe8749e98a3812a0dc4380ceae75c29450Johann          // Layer 0: predict from LAST and ARF, update LAST.
727bc9febe8749e98a3812a0dc4380ceae75c29450Johann          frame_flags =
737bc9febe8749e98a3812a0dc4380ceae75c29450Johann              VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
747ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        } else {
757bc9febe8749e98a3812a0dc4380ceae75c29450Johann          // Layer 0: predict from GF and ARF, update GF.
767bc9febe8749e98a3812a0dc4380ceae75c29450Johann          frame_flags = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_LAST |
777bc9febe8749e98a3812a0dc4380ceae75c29450Johann                        VP8_EFLAG_NO_UPD_ARF;
787ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        }
797bc9febe8749e98a3812a0dc4380ceae75c29450Johann      } else {
807bc9febe8749e98a3812a0dc4380ceae75c29450Johann        if (frame_num < pattern_switch || pattern_switch == 0) {
817bc9febe8749e98a3812a0dc4380ceae75c29450Johann          // Layer 1: predict from L, GF, and ARF, update GF.
827bc9febe8749e98a3812a0dc4380ceae75c29450Johann          frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
837bc9febe8749e98a3812a0dc4380ceae75c29450Johann        } else {
847bc9febe8749e98a3812a0dc4380ceae75c29450Johann          // Layer 1: predict from GF and ARF, update GF.
857bc9febe8749e98a3812a0dc4380ceae75c29450Johann          frame_flags = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_LAST |
867bc9febe8749e98a3812a0dc4380ceae75c29450Johann                        VP8_EFLAG_NO_UPD_ARF;
877bc9febe8749e98a3812a0dc4380ceae75c29450Johann        }
887bc9febe8749e98a3812a0dc4380ceae75c29450Johann      }
897ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    }
907ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    return frame_flags;
917ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
927ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
937bc9febe8749e98a3812a0dc4380ceae75c29450Johann  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video) {
947bc9febe8749e98a3812a0dc4380ceae75c29450Johann    frame_flags_ &=
957bc9febe8749e98a3812a0dc4380ceae75c29450Johann        ~(VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF);
967ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    // For temporal layer case.
977ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    if (cfg_.ts_number_layers > 1) {
987bc9febe8749e98a3812a0dc4380ceae75c29450Johann      frame_flags_ =
997bc9febe8749e98a3812a0dc4380ceae75c29450Johann          SetFrameFlags(video->frame(), cfg_.ts_number_layers, pattern_switch_);
100ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      for (unsigned int i = 0; i < droppable_nframes_; ++i) {
1013df0563f1b24dac6c0bd122fc922a48211269061hkuang        if (droppable_frames_[i] == video->frame()) {
1027bc9febe8749e98a3812a0dc4380ceae75c29450Johann          std::cout << "Encoding droppable frame: " << droppable_frames_[i]
1037bc9febe8749e98a3812a0dc4380ceae75c29450Johann                    << "\n";
104ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        }
105ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
1067ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    } else {
1077bc9febe8749e98a3812a0dc4380ceae75c29450Johann      if (droppable_nframes_ > 0 &&
1087bc9febe8749e98a3812a0dc4380ceae75c29450Johann          (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
1097bc9febe8749e98a3812a0dc4380ceae75c29450Johann        for (unsigned int i = 0; i < droppable_nframes_; ++i) {
1107bc9febe8749e98a3812a0dc4380ceae75c29450Johann          if (droppable_frames_[i] == video->frame()) {
1117bc9febe8749e98a3812a0dc4380ceae75c29450Johann            std::cout << "Encoding droppable frame: " << droppable_frames_[i]
1127bc9febe8749e98a3812a0dc4380ceae75c29450Johann                      << "\n";
1137bc9febe8749e98a3812a0dc4380ceae75c29450Johann            frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
1147bc9febe8749e98a3812a0dc4380ceae75c29450Johann                             VP8_EFLAG_NO_UPD_ARF);
1157bc9febe8749e98a3812a0dc4380ceae75c29450Johann            return;
1167bc9febe8749e98a3812a0dc4380ceae75c29450Johann          }
1177bc9febe8749e98a3812a0dc4380ceae75c29450Johann        }
1187bc9febe8749e98a3812a0dc4380ceae75c29450Johann      }
119ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
120ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
121ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1221b362b15af34006e6a11974088a46d42b903418eJohann  double GetAveragePsnr() const {
1237bc9febe8749e98a3812a0dc4380ceae75c29450Johann    if (nframes_) return psnr_ / nframes_;
1241b362b15af34006e6a11974088a46d42b903418eJohann    return 0.0;
1251b362b15af34006e6a11974088a46d42b903418eJohann  }
1261b362b15af34006e6a11974088a46d42b903418eJohann
127ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  double GetAverageMismatchPsnr() const {
1287bc9febe8749e98a3812a0dc4380ceae75c29450Johann    if (mismatch_nframes_) return mismatch_psnr_ / mismatch_nframes_;
129ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return 0.0;
130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
131ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
132ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  virtual bool DoDecode() const {
133ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (error_nframes_ > 0 &&
134ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
135ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      for (unsigned int i = 0; i < error_nframes_; ++i) {
136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        if (error_frames_[i] == nframes_ - 1) {
137ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          std::cout << "             Skipping decoding frame: "
138ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                    << error_frames_[i] << "\n";
139ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang          return 0;
140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang        }
141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      }
142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
143ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return 1;
144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
145ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1467bc9febe8749e98a3812a0dc4380ceae75c29450Johann  virtual void MismatchHook(const vpx_image_t *img1, const vpx_image_t *img2) {
147ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    double mismatch_psnr = compute_psnr(img1, img2);
148ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    mismatch_psnr_ += mismatch_psnr;
149ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ++mismatch_nframes_;
150ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    // std::cout << "Mismatch frame psnr: " << mismatch_psnr << "\n";
151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
152ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  void SetErrorFrames(int num, unsigned int *list) {
1547bc9febe8749e98a3812a0dc4380ceae75c29450Johann    if (num > kMaxErrorFrames) {
155ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      num = kMaxErrorFrames;
1567bc9febe8749e98a3812a0dc4380ceae75c29450Johann    } else if (num < 0) {
157ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      num = 0;
1587bc9febe8749e98a3812a0dc4380ceae75c29450Johann    }
159ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    error_nframes_ = num;
1607bc9febe8749e98a3812a0dc4380ceae75c29450Johann    for (unsigned int i = 0; i < error_nframes_; ++i) {
161ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      error_frames_[i] = list[i];
1627bc9febe8749e98a3812a0dc4380ceae75c29450Johann    }
163ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
164ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
165ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  void SetDroppableFrames(int num, unsigned int *list) {
1667bc9febe8749e98a3812a0dc4380ceae75c29450Johann    if (num > kMaxDroppableFrames) {
167ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      num = kMaxDroppableFrames;
1687bc9febe8749e98a3812a0dc4380ceae75c29450Johann    } else if (num < 0) {
169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      num = 0;
1707bc9febe8749e98a3812a0dc4380ceae75c29450Johann    }
171ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    droppable_nframes_ = num;
1727bc9febe8749e98a3812a0dc4380ceae75c29450Johann    for (unsigned int i = 0; i < droppable_nframes_; ++i) {
173ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      droppable_frames_[i] = list[i];
1747bc9febe8749e98a3812a0dc4380ceae75c29450Johann    }
175ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
176ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1777bc9febe8749e98a3812a0dc4380ceae75c29450Johann  unsigned int GetMismatchFrames() { return mismatch_nframes_; }
178ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1797bc9febe8749e98a3812a0dc4380ceae75c29450Johann  void SetPatternSwitch(int frame_switch) { pattern_switch_ = frame_switch; }
1807ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
181c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  bool svc_support_;
182c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann
1831b362b15af34006e6a11974088a46d42b903418eJohann private:
1841b362b15af34006e6a11974088a46d42b903418eJohann  double psnr_;
1851b362b15af34006e6a11974088a46d42b903418eJohann  unsigned int nframes_;
186ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  unsigned int error_nframes_;
187ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  unsigned int droppable_nframes_;
1887ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  unsigned int pattern_switch_;
189ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  double mismatch_psnr_;
190ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  unsigned int mismatch_nframes_;
191ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  unsigned int error_frames_[kMaxErrorFrames];
192ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  unsigned int droppable_frames_[kMaxDroppableFrames];
1931b362b15af34006e6a11974088a46d42b903418eJohann  libvpx_test::TestMode encoding_mode_;
1941b362b15af34006e6a11974088a46d42b903418eJohann};
1951b362b15af34006e6a11974088a46d42b903418eJohann
196a72801d7d92ababb50eecf27a36bd222d031d2feVignesh VenkatasubramanianTEST_P(ErrorResilienceTestLarge, OnVersusOff) {
1971b362b15af34006e6a11974088a46d42b903418eJohann  const vpx_rational timebase = { 33333333, 1000000000 };
1981b362b15af34006e6a11974088a46d42b903418eJohann  cfg_.g_timebase = timebase;
1991b362b15af34006e6a11974088a46d42b903418eJohann  cfg_.rc_target_bitrate = 2000;
2003df0563f1b24dac6c0bd122fc922a48211269061hkuang  cfg_.g_lag_in_frames = 10;
2011b362b15af34006e6a11974088a46d42b903418eJohann
2021b362b15af34006e6a11974088a46d42b903418eJohann  init_flags_ = VPX_CODEC_USE_PSNR;
2031b362b15af34006e6a11974088a46d42b903418eJohann
2041b362b15af34006e6a11974088a46d42b903418eJohann  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
2051b362b15af34006e6a11974088a46d42b903418eJohann                                     timebase.den, timebase.num, 0, 30);
2061b362b15af34006e6a11974088a46d42b903418eJohann
2071b362b15af34006e6a11974088a46d42b903418eJohann  // Error resilient mode OFF.
2081b362b15af34006e6a11974088a46d42b903418eJohann  cfg_.g_error_resilient = 0;
2091b362b15af34006e6a11974088a46d42b903418eJohann  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
2101b362b15af34006e6a11974088a46d42b903418eJohann  const double psnr_resilience_off = GetAveragePsnr();
2111b362b15af34006e6a11974088a46d42b903418eJohann  EXPECT_GT(psnr_resilience_off, 25.0);
2121b362b15af34006e6a11974088a46d42b903418eJohann
2131b362b15af34006e6a11974088a46d42b903418eJohann  // Error resilient mode ON.
2141b362b15af34006e6a11974088a46d42b903418eJohann  cfg_.g_error_resilient = 1;
2151b362b15af34006e6a11974088a46d42b903418eJohann  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
2161b362b15af34006e6a11974088a46d42b903418eJohann  const double psnr_resilience_on = GetAveragePsnr();
2171b362b15af34006e6a11974088a46d42b903418eJohann  EXPECT_GT(psnr_resilience_on, 25.0);
2181b362b15af34006e6a11974088a46d42b903418eJohann
2191b362b15af34006e6a11974088a46d42b903418eJohann  // Test that turning on error resilient mode hurts by 10% at most.
2201b362b15af34006e6a11974088a46d42b903418eJohann  if (psnr_resilience_off > 0.0) {
2211b362b15af34006e6a11974088a46d42b903418eJohann    const double psnr_ratio = psnr_resilience_on / psnr_resilience_off;
2221b362b15af34006e6a11974088a46d42b903418eJohann    EXPECT_GE(psnr_ratio, 0.9);
2231b362b15af34006e6a11974088a46d42b903418eJohann    EXPECT_LE(psnr_ratio, 1.1);
2241b362b15af34006e6a11974088a46d42b903418eJohann  }
2251b362b15af34006e6a11974088a46d42b903418eJohann}
2261b362b15af34006e6a11974088a46d42b903418eJohann
227b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// Check for successful decoding and no encoder/decoder mismatch
228b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// if we lose (i.e., drop before decoding) a set of droppable
229b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// frames (i.e., frames that don't update any reference buffers).
230b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian// Check both isolated and consecutive loss.
231a72801d7d92ababb50eecf27a36bd222d031d2feVignesh VenkatasubramanianTEST_P(ErrorResilienceTestLarge, DropFramesWithoutRecovery) {
232ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  const vpx_rational timebase = { 33333333, 1000000000 };
233ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  cfg_.g_timebase = timebase;
234ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  cfg_.rc_target_bitrate = 500;
2353df0563f1b24dac6c0bd122fc922a48211269061hkuang  // FIXME(debargha): Fix this to work for any lag.
2363df0563f1b24dac6c0bd122fc922a48211269061hkuang  // Currently this test only works for lag = 0
2373df0563f1b24dac6c0bd122fc922a48211269061hkuang  cfg_.g_lag_in_frames = 0;
238ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
239ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  init_flags_ = VPX_CODEC_USE_PSNR;
240ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
241ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
242b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                                     timebase.den, timebase.num, 0, 40);
243ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
244ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  // Error resilient mode ON.
245ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  cfg_.g_error_resilient = 1;
246b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  cfg_.kf_mode = VPX_KF_DISABLED;
247b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
248b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  // Set an arbitrary set of error frames same as droppable frames.
249b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  // In addition to isolated loss/drop, add a long consecutive series
250b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  // (of size 9) of dropped frames.
251b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  unsigned int num_droppable_frames = 11;
2527bc9febe8749e98a3812a0dc4380ceae75c29450Johann  unsigned int droppable_frame_list[] = { 5,  16, 22, 23, 24, 25,
2537bc9febe8749e98a3812a0dc4380ceae75c29450Johann                                          26, 27, 28, 29, 30 };
254ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  SetDroppableFrames(num_droppable_frames, droppable_frame_list);
255ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  SetErrorFrames(num_droppable_frames, droppable_frame_list);
256ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
257ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  // Test that no mismatches have been found
2587bc9febe8749e98a3812a0dc4380ceae75c29450Johann  std::cout << "             Mismatch frames: " << GetMismatchFrames() << "\n";
2597bc9febe8749e98a3812a0dc4380ceae75c29450Johann  EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
260ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
261b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  // Reset previously set of error/droppable frames.
262ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  Reset();
263ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
264ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#if 0
265ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  // TODO(jkoleszar): This test is disabled for the time being as too
266ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  // sensitive. It's not clear how to set a reasonable threshold for
267ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  // this behavior.
268ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
269ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  // Now set an arbitrary set of error frames that are non-droppable
270ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  unsigned int num_error_frames = 3;
271ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  unsigned int error_frame_list[] = {3, 10, 20};
272ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  SetErrorFrames(num_error_frames, error_frame_list);
273ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
274ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
275ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  // Test that dropping an arbitrary set of inter frames does not hurt too much
276ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  // Note the Average Mismatch PSNR is the average of the PSNR between
277ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  // decoded frame and encoder's version of the same frame for all frames
278ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  // with mismatch.
279ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  const double psnr_resilience_mismatch = GetAverageMismatchPsnr();
280ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  std::cout << "             Mismatch PSNR: "
281ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang            << psnr_resilience_mismatch << "\n";
282ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  EXPECT_GT(psnr_resilience_mismatch, 20.0);
283ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif
284ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
285ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2867ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// Check for successful decoding and no encoder/decoder mismatch
2877ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// if we lose (i.e., drop before decoding) the enhancement layer frames for a
2887ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// two layer temporal pattern. The base layer does not predict from the top
2897ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// layer, so successful decoding is expected.
2907ce0a1d1337c01056ba24006efab21f00e179e04Vignesh VenkatasubramanianTEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) {
291c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  // This test doesn't run if SVC is not supported.
2927bc9febe8749e98a3812a0dc4380ceae75c29450Johann  if (!svc_support_) return;
293c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann
2947ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  const vpx_rational timebase = { 33333333, 1000000000 };
2957ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.g_timebase = timebase;
2967ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.rc_target_bitrate = 500;
2977ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.g_lag_in_frames = 0;
2987ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
2997ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.rc_end_usage = VPX_CBR;
3007ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // 2 Temporal layers, no spatial layers, CBR mode.
3017ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ss_number_layers = 1;
3027ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_number_layers = 2;
3037ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_rate_decimator[0] = 2;
3047ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_rate_decimator[1] = 1;
3057ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_periodicity = 2;
3067ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
3077ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
3087ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3097ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  init_flags_ = VPX_CODEC_USE_PSNR;
3107ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3117ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
3127ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                                     timebase.den, timebase.num, 0, 40);
3137ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3147ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // Error resilient mode ON.
3157ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.g_error_resilient = 1;
3167ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.kf_mode = VPX_KF_DISABLED;
3177ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  SetPatternSwitch(0);
3187ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3197ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // The odd frames are the enhancement layer for 2 layer pattern, so set
3207ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // those frames as droppable. Drop the last 7 frames.
3217ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  unsigned int num_droppable_frames = 7;
3227bc9febe8749e98a3812a0dc4380ceae75c29450Johann  unsigned int droppable_frame_list[] = { 27, 29, 31, 33, 35, 37, 39 };
3237ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  SetDroppableFrames(num_droppable_frames, droppable_frame_list);
3247ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  SetErrorFrames(num_droppable_frames, droppable_frame_list);
3257ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
3267ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // Test that no mismatches have been found
3277bc9febe8749e98a3812a0dc4380ceae75c29450Johann  std::cout << "             Mismatch frames: " << GetMismatchFrames() << "\n";
3287bc9febe8749e98a3812a0dc4380ceae75c29450Johann  EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
3297ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3307ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // Reset previously set of error/droppable frames.
3317ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  Reset();
3327ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian}
3337ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3347ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// Check for successful decoding and no encoder/decoder mismatch
3357ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// for a two layer temporal pattern, where at some point in the
3367ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// sequence, the LAST ref is not used anymore.
3377ce0a1d1337c01056ba24006efab21f00e179e04Vignesh VenkatasubramanianTEST_P(ErrorResilienceTestLarge, 2LayersNoRefLast) {
338c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann  // This test doesn't run if SVC is not supported.
3397bc9febe8749e98a3812a0dc4380ceae75c29450Johann  if (!svc_support_) return;
340c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann
3417ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  const vpx_rational timebase = { 33333333, 1000000000 };
3427ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.g_timebase = timebase;
3437ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.rc_target_bitrate = 500;
3447ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.g_lag_in_frames = 0;
3457ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3467ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.rc_end_usage = VPX_CBR;
3477ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // 2 Temporal layers, no spatial layers, CBR mode.
3487ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ss_number_layers = 1;
3497ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_number_layers = 2;
3507ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_rate_decimator[0] = 2;
3517ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_rate_decimator[1] = 1;
3527ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_periodicity = 2;
3537ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
3547ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
3557ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3567ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  init_flags_ = VPX_CODEC_USE_PSNR;
3577ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3587ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
3597ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                                     timebase.den, timebase.num, 0, 100);
3607ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3617ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // Error resilient mode ON.
3627ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.g_error_resilient = 1;
3637ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.kf_mode = VPX_KF_DISABLED;
3647ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  SetPatternSwitch(60);
3657ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3667ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
3677ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // Test that no mismatches have been found
3687bc9febe8749e98a3812a0dc4380ceae75c29450Johann  std::cout << "             Mismatch frames: " << GetMismatchFrames() << "\n";
3697bc9febe8749e98a3812a0dc4380ceae75c29450Johann  EXPECT_EQ(GetMismatchFrames(), (unsigned int)0);
3707ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3717ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // Reset previously set of error/droppable frames.
3727ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  Reset();
3737ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian}
3747ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3757bc9febe8749e98a3812a0dc4380ceae75c29450Johannclass ErrorResilienceTestLargeCodecControls
3767bc9febe8749e98a3812a0dc4380ceae75c29450Johann    : public ::libvpx_test::EncoderTest,
3777bc9febe8749e98a3812a0dc4380ceae75c29450Johann      public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
3787ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian protected:
3797ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  ErrorResilienceTestLargeCodecControls()
3807bc9febe8749e98a3812a0dc4380ceae75c29450Johann      : EncoderTest(GET_PARAM(0)), encoding_mode_(GET_PARAM(1)) {
3817ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    Reset();
3827ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
3837ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3847ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  virtual ~ErrorResilienceTestLargeCodecControls() {}
3857ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3867ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  void Reset() {
3877ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    last_pts_ = 0;
3887ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    tot_frame_number_ = 0;
3897ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    // For testing up to 3 layers.
3907ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    for (int i = 0; i < 3; ++i) {
3917ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      bits_total_[i] = 0;
3927ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    }
3937ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    duration_ = 0.0;
3947ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
3957ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
3967ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  virtual void SetUp() {
3977ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    InitializeConfig();
3987ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    SetMode(encoding_mode_);
3997ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
4007ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
4017ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  //
4027ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // Frame flags and layer id for temporal layers.
4037ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  //
4047ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
4057ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // For two layers, test pattern is:
4067ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  //   1     3
4077ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // 0    2     .....
4087ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // For three layers, test pattern is:
4097ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  //   1      3    5      7
4107ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  //      2           6
4117ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // 0          4            ....
4127ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // LAST is always update on base/layer 0, GOLDEN is updated on layer 1,
4137ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // and ALTREF is updated on top layer for 3 layer pattern.
4147ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  int SetFrameFlags(int frame_num, int num_temp_layers) {
4157ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    int frame_flags = 0;
4167ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    if (num_temp_layers == 2) {
4177ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      if (frame_num % 2 == 0) {
4187ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        // Layer 0: predict from L and ARF, update L.
4197bc9febe8749e98a3812a0dc4380ceae75c29450Johann        frame_flags =
4207bc9febe8749e98a3812a0dc4380ceae75c29450Johann            VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
4217ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      } else {
4227ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        // Layer 1: predict from L, G and ARF, and update G.
4237ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
4247ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                      VP8_EFLAG_NO_UPD_ENTROPY;
4257ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      }
4267ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    } else if (num_temp_layers == 3) {
4277ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      if (frame_num % 4 == 0) {
4287ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        // Layer 0: predict from L, update L.
4297ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
4307ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                      VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
4317ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      } else if ((frame_num - 2) % 4 == 0) {
4327ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        // Layer 1: predict from L, G,  update G.
4337bc9febe8749e98a3812a0dc4380ceae75c29450Johann        frame_flags =
4347bc9febe8749e98a3812a0dc4380ceae75c29450Johann            VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_REF_ARF;
4357bc9febe8749e98a3812a0dc4380ceae75c29450Johann      } else if ((frame_num - 1) % 2 == 0) {
4367ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        // Layer 2: predict from L, G, ARF; update ARG.
4377ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
4387ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      }
4397ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    }
4407ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    return frame_flags;
4417ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
4427ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
4437ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  int SetLayerId(int frame_num, int num_temp_layers) {
4447ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    int layer_id = 0;
4457ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    if (num_temp_layers == 2) {
4467ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      if (frame_num % 2 == 0) {
4477ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        layer_id = 0;
4487ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      } else {
4497bc9febe8749e98a3812a0dc4380ceae75c29450Johann        layer_id = 1;
4507ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      }
4517ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    } else if (num_temp_layers == 3) {
4527ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      if (frame_num % 4 == 0) {
4537ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        layer_id = 0;
4547ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      } else if ((frame_num - 2) % 4 == 0) {
4557ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        layer_id = 1;
4567ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      } else if ((frame_num - 1) % 2 == 0) {
4577ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        layer_id = 2;
4587ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      }
4597ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    }
4607ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    return layer_id;
4617ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
4627ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
4637ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
4647ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                                  libvpx_test::Encoder *encoder) {
4657ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    if (cfg_.ts_number_layers > 1) {
4667bc9febe8749e98a3812a0dc4380ceae75c29450Johann      int layer_id = SetLayerId(video->frame(), cfg_.ts_number_layers);
4677bc9febe8749e98a3812a0dc4380ceae75c29450Johann      int frame_flags = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
4687bc9febe8749e98a3812a0dc4380ceae75c29450Johann      if (video->frame() > 0) {
4697bc9febe8749e98a3812a0dc4380ceae75c29450Johann        encoder->Control(VP8E_SET_TEMPORAL_LAYER_ID, layer_id);
4707bc9febe8749e98a3812a0dc4380ceae75c29450Johann        encoder->Control(VP8E_SET_FRAME_FLAGS, frame_flags);
4717bc9febe8749e98a3812a0dc4380ceae75c29450Johann      }
4727bc9febe8749e98a3812a0dc4380ceae75c29450Johann      const vpx_rational_t tb = video->timebase();
4737bc9febe8749e98a3812a0dc4380ceae75c29450Johann      timebase_ = static_cast<double>(tb.num) / tb.den;
4747bc9febe8749e98a3812a0dc4380ceae75c29450Johann      duration_ = 0;
4757bc9febe8749e98a3812a0dc4380ceae75c29450Johann      return;
4767ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    }
4777ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
4787ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
4797ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
4807ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    // Time since last timestamp = duration.
4817ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
4827ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    if (duration > 1) {
4837ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      // Update counter for total number of frames (#frames input to encoder).
4847ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      // Needed for setting the proper layer_id below.
4857ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      tot_frame_number_ += static_cast<int>(duration - 1);
4867ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    }
4877ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers);
4887ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
4897ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    // Update the total encoded bits. For temporal layers, update the cumulative
4907ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    // encoded bits per layer.
4917ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
4927ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      bits_total_[i] += frame_size_in_bits;
4937ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    }
4947ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    // Update the most recent pts.
4957ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    last_pts_ = pkt->data.frame.pts;
4967ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    ++tot_frame_number_;
4977ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
4987ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
4997ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  virtual void EndPassHook(void) {
5007ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    duration_ = (last_pts_ + 1) * timebase_;
5017bc9febe8749e98a3812a0dc4380ceae75c29450Johann    if (cfg_.ts_number_layers > 1) {
5027ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
5037bc9febe8749e98a3812a0dc4380ceae75c29450Johann           ++layer) {
5047ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        if (bits_total_[layer]) {
5057ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian          // Effective file datarate:
5067bc9febe8749e98a3812a0dc4380ceae75c29450Johann          effective_datarate_[layer] =
5077bc9febe8749e98a3812a0dc4380ceae75c29450Johann              (bits_total_[layer] / 1000.0) / duration_;
5087ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian        }
5097ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      }
5107ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    }
5117ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
5127ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
5137ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  double effective_datarate_[3];
5147bc9febe8749e98a3812a0dc4380ceae75c29450Johann
5157bc9febe8749e98a3812a0dc4380ceae75c29450Johann private:
5167bc9febe8749e98a3812a0dc4380ceae75c29450Johann  libvpx_test::TestMode encoding_mode_;
5177bc9febe8749e98a3812a0dc4380ceae75c29450Johann  vpx_codec_pts_t last_pts_;
5187bc9febe8749e98a3812a0dc4380ceae75c29450Johann  double timebase_;
5197bc9febe8749e98a3812a0dc4380ceae75c29450Johann  int64_t bits_total_[3];
5207bc9febe8749e98a3812a0dc4380ceae75c29450Johann  double duration_;
5217bc9febe8749e98a3812a0dc4380ceae75c29450Johann  int tot_frame_number_;
5227bc9febe8749e98a3812a0dc4380ceae75c29450Johann};
5237ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
5247ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// Check two codec controls used for:
5257ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// (1) for setting temporal layer id, and (2) for settings encoder flags.
5267ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// This test invokes those controls for each frame, and verifies encoder/decoder
5277ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// mismatch and basic rate control response.
5287ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian// TODO(marpan): Maybe move this test to datarate_test.cc.
5297ce0a1d1337c01056ba24006efab21f00e179e04Vignesh VenkatasubramanianTEST_P(ErrorResilienceTestLargeCodecControls, CodecControl3TemporalLayers) {
5307ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.rc_buf_initial_sz = 500;
5317ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.rc_buf_optimal_sz = 500;
5327ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.rc_buf_sz = 1000;
5337ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.rc_dropframe_thresh = 1;
5347ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.rc_min_quantizer = 2;
5357ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.rc_max_quantizer = 56;
5367ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.rc_end_usage = VPX_CBR;
5377ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.rc_dropframe_thresh = 1;
5387ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.g_lag_in_frames = 0;
5397ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.kf_mode = VPX_KF_DISABLED;
5407ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.g_error_resilient = 1;
5417ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
5427ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  // 3 Temporal layers. Framerate decimation (4, 2, 1).
5437ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_number_layers = 3;
5447ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_rate_decimator[0] = 4;
5457ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_rate_decimator[1] = 2;
5467ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_rate_decimator[2] = 1;
5477ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_periodicity = 4;
5487ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_layer_id[0] = 0;
5497ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_layer_id[1] = 2;
5507ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_layer_id[2] = 1;
5517ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  cfg_.ts_layer_id[3] = 2;
5527ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
5537ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
5547ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                                       30, 1, 0, 200);
5557ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  for (int i = 200; i <= 800; i += 200) {
5567ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    cfg_.rc_target_bitrate = i;
5577ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    Reset();
5587ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    // 40-20-40 bitrate allocation for 3 temporal layers.
5597ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
5607ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
5617ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate;
5627ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
5637ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
5647ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.75)
5657ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian          << " The datarate for the file is lower than target by too much, "
5667bc9febe8749e98a3812a0dc4380ceae75c29450Johann             "for layer: "
5677bc9febe8749e98a3812a0dc4380ceae75c29450Johann          << j;
5687ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian      ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.25)
5697ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian          << " The datarate for the file is greater than target by too much, "
5707bc9febe8749e98a3812a0dc4380ceae75c29450Johann             "for layer: "
5717bc9febe8749e98a3812a0dc4380ceae75c29450Johann          << j;
5727ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian    }
5737ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian  }
5747ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian}
5757ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian
576c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohannVP8_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
577c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann                          ::testing::Values(true));
5787ce0a1d1337c01056ba24006efab21f00e179e04Vignesh VenkatasubramanianVP8_INSTANTIATE_TEST_CASE(ErrorResilienceTestLargeCodecControls,
5797ce0a1d1337c01056ba24006efab21f00e179e04Vignesh Venkatasubramanian                          ONE_PASS_TEST_MODES);
580c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohannVP9_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
581c927526be9a7b72fb5edb3f29c4e8ceabe0ec98aJohann                          ::testing::Values(true));
5821b362b15af34006e6a11974088a46d42b903418eJohann}  // namespace
583