| 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 |