OLD | NEW |
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 <assert.h> |
13 #include <string.h> | 14 #include <string.h> |
14 | 15 |
15 #include <limits> | 16 #include <limits> |
16 #include <memory> | 17 #include <memory> |
17 #include <utility> | |
18 #include <vector> | 18 #include <vector> |
19 | 19 |
20 #include "webrtc/base/checks.h" | |
21 #include "webrtc/base/timeutils.h" | 20 #include "webrtc/base/timeutils.h" |
22 #include "webrtc/modules/video_coding/include/video_codec_initializer.h" | |
23 #include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h" | |
24 #include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h" | |
25 #include "webrtc/system_wrappers/include/cpu_info.h" | 21 #include "webrtc/system_wrappers/include/cpu_info.h" |
26 | 22 |
27 namespace webrtc { | 23 namespace webrtc { |
28 namespace test { | 24 namespace test { |
29 | 25 |
30 TestConfig::TestConfig() | 26 TestConfig::TestConfig() |
31 : name(""), | 27 : name(""), |
32 description(""), | 28 description(""), |
33 test_number(0), | 29 test_number(0), |
34 input_filename(""), | 30 input_filename(""), |
35 output_filename(""), | 31 output_filename(""), |
36 output_dir("out"), | 32 output_dir("out"), |
37 networking_config(), | 33 networking_config(), |
38 exclude_frame_types(kExcludeOnlyFirstKeyFrame), | 34 exclude_frame_types(kExcludeOnlyFirstKeyFrame), |
39 frame_length_in_bytes(0), | 35 frame_length_in_bytes(0), |
40 use_single_core(false), | 36 use_single_core(false), |
41 keyframe_interval(0), | 37 keyframe_interval(0), |
42 codec_settings(nullptr), | 38 codec_settings(NULL), |
43 verbose(true) {} | 39 verbose(true) {} |
44 | 40 |
45 TestConfig::~TestConfig() {} | 41 TestConfig::~TestConfig() {} |
46 | 42 |
47 VideoProcessorImpl::VideoProcessorImpl(webrtc::VideoEncoder* encoder, | 43 VideoProcessorImpl::VideoProcessorImpl(webrtc::VideoEncoder* encoder, |
48 webrtc::VideoDecoder* decoder, | 44 webrtc::VideoDecoder* decoder, |
49 FrameReader* frame_reader, | 45 FrameReader* frame_reader, |
50 FrameWriter* frame_writer, | 46 FrameWriter* frame_writer, |
51 PacketManipulator* packet_manipulator, | 47 PacketManipulator* packet_manipulator, |
52 const TestConfig& config, | 48 const TestConfig& config, |
53 Stats* stats) | 49 Stats* stats) |
54 : encoder_(encoder), | 50 : encoder_(encoder), |
55 decoder_(decoder), | 51 decoder_(decoder), |
56 frame_reader_(frame_reader), | 52 frame_reader_(frame_reader), |
57 frame_writer_(frame_writer), | 53 frame_writer_(frame_writer), |
58 packet_manipulator_(packet_manipulator), | 54 packet_manipulator_(packet_manipulator), |
59 config_(config), | 55 config_(config), |
60 stats_(stats), | 56 stats_(stats), |
61 encode_callback_(nullptr), | 57 encode_callback_(NULL), |
62 decode_callback_(nullptr), | 58 decode_callback_(NULL), |
63 last_successful_frame_buffer_(nullptr), | |
64 first_key_frame_has_been_excluded_(false), | 59 first_key_frame_has_been_excluded_(false), |
65 last_frame_missing_(false), | 60 last_frame_missing_(false), |
66 initialized_(false), | 61 initialized_(false), |
67 encoded_frame_size_(0), | 62 encoded_frame_size_(0), |
68 encoded_frame_type_(kVideoFrameKey), | 63 encoded_frame_type_(kVideoFrameKey), |
69 prev_time_stamp_(0), | 64 prev_time_stamp_(0), |
70 num_dropped_frames_(0), | 65 num_dropped_frames_(0), |
71 num_spatial_resizes_(0), | 66 num_spatial_resizes_(0), |
72 last_encoder_frame_width_(0), | 67 last_encoder_frame_width_(0), |
73 last_encoder_frame_height_(0), | 68 last_encoder_frame_height_(0) { |
74 bit_rate_factor_(0.0), | 69 assert(encoder); |
75 encode_start_ns_(0), | 70 assert(decoder); |
76 decode_start_ns_(0) { | 71 assert(frame_reader); |
77 std::unique_ptr<TemporalLayersFactory> tl_factory; | 72 assert(frame_writer); |
78 if (config_.codec_settings->codecType == VideoCodecType::kVideoCodecVP8) { | 73 assert(packet_manipulator); |
79 tl_factory.reset(new TemporalLayersFactory()); | 74 assert(stats); |
80 config.codec_settings->VP8()->tl_factory = tl_factory.get(); | |
81 } | |
82 bitrate_allocator_ = VideoCodecInitializer::CreateBitrateAllocator( | |
83 *config.codec_settings, std::move(tl_factory)); | |
84 RTC_DCHECK(encoder); | |
85 RTC_DCHECK(decoder); | |
86 RTC_DCHECK(frame_reader); | |
87 RTC_DCHECK(frame_writer); | |
88 RTC_DCHECK(packet_manipulator); | |
89 RTC_DCHECK(stats); | |
90 } | 75 } |
91 | 76 |
92 bool VideoProcessorImpl::Init() { | 77 bool VideoProcessorImpl::Init() { |
93 // Calculate a factor used for bit rate calculations: | 78 // Calculate a factor used for bit rate calculations: |
94 bit_rate_factor_ = config_.codec_settings->maxFramerate * 0.001 * 8; // bits | 79 bit_rate_factor_ = config_.codec_settings->maxFramerate * 0.001 * 8; // bits |
95 | 80 |
96 // Initialize data structures used by the encoder/decoder APIs | 81 // Initialize data structures used by the encoder/decoder APIs |
97 size_t frame_length_in_bytes = frame_reader_->FrameLength(); | 82 size_t frame_length_in_bytes = frame_reader_->FrameLength(); |
98 last_successful_frame_buffer_ = new uint8_t[frame_length_in_bytes]; | 83 last_successful_frame_buffer_ = new uint8_t[frame_length_in_bytes]; |
99 // Set fixed properties common for all frames. | 84 // Set fixed properties common for all frames. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 | 142 |
158 VideoProcessorImpl::~VideoProcessorImpl() { | 143 VideoProcessorImpl::~VideoProcessorImpl() { |
159 delete[] last_successful_frame_buffer_; | 144 delete[] last_successful_frame_buffer_; |
160 encoder_->RegisterEncodeCompleteCallback(NULL); | 145 encoder_->RegisterEncodeCompleteCallback(NULL); |
161 delete encode_callback_; | 146 delete encode_callback_; |
162 decoder_->RegisterDecodeCompleteCallback(NULL); | 147 decoder_->RegisterDecodeCompleteCallback(NULL); |
163 delete decode_callback_; | 148 delete decode_callback_; |
164 } | 149 } |
165 | 150 |
166 void VideoProcessorImpl::SetRates(int bit_rate, int frame_rate) { | 151 void VideoProcessorImpl::SetRates(int bit_rate, int frame_rate) { |
167 int set_rates_result = encoder_->SetRateAllocation( | 152 int set_rates_result = encoder_->SetRates(bit_rate, frame_rate); |
168 bitrate_allocator_->GetAllocation(bit_rate * 1000, frame_rate), | 153 assert(set_rates_result >= 0); |
169 frame_rate); | |
170 RTC_CHECK_GE(set_rates_result, 0); | |
171 if (set_rates_result < 0) { | 154 if (set_rates_result < 0) { |
172 fprintf(stderr, | 155 fprintf(stderr, |
173 "Failed to update encoder with new rate %d, " | 156 "Failed to update encoder with new rate %d, " |
174 "return code: %d\n", | 157 "return code: %d\n", |
175 bit_rate, set_rates_result); | 158 bit_rate, set_rates_result); |
176 } | 159 } |
177 num_dropped_frames_ = 0; | 160 num_dropped_frames_ = 0; |
178 num_spatial_resizes_ = 0; | 161 num_spatial_resizes_ = 0; |
179 } | 162 } |
180 | 163 |
181 size_t VideoProcessorImpl::EncodedFrameSize() { | 164 size_t VideoProcessorImpl::EncodedFrameSize() { |
182 return encoded_frame_size_; | 165 return encoded_frame_size_; |
183 } | 166 } |
184 | 167 |
185 FrameType VideoProcessorImpl::EncodedFrameType() { | 168 FrameType VideoProcessorImpl::EncodedFrameType() { |
186 return encoded_frame_type_; | 169 return encoded_frame_type_; |
187 } | 170 } |
188 | 171 |
189 int VideoProcessorImpl::NumberDroppedFrames() { | 172 int VideoProcessorImpl::NumberDroppedFrames() { |
190 return num_dropped_frames_; | 173 return num_dropped_frames_; |
191 } | 174 } |
192 | 175 |
193 int VideoProcessorImpl::NumberSpatialResizes() { | 176 int VideoProcessorImpl::NumberSpatialResizes() { |
194 return num_spatial_resizes_; | 177 return num_spatial_resizes_; |
195 } | 178 } |
196 | 179 |
197 bool VideoProcessorImpl::ProcessFrame(int frame_number) { | 180 bool VideoProcessorImpl::ProcessFrame(int frame_number) { |
198 RTC_DCHECK_GE(frame_number, 0); | 181 assert(frame_number >= 0); |
199 if (!initialized_) { | 182 if (!initialized_) { |
200 fprintf(stderr, "Attempting to use uninitialized VideoProcessor!\n"); | 183 fprintf(stderr, "Attempting to use uninitialized VideoProcessor!\n"); |
201 return false; | 184 return false; |
202 } | 185 } |
203 // |prev_time_stamp_| is used for getting number of dropped frames. | 186 // |prev_time_stamp_| is used for getting number of dropped frames. |
204 if (frame_number == 0) { | 187 if (frame_number == 0) { |
205 prev_time_stamp_ = -1; | 188 prev_time_stamp_ = -1; |
206 } | 189 } |
207 rtc::scoped_refptr<VideoFrameBuffer> buffer(frame_reader_->ReadFrame()); | 190 rtc::scoped_refptr<VideoFrameBuffer> buffer(frame_reader_->ReadFrame()); |
208 if (buffer) { | 191 if (buffer) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 case kExcludeOnlyFirstKeyFrame: | 265 case kExcludeOnlyFirstKeyFrame: |
283 if (!first_key_frame_has_been_excluded_) { | 266 if (!first_key_frame_has_been_excluded_) { |
284 first_key_frame_has_been_excluded_ = true; | 267 first_key_frame_has_been_excluded_ = true; |
285 exclude_this_frame = true; | 268 exclude_this_frame = true; |
286 } | 269 } |
287 break; | 270 break; |
288 case kExcludeAllKeyFrames: | 271 case kExcludeAllKeyFrames: |
289 exclude_this_frame = true; | 272 exclude_this_frame = true; |
290 break; | 273 break; |
291 default: | 274 default: |
292 RTC_NOTREACHED(); | 275 assert(false); |
293 } | 276 } |
294 } | 277 } |
295 | 278 |
296 // Make a raw copy of the |encoded_image| buffer. | 279 // Make a raw copy of the |encoded_image| buffer. |
297 size_t copied_buffer_size = encoded_image._length + | 280 size_t copied_buffer_size = encoded_image._length + |
298 EncodedImage::GetBufferPaddingBytes(codec); | 281 EncodedImage::GetBufferPaddingBytes(codec); |
299 std::unique_ptr<uint8_t[]> copied_buffer(new uint8_t[copied_buffer_size]); | 282 std::unique_ptr<uint8_t[]> copied_buffer(new uint8_t[copied_buffer_size]); |
300 memcpy(copied_buffer.get(), encoded_image._buffer, encoded_image._length); | 283 memcpy(copied_buffer.get(), encoded_image._buffer, encoded_image._length); |
301 // The image to feed to the decoder. | 284 // The image to feed to the decoder. |
302 EncodedImage copied_image; | 285 EncodedImage copied_image; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 config_.codec_settings->height)); | 334 config_.codec_settings->height)); |
352 | 335 |
353 // Should be the same aspect ratio, no cropping needed. | 336 // Should be the same aspect ratio, no cropping needed. |
354 up_image->ScaleFrom(image.video_frame_buffer()); | 337 up_image->ScaleFrom(image.video_frame_buffer()); |
355 | 338 |
356 // TODO(mikhal): Extracting the buffer for now - need to update test. | 339 // TODO(mikhal): Extracting the buffer for now - need to update test. |
357 size_t length = | 340 size_t length = |
358 CalcBufferSize(kI420, up_image->width(), up_image->height()); | 341 CalcBufferSize(kI420, up_image->width(), up_image->height()); |
359 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); | 342 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); |
360 int extracted_length = ExtractBuffer(up_image, length, image_buffer.get()); | 343 int extracted_length = ExtractBuffer(up_image, length, image_buffer.get()); |
361 RTC_DCHECK_GT(extracted_length, 0); | 344 assert(extracted_length > 0); |
362 // Update our copy of the last successful frame: | 345 // Update our copy of the last successful frame: |
363 memcpy(last_successful_frame_buffer_, image_buffer.get(), extracted_length); | 346 memcpy(last_successful_frame_buffer_, image_buffer.get(), extracted_length); |
364 bool write_success = frame_writer_->WriteFrame(image_buffer.get()); | 347 bool write_success = frame_writer_->WriteFrame(image_buffer.get()); |
365 RTC_DCHECK(write_success); | 348 assert(write_success); |
366 if (!write_success) { | 349 if (!write_success) { |
367 fprintf(stderr, "Failed to write frame %d to disk!", frame_number); | 350 fprintf(stderr, "Failed to write frame %d to disk!", frame_number); |
368 } | 351 } |
369 } else { // No resize. | 352 } else { // No resize. |
370 // Update our copy of the last successful frame: | 353 // Update our copy of the last successful frame: |
371 // TODO(mikhal): Add as a member function, so won't be allocated per frame. | 354 // TODO(mikhal): Add as a member function, so won't be allocated per frame. |
372 size_t length = CalcBufferSize(kI420, image.width(), image.height()); | 355 size_t length = CalcBufferSize(kI420, image.width(), image.height()); |
373 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); | 356 std::unique_ptr<uint8_t[]> image_buffer(new uint8_t[length]); |
374 int extracted_length = ExtractBuffer(image, length, image_buffer.get()); | 357 int extracted_length = ExtractBuffer(image, length, image_buffer.get()); |
375 RTC_DCHECK_GT(extracted_length, 0); | 358 assert(extracted_length > 0); |
376 memcpy(last_successful_frame_buffer_, image_buffer.get(), extracted_length); | 359 memcpy(last_successful_frame_buffer_, image_buffer.get(), extracted_length); |
377 | 360 |
378 bool write_success = frame_writer_->WriteFrame(image_buffer.get()); | 361 bool write_success = frame_writer_->WriteFrame(image_buffer.get()); |
379 RTC_DCHECK(write_success); | 362 assert(write_success); |
380 if (!write_success) { | 363 if (!write_success) { |
381 fprintf(stderr, "Failed to write frame %d to disk!", frame_number); | 364 fprintf(stderr, "Failed to write frame %d to disk!", frame_number); |
382 } | 365 } |
383 } | 366 } |
384 } | 367 } |
385 | 368 |
386 int VideoProcessorImpl::GetElapsedTimeMicroseconds(int64_t start, | 369 int VideoProcessorImpl::GetElapsedTimeMicroseconds(int64_t start, |
387 int64_t stop) { | 370 int64_t stop) { |
388 uint64_t encode_time = (stop - start) / rtc::kNumNanosecsPerMicrosec; | 371 uint64_t encode_time = (stop - start) / rtc::kNumNanosecsPerMicrosec; |
389 RTC_DCHECK_LT(encode_time, | 372 assert(encode_time < |
390 static_cast<unsigned int>(std::numeric_limits<int>::max())); | 373 static_cast<unsigned int>(std::numeric_limits<int>::max())); |
391 return static_cast<int>(encode_time); | 374 return static_cast<int>(encode_time); |
392 } | 375 } |
393 | 376 |
394 const char* ExcludeFrameTypesToStr(ExcludeFrameTypes e) { | 377 const char* ExcludeFrameTypesToStr(ExcludeFrameTypes e) { |
395 switch (e) { | 378 switch (e) { |
396 case kExcludeOnlyFirstKeyFrame: | 379 case kExcludeOnlyFirstKeyFrame: |
397 return "ExcludeOnlyFirstKeyFrame"; | 380 return "ExcludeOnlyFirstKeyFrame"; |
398 case kExcludeAllKeyFrames: | 381 case kExcludeAllKeyFrames: |
399 return "ExcludeAllKeyFrames"; | 382 return "ExcludeAllKeyFrames"; |
400 default: | 383 default: |
401 RTC_NOTREACHED(); | 384 assert(false); |
402 return "Unknown"; | 385 return "Unknown"; |
403 } | 386 } |
404 } | 387 } |
405 | 388 |
406 const char* VideoCodecTypeToStr(webrtc::VideoCodecType e) { | 389 const char* VideoCodecTypeToStr(webrtc::VideoCodecType e) { |
407 switch (e) { | 390 switch (e) { |
408 case kVideoCodecVP8: | 391 case kVideoCodecVP8: |
409 return "VP8"; | 392 return "VP8"; |
410 case kVideoCodecI420: | 393 case kVideoCodecI420: |
411 return "I420"; | 394 return "I420"; |
412 case kVideoCodecRED: | 395 case kVideoCodecRED: |
413 return "RED"; | 396 return "RED"; |
414 case kVideoCodecULPFEC: | 397 case kVideoCodecULPFEC: |
415 return "ULPFEC"; | 398 return "ULPFEC"; |
416 case kVideoCodecUnknown: | 399 case kVideoCodecUnknown: |
417 return "Unknown"; | 400 return "Unknown"; |
418 default: | 401 default: |
419 RTC_NOTREACHED(); | 402 assert(false); |
420 return "Unknown"; | 403 return "Unknown"; |
421 } | 404 } |
422 } | 405 } |
423 | 406 |
424 // Callbacks | 407 // Callbacks |
425 EncodedImageCallback::Result | 408 EncodedImageCallback::Result |
426 VideoProcessorImpl::VideoProcessorEncodeCompleteCallback::OnEncodedImage( | 409 VideoProcessorImpl::VideoProcessorEncodeCompleteCallback::OnEncodedImage( |
427 const EncodedImage& encoded_image, | 410 const EncodedImage& encoded_image, |
428 const webrtc::CodecSpecificInfo* codec_specific_info, | 411 const webrtc::CodecSpecificInfo* codec_specific_info, |
429 const webrtc::RTPFragmentationHeader* fragmentation) { | 412 const webrtc::RTPFragmentationHeader* fragmentation) { |
430 // Forward to parent class. | 413 // Forward to parent class. |
431 RTC_CHECK(codec_specific_info); | 414 RTC_CHECK(codec_specific_info); |
432 video_processor_->FrameEncoded(codec_specific_info->codecType, | 415 video_processor_->FrameEncoded(codec_specific_info->codecType, |
433 encoded_image, | 416 encoded_image, |
434 fragmentation); | 417 fragmentation); |
435 return Result(Result::OK, 0); | 418 return Result(Result::OK, 0); |
436 } | 419 } |
437 int32_t VideoProcessorImpl::VideoProcessorDecodeCompleteCallback::Decoded( | 420 int32_t VideoProcessorImpl::VideoProcessorDecodeCompleteCallback::Decoded( |
438 VideoFrame& image) { | 421 VideoFrame& image) { |
439 // Forward to parent class. | 422 // Forward to parent class. |
440 video_processor_->FrameDecoded(image); | 423 video_processor_->FrameDecoded(image); |
441 return 0; | 424 return 0; |
442 } | 425 } |
443 | 426 |
444 } // namespace test | 427 } // namespace test |
445 } // namespace webrtc | 428 } // namespace webrtc |
OLD | NEW |