Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(769)

Side by Side Diff: webrtc/modules/video_coding/generic_encoder_unittest.cc

Issue 2911193002: Implement timing frames. (Closed)
Patch Set: Implement Holmer@ comments Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2017 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 <vector>
12
13 #include "webrtc/modules/video_coding/encoded_frame.h"
14 #include "webrtc/modules/video_coding/generic_encoder.h"
15 #include "webrtc/modules/video_coding/include/video_coding_defines.h"
16 #include "webrtc/test/gtest.h"
17
18 namespace webrtc {
19 namespace test {
20 namespace {
21 inline size_t FrameSize(const size_t& min_frame_size,
22 const size_t& max_frame_size,
23 const int& s,
24 const int& i) {
25 return min_frame_size + (s + 1) * i % (max_frame_size - min_frame_size);
26 }
27
28 class FakeEncodedImageCallback : public EncodedImageCallback {
29 public:
30 FakeEncodedImageCallback() : last_frame_was_timing_(false) {}
31 Result OnEncodedImage(const EncodedImage& encoded_image,
32 const CodecSpecificInfo* codec_specific_info,
33 const RTPFragmentationHeader* fragmentation) override {
34 last_frame_was_timing_ = encoded_image.timing_.is_timing_frame;
35 return Result::OK;
36 };
37
38 bool WasTimingFrame() { return last_frame_was_timing_; }
39
40 private:
41 bool last_frame_was_timing_;
42 };
43
44 enum class FrameType {
45 kNormal,
46 kTiming,
47 kDropped,
48 };
49
50 // Emulates |num_frames| on |num_streams| frames with capture timestamps
51 // increased by 1 from 0. Size of each frame is between
52 // |min_frame_size| and |max_frame_size|, outliers are counted relatevely to
53 // |average_frame_sizes[]| for each stream.
54 std::vector<std::vector<FrameType>> GetTimingFrames(
55 const int64_t delay_ms,
56 const size_t min_frame_size,
57 const size_t max_frame_size,
58 std::vector<size_t> average_frame_sizes,
59 const int num_streams,
60 const int num_frames) {
61 FakeEncodedImageCallback sink;
62 VCMEncodedFrameCallback callback(&sink, nullptr);
63 const size_t kFramerate = 30;
64 callback.SetTimingFramesThresholds(
65 {delay_ms, kDefaultOutlierFrameSizePercent});
66 callback.OnFrameRateChanged(kFramerate);
67 int s, i;
68 std::vector<std::vector<FrameType>> result(num_streams);
69 for (s = 0; s < num_streams; ++s)
70 callback.OnTargetBitrateChanged(average_frame_sizes[s] * kFramerate, s);
71 int64_t current_timestamp = 0;
72 for (i = 0; i < num_frames; ++i) {
73 current_timestamp += 1;
74 for (s = 0; s < num_streams; ++s) {
75 // every (5+s)-th frame is dropped on s-th stream by design.
76 bool dropped = i % (5 + s) == 0;
77
78 EncodedImage image;
79 CodecSpecificInfo codec_specific;
80 image._length = FrameSize(min_frame_size, max_frame_size, s, i);
81 image.capture_time_ms_ = current_timestamp;
82 codec_specific.codecType = kVideoCodecGeneric;
83 codec_specific.codecSpecific.generic.simulcast_idx = s;
84 callback.OnEncodeStarted(current_timestamp, s);
85 if (dropped) {
86 result[s].push_back(FrameType::kDropped);
87 continue;
88 }
89 callback.OnEncodedImage(image, &codec_specific, nullptr);
90 if (sink.WasTimingFrame()) {
91 result[s].push_back(FrameType::kTiming);
92 } else {
93 result[s].push_back(FrameType::kNormal);
94 }
95 }
96 }
97 return result;
98 }
99 } // namespace
100
101 TEST(TestVCMEncodedFrameCallback, MarksTimingFramesPeriodicallyTogether) {
102 const int64_t kDelayMs = 29;
103 const size_t kMinFrameSize = 10;
104 const size_t kMaxFrameSize = 20;
105 const int kNumFrames = 1000;
106 const int kNumStreams = 3;
107 // No outliers as 1000 is larger than anything from range [10,20].
108 const std::vector<size_t> kAverageSize = {1000, 1000, 1000};
109 auto frames = GetTimingFrames(kDelayMs, kMinFrameSize, kMaxFrameSize,
110 kAverageSize, kNumStreams, kNumFrames);
111 // Timing frames should be tirggered every delayMs.
112 // As no outliers are expected, frames on all streams have to be
113 // marked together.
114 int last_timing_frame = -1;
115 for (int i = 0; i < kNumFrames; ++i) {
116 int num_normal = 0;
117 int num_timing = 0;
118 int num_dropped = 0;
119 for (int s = 0; s < kNumStreams; ++s) {
120 if (frames[s][i] == FrameType::kTiming) {
121 ++num_timing;
122 } else if (frames[s][i] == FrameType::kNormal) {
123 ++num_normal;
124 } else {
125 ++num_dropped;
126 }
127 }
128 // Can't have both normal and timing frames at the same timstamp.
129 EXPECT_TRUE(num_timing == 0 || num_normal == 0);
130 if (num_dropped < kNumStreams) {
131 if (last_timing_frame == -1 || i >= last_timing_frame + kDelayMs) {
132 // If didn't have timing frames for a period, current sent frame has to
133 // be one. No normal frames should be sent.
134 EXPECT_EQ(num_normal, 0);
135 } else {
136 // No unneeded timing frames should be sent.
137 EXPECT_EQ(num_timing, 0);
138 }
139 }
140 if (num_timing > 0)
141 last_timing_frame = i;
142 }
143 }
144
145 TEST(TestVCMEncodedFrameCallback, MarksOutliers) {
146 const int64_t kDelayMs = 29;
147 const size_t kMinFrameSize = 2495;
148 const size_t kMaxFrameSize = 2505;
149 const int kNumFrames = 1000;
150 const int kNumStreams = 3;
151 // Possible outliers as 1000 lies in range [995, 1005].
152 const std::vector<size_t> kAverageSize = {998, 1000, 1004};
153 auto frames = GetTimingFrames(kDelayMs, kMinFrameSize, kMaxFrameSize,
154 kAverageSize, kNumStreams, kNumFrames);
155 // All outliers should be marked.
156 for (int i = 0; i < kNumFrames; ++i) {
157 for (int s = 0; s < kNumStreams; ++s) {
158 if (FrameSize(kMinFrameSize, kMaxFrameSize, s, i) >=
159 kAverageSize[s] * kDefaultOutlierFrameSizePercent / 100) {
160 // Too big frame. May be dropped or timing, but not normal.
161 EXPECT_NE(frames[s][i], FrameType::kNormal);
162 }
163 }
164 }
165 }
166
167 } // namespace test
168 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/generic_encoder.cc ('k') | webrtc/modules/video_coding/include/video_coding_defines.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698