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

Side by Side Diff: webrtc/modules/video_coding/codecs/test/videoprocessor.cc

Issue 2995513002: Minor improvements to VideoProcessor and corresponding test. (Closed)
Patch Set: Created 3 years, 4 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
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h" 11 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h"
12 12
13 #include <string.h> 13 #include <string.h>
14 14
15 #include <limits> 15 #include <limits>
16 #include <memory> 16 #include <memory>
17 #include <utility> 17 #include <utility>
18 #include <vector> 18 #include <vector>
19 19
20 #include "webrtc/api/video/i420_buffer.h" 20 #include "webrtc/api/video/i420_buffer.h"
21 #include "webrtc/common_types.h" 21 #include "webrtc/common_types.h"
22 #include "webrtc/modules/video_coding/codecs/vp8/simulcast_rate_allocator.h" 22 #include "webrtc/modules/video_coding/codecs/vp8/simulcast_rate_allocator.h"
23 #include "webrtc/modules/video_coding/include/video_codec_initializer.h" 23 #include "webrtc/modules/video_coding/include/video_codec_initializer.h"
24 #include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h" 24 #include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h"
25 #include "webrtc/rtc_base/checks.h" 25 #include "webrtc/rtc_base/checks.h"
26 #include "webrtc/rtc_base/logging.h"
26 #include "webrtc/rtc_base/timeutils.h" 27 #include "webrtc/rtc_base/timeutils.h"
27 #include "webrtc/system_wrappers/include/cpu_info.h" 28 #include "webrtc/system_wrappers/include/cpu_info.h"
28 29
29 namespace webrtc { 30 namespace webrtc {
30 namespace test { 31 namespace test {
31 32
32 namespace { 33 namespace {
33 34
34 // TODO(brandtr): Update this to use the real frame rate. 35 const int kRtpClockRateHz = 90000;
35 const int k90khzTimestampFrameDiff = 3000; // Assuming 30 fps.
36
37 // Use the frame number as the basis for timestamp to identify frames. Let the
38 // first timestamp be non-zero, to not make the IvfFileWriter believe that we
39 // want to use capture timestamps in the IVF files.
40 uint32_t FrameNumberToTimestamp(int frame_number) {
41 RTC_DCHECK_GE(frame_number, 0);
42 return (frame_number + 1) * k90khzTimestampFrameDiff;
43 }
44
45 int TimestampToFrameNumber(uint32_t timestamp) {
46 RTC_DCHECK_GT(timestamp, 0);
47 RTC_DCHECK_EQ(timestamp % k90khzTimestampFrameDiff, 0);
48 return (timestamp / k90khzTimestampFrameDiff) - 1;
49 }
50 36
51 std::unique_ptr<VideoBitrateAllocator> CreateBitrateAllocator( 37 std::unique_ptr<VideoBitrateAllocator> CreateBitrateAllocator(
52 const TestConfig& config) { 38 const TestConfig& config) {
53 std::unique_ptr<TemporalLayersFactory> tl_factory; 39 std::unique_ptr<TemporalLayersFactory> tl_factory;
54 if (config.codec_settings->codecType == VideoCodecType::kVideoCodecVP8) { 40 if (config.codec_settings->codecType == VideoCodecType::kVideoCodecVP8) {
55 tl_factory.reset(new TemporalLayersFactory()); 41 tl_factory.reset(new TemporalLayersFactory());
56 config.codec_settings->VP8()->tl_factory = tl_factory.get(); 42 config.codec_settings->VP8()->tl_factory = tl_factory.get();
57 } 43 }
58 return std::unique_ptr<VideoBitrateAllocator>( 44 return std::unique_ptr<VideoBitrateAllocator>(
59 VideoCodecInitializer::CreateBitrateAllocator(*config.codec_settings, 45 VideoCodecInitializer::CreateBitrateAllocator(*config.codec_settings,
60 std::move(tl_factory))); 46 std::move(tl_factory)));
61 } 47 }
62 48
63 void PrintCodecSettings(const VideoCodec* config) { 49 void PrintCodecSettings(const VideoCodec* codec_settings) {
64 printf(" Start bitrate : %d kbps\n", config->startBitrate); 50 RTC_DCHECK(codec_settings);
65 printf(" Width : %d\n", config->width); 51 printf(" Codec settings:\n");
66 printf(" Height : %d\n", config->height); 52 printf(" Start bitrate : %d kbps\n", codec_settings->startBitrate);
67 printf(" Codec type : %s\n", 53 printf(" Max bitrate : %d kbps\n", codec_settings->maxBitrate);
68 CodecTypeToPayloadName(config->codecType).value_or("Unknown")); 54 printf(" Min bitrate : %d kbps\n", codec_settings->minBitrate);
åsapersson 2017/08/07 08:30:10 Update plot_webrtc_test_logs.py accordingly?
brandtr 2017/08/07 09:21:45 I had misread the "codec implementation name" fiel
69 if (config->codecType == kVideoCodecVP8) { 55 printf(" Width : %d\n", codec_settings->width);
70 printf(" Denoising : %d\n", config->VP8().denoisingOn); 56 printf(" Height : %d\n", codec_settings->height);
71 printf(" Error concealment: %d\n", config->VP8().errorConcealmentOn); 57 printf(" Max frame rate : %d\n", codec_settings->maxFramerate);
72 printf(" Frame dropping : %d\n", config->VP8().frameDroppingOn); 58 printf(" QPmax : %d\n", codec_settings->qpMax);
73 printf(" Resilience : %d\n", config->VP8().resilience); 59 if (codec_settings->codecType == kVideoCodecVP8) {
74 } else if (config->codecType == kVideoCodecVP9) { 60 printf(" Complexity : %d\n", codec_settings->VP8().complexity);
75 printf(" Denoising : %d\n", config->VP9().denoisingOn); 61 printf(" Denoising : %d\n", codec_settings->VP8().denoisingOn);
76 printf(" Frame dropping : %d\n", config->VP9().frameDroppingOn); 62 printf(" Error concealment : %d\n",
77 printf(" Resilience : %d\n", config->VP9().resilienceOn); 63 codec_settings->VP8().errorConcealmentOn);
64 printf(" Frame dropping : %d\n", codec_settings->VP8().frameDroppingOn);
65 printf(" Resilience : %d\n", codec_settings->VP8().resilience);
66 printf(" Key frame interval: %d\n",
67 codec_settings->VP8().keyFrameInterval);
68 } else if (codec_settings->codecType == kVideoCodecVP9) {
69 printf(" Complexity : %d\n", codec_settings->VP9().complexity);
70 printf(" Denoising : %d\n", codec_settings->VP9().denoisingOn);
71 printf(" Frame dropping : %d\n", codec_settings->VP9().frameDroppingOn);
72 printf(" Resilience : %d\n", codec_settings->VP9().resilienceOn);
73 printf(" Key frame interval: %d\n",
74 codec_settings->VP9().keyFrameInterval);
75 printf(" Adaptive QP mode : %d\n", codec_settings->VP9().adaptiveQpMode);
76 } else if (codec_settings->codecType == kVideoCodecH264) {
77 printf(" Frame dropping : %d\n",
78 codec_settings->H264().frameDroppingOn);
79 printf(" Key frame interval: %d\n",
80 codec_settings->H264().keyFrameInterval);
81 printf(" Profile : %d\n", codec_settings->H264().profile);
78 } 82 }
79 } 83 }
80 84
81 int GetElapsedTimeMicroseconds(int64_t start_ns, int64_t stop_ns) { 85 int GetElapsedTimeMicroseconds(int64_t start_ns, int64_t stop_ns) {
82 int64_t diff_us = (stop_ns - start_ns) / rtc::kNumNanosecsPerMicrosec; 86 int64_t diff_us = (stop_ns - start_ns) / rtc::kNumNanosecsPerMicrosec;
83 RTC_DCHECK_GE(diff_us, std::numeric_limits<int>::min()); 87 RTC_DCHECK_GE(diff_us, std::numeric_limits<int>::min());
84 RTC_DCHECK_LE(diff_us, std::numeric_limits<int>::max()); 88 RTC_DCHECK_LE(diff_us, std::numeric_limits<int>::max());
85 return static_cast<int>(diff_us); 89 return static_cast<int>(diff_us);
86 } 90 }
87 91
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 num_spatial_resizes_(0) { 135 num_spatial_resizes_(0) {
132 RTC_DCHECK(encoder); 136 RTC_DCHECK(encoder);
133 RTC_DCHECK(decoder); 137 RTC_DCHECK(decoder);
134 RTC_DCHECK(packet_manipulator); 138 RTC_DCHECK(packet_manipulator);
135 RTC_DCHECK(analysis_frame_reader); 139 RTC_DCHECK(analysis_frame_reader);
136 RTC_DCHECK(analysis_frame_writer); 140 RTC_DCHECK(analysis_frame_writer);
137 RTC_DCHECK(stats); 141 RTC_DCHECK(stats);
138 frame_infos_.reserve(analysis_frame_reader->NumberOfFrames()); 142 frame_infos_.reserve(analysis_frame_reader->NumberOfFrames());
139 } 143 }
140 144
145 VideoProcessorImpl::~VideoProcessorImpl() {
146 encoder_->RegisterEncodeCompleteCallback(nullptr);
147 decoder_->RegisterDecodeCompleteCallback(nullptr);
148 }
149
141 void VideoProcessorImpl::Init() { 150 void VideoProcessorImpl::Init() {
142 RTC_DCHECK(!initialized_) << "VideoProcessor already initialized."; 151 RTC_DCHECK(!initialized_) << "VideoProcessor already initialized.";
152 RTC_DCHECK(config_.codec_settings) << "No codec settings supplied.";
143 initialized_ = true; 153 initialized_ = true;
144 154
145 // Setup required callbacks for the encoder/decoder. 155 // Setup required callbacks for the encoder and decoder.
146 RTC_CHECK_EQ(encoder_->RegisterEncodeCompleteCallback(encode_callback_.get()), 156 RTC_CHECK_EQ(encoder_->RegisterEncodeCompleteCallback(encode_callback_.get()),
147 WEBRTC_VIDEO_CODEC_OK) 157 WEBRTC_VIDEO_CODEC_OK)
148 << "Failed to register encode complete callback"; 158 << "Failed to register encode complete callback";
149 RTC_CHECK_EQ(decoder_->RegisterDecodeCompleteCallback(decode_callback_.get()), 159 RTC_CHECK_EQ(decoder_->RegisterDecodeCompleteCallback(decode_callback_.get()),
150 WEBRTC_VIDEO_CODEC_OK) 160 WEBRTC_VIDEO_CODEC_OK)
151 << "Failed to register decode complete callback"; 161 << "Failed to register decode complete callback";
152 162
153 // Initialize the encoder and decoder. 163 // Initialize the encoder and decoder.
154 uint32_t num_cores = 164 uint32_t num_cores =
155 config_.use_single_core ? 1 : CpuInfo::DetectNumberOfCores(); 165 config_.use_single_core ? 1 : CpuInfo::DetectNumberOfCores();
156 RTC_CHECK_EQ( 166 RTC_CHECK_EQ(
157 encoder_->InitEncode(config_.codec_settings, num_cores, 167 encoder_->InitEncode(config_.codec_settings, num_cores,
158 config_.networking_config.max_payload_size_in_bytes), 168 config_.networking_config.max_payload_size_in_bytes),
159 WEBRTC_VIDEO_CODEC_OK) 169 WEBRTC_VIDEO_CODEC_OK)
160 << "Failed to initialize VideoEncoder"; 170 << "Failed to initialize VideoEncoder";
161 171
162 RTC_CHECK_EQ(decoder_->InitDecode(config_.codec_settings, num_cores), 172 RTC_CHECK_EQ(decoder_->InitDecode(config_.codec_settings, num_cores),
163 WEBRTC_VIDEO_CODEC_OK) 173 WEBRTC_VIDEO_CODEC_OK)
164 << "Failed to initialize VideoDecoder"; 174 << "Failed to initialize VideoDecoder";
165 175
166 if (config_.verbose) { 176 if (config_.verbose) {
167 printf("Filename: %s\n", config_.filename.c_str());
168 printf("Video Processor:\n"); 177 printf("Video Processor:\n");
169 printf(" #CPU cores used : %d\n", num_cores); 178 printf(" Filename : %s\n", config_.filename.c_str());
170 printf(" Total # of frames: %d\n", 179 printf(" Total # of frames: %d\n",
171 analysis_frame_reader_->NumberOfFrames()); 180 analysis_frame_reader_->NumberOfFrames());
172 printf(" Codec settings:\n"); 181 printf(" # CPU cores used : %d\n", num_cores);
173 printf(" Encoder implementation name: %s\n", 182 const char* encoder_name = encoder_->ImplementationName();
174 encoder_->ImplementationName()); 183 printf(" Encoder implementation name: %s\n", encoder_name);
175 printf(" Decoder implementation name: %s\n", 184 const char* decoder_name = decoder_->ImplementationName();
176 decoder_->ImplementationName()); 185 printf(" Decoder implementation name: %s\n", decoder_name);
177 if (strcmp(encoder_->ImplementationName(), 186 if (strcmp(encoder_name, decoder_name) == 0) {
178 decoder_->ImplementationName()) == 0) { 187 printf(" Codec implementation name : %s_%s\n",
179 printf(" Codec implementation name: %s_%s\n",
180 CodecTypeToPayloadName(config_.codec_settings->codecType) 188 CodecTypeToPayloadName(config_.codec_settings->codecType)
181 .value_or("Unknown"), 189 .value_or("Unknown"),
182 encoder_->ImplementationName()); 190 encoder_->ImplementationName());
183 } 191 }
184 PrintCodecSettings(config_.codec_settings); 192 PrintCodecSettings(config_.codec_settings);
193 printf("\n");
185 } 194 }
186 } 195 }
187 196
188 VideoProcessorImpl::~VideoProcessorImpl() {
189 encoder_->RegisterEncodeCompleteCallback(nullptr);
190 decoder_->RegisterDecodeCompleteCallback(nullptr);
191 }
192
193 void VideoProcessorImpl::SetRates(int bit_rate, int frame_rate) {
194 int set_rates_result = encoder_->SetRateAllocation(
195 bitrate_allocator_->GetAllocation(bit_rate * 1000, frame_rate),
196 frame_rate);
197 RTC_DCHECK_GE(set_rates_result, 0)
198 << "Failed to update encoder with new rate " << bit_rate;
199 num_dropped_frames_ = 0;
200 num_spatial_resizes_ = 0;
201 }
202
203 size_t VideoProcessorImpl::EncodedFrameSize(int frame_number) {
204 RTC_DCHECK_LT(frame_number, frame_infos_.size());
205 return frame_infos_[frame_number].encoded_frame_size;
206 }
207
208 FrameType VideoProcessorImpl::EncodedFrameType(int frame_number) {
209 RTC_DCHECK_LT(frame_number, frame_infos_.size());
210 return frame_infos_[frame_number].encoded_frame_type;
211 }
212
213 int VideoProcessorImpl::GetQpFromEncoder(int frame_number) {
214 RTC_DCHECK_LT(frame_number, frame_infos_.size());
215 return frame_infos_[frame_number].qp_encoder;
216 }
217
218 int VideoProcessorImpl::GetQpFromBitstream(int frame_number) {
219 RTC_DCHECK_LT(frame_number, frame_infos_.size());
220 return frame_infos_[frame_number].qp_bitstream;
221 }
222
223 int VideoProcessorImpl::NumberDroppedFrames() {
224 return num_dropped_frames_;
225 }
226
227 int VideoProcessorImpl::NumberSpatialResizes() {
228 return num_spatial_resizes_;
229 }
230
231 bool VideoProcessorImpl::ProcessFrame(int frame_number) { 197 bool VideoProcessorImpl::ProcessFrame(int frame_number) {
232 RTC_DCHECK_GE(frame_number, 0); 198 RTC_DCHECK_GE(frame_number, 0);
233 RTC_DCHECK_LE(frame_number, frame_infos_.size()) 199 RTC_DCHECK_LE(frame_number, frame_infos_.size())
234 << "Must process frames without gaps."; 200 << "Must process frames without gaps.";
235 RTC_DCHECK(initialized_) << "VideoProcessor not initialized."; 201 RTC_DCHECK(initialized_) << "VideoProcessor not initialized.";
236 202
237 rtc::scoped_refptr<I420BufferInterface> buffer( 203 rtc::scoped_refptr<I420BufferInterface> buffer(
238 analysis_frame_reader_->ReadFrame()); 204 analysis_frame_reader_->ReadFrame());
239 205
240 if (!buffer) { 206 if (!buffer) {
(...skipping 29 matching lines...) Expand all
270 // Create frame statistics object used for aggregation at end of test run. 236 // Create frame statistics object used for aggregation at end of test run.
271 FrameStatistic* frame_stat = &stats_->NewFrame(frame_number); 237 FrameStatistic* frame_stat = &stats_->NewFrame(frame_number);
272 238
273 // For the highest measurement accuracy of the encode time, the start/stop 239 // For the highest measurement accuracy of the encode time, the start/stop
274 // time recordings should wrap the Encode call as tightly as possible. 240 // time recordings should wrap the Encode call as tightly as possible.
275 frame_info->encode_start_ns = rtc::TimeNanos(); 241 frame_info->encode_start_ns = rtc::TimeNanos();
276 frame_stat->encode_return_code = 242 frame_stat->encode_return_code =
277 encoder_->Encode(source_frame, nullptr, &frame_types); 243 encoder_->Encode(source_frame, nullptr, &frame_types);
278 244
279 if (frame_stat->encode_return_code != WEBRTC_VIDEO_CODEC_OK) { 245 if (frame_stat->encode_return_code != WEBRTC_VIDEO_CODEC_OK) {
280 fprintf(stderr, "Failed to encode frame %d, return code: %d\n", 246 LOG(LS_WARNING) << "Failed to encode frame " << frame_number
281 frame_number, frame_stat->encode_return_code); 247 << ", return code: " << frame_stat->encode_return_code
248 << ".";
282 } 249 }
283 250
284 return true; 251 return true;
285 } 252 }
286 253
254 void VideoProcessorImpl::SetRates(int bit_rate, int frame_rate) {
255 config_.codec_settings->maxFramerate = frame_rate;
256 int set_rates_result = encoder_->SetRateAllocation(
257 bitrate_allocator_->GetAllocation(bit_rate * 1000, frame_rate),
258 frame_rate);
259 RTC_DCHECK_GE(set_rates_result, 0)
260 << "Failed to update encoder with new rate " << bit_rate;
261 num_dropped_frames_ = 0;
262 num_spatial_resizes_ = 0;
263 }
264
265 size_t VideoProcessorImpl::EncodedFrameSize(int frame_number) {
266 RTC_DCHECK_LT(frame_number, frame_infos_.size());
267 return frame_infos_[frame_number].encoded_frame_size;
268 }
269
270 FrameType VideoProcessorImpl::EncodedFrameType(int frame_number) {
271 RTC_DCHECK_LT(frame_number, frame_infos_.size());
272 return frame_infos_[frame_number].encoded_frame_type;
273 }
274
275 int VideoProcessorImpl::GetQpFromEncoder(int frame_number) {
276 RTC_DCHECK_LT(frame_number, frame_infos_.size());
277 return frame_infos_[frame_number].qp_encoder;
278 }
279
280 int VideoProcessorImpl::GetQpFromBitstream(int frame_number) {
281 RTC_DCHECK_LT(frame_number, frame_infos_.size());
282 return frame_infos_[frame_number].qp_bitstream;
283 }
284
285 int VideoProcessorImpl::NumberDroppedFrames() {
286 return num_dropped_frames_;
287 }
288
289 int VideoProcessorImpl::NumberSpatialResizes() {
290 return num_spatial_resizes_;
291 }
292
287 void VideoProcessorImpl::FrameEncoded( 293 void VideoProcessorImpl::FrameEncoded(
288 webrtc::VideoCodecType codec, 294 webrtc::VideoCodecType codec,
289 const EncodedImage& encoded_image, 295 const EncodedImage& encoded_image,
290 const webrtc::RTPFragmentationHeader* fragmentation) { 296 const webrtc::RTPFragmentationHeader* fragmentation) {
291 // For the highest measurement accuracy of the encode time, the start/stop 297 // For the highest measurement accuracy of the encode time, the start/stop
292 // time recordings should wrap the Encode call as tightly as possible. 298 // time recordings should wrap the Encode call as tightly as possible.
293 int64_t encode_stop_ns = rtc::TimeNanos(); 299 int64_t encode_stop_ns = rtc::TimeNanos();
294 300
295 if (encoded_frame_writer_) { 301 if (encoded_frame_writer_) {
296 RTC_CHECK(encoded_frame_writer_->WriteFrame(encoded_image, codec)); 302 RTC_CHECK(encoded_frame_writer_->WriteFrame(encoded_image, codec));
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 RTC_DCHECK_EQ(extracted_length, analysis_frame_writer_->FrameLength()); 487 RTC_DCHECK_EQ(extracted_length, analysis_frame_writer_->FrameLength());
482 RTC_CHECK(analysis_frame_writer_->WriteFrame(extracted_buffer.data())); 488 RTC_CHECK(analysis_frame_writer_->WriteFrame(extracted_buffer.data()));
483 if (decoded_frame_writer_) { 489 if (decoded_frame_writer_) {
484 RTC_DCHECK_EQ(extracted_length, decoded_frame_writer_->FrameLength()); 490 RTC_DCHECK_EQ(extracted_length, decoded_frame_writer_->FrameLength());
485 RTC_CHECK(decoded_frame_writer_->WriteFrame(extracted_buffer.data())); 491 RTC_CHECK(decoded_frame_writer_->WriteFrame(extracted_buffer.data()));
486 } 492 }
487 493
488 last_decoded_frame_buffer_ = std::move(extracted_buffer); 494 last_decoded_frame_buffer_ = std::move(extracted_buffer);
489 } 495 }
490 496
497 uint32_t VideoProcessorImpl::FrameNumberToTimestamp(int frame_number) {
498 RTC_DCHECK_GE(frame_number, 0);
499 const int ticks_per_frame =
500 kRtpClockRateHz / config_.codec_settings->maxFramerate;
501 return (frame_number + 1) * ticks_per_frame;
502 }
503
504 int VideoProcessorImpl::TimestampToFrameNumber(uint32_t timestamp) {
505 RTC_DCHECK_GT(timestamp, 0);
506 const int ticks_per_frame =
507 kRtpClockRateHz / config_.codec_settings->maxFramerate;
508 RTC_DCHECK_EQ(timestamp % ticks_per_frame, 0);
509 return (timestamp / ticks_per_frame) - 1;
510 }
511
491 } // namespace test 512 } // namespace test
492 } // namespace webrtc 513 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698