blob: 5106e0e16d2a98d6e2709a0d30e6d4a6717aa291 [file] [log] [blame]
ilnik04f4d122017-06-19 14:18:551/*
Erik Språng6a7baa72019-02-26 17:31:002 * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
ilnik04f4d122017-06-19 14:18:553 *
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 14:13:3611#include "video/frame_encode_metadata_writer.h"
12
Yves Gerey3e707812018-11-28 15:47:4913#include <cstddef>
ilnik04f4d122017-06-19 14:18:5514#include <vector>
15
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:3616#include "api/video/i420_buffer.h"
17#include "api/video/video_frame.h"
Yves Gerey3e707812018-11-28 15:47:4918#include "api/video/video_timing.h"
Mirta Dvornicic28f0eb22019-05-28 14:30:1619#include "common_video/h264/h264_common.h"
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:3620#include "common_video/test/utilities.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3121#include "modules/video_coding/include/video_coding_defines.h"
Steve Anton10542f22019-01-11 17:11:0022#include "rtc_base/time_utils.h"
Mirta Dvornicic28f0eb22019-05-28 14:30:1623#include "test/gmock.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3124#include "test/gtest.h"
ilnik04f4d122017-06-19 14:18:5525
26namespace webrtc {
27namespace test {
28namespace {
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:3629
30const rtc::scoped_refptr<I420Buffer> kFrameBuffer = I420Buffer::Create(4, 4);
31
ilnik04f4d122017-06-19 14:18:5532inline size_t FrameSize(const size_t& min_frame_size,
33 const size_t& max_frame_size,
34 const int& s,
35 const int& i) {
36 return min_frame_size + (s + 1) * i % (max_frame_size - min_frame_size);
37}
38
39class FakeEncodedImageCallback : public EncodedImageCallback {
40 public:
Erik Språng6a7baa72019-02-26 17:31:0041 FakeEncodedImageCallback() : num_frames_dropped_(0) {}
ilnik04f4d122017-06-19 14:18:5542 Result OnEncodedImage(const EncodedImage& encoded_image,
Danil Chapovalov2549f172020-08-12 15:30:3643 const CodecSpecificInfo* codec_specific_info) override {
mflodman351424e2017-08-10 09:43:1444 return Result(Result::OK);
Mirko Bonadeic4dd7302019-02-25 08:12:0245 }
Ilya Nikolaevskiyd79314f2017-10-23 08:45:3746 void OnDroppedFrame(DropReason reason) override { ++num_frames_dropped_; }
Ilya Nikolaevskiyd79314f2017-10-23 08:45:3747 size_t GetNumFramesDropped() { return num_frames_dropped_; }
48
ilnik04f4d122017-06-19 14:18:5549 private:
Ilya Nikolaevskiyd79314f2017-10-23 08:45:3750 size_t num_frames_dropped_;
ilnik04f4d122017-06-19 14:18:5551};
52
53enum class FrameType {
54 kNormal,
55 kTiming,
56 kDropped,
57};
58
Erik Språng6a7baa72019-02-26 17:31:0059bool IsTimingFrame(const EncodedImage& image) {
60 return image.timing_.flags != VideoSendTiming::kInvalid &&
61 image.timing_.flags != VideoSendTiming::kNotTriggered;
62}
63
Artem Titovab30d722021-07-27 14:22:1164// Emulates `num_frames` on `num_streams` frames with capture timestamps
ilnik04f4d122017-06-19 14:18:5565// increased by 1 from 0. Size of each frame is between
Artem Titovab30d722021-07-27 14:22:1166// `min_frame_size` and `max_frame_size`, outliers are counted relatevely to
Artem Titovcfea2182021-08-09 23:22:3167// `average_frame_sizes[]` for each stream.
ilnik04f4d122017-06-19 14:18:5568std::vector<std::vector<FrameType>> GetTimingFrames(
69 const int64_t delay_ms,
70 const size_t min_frame_size,
71 const size_t max_frame_size,
72 std::vector<size_t> average_frame_sizes,
73 const int num_streams,
74 const int num_frames) {
75 FakeEncodedImageCallback sink;
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:3676 FrameEncodeMetadataWriter encode_timer(&sink);
Erik Språng6a7baa72019-02-26 17:31:0077 VideoCodec codec_settings;
78 codec_settings.numberOfSimulcastStreams = num_streams;
79 codec_settings.timing_frame_thresholds = {delay_ms,
80 kDefaultOutlierFrameSizePercent};
Niels Möller13d16362021-11-16 10:39:2781 encode_timer.OnEncoderInit(codec_settings);
ilnik04f4d122017-06-19 14:18:5582 const size_t kFramerate = 30;
Erik Språng6a7baa72019-02-26 17:31:0083 VideoBitrateAllocation bitrate_allocation;
84 for (int si = 0; si < num_streams; ++si) {
85 bitrate_allocation.SetBitrate(si, 0,
86 average_frame_sizes[si] * 8 * kFramerate);
87 }
88 encode_timer.OnSetRates(bitrate_allocation, kFramerate);
89
ilnik04f4d122017-06-19 14:18:5590 std::vector<std::vector<FrameType>> result(num_streams);
ilnik04f4d122017-06-19 14:18:5591 int64_t current_timestamp = 0;
Erik Språng6a7baa72019-02-26 17:31:0092 for (int i = 0; i < num_frames; ++i) {
ilnik04f4d122017-06-19 14:18:5593 current_timestamp += 1;
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:3694 VideoFrame frame = VideoFrame::Builder()
95 .set_timestamp_rtp(current_timestamp * 90)
96 .set_timestamp_ms(current_timestamp)
97 .set_video_frame_buffer(kFrameBuffer)
98 .build();
99 encode_timer.OnEncodeStarted(frame);
Erik Språng6a7baa72019-02-26 17:31:00100 for (int si = 0; si < num_streams; ++si) {
ilnik04f4d122017-06-19 14:18:55101 // every (5+s)-th frame is dropped on s-th stream by design.
Erik Språng6a7baa72019-02-26 17:31:00102 bool dropped = i % (5 + si) == 0;
ilnik04f4d122017-06-19 14:18:55103
104 EncodedImage image;
Niels Möller4d504c72019-06-18 13:56:56105 image.SetEncodedData(EncodedImageBuffer::Create(max_frame_size));
Erik Språng6a7baa72019-02-26 17:31:00106 image.set_size(FrameSize(min_frame_size, max_frame_size, si, i));
ilnik04f4d122017-06-19 14:18:55107 image.capture_time_ms_ = current_timestamp;
Danil Chapovalov9c584832023-09-18 13:48:49108 image.SetRtpTimestamp(static_cast<uint32_t>(current_timestamp * 90));
Erik Språng6a7baa72019-02-26 17:31:00109 image.SetSpatialIndex(si);
110
ilnik04f4d122017-06-19 14:18:55111 if (dropped) {
Erik Språng6a7baa72019-02-26 17:31:00112 result[si].push_back(FrameType::kDropped);
ilnik04f4d122017-06-19 14:18:55113 continue;
114 }
Erik Språng6a7baa72019-02-26 17:31:00115
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36116 encode_timer.FillTimingInfo(si, &image);
Erik Språng6a7baa72019-02-26 17:31:00117
118 if (IsTimingFrame(image)) {
119 result[si].push_back(FrameType::kTiming);
ilnik04f4d122017-06-19 14:18:55120 } else {
Erik Språng6a7baa72019-02-26 17:31:00121 result[si].push_back(FrameType::kNormal);
ilnik04f4d122017-06-19 14:18:55122 }
123 }
124 }
125 return result;
126}
127} // namespace
128
Mirta Dvornicic28f0eb22019-05-28 14:30:16129TEST(FrameEncodeMetadataWriterTest, MarksTimingFramesPeriodicallyTogether) {
ilnik04f4d122017-06-19 14:18:55130 const int64_t kDelayMs = 29;
131 const size_t kMinFrameSize = 10;
132 const size_t kMaxFrameSize = 20;
133 const int kNumFrames = 1000;
134 const int kNumStreams = 3;
135 // No outliers as 1000 is larger than anything from range [10,20].
136 const std::vector<size_t> kAverageSize = {1000, 1000, 1000};
137 auto frames = GetTimingFrames(kDelayMs, kMinFrameSize, kMaxFrameSize,
138 kAverageSize, kNumStreams, kNumFrames);
139 // Timing frames should be tirggered every delayMs.
140 // As no outliers are expected, frames on all streams have to be
141 // marked together.
142 int last_timing_frame = -1;
143 for (int i = 0; i < kNumFrames; ++i) {
144 int num_normal = 0;
145 int num_timing = 0;
146 int num_dropped = 0;
147 for (int s = 0; s < kNumStreams; ++s) {
148 if (frames[s][i] == FrameType::kTiming) {
149 ++num_timing;
150 } else if (frames[s][i] == FrameType::kNormal) {
151 ++num_normal;
152 } else {
153 ++num_dropped;
154 }
155 }
156 // Can't have both normal and timing frames at the same timstamp.
157 EXPECT_TRUE(num_timing == 0 || num_normal == 0);
158 if (num_dropped < kNumStreams) {
159 if (last_timing_frame == -1 || i >= last_timing_frame + kDelayMs) {
160 // If didn't have timing frames for a period, current sent frame has to
161 // be one. No normal frames should be sent.
162 EXPECT_EQ(num_normal, 0);
163 } else {
164 // No unneeded timing frames should be sent.
165 EXPECT_EQ(num_timing, 0);
166 }
167 }
168 if (num_timing > 0)
169 last_timing_frame = i;
170 }
171}
172
Mirta Dvornicic28f0eb22019-05-28 14:30:16173TEST(FrameEncodeMetadataWriterTest, MarksOutliers) {
ilnik04f4d122017-06-19 14:18:55174 const int64_t kDelayMs = 29;
175 const size_t kMinFrameSize = 2495;
176 const size_t kMaxFrameSize = 2505;
177 const int kNumFrames = 1000;
178 const int kNumStreams = 3;
179 // Possible outliers as 1000 lies in range [995, 1005].
180 const std::vector<size_t> kAverageSize = {998, 1000, 1004};
181 auto frames = GetTimingFrames(kDelayMs, kMinFrameSize, kMaxFrameSize,
182 kAverageSize, kNumStreams, kNumFrames);
183 // All outliers should be marked.
184 for (int i = 0; i < kNumFrames; ++i) {
185 for (int s = 0; s < kNumStreams; ++s) {
186 if (FrameSize(kMinFrameSize, kMaxFrameSize, s, i) >=
187 kAverageSize[s] * kDefaultOutlierFrameSizePercent / 100) {
188 // Too big frame. May be dropped or timing, but not normal.
189 EXPECT_NE(frames[s][i], FrameType::kNormal);
190 }
191 }
192 }
193}
194
Mirta Dvornicic28f0eb22019-05-28 14:30:16195TEST(FrameEncodeMetadataWriterTest, NoTimingFrameIfNoEncodeStartTime) {
sprangba050a62017-08-18 09:51:12196 int64_t timestamp = 1;
Niels Möller663844d2019-02-14 15:15:54197 constexpr size_t kFrameSize = 500;
Erik Språng6a7baa72019-02-26 17:31:00198 EncodedImage image;
Niels Möller4d504c72019-06-18 13:56:56199 image.SetEncodedData(EncodedImageBuffer::Create(kFrameSize));
sprangba050a62017-08-18 09:51:12200 image.capture_time_ms_ = timestamp;
Danil Chapovalov9c584832023-09-18 13:48:49201 image.SetRtpTimestamp(static_cast<uint32_t>(timestamp * 90));
Erik Språng6a7baa72019-02-26 17:31:00202
sprangba050a62017-08-18 09:51:12203 FakeEncodedImageCallback sink;
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36204 FrameEncodeMetadataWriter encode_timer(&sink);
Erik Språng6a7baa72019-02-26 17:31:00205 VideoCodec codec_settings;
206 // Make all frames timing frames.
207 codec_settings.timing_frame_thresholds.delay_ms = 1;
Niels Möller13d16362021-11-16 10:39:27208 encode_timer.OnEncoderInit(codec_settings);
Erik Språng6a7baa72019-02-26 17:31:00209 VideoBitrateAllocation bitrate_allocation;
210 bitrate_allocation.SetBitrate(0, 0, 500000);
211 encode_timer.OnSetRates(bitrate_allocation, 30);
sprangba050a62017-08-18 09:51:12212
213 // Verify a single frame works with encode start time set.
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36214 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 17:31:00221 EXPECT_TRUE(IsTimingFrame(image));
sprangba050a62017-08-18 09:51:12222
223 // New frame, now skip OnEncodeStarted. Should not result in timing frame.
224 image.capture_time_ms_ = ++timestamp;
Danil Chapovalov9c584832023-09-18 13:48:49225 image.SetRtpTimestamp(static_cast<uint32_t>(timestamp * 90));
Erik Språng6a7baa72019-02-26 17:31:00226 image.timing_ = EncodedImage::Timing();
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36227 encode_timer.FillTimingInfo(0, &image);
Erik Språng6a7baa72019-02-26 17:31:00228 EXPECT_FALSE(IsTimingFrame(image));
sprangba050a62017-08-18 09:51:12229}
230
Mirta Dvornicic28f0eb22019-05-28 14:30:16231TEST(FrameEncodeMetadataWriterTest, NotifiesAboutDroppedFrames) {
Ilya Nikolaevskiy76f2a852017-11-16 13:33:53232 const int64_t kTimestampMs1 = 47721840;
233 const int64_t kTimestampMs2 = 47721850;
234 const int64_t kTimestampMs3 = 47721860;
235 const int64_t kTimestampMs4 = 47721870;
Erik Språng6a7baa72019-02-26 17:31:00236
Ilya Nikolaevskiyd79314f2017-10-23 08:45:37237 FakeEncodedImageCallback sink;
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36238 FrameEncodeMetadataWriter encode_timer(&sink);
Niels Möller13d16362021-11-16 10:39:27239 encode_timer.OnEncoderInit(VideoCodec());
Ilya Nikolaevskiye0da9ea2017-11-08 13:39:02240 // Any non-zero bitrate needed to be set before the first frame.
Erik Språng6a7baa72019-02-26 17:31:00241 VideoBitrateAllocation bitrate_allocation;
242 bitrate_allocation.SetBitrate(0, 0, 500000);
243 encode_timer.OnSetRates(bitrate_allocation, 30);
244
245 EncodedImage image;
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36246 VideoFrame frame = VideoFrame::Builder()
247 .set_timestamp_rtp(kTimestampMs1 * 90)
248 .set_timestamp_ms(kTimestampMs1)
249 .set_video_frame_buffer(kFrameBuffer)
250 .build();
251
Ilya Nikolaevskiy76f2a852017-11-16 13:33:53252 image.capture_time_ms_ = kTimestampMs1;
Danil Chapovalov9c584832023-09-18 13:48:49253 image.SetRtpTimestamp(static_cast<uint32_t>(image.capture_time_ms_ * 90));
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36254 frame.set_timestamp(image.capture_time_ms_ * 90);
255 frame.set_timestamp_us(image.capture_time_ms_ * 1000);
256 encode_timer.OnEncodeStarted(frame);
Erik Språng6a7baa72019-02-26 17:31:00257
Ilya Nikolaevskiyd79314f2017-10-23 08:45:37258 EXPECT_EQ(0u, sink.GetNumFramesDropped());
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36259 encode_timer.FillTimingInfo(0, &image);
Ilya Nikolaevskiy76f2a852017-11-16 13:33:53260
261 image.capture_time_ms_ = kTimestampMs2;
Danil Chapovalov9c584832023-09-18 13:48:49262 image.SetRtpTimestamp(static_cast<uint32_t>(image.capture_time_ms_ * 90));
Erik Språng6a7baa72019-02-26 17:31:00263 image.timing_ = EncodedImage::Timing();
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36264 frame.set_timestamp(image.capture_time_ms_ * 90);
265 frame.set_timestamp_us(image.capture_time_ms_ * 1000);
266 encode_timer.OnEncodeStarted(frame);
Ilya Nikolaevskiyd79314f2017-10-23 08:45:37267 // No OnEncodedImageCall for timestamp2. Yet, at this moment it's not known
268 // that frame with timestamp2 was dropped.
269 EXPECT_EQ(0u, sink.GetNumFramesDropped());
Ilya Nikolaevskiy76f2a852017-11-16 13:33:53270
271 image.capture_time_ms_ = kTimestampMs3;
Danil Chapovalov9c584832023-09-18 13:48:49272 image.SetRtpTimestamp(static_cast<uint32_t>(image.capture_time_ms_ * 90));
Erik Språng6a7baa72019-02-26 17:31:00273 image.timing_ = EncodedImage::Timing();
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36274 frame.set_timestamp(image.capture_time_ms_ * 90);
275 frame.set_timestamp_us(image.capture_time_ms_ * 1000);
276 encode_timer.OnEncodeStarted(frame);
277 encode_timer.FillTimingInfo(0, &image);
Ilya Nikolaevskiyd79314f2017-10-23 08:45:37278 EXPECT_EQ(1u, sink.GetNumFramesDropped());
Ilya Nikolaevskiy76f2a852017-11-16 13:33:53279
280 image.capture_time_ms_ = kTimestampMs4;
Danil Chapovalov9c584832023-09-18 13:48:49281 image.SetRtpTimestamp(static_cast<uint32_t>(image.capture_time_ms_ * 90));
Erik Språng6a7baa72019-02-26 17:31:00282 image.timing_ = EncodedImage::Timing();
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36283 frame.set_timestamp(image.capture_time_ms_ * 90);
284 frame.set_timestamp_us(image.capture_time_ms_ * 1000);
285 encode_timer.OnEncodeStarted(frame);
286 encode_timer.FillTimingInfo(0, &image);
Ilya Nikolaevskiyd79314f2017-10-23 08:45:37287 EXPECT_EQ(1u, sink.GetNumFramesDropped());
288}
289
Mirta Dvornicic28f0eb22019-05-28 14:30:16290TEST(FrameEncodeMetadataWriterTest, RestoresCaptureTimestamps) {
Ilya Nikolaevskiy76f2a852017-11-16 13:33:53291 EncodedImage image;
Ilya Nikolaevskiy76f2a852017-11-16 13:33:53292 const int64_t kTimestampMs = 123456;
Ilya Nikolaevskiy76f2a852017-11-16 13:33:53293 FakeEncodedImageCallback sink;
Erik Språng6a7baa72019-02-26 17:31:00294
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36295 FrameEncodeMetadataWriter encode_timer(&sink);
Niels Möller13d16362021-11-16 10:39:27296 encode_timer.OnEncoderInit(VideoCodec());
Ilya Nikolaevskiy76f2a852017-11-16 13:33:53297 // Any non-zero bitrate needed to be set before the first frame.
Erik Språng6a7baa72019-02-26 17:31:00298 VideoBitrateAllocation bitrate_allocation;
299 bitrate_allocation.SetBitrate(0, 0, 500000);
300 encode_timer.OnSetRates(bitrate_allocation, 30);
301
302 image.capture_time_ms_ = kTimestampMs; // Correct timestamp.
Danil Chapovalov9c584832023-09-18 13:48:49303 image.SetRtpTimestamp(static_cast<uint32_t>(image.capture_time_ms_ * 90));
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36304 VideoFrame frame = VideoFrame::Builder()
305 .set_timestamp_ms(image.capture_time_ms_)
306 .set_timestamp_rtp(image.capture_time_ms_ * 90)
307 .set_video_frame_buffer(kFrameBuffer)
308 .build();
309 encode_timer.OnEncodeStarted(frame);
Erik Språng6a7baa72019-02-26 17:31:00310 image.capture_time_ms_ = 0; // Incorrect timestamp.
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36311 encode_timer.FillTimingInfo(0, &image);
Erik Språng6a7baa72019-02-26 17:31:00312 EXPECT_EQ(kTimestampMs, image.capture_time_ms_);
Ilya Nikolaevskiy76f2a852017-11-16 13:33:53313}
314
Mirta Dvornicic28f0eb22019-05-28 14:30:16315TEST(FrameEncodeMetadataWriterTest, CopiesRotation) {
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36316 EncodedImage image;
317 const int64_t kTimestampMs = 123456;
318 FakeEncodedImageCallback sink;
319
320 FrameEncodeMetadataWriter encode_timer(&sink);
Niels Möller13d16362021-11-16 10:39:27321 encode_timer.OnEncoderInit(VideoCodec());
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36322 // Any non-zero bitrate needed to be set before the first frame.
323 VideoBitrateAllocation bitrate_allocation;
324 bitrate_allocation.SetBitrate(0, 0, 500000);
325 encode_timer.OnSetRates(bitrate_allocation, 30);
326
Danil Chapovalov9c584832023-09-18 13:48:49327 image.SetRtpTimestamp(static_cast<uint32_t>(kTimestampMs * 90));
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36328 VideoFrame frame = VideoFrame::Builder()
329 .set_timestamp_ms(kTimestampMs)
330 .set_timestamp_rtp(kTimestampMs * 90)
331 .set_rotation(kVideoRotation_180)
332 .set_video_frame_buffer(kFrameBuffer)
333 .build();
334 encode_timer.OnEncodeStarted(frame);
335 encode_timer.FillTimingInfo(0, &image);
336 EXPECT_EQ(kVideoRotation_180, image.rotation_);
337}
338
Mirta Dvornicic28f0eb22019-05-28 14:30:16339TEST(FrameEncodeMetadataWriterTest, SetsContentType) {
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36340 EncodedImage image;
341 const int64_t kTimestampMs = 123456;
342 FakeEncodedImageCallback sink;
343
344 FrameEncodeMetadataWriter encode_timer(&sink);
345 VideoCodec codec;
346 codec.mode = VideoCodecMode::kScreensharing;
Niels Möller13d16362021-11-16 10:39:27347 encode_timer.OnEncoderInit(codec);
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36348 // Any non-zero bitrate needed to be set before the first frame.
349 VideoBitrateAllocation bitrate_allocation;
350 bitrate_allocation.SetBitrate(0, 0, 500000);
351 encode_timer.OnSetRates(bitrate_allocation, 30);
352
Danil Chapovalov9c584832023-09-18 13:48:49353 image.SetRtpTimestamp(static_cast<uint32_t>(kTimestampMs * 90));
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36354 VideoFrame frame = VideoFrame::Builder()
355 .set_timestamp_ms(kTimestampMs)
356 .set_timestamp_rtp(kTimestampMs * 90)
357 .set_rotation(kVideoRotation_180)
358 .set_video_frame_buffer(kFrameBuffer)
359 .build();
360 encode_timer.OnEncodeStarted(frame);
361 encode_timer.FillTimingInfo(0, &image);
362 EXPECT_EQ(VideoContentType::SCREENSHARE, image.content_type_);
363}
364
Mirta Dvornicic28f0eb22019-05-28 14:30:16365TEST(FrameEncodeMetadataWriterTest, CopiesColorSpace) {
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36366 EncodedImage image;
367 const int64_t kTimestampMs = 123456;
368 FakeEncodedImageCallback sink;
369
370 FrameEncodeMetadataWriter encode_timer(&sink);
Niels Möller13d16362021-11-16 10:39:27371 encode_timer.OnEncoderInit(VideoCodec());
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36372 // Any non-zero bitrate needed to be set before the first frame.
373 VideoBitrateAllocation bitrate_allocation;
374 bitrate_allocation.SetBitrate(0, 0, 500000);
375 encode_timer.OnSetRates(bitrate_allocation, 30);
376
377 webrtc::ColorSpace color_space =
378 CreateTestColorSpace(/*with_hdr_metadata=*/true);
Danil Chapovalov9c584832023-09-18 13:48:49379 image.SetRtpTimestamp(static_cast<uint32_t>(kTimestampMs * 90));
Ilya Nikolaevskiy2ebf5232019-05-13 14:13:36380 VideoFrame frame = VideoFrame::Builder()
381 .set_timestamp_ms(kTimestampMs)
382 .set_timestamp_rtp(kTimestampMs * 90)
383 .set_color_space(color_space)
384 .set_video_frame_buffer(kFrameBuffer)
385 .build();
386 encode_timer.OnEncodeStarted(frame);
387 encode_timer.FillTimingInfo(0, &image);
388 ASSERT_NE(image.ColorSpace(), nullptr);
389 EXPECT_EQ(color_space, *image.ColorSpace());
390}
391
Chen Xingf00bf422019-06-20 08:05:55392TEST(FrameEncodeMetadataWriterTest, CopiesPacketInfos) {
393 EncodedImage image;
394 const int64_t kTimestampMs = 123456;
395 FakeEncodedImageCallback sink;
396
397 FrameEncodeMetadataWriter encode_timer(&sink);
Niels Möller13d16362021-11-16 10:39:27398 encode_timer.OnEncoderInit(VideoCodec());
Chen Xingf00bf422019-06-20 08:05:55399 // Any non-zero bitrate needed to be set before the first frame.
400 VideoBitrateAllocation bitrate_allocation;
401 bitrate_allocation.SetBitrate(0, 0, 500000);
402 encode_timer.OnSetRates(bitrate_allocation, 30);
403
404 RtpPacketInfos packet_infos = CreatePacketInfos(3);
Danil Chapovalov9c584832023-09-18 13:48:49405 image.SetRtpTimestamp(static_cast<uint32_t>(kTimestampMs * 90));
Chen Xingf00bf422019-06-20 08:05:55406 VideoFrame frame = VideoFrame::Builder()
407 .set_timestamp_ms(kTimestampMs)
408 .set_timestamp_rtp(kTimestampMs * 90)
409 .set_packet_infos(packet_infos)
410 .set_video_frame_buffer(kFrameBuffer)
411 .build();
412 encode_timer.OnEncodeStarted(frame);
413 encode_timer.FillTimingInfo(0, &image);
414 EXPECT_EQ(image.PacketInfos().size(), 3U);
415}
416
Mirta Dvornicic28f0eb22019-05-28 14:30:16417TEST(FrameEncodeMetadataWriterTest, DoesNotRewriteBitstreamWithoutCodecInfo) {
418 uint8_t buffer[] = {1, 2, 3};
Niels Möller12f465c2020-09-23 10:45:17419 auto image_buffer = EncodedImageBuffer::Create(buffer, sizeof(buffer));
420 EncodedImage image;
421 image.SetEncodedData(image_buffer);
Mirta Dvornicic28f0eb22019-05-28 14:30:16422
423 FakeEncodedImageCallback sink;
424 FrameEncodeMetadataWriter encode_metadata_writer(&sink);
Danil Chapovalov6d008a82020-07-22 17:49:36425 encode_metadata_writer.UpdateBitstream(nullptr, &image);
Niels Möller12f465c2020-09-23 10:45:17426 EXPECT_EQ(image.GetEncodedData(), image_buffer);
Mirta Dvornicic28f0eb22019-05-28 14:30:16427 EXPECT_EQ(image.size(), sizeof(buffer));
428}
429
430TEST(FrameEncodeMetadataWriterTest, DoesNotRewriteVp8Bitstream) {
431 uint8_t buffer[] = {1, 2, 3};
Niels Möller12f465c2020-09-23 10:45:17432 auto image_buffer = EncodedImageBuffer::Create(buffer, sizeof(buffer));
433 EncodedImage image;
434 image.SetEncodedData(image_buffer);
Mirta Dvornicic28f0eb22019-05-28 14:30:16435 CodecSpecificInfo codec_specific_info;
436 codec_specific_info.codecType = kVideoCodecVP8;
Mirta Dvornicic28f0eb22019-05-28 14:30:16437
438 FakeEncodedImageCallback sink;
439 FrameEncodeMetadataWriter encode_metadata_writer(&sink);
Danil Chapovalov6d008a82020-07-22 17:49:36440 encode_metadata_writer.UpdateBitstream(&codec_specific_info, &image);
Niels Möller12f465c2020-09-23 10:45:17441 EXPECT_EQ(image.GetEncodedData(), image_buffer);
Mirta Dvornicic28f0eb22019-05-28 14:30:16442 EXPECT_EQ(image.size(), sizeof(buffer));
443}
444
445TEST(FrameEncodeMetadataWriterTest, RewritesH264BitstreamWithNonOptimalSps) {
Niels Möller12f465c2020-09-23 10:45:17446 const uint8_t kOriginalSps[] = {0, 0, 0, 1, H264::NaluType::kSps,
447 0x00, 0x00, 0x03, 0x03, 0xF4,
448 0x05, 0x03, 0xC7, 0xC0};
Mirta Dvornicic28f0eb22019-05-28 14:30:16449 const uint8_t kRewrittenSps[] = {0, 0, 0, 1, H264::NaluType::kSps,
450 0x00, 0x00, 0x03, 0x03, 0xF4,
451 0x05, 0x03, 0xC7, 0xE0, 0x1B,
452 0x41, 0x10, 0x8D, 0x00};
453
Niels Möller12f465c2020-09-23 10:45:17454 EncodedImage image;
455 image.SetEncodedData(
456 EncodedImageBuffer::Create(kOriginalSps, sizeof(kOriginalSps)));
Mirta Dvornicic28f0eb22019-05-28 14:30:16457 image._frameType = VideoFrameType::kVideoFrameKey;
458
459 CodecSpecificInfo codec_specific_info;
460 codec_specific_info.codecType = kVideoCodecH264;
461
Mirta Dvornicic28f0eb22019-05-28 14:30:16462 FakeEncodedImageCallback sink;
463 FrameEncodeMetadataWriter encode_metadata_writer(&sink);
Danil Chapovalov6d008a82020-07-22 17:49:36464 encode_metadata_writer.UpdateBitstream(&codec_specific_info, &image);
Mirta Dvornicic28f0eb22019-05-28 14:30:16465
Mirta Dvornicic28f0eb22019-05-28 14:30:16466 EXPECT_THAT(std::vector<uint8_t>(image.data(), image.data() + image.size()),
467 testing::ElementsAreArray(kRewrittenSps));
Mirta Dvornicic28f0eb22019-05-28 14:30:16468}
469
ilnik04f4d122017-06-19 14:18:55470} // namespace test
471} // namespace webrtc