| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  *  Copyright (c) 2010 The WebRTC project authors. All Rights Reserved. | 2  *  Copyright (c) 2010 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/media/base/videoadapter.h" | 11 #include "webrtc/media/base/videoadapter.h" | 
| 12 | 12 | 
| 13 #include <algorithm> | 13 #include <algorithm> | 
|  | 14 #include <cstdlib> | 
| 14 #include <limits> | 15 #include <limits> | 
| 15 | 16 | 
| 16 #include "webrtc/base/checks.h" | 17 #include "webrtc/base/checks.h" | 
| 17 #include "webrtc/base/logging.h" | 18 #include "webrtc/base/logging.h" | 
| 18 #include "webrtc/media/base/mediaconstants.h" | 19 #include "webrtc/media/base/mediaconstants.h" | 
| 19 #include "webrtc/media/base/videocommon.h" | 20 #include "webrtc/media/base/videocommon.h" | 
| 20 | 21 | 
| 21 namespace { | 22 namespace { | 
| 22 | 23 | 
| 23 struct Fraction { | 24 struct Fraction { | 
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 111 | 112 | 
| 112 namespace cricket { | 113 namespace cricket { | 
| 113 | 114 | 
| 114 VideoAdapter::VideoAdapter() | 115 VideoAdapter::VideoAdapter() | 
| 115     : frames_in_(0), | 116     : frames_in_(0), | 
| 116       frames_out_(0), | 117       frames_out_(0), | 
| 117       frames_scaled_(0), | 118       frames_scaled_(0), | 
| 118       adaption_changes_(0), | 119       adaption_changes_(0), | 
| 119       previous_width_(0), | 120       previous_width_(0), | 
| 120       previous_height_(0), | 121       previous_height_(0), | 
| 121       input_interval_(0), |  | 
| 122       interval_next_frame_(0), |  | 
| 123       resolution_request_max_pixel_count_(std::numeric_limits<int>::max()), | 122       resolution_request_max_pixel_count_(std::numeric_limits<int>::max()), | 
| 124       resolution_request_max_pixel_count_step_up_(0) {} | 123       resolution_request_max_pixel_count_step_up_(0) {} | 
| 125 | 124 | 
| 126 VideoAdapter::~VideoAdapter() {} | 125 VideoAdapter::~VideoAdapter() {} | 
| 127 | 126 | 
| 128 void VideoAdapter::SetExpectedInputFrameInterval(int64_t interval) { | 127 bool VideoAdapter::KeepFrame(int64_t in_timestamp_ns) { | 
| 129   // TODO(perkj): Consider measuring input frame rate instead. |  | 
| 130   // Frame rate typically varies depending on lighting. |  | 
| 131   rtc::CritScope cs(&critical_section_); | 128   rtc::CritScope cs(&critical_section_); | 
| 132   input_interval_ = interval; | 129   if (!requested_format_ || requested_format_->interval == 0) | 
|  | 130     return true; | 
|  | 131 | 
|  | 132   if (next_frame_timestamp_ns_) { | 
|  | 133     // Time until next frame should be outputted. | 
|  | 134     const int64_t time_until_next_frame_ns = | 
|  | 135         (*next_frame_timestamp_ns_ - in_timestamp_ns); | 
|  | 136 | 
|  | 137     // Continue if timestamp is withing expected range. | 
|  | 138     if (std::abs(time_until_next_frame_ns) < 2 * requested_format_->interval) { | 
|  | 139       // Drop if a frame shouldn't be outputted yet. | 
|  | 140       if (time_until_next_frame_ns > 0) | 
|  | 141         return false; | 
|  | 142       // Time to output new frame. | 
|  | 143       *next_frame_timestamp_ns_ += requested_format_->interval; | 
|  | 144       return true; | 
|  | 145     } | 
|  | 146   } | 
|  | 147 | 
|  | 148   // First timestamp received or timestamp is way outside expected range, so | 
|  | 149   // reset. Set first timestamp target to just half the interval to prefer | 
|  | 150   // keeping frames in case of jitter. | 
|  | 151   next_frame_timestamp_ns_ = | 
|  | 152       rtc::Optional<int64_t>(in_timestamp_ns + requested_format_->interval / 2); | 
|  | 153   return true; | 
| 133 } | 154 } | 
| 134 | 155 | 
| 135 void VideoAdapter::AdaptFrameResolution(int in_width, | 156 void VideoAdapter::AdaptFrameResolution(int in_width, | 
| 136                                         int in_height, | 157                                         int in_height, | 
|  | 158                                         int64_t in_timestamp_ns, | 
| 137                                         int* cropped_width, | 159                                         int* cropped_width, | 
| 138                                         int* cropped_height, | 160                                         int* cropped_height, | 
| 139                                         int* out_width, | 161                                         int* out_width, | 
| 140                                         int* out_height) { | 162                                         int* out_height) { | 
| 141   rtc::CritScope cs(&critical_section_); | 163   rtc::CritScope cs(&critical_section_); | 
| 142   ++frames_in_; | 164   ++frames_in_; | 
| 143 | 165 | 
| 144   // The max output pixel count is the minimum of the requests from | 166   // The max output pixel count is the minimum of the requests from | 
| 145   // OnOutputFormatRequest and OnResolutionRequest. | 167   // OnOutputFormatRequest and OnResolutionRequest. | 
| 146   int max_pixel_count = resolution_request_max_pixel_count_; | 168   int max_pixel_count = resolution_request_max_pixel_count_; | 
| 147   if (requested_format_) { | 169   if (requested_format_) { | 
| 148     max_pixel_count = std::min( | 170     max_pixel_count = std::min( | 
| 149         max_pixel_count, requested_format_->width * requested_format_->height); | 171         max_pixel_count, requested_format_->width * requested_format_->height); | 
| 150   } | 172   } | 
| 151 | 173 | 
| 152   // Drop the input frame if necessary. | 174   // Drop the input frame if necessary. | 
| 153   bool should_drop = false; | 175   if (max_pixel_count == 0 || !KeepFrame(in_timestamp_ns)) { | 
| 154   if (max_pixel_count == 0) { |  | 
| 155     // Drop all frames as the output format is 0x0. |  | 
| 156     should_drop = true; |  | 
| 157   } else if (requested_format_ && requested_format_->interval > 0) { |  | 
| 158     // Drop some frames based on input fps and output fps. |  | 
| 159     // Normally output fps is less than input fps. |  | 
| 160     interval_next_frame_ += input_interval_; |  | 
| 161     if (interval_next_frame_ >= requested_format_->interval) { |  | 
| 162       interval_next_frame_ -= requested_format_->interval; |  | 
| 163       // Reset |interval_next_frame_| if it accumulates too much to avoid |  | 
| 164       // "catching up" behaviour. |  | 
| 165       if (interval_next_frame_ >= requested_format_->interval) |  | 
| 166         interval_next_frame_ = 0; |  | 
| 167     } else { |  | 
| 168       should_drop = true; |  | 
| 169     } |  | 
| 170   } |  | 
| 171   if (should_drop) { |  | 
| 172     // Show VAdapt log every 90 frames dropped. (3 seconds) | 176     // Show VAdapt log every 90 frames dropped. (3 seconds) | 
| 173     if ((frames_in_ - frames_out_) % 90 == 0) { | 177     if ((frames_in_ - frames_out_) % 90 == 0) { | 
| 174       // TODO(fbarchard): Reduce to LS_VERBOSE when adapter info is not needed | 178       // TODO(fbarchard): Reduce to LS_VERBOSE when adapter info is not needed | 
| 175       // in default calls. | 179       // in default calls. | 
| 176       LOG(LS_INFO) << "VAdapt Drop Frame: scaled " << frames_scaled_ | 180       LOG(LS_INFO) << "VAdapt Drop Frame: scaled " << frames_scaled_ | 
| 177                    << " / out " << frames_out_ | 181                    << " / out " << frames_out_ | 
| 178                    << " / in " << frames_in_ | 182                    << " / in " << frames_in_ | 
| 179                    << " Changes: " << adaption_changes_ | 183                    << " Changes: " << adaption_changes_ | 
| 180                    << " Input: " << in_width | 184                    << " Input: " << in_width | 
| 181                    << "x" << in_height | 185                    << "x" << in_height | 
| 182                    << " i" << input_interval_ | 186                    << " timestamp: " << in_timestamp_ns | 
| 183                    << " Output: i" | 187                    << " Output: i" | 
| 184                    << (requested_format_ ? requested_format_->interval : 0); | 188                    << (requested_format_ ? requested_format_->interval : 0); | 
| 185     } | 189     } | 
| 186 | 190 | 
| 187     // Drop frame. | 191     // Drop frame. | 
| 188     *cropped_width = 0; | 192     *cropped_width = 0; | 
| 189     *cropped_height = 0; | 193     *cropped_height = 0; | 
| 190     *out_width = 0; | 194     *out_width = 0; | 
| 191     *out_height = 0; | 195     *out_height = 0; | 
| 192     return; | 196     return; | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 231   ++frames_out_; | 235   ++frames_out_; | 
| 232   if (scale.numerator != scale.denominator) | 236   if (scale.numerator != scale.denominator) | 
| 233     ++frames_scaled_; | 237     ++frames_scaled_; | 
| 234 | 238 | 
| 235   if (previous_width_ && (previous_width_ != *out_width || | 239   if (previous_width_ && (previous_width_ != *out_width || | 
| 236                           previous_height_ != *out_height)) { | 240                           previous_height_ != *out_height)) { | 
| 237     ++adaption_changes_; | 241     ++adaption_changes_; | 
| 238     LOG(LS_INFO) << "Frame size changed: scaled " << frames_scaled_ << " / out " | 242     LOG(LS_INFO) << "Frame size changed: scaled " << frames_scaled_ << " / out " | 
| 239                  << frames_out_ << " / in " << frames_in_ | 243                  << frames_out_ << " / in " << frames_in_ | 
| 240                  << " Changes: " << adaption_changes_ << " Input: " << in_width | 244                  << " Changes: " << adaption_changes_ << " Input: " << in_width | 
| 241                  << "x" << in_height << " i" << input_interval_ | 245                  << "x" << in_height | 
| 242                  << " Scale: " << scale.numerator << "/" << scale.denominator | 246                  << " Scale: " << scale.numerator << "/" << scale.denominator | 
| 243                  << " Output: " << *out_width << "x" << *out_height << " i" | 247                  << " Output: " << *out_width << "x" << *out_height << " i" | 
| 244                  << (requested_format_ ? requested_format_->interval : 0); | 248                  << (requested_format_ ? requested_format_->interval : 0); | 
| 245   } | 249   } | 
| 246 | 250 | 
| 247   previous_width_ = *out_width; | 251   previous_width_ = *out_width; | 
| 248   previous_height_ = *out_height; | 252   previous_height_ = *out_height; | 
| 249 } | 253 } | 
| 250 | 254 | 
| 251 void VideoAdapter::OnOutputFormatRequest(const VideoFormat& format) { | 255 void VideoAdapter::OnOutputFormatRequest(const VideoFormat& format) { | 
| 252   rtc::CritScope cs(&critical_section_); | 256   rtc::CritScope cs(&critical_section_); | 
| 253   requested_format_ = rtc::Optional<VideoFormat>(format); | 257   requested_format_ = rtc::Optional<VideoFormat>(format); | 
| 254   interval_next_frame_ = 0; | 258   next_frame_timestamp_ns_ = rtc::Optional<int64_t>(); | 
| 255 } | 259 } | 
| 256 | 260 | 
| 257 void VideoAdapter::OnResolutionRequest( | 261 void VideoAdapter::OnResolutionRequest( | 
| 258     rtc::Optional<int> max_pixel_count, | 262     rtc::Optional<int> max_pixel_count, | 
| 259     rtc::Optional<int> max_pixel_count_step_up) { | 263     rtc::Optional<int> max_pixel_count_step_up) { | 
| 260   rtc::CritScope cs(&critical_section_); | 264   rtc::CritScope cs(&critical_section_); | 
| 261   resolution_request_max_pixel_count_ = | 265   resolution_request_max_pixel_count_ = | 
| 262       max_pixel_count.value_or(std::numeric_limits<int>::max()); | 266       max_pixel_count.value_or(std::numeric_limits<int>::max()); | 
| 263   resolution_request_max_pixel_count_step_up_ = | 267   resolution_request_max_pixel_count_step_up_ = | 
| 264       max_pixel_count_step_up.value_or(0); | 268       max_pixel_count_step_up.value_or(0); | 
| 265 } | 269 } | 
| 266 | 270 | 
| 267 }  // namespace cricket | 271 }  // namespace cricket | 
| OLD | NEW | 
|---|