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