blob: dcb870b014ee8fca597c34097fa69d9daaecff74 [file] [log] [blame]
ilnik04f4d122017-06-19 07:18:55 -07001/*
Erik Språng6a7baa72019-02-26 18:31:00 +01002 * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
ilnik04f4d122017-06-19 07:18:55 -07003 *
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
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020011#include "video/frame_encode_metadata_writer.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <cstddef>
ilnik04f4d122017-06-19 07:18:55 -070014#include <vector>
15
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020016#include "api/video/i420_buffer.h"
17#include "api/video/video_frame.h"
Yves Gerey3e707812018-11-28 16:47:49 +010018#include "api/video/video_timing.h"
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020019#include "common_video/test/utilities.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/video_coding/include/video_coding_defines.h"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "rtc_base/time_utils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "test/gtest.h"
ilnik04f4d122017-06-19 07:18:55 -070023
24namespace webrtc {
25namespace test {
26namespace {
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020027
28const rtc::scoped_refptr<I420Buffer> kFrameBuffer = I420Buffer::Create(4, 4);
29
ilnik04f4d122017-06-19 07:18:55 -070030inline size_t FrameSize(const size_t& min_frame_size,
31 const size_t& max_frame_size,
32 const int& s,
33 const int& i) {
34 return min_frame_size + (s + 1) * i % (max_frame_size - min_frame_size);
35}
36
37class FakeEncodedImageCallback : public EncodedImageCallback {
38 public:
Erik Språng6a7baa72019-02-26 18:31:00 +010039 FakeEncodedImageCallback() : num_frames_dropped_(0) {}
ilnik04f4d122017-06-19 07:18:55 -070040 Result OnEncodedImage(const EncodedImage& encoded_image,
41 const CodecSpecificInfo* codec_specific_info,
42 const RTPFragmentationHeader* fragmentation) override {
mflodman351424e2017-08-10 02:43:14 -070043 return Result(Result::OK);
Mirko Bonadeic4dd7302019-02-25 09:12:02 +010044 }
Ilya Nikolaevskiyd79314f2017-10-23 10:45:37 +020045 void OnDroppedFrame(DropReason reason) override { ++num_frames_dropped_; }
Ilya Nikolaevskiyd79314f2017-10-23 10:45:37 +020046 size_t GetNumFramesDropped() { return num_frames_dropped_; }
47
ilnik04f4d122017-06-19 07:18:55 -070048 private:
Ilya Nikolaevskiyd79314f2017-10-23 10:45:37 +020049 size_t num_frames_dropped_;
ilnik04f4d122017-06-19 07:18:55 -070050};
51
52enum class FrameType {
53 kNormal,
54 kTiming,
55 kDropped,
56};
57
Erik Språng6a7baa72019-02-26 18:31:00 +010058bool IsTimingFrame(const EncodedImage& image) {
59 return image.timing_.flags != VideoSendTiming::kInvalid &&
60 image.timing_.flags != VideoSendTiming::kNotTriggered;
61}
62
ilnik04f4d122017-06-19 07:18:55 -070063// Emulates |num_frames| on |num_streams| frames with capture timestamps
64// increased by 1 from 0. Size of each frame is between
65// |min_frame_size| and |max_frame_size|, outliers are counted relatevely to
66// |average_frame_sizes[]| for each stream.
67std::vector<std::vector<FrameType>> GetTimingFrames(
68 const int64_t delay_ms,
69 const size_t min_frame_size,
70 const size_t max_frame_size,
71 std::vector<size_t> average_frame_sizes,
72 const int num_streams,
73 const int num_frames) {
74 FakeEncodedImageCallback sink;
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020075 FrameEncodeMetadataWriter encode_timer(&sink);
Erik Språng6a7baa72019-02-26 18:31:00 +010076 VideoCodec codec_settings;
77 codec_settings.numberOfSimulcastStreams = num_streams;
78 codec_settings.timing_frame_thresholds = {delay_ms,
79 kDefaultOutlierFrameSizePercent};
80 encode_timer.OnEncoderInit(codec_settings, false);
ilnik04f4d122017-06-19 07:18:55 -070081 const size_t kFramerate = 30;
Erik Språng6a7baa72019-02-26 18:31:00 +010082 VideoBitrateAllocation bitrate_allocation;
83 for (int si = 0; si < num_streams; ++si) {
84 bitrate_allocation.SetBitrate(si, 0,
85 average_frame_sizes[si] * 8 * kFramerate);
86 }
87 encode_timer.OnSetRates(bitrate_allocation, kFramerate);
88
ilnik04f4d122017-06-19 07:18:55 -070089 std::vector<std::vector<FrameType>> result(num_streams);
ilnik04f4d122017-06-19 07:18:55 -070090 int64_t current_timestamp = 0;
Erik Språng6a7baa72019-02-26 18:31:00 +010091 for (int i = 0; i < num_frames; ++i) {
ilnik04f4d122017-06-19 07:18:55 -070092 current_timestamp += 1;
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +020093 VideoFrame frame = VideoFrame::Builder()
94 .set_timestamp_rtp(current_timestamp * 90)
95 .set_timestamp_ms(current_timestamp)
96 .set_video_frame_buffer(kFrameBuffer)
97 .build();
98 encode_timer.OnEncodeStarted(frame);
Erik Språng6a7baa72019-02-26 18:31:00 +010099 for (int si = 0; si < num_streams; ++si) {
ilnik04f4d122017-06-19 07:18:55 -0700100 // every (5+s)-th frame is dropped on s-th stream by design.
Erik Språng6a7baa72019-02-26 18:31:00 +0100101 bool dropped = i % (5 + si) == 0;
ilnik04f4d122017-06-19 07:18:55 -0700102
103 EncodedImage image;
Niels Möller663844d2019-02-14 16:15:54 +0100104 image.Allocate(max_frame_size);
Erik Språng6a7baa72019-02-26 18:31:00 +0100105 image.set_size(FrameSize(min_frame_size, max_frame_size, si, i));
ilnik04f4d122017-06-19 07:18:55 -0700106 image.capture_time_ms_ = current_timestamp;
Niels Möller23775882018-08-16 10:24:12 +0200107 image.SetTimestamp(static_cast<uint32_t>(current_timestamp * 90));
Erik Språng6a7baa72019-02-26 18:31:00 +0100108 image.SetSpatialIndex(si);
109
ilnik04f4d122017-06-19 07:18:55 -0700110 if (dropped) {
Erik Språng6a7baa72019-02-26 18:31:00 +0100111 result[si].push_back(FrameType::kDropped);
ilnik04f4d122017-06-19 07:18:55 -0700112 continue;
113 }
Erik Språng6a7baa72019-02-26 18:31:00 +0100114
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200115 encode_timer.FillTimingInfo(si, &image);
Erik Språng6a7baa72019-02-26 18:31:00 +0100116
117 if (IsTimingFrame(image)) {
118 result[si].push_back(FrameType::kTiming);
ilnik04f4d122017-06-19 07:18:55 -0700119 } else {
Erik Språng6a7baa72019-02-26 18:31:00 +0100120 result[si].push_back(FrameType::kNormal);
ilnik04f4d122017-06-19 07:18:55 -0700121 }
122 }
123 }
124 return result;
125}
126} // namespace
127
Erik Språng6a7baa72019-02-26 18:31:00 +0100128TEST(FrameEncodeTimerTest, MarksTimingFramesPeriodicallyTogether) {
ilnik04f4d122017-06-19 07:18:55 -0700129 const int64_t kDelayMs = 29;
130 const size_t kMinFrameSize = 10;
131 const size_t kMaxFrameSize = 20;
132 const int kNumFrames = 1000;
133 const int kNumStreams = 3;
134 // No outliers as 1000 is larger than anything from range [10,20].
135 const std::vector<size_t> kAverageSize = {1000, 1000, 1000};
136 auto frames = GetTimingFrames(kDelayMs, kMinFrameSize, kMaxFrameSize,
137 kAverageSize, kNumStreams, kNumFrames);
138 // Timing frames should be tirggered every delayMs.
139 // As no outliers are expected, frames on all streams have to be
140 // marked together.
141 int last_timing_frame = -1;
142 for (int i = 0; i < kNumFrames; ++i) {
143 int num_normal = 0;
144 int num_timing = 0;
145 int num_dropped = 0;
146 for (int s = 0; s < kNumStreams; ++s) {
147 if (frames[s][i] == FrameType::kTiming) {
148 ++num_timing;
149 } else if (frames[s][i] == FrameType::kNormal) {
150 ++num_normal;
151 } else {
152 ++num_dropped;
153 }
154 }
155 // Can't have both normal and timing frames at the same timstamp.
156 EXPECT_TRUE(num_timing == 0 || num_normal == 0);
157 if (num_dropped < kNumStreams) {
158 if (last_timing_frame == -1 || i >= last_timing_frame + kDelayMs) {
159 // If didn't have timing frames for a period, current sent frame has to
160 // be one. No normal frames should be sent.
161 EXPECT_EQ(num_normal, 0);
162 } else {
163 // No unneeded timing frames should be sent.
164 EXPECT_EQ(num_timing, 0);
165 }
166 }
167 if (num_timing > 0)
168 last_timing_frame = i;
169 }
170}
171
Erik Språng6a7baa72019-02-26 18:31:00 +0100172TEST(FrameEncodeTimerTest, MarksOutliers) {
ilnik04f4d122017-06-19 07:18:55 -0700173 const int64_t kDelayMs = 29;
174 const size_t kMinFrameSize = 2495;
175 const size_t kMaxFrameSize = 2505;
176 const int kNumFrames = 1000;
177 const int kNumStreams = 3;
178 // Possible outliers as 1000 lies in range [995, 1005].
179 const std::vector<size_t> kAverageSize = {998, 1000, 1004};
180 auto frames = GetTimingFrames(kDelayMs, kMinFrameSize, kMaxFrameSize,
181 kAverageSize, kNumStreams, kNumFrames);
182 // All outliers should be marked.
183 for (int i = 0; i < kNumFrames; ++i) {
184 for (int s = 0; s < kNumStreams; ++s) {
185 if (FrameSize(kMinFrameSize, kMaxFrameSize, s, i) >=
186 kAverageSize[s] * kDefaultOutlierFrameSizePercent / 100) {
187 // Too big frame. May be dropped or timing, but not normal.
188 EXPECT_NE(frames[s][i], FrameType::kNormal);
189 }
190 }
191 }
192}
193
Erik Språng6a7baa72019-02-26 18:31:00 +0100194TEST(FrameEncodeTimerTest, NoTimingFrameIfNoEncodeStartTime) {
sprangba050a62017-08-18 02:51:12 -0700195 int64_t timestamp = 1;
Niels Möller663844d2019-02-14 16:15:54 +0100196 constexpr size_t kFrameSize = 500;
Erik Språng6a7baa72019-02-26 18:31:00 +0100197 EncodedImage image;
Niels Möller663844d2019-02-14 16:15:54 +0100198 image.Allocate(kFrameSize);
199 image.set_size(kFrameSize);
sprangba050a62017-08-18 02:51:12 -0700200 image.capture_time_ms_ = timestamp;
Niels Möller23775882018-08-16 10:24:12 +0200201 image.SetTimestamp(static_cast<uint32_t>(timestamp * 90));
Erik Språng6a7baa72019-02-26 18:31:00 +0100202
sprangba050a62017-08-18 02:51:12 -0700203 FakeEncodedImageCallback sink;
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200204 FrameEncodeMetadataWriter encode_timer(&sink);
Erik Språng6a7baa72019-02-26 18:31:00 +0100205 VideoCodec codec_settings;
206 // Make all frames timing frames.
207 codec_settings.timing_frame_thresholds.delay_ms = 1;
208 encode_timer.OnEncoderInit(codec_settings, false);
209 VideoBitrateAllocation bitrate_allocation;
210 bitrate_allocation.SetBitrate(0, 0, 500000);
211 encode_timer.OnSetRates(bitrate_allocation, 30);
sprangba050a62017-08-18 02:51:12 -0700212
213 // Verify a single frame works with encode start time set.
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200214 VideoFrame frame = VideoFrame::Builder()
215 .set_timestamp_ms(timestamp)
216 .set_timestamp_rtp(timestamp * 90)
217 .set_video_frame_buffer(kFrameBuffer)
218 .build();
219 encode_timer.OnEncodeStarted(frame);
220 encode_timer.FillTimingInfo(0, &image);
Erik Språng6a7baa72019-02-26 18:31:00 +0100221 EXPECT_TRUE(IsTimingFrame(image));
sprangba050a62017-08-18 02:51:12 -0700222
223 // New frame, now skip OnEncodeStarted. Should not result in timing frame.
224 image.capture_time_ms_ = ++timestamp;
Niels Möller23775882018-08-16 10:24:12 +0200225 image.SetTimestamp(static_cast<uint32_t>(timestamp * 90));
Erik Språng6a7baa72019-02-26 18:31:00 +0100226 image.timing_ = EncodedImage::Timing();
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200227 encode_timer.FillTimingInfo(0, &image);
Erik Språng6a7baa72019-02-26 18:31:00 +0100228 EXPECT_FALSE(IsTimingFrame(image));
sprangba050a62017-08-18 02:51:12 -0700229}
230
Erik Språng6a7baa72019-02-26 18:31:00 +0100231TEST(FrameEncodeTimerTest, AdjustsCaptureTimeForInternalSourceEncoder) {
Ilya Nikolaevskiy764aeb72018-04-03 10:01:52 +0200232 const int64_t kEncodeStartDelayMs = 2;
233 const int64_t kEncodeFinishDelayMs = 10;
Niels Möller663844d2019-02-14 16:15:54 +0100234 constexpr size_t kFrameSize = 500;
Erik Språng6a7baa72019-02-26 18:31:00 +0100235
236 int64_t timestamp = 1;
237 EncodedImage image;
Niels Möller663844d2019-02-14 16:15:54 +0100238 image.Allocate(kFrameSize);
239 image.set_size(kFrameSize);
Ilya Nikolaevskiy764aeb72018-04-03 10:01:52 +0200240 image.capture_time_ms_ = timestamp;
Niels Möller23775882018-08-16 10:24:12 +0200241 image.SetTimestamp(static_cast<uint32_t>(timestamp * 90));
Erik Språng6a7baa72019-02-26 18:31:00 +0100242
Ilya Nikolaevskiy764aeb72018-04-03 10:01:52 +0200243 FakeEncodedImageCallback sink;
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200244 FrameEncodeMetadataWriter encode_timer(&sink);
Erik Språng6a7baa72019-02-26 18:31:00 +0100245
246 VideoCodec codec_settings;
247 // Make all frames timing frames.
248 codec_settings.timing_frame_thresholds.delay_ms = 1;
249 encode_timer.OnEncoderInit(codec_settings, true);
250
251 VideoBitrateAllocation bitrate_allocation;
252 bitrate_allocation.SetBitrate(0, 0, 500000);
253 encode_timer.OnSetRates(bitrate_allocation, 30);
Ilya Nikolaevskiy764aeb72018-04-03 10:01:52 +0200254
255 // Verify a single frame without encode timestamps isn't a timing frame.
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200256 encode_timer.FillTimingInfo(0, &image);
Erik Språng6a7baa72019-02-26 18:31:00 +0100257 EXPECT_FALSE(IsTimingFrame(image));
Ilya Nikolaevskiy764aeb72018-04-03 10:01:52 +0200258
259 // New frame, but this time with encode timestamps set in timing_.
260 // This should be a timing frame.
261 image.capture_time_ms_ = ++timestamp;
Niels Möller23775882018-08-16 10:24:12 +0200262 image.SetTimestamp(static_cast<uint32_t>(timestamp * 90));
Erik Språng6a7baa72019-02-26 18:31:00 +0100263 image.timing_ = EncodedImage::Timing();
Ilya Nikolaevskiy764aeb72018-04-03 10:01:52 +0200264 image.timing_.encode_start_ms = timestamp + kEncodeStartDelayMs;
265 image.timing_.encode_finish_ms = timestamp + kEncodeFinishDelayMs;
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200266
267 encode_timer.FillTimingInfo(0, &image);
Erik Språng6a7baa72019-02-26 18:31:00 +0100268 EXPECT_TRUE(IsTimingFrame(image));
269
Ilya Nikolaevskiy764aeb72018-04-03 10:01:52 +0200270 // Frame is captured kEncodeFinishDelayMs before it's encoded, so restored
271 // capture timestamp should be kEncodeFinishDelayMs in the past.
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200272 EXPECT_NEAR(image.capture_time_ms_, rtc::TimeMillis() - kEncodeFinishDelayMs,
273 1);
Ilya Nikolaevskiy764aeb72018-04-03 10:01:52 +0200274}
275
Erik Språng6a7baa72019-02-26 18:31:00 +0100276TEST(FrameEncodeTimerTest, NotifiesAboutDroppedFrames) {
Ilya Nikolaevskiy76f2a852017-11-16 14:33:53 +0100277 const int64_t kTimestampMs1 = 47721840;
278 const int64_t kTimestampMs2 = 47721850;
279 const int64_t kTimestampMs3 = 47721860;
280 const int64_t kTimestampMs4 = 47721870;
Erik Språng6a7baa72019-02-26 18:31:00 +0100281
Ilya Nikolaevskiyd79314f2017-10-23 10:45:37 +0200282 FakeEncodedImageCallback sink;
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200283 FrameEncodeMetadataWriter encode_timer(&sink);
Erik Språng6a7baa72019-02-26 18:31:00 +0100284 encode_timer.OnEncoderInit(VideoCodec(), false);
Ilya Nikolaevskiye0da9ea2017-11-08 14:39:02 +0100285 // Any non-zero bitrate needed to be set before the first frame.
Erik Språng6a7baa72019-02-26 18:31:00 +0100286 VideoBitrateAllocation bitrate_allocation;
287 bitrate_allocation.SetBitrate(0, 0, 500000);
288 encode_timer.OnSetRates(bitrate_allocation, 30);
289
290 EncodedImage image;
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200291 VideoFrame frame = VideoFrame::Builder()
292 .set_timestamp_rtp(kTimestampMs1 * 90)
293 .set_timestamp_ms(kTimestampMs1)
294 .set_video_frame_buffer(kFrameBuffer)
295 .build();
296
Ilya Nikolaevskiy76f2a852017-11-16 14:33:53 +0100297 image.capture_time_ms_ = kTimestampMs1;
Niels Möller23775882018-08-16 10:24:12 +0200298 image.SetTimestamp(static_cast<uint32_t>(image.capture_time_ms_ * 90));
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200299 frame.set_timestamp(image.capture_time_ms_ * 90);
300 frame.set_timestamp_us(image.capture_time_ms_ * 1000);
301 encode_timer.OnEncodeStarted(frame);
Erik Språng6a7baa72019-02-26 18:31:00 +0100302
Ilya Nikolaevskiyd79314f2017-10-23 10:45:37 +0200303 EXPECT_EQ(0u, sink.GetNumFramesDropped());
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200304 encode_timer.FillTimingInfo(0, &image);
Ilya Nikolaevskiy76f2a852017-11-16 14:33:53 +0100305
306 image.capture_time_ms_ = kTimestampMs2;
Niels Möller23775882018-08-16 10:24:12 +0200307 image.SetTimestamp(static_cast<uint32_t>(image.capture_time_ms_ * 90));
Erik Språng6a7baa72019-02-26 18:31:00 +0100308 image.timing_ = EncodedImage::Timing();
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200309 frame.set_timestamp(image.capture_time_ms_ * 90);
310 frame.set_timestamp_us(image.capture_time_ms_ * 1000);
311 encode_timer.OnEncodeStarted(frame);
Ilya Nikolaevskiyd79314f2017-10-23 10:45:37 +0200312 // No OnEncodedImageCall for timestamp2. Yet, at this moment it's not known
313 // that frame with timestamp2 was dropped.
314 EXPECT_EQ(0u, sink.GetNumFramesDropped());
Ilya Nikolaevskiy76f2a852017-11-16 14:33:53 +0100315
316 image.capture_time_ms_ = kTimestampMs3;
Niels Möller23775882018-08-16 10:24:12 +0200317 image.SetTimestamp(static_cast<uint32_t>(image.capture_time_ms_ * 90));
Erik Språng6a7baa72019-02-26 18:31:00 +0100318 image.timing_ = EncodedImage::Timing();
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200319 frame.set_timestamp(image.capture_time_ms_ * 90);
320 frame.set_timestamp_us(image.capture_time_ms_ * 1000);
321 encode_timer.OnEncodeStarted(frame);
322 encode_timer.FillTimingInfo(0, &image);
Ilya Nikolaevskiyd79314f2017-10-23 10:45:37 +0200323 EXPECT_EQ(1u, sink.GetNumFramesDropped());
Ilya Nikolaevskiy76f2a852017-11-16 14:33:53 +0100324
325 image.capture_time_ms_ = kTimestampMs4;
Niels Möller23775882018-08-16 10:24:12 +0200326 image.SetTimestamp(static_cast<uint32_t>(image.capture_time_ms_ * 90));
Erik Språng6a7baa72019-02-26 18:31:00 +0100327 image.timing_ = EncodedImage::Timing();
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200328 frame.set_timestamp(image.capture_time_ms_ * 90);
329 frame.set_timestamp_us(image.capture_time_ms_ * 1000);
330 encode_timer.OnEncodeStarted(frame);
331 encode_timer.FillTimingInfo(0, &image);
Ilya Nikolaevskiyd79314f2017-10-23 10:45:37 +0200332 EXPECT_EQ(1u, sink.GetNumFramesDropped());
333}
334
Erik Språng6a7baa72019-02-26 18:31:00 +0100335TEST(FrameEncodeTimerTest, RestoresCaptureTimestamps) {
Ilya Nikolaevskiy76f2a852017-11-16 14:33:53 +0100336 EncodedImage image;
Ilya Nikolaevskiy76f2a852017-11-16 14:33:53 +0100337 const int64_t kTimestampMs = 123456;
Ilya Nikolaevskiy76f2a852017-11-16 14:33:53 +0100338 FakeEncodedImageCallback sink;
Erik Språng6a7baa72019-02-26 18:31:00 +0100339
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200340 FrameEncodeMetadataWriter encode_timer(&sink);
Erik Språng6a7baa72019-02-26 18:31:00 +0100341 encode_timer.OnEncoderInit(VideoCodec(), false);
Ilya Nikolaevskiy76f2a852017-11-16 14:33:53 +0100342 // Any non-zero bitrate needed to be set before the first frame.
Erik Språng6a7baa72019-02-26 18:31:00 +0100343 VideoBitrateAllocation bitrate_allocation;
344 bitrate_allocation.SetBitrate(0, 0, 500000);
345 encode_timer.OnSetRates(bitrate_allocation, 30);
346
347 image.capture_time_ms_ = kTimestampMs; // Correct timestamp.
Niels Möller23775882018-08-16 10:24:12 +0200348 image.SetTimestamp(static_cast<uint32_t>(image.capture_time_ms_ * 90));
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200349 VideoFrame frame = VideoFrame::Builder()
350 .set_timestamp_ms(image.capture_time_ms_)
351 .set_timestamp_rtp(image.capture_time_ms_ * 90)
352 .set_video_frame_buffer(kFrameBuffer)
353 .build();
354 encode_timer.OnEncodeStarted(frame);
Erik Språng6a7baa72019-02-26 18:31:00 +0100355 image.capture_time_ms_ = 0; // Incorrect timestamp.
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200356 encode_timer.FillTimingInfo(0, &image);
Erik Språng6a7baa72019-02-26 18:31:00 +0100357 EXPECT_EQ(kTimestampMs, image.capture_time_ms_);
Ilya Nikolaevskiy76f2a852017-11-16 14:33:53 +0100358}
359
Ilya Nikolaevskiy2ebf5232019-05-13 16:13:36 +0200360TEST(FrameEncodeTimerTest, CopiesRotation) {
361 EncodedImage image;
362 const int64_t kTimestampMs = 123456;
363 FakeEncodedImageCallback sink;
364
365 FrameEncodeMetadataWriter encode_timer(&sink);
366 encode_timer.OnEncoderInit(VideoCodec(), false);
367 // Any non-zero bitrate needed to be set before the first frame.
368 VideoBitrateAllocation bitrate_allocation;
369 bitrate_allocation.SetBitrate(0, 0, 500000);
370 encode_timer.OnSetRates(bitrate_allocation, 30);
371
372 image.SetTimestamp(static_cast<uint32_t>(kTimestampMs * 90));
373 VideoFrame frame = VideoFrame::Builder()
374 .set_timestamp_ms(kTimestampMs)
375 .set_timestamp_rtp(kTimestampMs * 90)
376 .set_rotation(kVideoRotation_180)
377 .set_video_frame_buffer(kFrameBuffer)
378 .build();
379 encode_timer.OnEncodeStarted(frame);
380 encode_timer.FillTimingInfo(0, &image);
381 EXPECT_EQ(kVideoRotation_180, image.rotation_);
382}
383
384TEST(FrameEncodeTimerTest, SetsContentType) {
385 EncodedImage image;
386 const int64_t kTimestampMs = 123456;
387 FakeEncodedImageCallback sink;
388
389 FrameEncodeMetadataWriter encode_timer(&sink);
390 VideoCodec codec;
391 codec.mode = VideoCodecMode::kScreensharing;
392 encode_timer.OnEncoderInit(codec, false);
393 // Any non-zero bitrate needed to be set before the first frame.
394 VideoBitrateAllocation bitrate_allocation;
395 bitrate_allocation.SetBitrate(0, 0, 500000);
396 encode_timer.OnSetRates(bitrate_allocation, 30);
397
398 image.SetTimestamp(static_cast<uint32_t>(kTimestampMs * 90));
399 VideoFrame frame = VideoFrame::Builder()
400 .set_timestamp_ms(kTimestampMs)
401 .set_timestamp_rtp(kTimestampMs * 90)
402 .set_rotation(kVideoRotation_180)
403 .set_video_frame_buffer(kFrameBuffer)
404 .build();
405 encode_timer.OnEncodeStarted(frame);
406 encode_timer.FillTimingInfo(0, &image);
407 EXPECT_EQ(VideoContentType::SCREENSHARE, image.content_type_);
408}
409
410TEST(FrameEncodeTimerTest, CopiesColorSpace) {
411 EncodedImage image;
412 const int64_t kTimestampMs = 123456;
413 FakeEncodedImageCallback sink;
414
415 FrameEncodeMetadataWriter encode_timer(&sink);
416 encode_timer.OnEncoderInit(VideoCodec(), false);
417 // Any non-zero bitrate needed to be set before the first frame.
418 VideoBitrateAllocation bitrate_allocation;
419 bitrate_allocation.SetBitrate(0, 0, 500000);
420 encode_timer.OnSetRates(bitrate_allocation, 30);
421
422 webrtc::ColorSpace color_space =
423 CreateTestColorSpace(/*with_hdr_metadata=*/true);
424 image.SetTimestamp(static_cast<uint32_t>(kTimestampMs * 90));
425 VideoFrame frame = VideoFrame::Builder()
426 .set_timestamp_ms(kTimestampMs)
427 .set_timestamp_rtp(kTimestampMs * 90)
428 .set_color_space(color_space)
429 .set_video_frame_buffer(kFrameBuffer)
430 .build();
431 encode_timer.OnEncodeStarted(frame);
432 encode_timer.FillTimingInfo(0, &image);
433 ASSERT_NE(image.ColorSpace(), nullptr);
434 EXPECT_EQ(color_space, *image.ColorSpace());
435}
436
ilnik04f4d122017-06-19 07:18:55 -0700437} // namespace test
438} // namespace webrtc