1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <math.h>
12
13#include "testing/gtest/include/gtest/gtest.h"
14
15#include "webrtc/modules/video_coding/include/video_codec_interface.h"
16#include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h"
17#include "webrtc/modules/video_coding/codecs/test/videoprocessor.h"
18#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
19#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
20#include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h"
21#include "webrtc/modules/video_coding/include/video_coding.h"
22#include "webrtc/test/testsupport/fileutils.h"
23#include "webrtc/test/testsupport/frame_reader.h"
24#include "webrtc/test/testsupport/frame_writer.h"
25#include "webrtc/test/testsupport/metrics/video_metrics.h"
26#include "webrtc/test/testsupport/packet_reader.h"
27#include "webrtc/typedefs.h"
28
29namespace webrtc {
30
31// Maximum number of rate updates (i.e., calls to encoder to change bitrate
32// and/or frame rate) for the current tests.
33const int kMaxNumRateUpdates = 3;
34
35const int kPercTargetvsActualMismatch = 20;
36const int kBaseKeyFrameInterval = 3000;
37
38// Codec and network settings.
39struct CodecConfigPars {
40  VideoCodecType codec_type;
41  float packet_loss;
42  int num_temporal_layers;
43  int key_frame_interval;
44  bool error_concealment_on;
45  bool denoising_on;
46  bool frame_dropper_on;
47  bool spatial_resize_on;
48};
49
50// Quality metrics.
51struct QualityMetrics {
52  double minimum_avg_psnr;
53  double minimum_min_psnr;
54  double minimum_avg_ssim;
55  double minimum_min_ssim;
56};
57
58// The sequence of bitrate and frame rate changes for the encoder, the frame
59// number where the changes are made, and the total number of frames for the
60// test.
61struct RateProfile {
62  int target_bit_rate[kMaxNumRateUpdates];
63  int input_frame_rate[kMaxNumRateUpdates];
64  int frame_index_rate_update[kMaxNumRateUpdates + 1];
65  int num_frames;
66};
67
68// Metrics for the rate control. The rate mismatch metrics are defined as
69// percentages.|max_time_hit_target| is defined as number of frames, after a
70// rate update is made to the encoder, for the encoder to reach within
71// |kPercTargetvsActualMismatch| of new target rate. The metrics are defined for
72// each rate update sequence.
73struct RateControlMetrics {
74  int max_num_dropped_frames;
75  int max_key_frame_size_mismatch;
76  int max_delta_frame_size_mismatch;
77  int max_encoding_rate_mismatch;
78  int max_time_hit_target;
79  int num_spatial_resizes;
80  int num_key_frames;
81};
82
83// Sequence used is foreman (CIF): may be better to use VGA for resize test.
84const int kCIFWidth = 352;
85const int kCIFHeight = 288;
86const int kNbrFramesShort = 100;  // Some tests are run for shorter sequence.
87const int kNbrFramesLong = 299;
88
89// Parameters from VP8 wrapper, which control target size of key frames.
90const float kInitialBufferSize = 0.5f;
91const float kOptimalBufferSize = 0.6f;
92const float kScaleKeyFrameSize = 0.5f;
93
94// Integration test for video processor. Encodes+decodes a clip and
95// writes it to the output directory. After completion, quality metrics
96// (PSNR and SSIM) and rate control metrics are computed to verify that the
97// quality and encoder response is acceptable. The rate control tests allow us
98// to verify the behavior for changing bitrate, changing frame rate, frame
99// dropping/spatial resize, and temporal layers. The limits for the rate
100// control metrics are set to be fairly conservative, so failure should only
101// happen when some significant regression or breakdown occurs.
102class VideoProcessorIntegrationTest : public testing::Test {
103 protected:
104  VideoEncoder* encoder_;
105  VideoDecoder* decoder_;
106  webrtc::test::FrameReader* frame_reader_;
107  webrtc::test::FrameWriter* frame_writer_;
108  webrtc::test::PacketReader packet_reader_;
109  webrtc::test::PacketManipulator* packet_manipulator_;
110  webrtc::test::Stats stats_;
111  webrtc::test::TestConfig config_;
112  VideoCodec codec_settings_;
113  webrtc::test::VideoProcessor* processor_;
114
115  // Quantities defined/updated for every encoder rate update.
116  // Some quantities defined per temporal layer (at most 3 layers in this test).
117  int num_frames_per_update_[3];
118  float sum_frame_size_mismatch_[3];
119  float sum_encoded_frame_size_[3];
120  float encoding_bitrate_[3];
121  float per_frame_bandwidth_[3];
122  float bit_rate_layer_[3];
123  float frame_rate_layer_[3];
124  int num_frames_total_;
125  float sum_encoded_frame_size_total_;
126  float encoding_bitrate_total_;
127  float perc_encoding_rate_mismatch_;
128  int num_frames_to_hit_target_;
129  bool encoding_rate_within_target_;
130  int bit_rate_;
131  int frame_rate_;
132  int layer_;
133  float target_size_key_frame_initial_;
134  float target_size_key_frame_;
135  float sum_key_frame_size_mismatch_;
136  int num_key_frames_;
137  float start_bitrate_;
138
139  // Codec and network settings.
140  VideoCodecType codec_type_;
141  float packet_loss_;
142  int num_temporal_layers_;
143  int key_frame_interval_;
144  bool error_concealment_on_;
145  bool denoising_on_;
146  bool frame_dropper_on_;
147  bool spatial_resize_on_;
148
149  VideoProcessorIntegrationTest() {}
150  virtual ~VideoProcessorIntegrationTest() {}
151
152  void SetUpCodecConfig() {
153    if (codec_type_ == kVideoCodecVP8) {
154      encoder_ = VP8Encoder::Create();
155      decoder_ = VP8Decoder::Create();
156      VideoCodingModule::Codec(kVideoCodecVP8, &codec_settings_);
157    } else if (codec_type_ == kVideoCodecVP9) {
158      encoder_ = VP9Encoder::Create();
159      decoder_ = VP9Decoder::Create();
160      VideoCodingModule::Codec(kVideoCodecVP9, &codec_settings_);
161    }
162
163    // CIF is currently used for all tests below.
164    // Setup the TestConfig struct for processing of a clip in CIF resolution.
165    config_.input_filename = webrtc::test::ResourcePath("foreman_cif", "yuv");
166
167    // Generate an output filename in a safe way.
168    config_.output_filename = webrtc::test::TempFilename(
169        webrtc::test::OutputPath(), "videoprocessor_integrationtest");
170    config_.frame_length_in_bytes =
171        CalcBufferSize(kI420, kCIFWidth, kCIFHeight);
172    config_.verbose = false;
173    // Only allow encoder/decoder to use single core, for predictability.
174    config_.use_single_core = true;
175    // Key frame interval and packet loss are set for each test.
176    config_.keyframe_interval = key_frame_interval_;
177    config_.networking_config.packet_loss_probability = packet_loss_;
178
179    // Configure codec settings.
180    config_.codec_settings = &codec_settings_;
181    config_.codec_settings->startBitrate = start_bitrate_;
182    config_.codec_settings->width = kCIFWidth;
183    config_.codec_settings->height = kCIFHeight;
184
185    // These features may be set depending on the test.
186    switch (config_.codec_settings->codecType) {
187      case kVideoCodecVP8:
188        config_.codec_settings->codecSpecific.VP8.errorConcealmentOn =
189            error_concealment_on_;
190        config_.codec_settings->codecSpecific.VP8.denoisingOn = denoising_on_;
191        config_.codec_settings->codecSpecific.VP8.numberOfTemporalLayers =
192            num_temporal_layers_;
193        config_.codec_settings->codecSpecific.VP8.frameDroppingOn =
194            frame_dropper_on_;
195        config_.codec_settings->codecSpecific.VP8.automaticResizeOn =
196            spatial_resize_on_;
197        config_.codec_settings->codecSpecific.VP8.keyFrameInterval =
198            kBaseKeyFrameInterval;
199        break;
200      case kVideoCodecVP9:
201        config_.codec_settings->codecSpecific.VP9.denoisingOn = denoising_on_;
202        config_.codec_settings->codecSpecific.VP9.numberOfTemporalLayers =
203            num_temporal_layers_;
204        config_.codec_settings->codecSpecific.VP9.frameDroppingOn =
205            frame_dropper_on_;
206        config_.codec_settings->codecSpecific.VP9.automaticResizeOn =
207            spatial_resize_on_;
208        config_.codec_settings->codecSpecific.VP9.keyFrameInterval =
209            kBaseKeyFrameInterval;
210        break;
211      default:
212        assert(false);
213        break;
214    }
215    frame_reader_ = new webrtc::test::FrameReaderImpl(
216        config_.input_filename, config_.frame_length_in_bytes);
217    frame_writer_ = new webrtc::test::FrameWriterImpl(
218        config_.output_filename, config_.frame_length_in_bytes);
219    ASSERT_TRUE(frame_reader_->Init());
220    ASSERT_TRUE(frame_writer_->Init());
221
222    packet_manipulator_ = new webrtc::test::PacketManipulatorImpl(
223        &packet_reader_, config_.networking_config, config_.verbose);
224    processor_ = new webrtc::test::VideoProcessorImpl(
225        encoder_, decoder_, frame_reader_, frame_writer_, packet_manipulator_,
226        config_, &stats_);
227    ASSERT_TRUE(processor_->Init());
228  }
229
230  // Reset quantities after each encoder update, update the target
231  // per-frame bandwidth.
232  void ResetRateControlMetrics(int num_frames) {
233    for (int i = 0; i < num_temporal_layers_; i++) {
234      num_frames_per_update_[i] = 0;
235      sum_frame_size_mismatch_[i] = 0.0f;
236      sum_encoded_frame_size_[i] = 0.0f;
237      encoding_bitrate_[i] = 0.0f;
238      // Update layer per-frame-bandwidth.
239      per_frame_bandwidth_[i] = static_cast<float>(bit_rate_layer_[i]) /
240                                static_cast<float>(frame_rate_layer_[i]);
241    }
242    // Set maximum size of key frames, following setting in the VP8 wrapper.
243    float max_key_size = kScaleKeyFrameSize * kOptimalBufferSize * frame_rate_;
244    // We don't know exact target size of the key frames (except for first one),
245    // but the minimum in libvpx is ~|3 * per_frame_bandwidth| and maximum is
246    // set by |max_key_size_  * per_frame_bandwidth|. Take middle point/average
247    // as reference for mismatch. Note key frames always correspond to base
248    // layer frame in this test.
249    target_size_key_frame_ = 0.5 * (3 + max_key_size) * per_frame_bandwidth_[0];
250    num_frames_total_ = 0;
251    sum_encoded_frame_size_total_ = 0.0f;
252    encoding_bitrate_total_ = 0.0f;
253    perc_encoding_rate_mismatch_ = 0.0f;
254    num_frames_to_hit_target_ = num_frames;
255    encoding_rate_within_target_ = false;
256    sum_key_frame_size_mismatch_ = 0.0;
257    num_key_frames_ = 0;
258  }
259
260  // For every encoded frame, update the rate control metrics.
261  void UpdateRateControlMetrics(int frame_num, FrameType frame_type) {
262    float encoded_size_kbits = processor_->EncodedFrameSize() * 8.0f / 1000.0f;
263    // Update layer data.
264    // Update rate mismatch relative to per-frame bandwidth for delta frames.
265    if (frame_type == kVideoFrameDelta) {
266      // TODO(marpan): Should we count dropped (zero size) frames in mismatch?
267      sum_frame_size_mismatch_[layer_] +=
268          fabs(encoded_size_kbits - per_frame_bandwidth_[layer_]) /
269          per_frame_bandwidth_[layer_];
270    } else {
271      float target_size = (frame_num == 1) ? target_size_key_frame_initial_
272                                           : target_size_key_frame_;
273      sum_key_frame_size_mismatch_ +=
274          fabs(encoded_size_kbits - target_size) / target_size;
275      num_key_frames_ += 1;
276    }
277    sum_encoded_frame_size_[layer_] += encoded_size_kbits;
278    // Encoding bitrate per layer: from the start of the update/run to the
279    // current frame.
280    encoding_bitrate_[layer_] = sum_encoded_frame_size_[layer_] *
281                                frame_rate_layer_[layer_] /
282                                num_frames_per_update_[layer_];
283    // Total encoding rate: from the start of the update/run to current frame.
284    sum_encoded_frame_size_total_ += encoded_size_kbits;
285    encoding_bitrate_total_ =
286        sum_encoded_frame_size_total_ * frame_rate_ / num_frames_total_;
287    perc_encoding_rate_mismatch_ =
288        100 * fabs(encoding_bitrate_total_ - bit_rate_) / bit_rate_;
289    if (perc_encoding_rate_mismatch_ < kPercTargetvsActualMismatch &&
290        !encoding_rate_within_target_) {
291      num_frames_to_hit_target_ = num_frames_total_;
292      encoding_rate_within_target_ = true;
293    }
294  }
295
296  // Verify expected behavior of rate control and print out data.
297  void VerifyRateControl(int update_index,
298                         int max_key_frame_size_mismatch,
299                         int max_delta_frame_size_mismatch,
300                         int max_encoding_rate_mismatch,
301                         int max_time_hit_target,
302                         int max_num_dropped_frames,
303                         int num_spatial_resizes,
304                         int num_key_frames) {
305    int num_dropped_frames = processor_->NumberDroppedFrames();
306    int num_resize_actions = processor_->NumberSpatialResizes();
307    printf(
308        "For update #: %d,\n "
309        " Target Bitrate: %d,\n"
310        " Encoding bitrate: %f,\n"
311        " Frame rate: %d \n",
312        update_index, bit_rate_, encoding_bitrate_total_, frame_rate_);
313    printf(
314        " Number of frames to approach target rate = %d, \n"
315        " Number of dropped frames = %d, \n"
316        " Number of spatial resizes = %d, \n",
317        num_frames_to_hit_target_, num_dropped_frames, num_resize_actions);
318    EXPECT_LE(perc_encoding_rate_mismatch_, max_encoding_rate_mismatch);
319    if (num_key_frames_ > 0) {
320      int perc_key_frame_size_mismatch =
321          100 * sum_key_frame_size_mismatch_ / num_key_frames_;
322      printf(
323          " Number of Key frames: %d \n"
324          " Key frame rate mismatch: %d \n",
325          num_key_frames_, perc_key_frame_size_mismatch);
326      EXPECT_LE(perc_key_frame_size_mismatch, max_key_frame_size_mismatch);
327    }
328    printf("\n");
329    printf("Rates statistics for Layer data \n");
330    for (int i = 0; i < num_temporal_layers_; i++) {
331      printf("Layer #%d \n", i);
332      int perc_frame_size_mismatch =
333          100 * sum_frame_size_mismatch_[i] / num_frames_per_update_[i];
334      int perc_encoding_rate_mismatch =
335          100 * fabs(encoding_bitrate_[i] - bit_rate_layer_[i]) /
336          bit_rate_layer_[i];
337      printf(
338          " Target Layer Bit rate: %f \n"
339          " Layer frame rate: %f, \n"
340          " Layer per frame bandwidth: %f, \n"
341          " Layer Encoding bit rate: %f, \n"
342          " Layer Percent frame size mismatch: %d,  \n"
343          " Layer Percent encoding rate mismatch = %d, \n"
344          " Number of frame processed per layer = %d \n",
345          bit_rate_layer_[i], frame_rate_layer_[i], per_frame_bandwidth_[i],
346          encoding_bitrate_[i], perc_frame_size_mismatch,
347          perc_encoding_rate_mismatch, num_frames_per_update_[i]);
348      EXPECT_LE(perc_frame_size_mismatch, max_delta_frame_size_mismatch);
349      EXPECT_LE(perc_encoding_rate_mismatch, max_encoding_rate_mismatch);
350    }
351    printf("\n");
352    EXPECT_LE(num_frames_to_hit_target_, max_time_hit_target);
353    EXPECT_LE(num_dropped_frames, max_num_dropped_frames);
354    EXPECT_EQ(num_resize_actions, num_spatial_resizes);
355    EXPECT_EQ(num_key_frames_, num_key_frames);
356  }
357
358  // Layer index corresponding to frame number, for up to 3 layers.
359  void LayerIndexForFrame(int frame_number) {
360    if (num_temporal_layers_ == 1) {
361      layer_ = 0;
362    } else if (num_temporal_layers_ == 2) {
363      // layer 0:  0     2     4 ...
364      // layer 1:     1     3
365      if (frame_number % 2 == 0) {
366        layer_ = 0;
367      } else {
368        layer_ = 1;
369      }
370    } else if (num_temporal_layers_ == 3) {
371      // layer 0:  0            4            8 ...
372      // layer 1:        2            6
373      // layer 2:     1      3     5      7
374      if (frame_number % 4 == 0) {
375        layer_ = 0;
376      } else if ((frame_number + 2) % 4 == 0) {
377        layer_ = 1;
378      } else if ((frame_number + 1) % 2 == 0) {
379        layer_ = 2;
380      }
381    } else {
382      assert(false);  // Only up to 3 layers.
383    }
384  }
385
386  // Set the bitrate and frame rate per layer, for up to 3 layers.
387  void SetLayerRates() {
388    assert(num_temporal_layers_ <= 3);
389    for (int i = 0; i < num_temporal_layers_; i++) {
390      float bit_rate_ratio =
391          kVp8LayerRateAlloction[num_temporal_layers_ - 1][i];
392      if (i > 0) {
393        float bit_rate_delta_ratio =
394            kVp8LayerRateAlloction[num_temporal_layers_ - 1][i] -
395            kVp8LayerRateAlloction[num_temporal_layers_ - 1][i - 1];
396        bit_rate_layer_[i] = bit_rate_ * bit_rate_delta_ratio;
397      } else {
398        bit_rate_layer_[i] = bit_rate_ * bit_rate_ratio;
399      }
400      frame_rate_layer_[i] =
401          frame_rate_ / static_cast<float>(1 << (num_temporal_layers_ - 1));
402    }
403    if (num_temporal_layers_ == 3) {
404      frame_rate_layer_[2] = frame_rate_ / 2.0f;
405    }
406  }
407
408  void TearDown() {
409    delete processor_;
410    delete packet_manipulator_;
411    delete frame_writer_;
412    delete frame_reader_;
413    delete decoder_;
414    delete encoder_;
415  }
416
417  // Processes all frames in the clip and verifies the result.
418  void ProcessFramesAndVerify(QualityMetrics quality_metrics,
419                              RateProfile rate_profile,
420                              CodecConfigPars process,
421                              RateControlMetrics* rc_metrics) {
422    // Codec/config settings.
423    codec_type_ = process.codec_type;
424    start_bitrate_ = rate_profile.target_bit_rate[0];
425    packet_loss_ = process.packet_loss;
426    key_frame_interval_ = process.key_frame_interval;
427    num_temporal_layers_ = process.num_temporal_layers;
428    error_concealment_on_ = process.error_concealment_on;
429    denoising_on_ = process.denoising_on;
430    frame_dropper_on_ = process.frame_dropper_on;
431    spatial_resize_on_ = process.spatial_resize_on;
432    SetUpCodecConfig();
433    // Update the layers and the codec with the initial rates.
434    bit_rate_ = rate_profile.target_bit_rate[0];
435    frame_rate_ = rate_profile.input_frame_rate[0];
436    SetLayerRates();
437    // Set the initial target size for key frame.
438    target_size_key_frame_initial_ =
439        0.5 * kInitialBufferSize * bit_rate_layer_[0];
440    processor_->SetRates(bit_rate_, frame_rate_);
441    // Process each frame, up to |num_frames|.
442    int num_frames = rate_profile.num_frames;
443    int update_index = 0;
444    ResetRateControlMetrics(
445        rate_profile.frame_index_rate_update[update_index + 1]);
446    int frame_number = 0;
447    FrameType frame_type = kVideoFrameDelta;
448    while (processor_->ProcessFrame(frame_number) &&
449           frame_number < num_frames) {
450      // Get the layer index for the frame |frame_number|.
451      LayerIndexForFrame(frame_number);
452      // Get the frame_type.
453      frame_type = processor_->EncodedFrameType();
454      // Counter for whole sequence run.
455      ++frame_number;
456      // Counters for each rate update.
457      ++num_frames_per_update_[layer_];
458      ++num_frames_total_;
459      UpdateRateControlMetrics(frame_number, frame_type);
460      // If we hit another/next update, verify stats for current state and
461      // update layers and codec with new rates.
462      if (frame_number ==
463          rate_profile.frame_index_rate_update[update_index + 1]) {
464        VerifyRateControl(
465            update_index, rc_metrics[update_index].max_key_frame_size_mismatch,
466            rc_metrics[update_index].max_delta_frame_size_mismatch,
467            rc_metrics[update_index].max_encoding_rate_mismatch,
468            rc_metrics[update_index].max_time_hit_target,
469            rc_metrics[update_index].max_num_dropped_frames,
470            rc_metrics[update_index].num_spatial_resizes,
471            rc_metrics[update_index].num_key_frames);
472        // Update layer rates and the codec with new rates.
473        ++update_index;
474        bit_rate_ = rate_profile.target_bit_rate[update_index];
475        frame_rate_ = rate_profile.input_frame_rate[update_index];
476        SetLayerRates();
477        ResetRateControlMetrics(
478            rate_profile.frame_index_rate_update[update_index + 1]);
479        processor_->SetRates(bit_rate_, frame_rate_);
480      }
481    }
482    VerifyRateControl(update_index,
483                      rc_metrics[update_index].max_key_frame_size_mismatch,
484                      rc_metrics[update_index].max_delta_frame_size_mismatch,
485                      rc_metrics[update_index].max_encoding_rate_mismatch,
486                      rc_metrics[update_index].max_time_hit_target,
487                      rc_metrics[update_index].max_num_dropped_frames,
488                      rc_metrics[update_index].num_spatial_resizes,
489                      rc_metrics[update_index].num_key_frames);
490    EXPECT_EQ(num_frames, frame_number);
491    EXPECT_EQ(num_frames + 1, static_cast<int>(stats_.stats_.size()));
492
493    // Release encoder and decoder to make sure they have finished processing:
494    EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
495    EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release());
496    // Close the files before we start using them for SSIM/PSNR calculations.
497    frame_reader_->Close();
498    frame_writer_->Close();
499
500    // TODO(marpan): should compute these quality metrics per SetRates update.
501    webrtc::test::QualityMetricsResult psnr_result, ssim_result;
502    EXPECT_EQ(
503        0, webrtc::test::I420MetricsFromFiles(
504               config_.input_filename.c_str(), config_.output_filename.c_str(),
505               config_.codec_settings->width, config_.codec_settings->height,
506               &psnr_result, &ssim_result));
507    printf("PSNR avg: %f, min: %f    SSIM avg: %f, min: %f\n",
508           psnr_result.average, psnr_result.min, ssim_result.average,
509           ssim_result.min);
510    stats_.PrintSummary();
511    EXPECT_GT(psnr_result.average, quality_metrics.minimum_avg_psnr);
512    EXPECT_GT(psnr_result.min, quality_metrics.minimum_min_psnr);
513    EXPECT_GT(ssim_result.average, quality_metrics.minimum_avg_ssim);
514    EXPECT_GT(ssim_result.min, quality_metrics.minimum_min_ssim);
515    if (!remove(config_.output_filename.c_str())) {
516      fprintf(stderr, "Failed to remove temporary file!");
517    }
518  }
519};
520
521void SetRateProfilePars(RateProfile* rate_profile,
522                        int update_index,
523                        int bit_rate,
524                        int frame_rate,
525                        int frame_index_rate_update) {
526  rate_profile->target_bit_rate[update_index] = bit_rate;
527  rate_profile->input_frame_rate[update_index] = frame_rate;
528  rate_profile->frame_index_rate_update[update_index] = frame_index_rate_update;
529}
530
531void SetCodecParameters(CodecConfigPars* process_settings,
532                        VideoCodecType codec_type,
533                        float packet_loss,
534                        int key_frame_interval,
535                        int num_temporal_layers,
536                        bool error_concealment_on,
537                        bool denoising_on,
538                        bool frame_dropper_on,
539                        bool spatial_resize_on) {
540  process_settings->codec_type = codec_type;
541  process_settings->packet_loss = packet_loss;
542  process_settings->key_frame_interval = key_frame_interval;
543  process_settings->num_temporal_layers = num_temporal_layers,
544  process_settings->error_concealment_on = error_concealment_on;
545  process_settings->denoising_on = denoising_on;
546  process_settings->frame_dropper_on = frame_dropper_on;
547  process_settings->spatial_resize_on = spatial_resize_on;
548}
549
550void SetQualityMetrics(QualityMetrics* quality_metrics,
551                       double minimum_avg_psnr,
552                       double minimum_min_psnr,
553                       double minimum_avg_ssim,
554                       double minimum_min_ssim) {
555  quality_metrics->minimum_avg_psnr = minimum_avg_psnr;
556  quality_metrics->minimum_min_psnr = minimum_min_psnr;
557  quality_metrics->minimum_avg_ssim = minimum_avg_ssim;
558  quality_metrics->minimum_min_ssim = minimum_min_ssim;
559}
560
561void SetRateControlMetrics(RateControlMetrics* rc_metrics,
562                           int update_index,
563                           int max_num_dropped_frames,
564                           int max_key_frame_size_mismatch,
565                           int max_delta_frame_size_mismatch,
566                           int max_encoding_rate_mismatch,
567                           int max_time_hit_target,
568                           int num_spatial_resizes,
569                           int num_key_frames) {
570  rc_metrics[update_index].max_num_dropped_frames = max_num_dropped_frames;
571  rc_metrics[update_index].max_key_frame_size_mismatch =
572      max_key_frame_size_mismatch;
573  rc_metrics[update_index].max_delta_frame_size_mismatch =
574      max_delta_frame_size_mismatch;
575  rc_metrics[update_index].max_encoding_rate_mismatch =
576      max_encoding_rate_mismatch;
577  rc_metrics[update_index].max_time_hit_target = max_time_hit_target;
578  rc_metrics[update_index].num_spatial_resizes = num_spatial_resizes;
579  rc_metrics[update_index].num_key_frames = num_key_frames;
580}
581
582// VP9: Run with no packet loss and fixed bitrate. Quality should be very high.
583// One key frame (first frame only) in sequence. Setting |key_frame_interval|
584// to -1 below means no periodic key frames in test.
585TEST_F(VideoProcessorIntegrationTest, Process0PercentPacketLossVP9) {
586  // Bitrate and frame rate profile.
587  RateProfile rate_profile;
588  SetRateProfilePars(&rate_profile, 0, 500, 30, 0);
589  rate_profile.frame_index_rate_update[1] = kNbrFramesShort + 1;
590  rate_profile.num_frames = kNbrFramesShort;
591  // Codec/network settings.
592  CodecConfigPars process_settings;
593  SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false,
594                     false, true, false);
595  // Metrics for expected quality.
596  QualityMetrics quality_metrics;
597  SetQualityMetrics(&quality_metrics, 37.0, 36.0, 0.93, 0.92);
598  // Metrics for rate control.
599  RateControlMetrics rc_metrics[1];
600  SetRateControlMetrics(rc_metrics, 0, 0, 40, 20, 10, 20, 0, 1);
601  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
602                         rc_metrics);
603}
604
605// VP9: Run with 5% packet loss and fixed bitrate. Quality should be a bit
606// lower. One key frame (first frame only) in sequence.
607TEST_F(VideoProcessorIntegrationTest, Process5PercentPacketLossVP9) {
608  // Bitrate and frame rate profile.
609  RateProfile rate_profile;
610  SetRateProfilePars(&rate_profile, 0, 500, 30, 0);
611  rate_profile.frame_index_rate_update[1] = kNbrFramesShort + 1;
612  rate_profile.num_frames = kNbrFramesShort;
613  // Codec/network settings.
614  CodecConfigPars process_settings;
615  SetCodecParameters(&process_settings, kVideoCodecVP9, 0.05f, -1, 1, false,
616                     false, true, false);
617  // Metrics for expected quality.
618  QualityMetrics quality_metrics;
619  SetQualityMetrics(&quality_metrics, 17.0, 14.0, 0.45, 0.36);
620  // Metrics for rate control.
621  RateControlMetrics rc_metrics[1];
622  SetRateControlMetrics(rc_metrics, 0, 0, 40, 20, 10, 20, 0, 1);
623  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
624                         rc_metrics);
625}
626
627// VP9: Run with no packet loss, with varying bitrate (3 rate updates):
628// low to high to medium. Check that quality and encoder response to the new
629// target rate/per-frame bandwidth (for each rate update) is within limits.
630// One key frame (first frame only) in sequence.
631TEST_F(VideoProcessorIntegrationTest, ProcessNoLossChangeBitRateVP9) {
632  // Bitrate and frame rate profile.
633  RateProfile rate_profile;
634  SetRateProfilePars(&rate_profile, 0, 200, 30, 0);
635  SetRateProfilePars(&rate_profile, 1, 700, 30, 100);
636  SetRateProfilePars(&rate_profile, 2, 500, 30, 200);
637  rate_profile.frame_index_rate_update[3] = kNbrFramesLong + 1;
638  rate_profile.num_frames = kNbrFramesLong;
639  // Codec/network settings.
640  CodecConfigPars process_settings;
641  SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false,
642                     false, true, false);
643  // Metrics for expected quality.
644  QualityMetrics quality_metrics;
645  SetQualityMetrics(&quality_metrics, 35.7, 30.0, 0.90, 0.85);
646  // Metrics for rate control.
647  RateControlMetrics rc_metrics[3];
648  SetRateControlMetrics(rc_metrics, 0, 0, 30, 20, 20, 30, 0, 1);
649  SetRateControlMetrics(rc_metrics, 1, 2, 0, 20, 20, 60, 0, 0);
650  SetRateControlMetrics(rc_metrics, 2, 0, 0, 25, 20, 40, 0, 0);
651  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
652                         rc_metrics);
653}
654
655// VP9: Run with no packet loss, with an update (decrease) in frame rate.
656// Lower frame rate means higher per-frame-bandwidth, so easier to encode.
657// At the low bitrate in this test, this means better rate control after the
658// update(s) to lower frame rate. So expect less frame drops, and max values
659// for the rate control metrics can be lower. One key frame (first frame only).
660// Note: quality after update should be higher but we currently compute quality
661// metrics averaged over whole sequence run.
662TEST_F(VideoProcessorIntegrationTest,
663       ProcessNoLossChangeFrameRateFrameDropVP9) {
664  config_.networking_config.packet_loss_probability = 0;
665  // Bitrate and frame rate profile.
666  RateProfile rate_profile;
667  SetRateProfilePars(&rate_profile, 0, 100, 24, 0);
668  SetRateProfilePars(&rate_profile, 1, 100, 15, 100);
669  SetRateProfilePars(&rate_profile, 2, 100, 10, 200);
670  rate_profile.frame_index_rate_update[3] = kNbrFramesLong + 1;
671  rate_profile.num_frames = kNbrFramesLong;
672  // Codec/network settings.
673  CodecConfigPars process_settings;
674  SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false,
675                     false, true, false);
676  // Metrics for expected quality.
677  QualityMetrics quality_metrics;
678  SetQualityMetrics(&quality_metrics, 31.5, 18.0, 0.80, 0.44);
679  // Metrics for rate control.
680  RateControlMetrics rc_metrics[3];
681  SetRateControlMetrics(rc_metrics, 0, 38, 50, 75, 15, 45, 0, 1);
682  SetRateControlMetrics(rc_metrics, 1, 10, 0, 40, 10, 30, 0, 0);
683  SetRateControlMetrics(rc_metrics, 2, 5, 0, 30, 5, 20, 0, 0);
684  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
685                         rc_metrics);
686}
687
688// VP9: Run with no packet loss and denoiser on. One key frame (first frame).
689TEST_F(VideoProcessorIntegrationTest, ProcessNoLossDenoiserOnVP9) {
690  // Bitrate and frame rate profile.
691  RateProfile rate_profile;
692  SetRateProfilePars(&rate_profile, 0, 500, 30, 0);
693  rate_profile.frame_index_rate_update[1] = kNbrFramesShort + 1;
694  rate_profile.num_frames = kNbrFramesShort;
695  // Codec/network settings.
696  CodecConfigPars process_settings;
697  SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false,
698                     true, true, false);
699  // Metrics for expected quality.
700  QualityMetrics quality_metrics;
701  SetQualityMetrics(&quality_metrics, 36.8, 35.8, 0.92, 0.91);
702  // Metrics for rate control.
703  RateControlMetrics rc_metrics[1];
704  SetRateControlMetrics(rc_metrics, 0, 0, 40, 20, 10, 20, 0, 1);
705  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
706                         rc_metrics);
707}
708
709// Run with no packet loss, at low bitrate.
710// spatial_resize is on, for this low bitrate expect one resize in sequence.
711// Resize happens on delta frame. Expect only one key frame (first frame).
712TEST_F(VideoProcessorIntegrationTest, ProcessNoLossSpatialResizeFrameDropVP9) {
713  config_.networking_config.packet_loss_probability = 0;
714  // Bitrate and frame rate profile.
715  RateProfile rate_profile;
716  SetRateProfilePars(&rate_profile, 0, 50, 30, 0);
717  rate_profile.frame_index_rate_update[1] = kNbrFramesLong + 1;
718  rate_profile.num_frames = kNbrFramesLong;
719  // Codec/network settings.
720  CodecConfigPars process_settings;
721  SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false,
722                     false, true, true);
723  // Metrics for expected quality.
724  QualityMetrics quality_metrics;
725  SetQualityMetrics(&quality_metrics, 24.0, 13.0, 0.65, 0.37);
726  // Metrics for rate control.
727  RateControlMetrics rc_metrics[1];
728  SetRateControlMetrics(rc_metrics, 0, 228, 70, 160, 15, 80, 1, 1);
729  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
730                         rc_metrics);
731}
732
733// TODO(marpan): Add temporal layer test for VP9, once changes are in
734// vp9 wrapper for this.
735
736// VP8: Run with no packet loss and fixed bitrate. Quality should be very high.
737// One key frame (first frame only) in sequence. Setting |key_frame_interval|
738// to -1 below means no periodic key frames in test.
739TEST_F(VideoProcessorIntegrationTest, ProcessZeroPacketLoss) {
740  // Bitrate and frame rate profile.
741  RateProfile rate_profile;
742  SetRateProfilePars(&rate_profile, 0, 500, 30, 0);
743  rate_profile.frame_index_rate_update[1] = kNbrFramesShort + 1;
744  rate_profile.num_frames = kNbrFramesShort;
745  // Codec/network settings.
746  CodecConfigPars process_settings;
747  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 1, false,
748                     true, true, false);
749  // Metrics for expected quality.
750  QualityMetrics quality_metrics;
751  SetQualityMetrics(&quality_metrics, 34.95, 33.0, 0.90, 0.89);
752  // Metrics for rate control.
753  RateControlMetrics rc_metrics[1];
754  SetRateControlMetrics(rc_metrics, 0, 0, 40, 20, 10, 15, 0, 1);
755  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
756                         rc_metrics);
757}
758
759// VP8: Run with 5% packet loss and fixed bitrate. Quality should be a bit
760// lower. One key frame (first frame only) in sequence.
761TEST_F(VideoProcessorIntegrationTest, Process5PercentPacketLoss) {
762  // Bitrate and frame rate profile.
763  RateProfile rate_profile;
764  SetRateProfilePars(&rate_profile, 0, 500, 30, 0);
765  rate_profile.frame_index_rate_update[1] = kNbrFramesShort + 1;
766  rate_profile.num_frames = kNbrFramesShort;
767  // Codec/network settings.
768  CodecConfigPars process_settings;
769  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.05f, -1, 1, false,
770                     true, true, false);
771  // Metrics for expected quality.
772  QualityMetrics quality_metrics;
773  SetQualityMetrics(&quality_metrics, 20.0, 16.0, 0.60, 0.40);
774  // Metrics for rate control.
775  RateControlMetrics rc_metrics[1];
776  SetRateControlMetrics(rc_metrics, 0, 0, 40, 20, 10, 15, 0, 1);
777  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
778                         rc_metrics);
779}
780
781// VP8: Run with 10% packet loss and fixed bitrate. Quality should be lower.
782// One key frame (first frame only) in sequence.
783TEST_F(VideoProcessorIntegrationTest, Process10PercentPacketLoss) {
784  // Bitrate and frame rate profile.
785  RateProfile rate_profile;
786  SetRateProfilePars(&rate_profile, 0, 500, 30, 0);
787  rate_profile.frame_index_rate_update[1] = kNbrFramesShort + 1;
788  rate_profile.num_frames = kNbrFramesShort;
789  // Codec/network settings.
790  CodecConfigPars process_settings;
791  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.1f, -1, 1, false,
792                     true, true, false);
793  // Metrics for expected quality.
794  QualityMetrics quality_metrics;
795  SetQualityMetrics(&quality_metrics, 19.0, 16.0, 0.50, 0.35);
796  // Metrics for rate control.
797  RateControlMetrics rc_metrics[1];
798  SetRateControlMetrics(rc_metrics, 0, 0, 40, 20, 10, 15, 0, 1);
799  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
800                         rc_metrics);
801}
802
803// The tests below are currently disabled for Android. For ARM, the encoder
804// uses |cpu_speed| = 12, as opposed to default |cpu_speed| <= 6 for x86,
805// which leads to significantly different quality. The quality and rate control
806// settings in the tests below are defined for encoder speed setting
807// |cpu_speed| <= ~6. A number of settings would need to be significantly
808// modified for the |cpu_speed| = 12 case. For now, keep the tests below
809// disabled on Android. Some quality parameter in the above test has been
810// adjusted to also pass for |cpu_speed| <= 12.
811
812// VP8: Run with no packet loss, with varying bitrate (3 rate updates):
813// low to high to medium. Check that quality and encoder response to the new
814// target rate/per-frame bandwidth (for each rate update) is within limits.
815// One key frame (first frame only) in sequence.
816#if defined(WEBRTC_ANDROID)
817#define MAYBE_ProcessNoLossChangeBitRateVP8 \
818  DISABLED_ProcessNoLossChangeBitRateVP8
819#else
820#define MAYBE_ProcessNoLossChangeBitRateVP8 ProcessNoLossChangeBitRateVP8
821#endif
822TEST_F(VideoProcessorIntegrationTest, MAYBE_ProcessNoLossChangeBitRateVP8) {
823  // Bitrate and frame rate profile.
824  RateProfile rate_profile;
825  SetRateProfilePars(&rate_profile, 0, 200, 30, 0);
826  SetRateProfilePars(&rate_profile, 1, 800, 30, 100);
827  SetRateProfilePars(&rate_profile, 2, 500, 30, 200);
828  rate_profile.frame_index_rate_update[3] = kNbrFramesLong + 1;
829  rate_profile.num_frames = kNbrFramesLong;
830  // Codec/network settings.
831  CodecConfigPars process_settings;
832  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 1, false,
833                     true, true, false);
834  // Metrics for expected quality.
835  QualityMetrics quality_metrics;
836  SetQualityMetrics(&quality_metrics, 34.0, 32.0, 0.85, 0.80);
837  // Metrics for rate control.
838  RateControlMetrics rc_metrics[3];
839  SetRateControlMetrics(rc_metrics, 0, 0, 45, 20, 10, 15, 0, 1);
840  SetRateControlMetrics(rc_metrics, 1, 0, 0, 25, 20, 10, 0, 0);
841  SetRateControlMetrics(rc_metrics, 2, 0, 0, 25, 15, 10, 0, 0);
842  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
843                         rc_metrics);
844}
845
846// VP8: Run with no packet loss, with an update (decrease) in frame rate.
847// Lower frame rate means higher per-frame-bandwidth, so easier to encode.
848// At the bitrate in this test, this means better rate control after the
849// update(s) to lower frame rate. So expect less frame drops, and max values
850// for the rate control metrics can be lower. One key frame (first frame only).
851// Note: quality after update should be higher but we currently compute quality
852// metrics averaged over whole sequence run.
853#if defined(WEBRTC_ANDROID)
854#define MAYBE_ProcessNoLossChangeFrameRateFrameDropVP8 \
855  DISABLED_ProcessNoLossChangeFrameRateFrameDropVP8
856#else
857#define MAYBE_ProcessNoLossChangeFrameRateFrameDropVP8 \
858  ProcessNoLossChangeFrameRateFrameDropVP8
859#endif
860TEST_F(VideoProcessorIntegrationTest,
861       MAYBE_ProcessNoLossChangeFrameRateFrameDropVP8) {
862  config_.networking_config.packet_loss_probability = 0;
863  // Bitrate and frame rate profile.
864  RateProfile rate_profile;
865  SetRateProfilePars(&rate_profile, 0, 80, 24, 0);
866  SetRateProfilePars(&rate_profile, 1, 80, 15, 100);
867  SetRateProfilePars(&rate_profile, 2, 80, 10, 200);
868  rate_profile.frame_index_rate_update[3] = kNbrFramesLong + 1;
869  rate_profile.num_frames = kNbrFramesLong;
870  // Codec/network settings.
871  CodecConfigPars process_settings;
872  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 1, false,
873                     true, true, false);
874  // Metrics for expected quality.
875  QualityMetrics quality_metrics;
876  SetQualityMetrics(&quality_metrics, 31.0, 22.0, 0.80, 0.65);
877  // Metrics for rate control.
878  RateControlMetrics rc_metrics[3];
879  SetRateControlMetrics(rc_metrics, 0, 40, 20, 75, 15, 60, 0, 1);
880  SetRateControlMetrics(rc_metrics, 1, 10, 0, 25, 10, 35, 0, 0);
881  SetRateControlMetrics(rc_metrics, 2, 0, 0, 20, 10, 15, 0, 0);
882  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
883                         rc_metrics);
884}
885
886// Run with no packet loss, at low bitrate. During this time we should've
887// resized once. Expect 2 key frames generated (first and one for resize).
888#if defined(WEBRTC_ANDROID)
889#define MAYBE_ProcessNoLossSpatialResizeFrameDropVP8 \
890  DISABLED_ProcessNoLossSpatialResizeFrameDropVP8
891#else
892#define MAYBE_ProcessNoLossSpatialResizeFrameDropVP8 \
893  ProcessNoLossSpatialResizeFrameDropVP8
894#endif
895TEST_F(VideoProcessorIntegrationTest,
896       MAYBE_ProcessNoLossSpatialResizeFrameDropVP8) {
897  config_.networking_config.packet_loss_probability = 0;
898  // Bitrate and frame rate profile.
899  RateProfile rate_profile;
900  SetRateProfilePars(&rate_profile, 0, 50, 30, 0);
901  rate_profile.frame_index_rate_update[1] = kNbrFramesLong + 1;
902  rate_profile.num_frames = kNbrFramesLong;
903  // Codec/network settings.
904  CodecConfigPars process_settings;
905  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 1, false,
906                     true, true, true);
907  // Metrics for expected quality.
908  QualityMetrics quality_metrics;
909  SetQualityMetrics(&quality_metrics, 25.0, 15.0, 0.70, 0.40);
910  // Metrics for rate control.
911  RateControlMetrics rc_metrics[1];
912  SetRateControlMetrics(rc_metrics, 0, 160, 60, 120, 20, 70, 1, 2);
913  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
914                         rc_metrics);
915}
916
917// VP8: Run with no packet loss, with 3 temporal layers, with a rate update in
918// the middle of the sequence. The max values for the frame size mismatch and
919// encoding rate mismatch are applied to each layer.
920// No dropped frames in this test, and internal spatial resizer is off.
921// One key frame (first frame only) in sequence, so no spatial resizing.
922#if defined(WEBRTC_ANDROID)
923#define MAYBE_ProcessNoLossTemporalLayersVP8 \
924  DISABLED_ProcessNoLossTemporalLayersVP8
925#else
926#define MAYBE_ProcessNoLossTemporalLayersVP8 ProcessNoLossTemporalLayersVP8
927#endif
928TEST_F(VideoProcessorIntegrationTest, MAYBE_ProcessNoLossTemporalLayersVP8) {
929  config_.networking_config.packet_loss_probability = 0;
930  // Bitrate and frame rate profile.
931  RateProfile rate_profile;
932  SetRateProfilePars(&rate_profile, 0, 200, 30, 0);
933  SetRateProfilePars(&rate_profile, 1, 400, 30, 150);
934  rate_profile.frame_index_rate_update[2] = kNbrFramesLong + 1;
935  rate_profile.num_frames = kNbrFramesLong;
936  // Codec/network settings.
937  CodecConfigPars process_settings;
938  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 3, false,
939                     true, true, false);
940  // Metrics for expected quality.
941  QualityMetrics quality_metrics;
942  SetQualityMetrics(&quality_metrics, 32.5, 30.0, 0.85, 0.80);
943  // Metrics for rate control.
944  RateControlMetrics rc_metrics[2];
945  SetRateControlMetrics(rc_metrics, 0, 0, 20, 30, 10, 10, 0, 1);
946  SetRateControlMetrics(rc_metrics, 1, 0, 0, 30, 15, 10, 0, 0);
947  ProcessFramesAndVerify(quality_metrics, rate_profile, process_settings,
948                         rc_metrics);
949}
950}  // namespace webrtc
951