LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/video_coding - timing.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 159 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
       3             :  *
       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
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "webrtc/modules/video_coding/timing.h"
      12             : 
      13             : #include <algorithm>
      14             : 
      15             : #include "webrtc/modules/video_coding/internal_defines.h"
      16             : #include "webrtc/modules/video_coding/jitter_buffer_common.h"
      17             : #include "webrtc/system_wrappers/include/clock.h"
      18             : #include "webrtc/system_wrappers/include/metrics.h"
      19             : #include "webrtc/system_wrappers/include/timestamp_extrapolator.h"
      20             : 
      21             : namespace webrtc {
      22             : 
      23           0 : VCMTiming::VCMTiming(Clock* clock, VCMTiming* master_timing)
      24           0 :     : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
      25             :       clock_(clock),
      26             :       master_(false),
      27             :       ts_extrapolator_(),
      28           0 :       codec_timer_(new VCMCodecTimer()),
      29             :       render_delay_ms_(kDefaultRenderDelayMs),
      30             :       min_playout_delay_ms_(0),
      31             :       max_playout_delay_ms_(10000),
      32             :       jitter_delay_ms_(0),
      33             :       current_delay_ms_(0),
      34             :       last_decode_ms_(0),
      35             :       prev_frame_timestamp_(0),
      36             :       num_decoded_frames_(0),
      37             :       num_delayed_decoded_frames_(0),
      38             :       first_decoded_frame_ms_(-1),
      39           0 :       sum_missed_render_deadline_ms_(0) {
      40           0 :   if (master_timing == NULL) {
      41           0 :     master_ = true;
      42           0 :     ts_extrapolator_ = new TimestampExtrapolator(clock_->TimeInMilliseconds());
      43             :   } else {
      44           0 :     ts_extrapolator_ = master_timing->ts_extrapolator_;
      45             :   }
      46           0 : }
      47             : 
      48           0 : VCMTiming::~VCMTiming() {
      49           0 :   UpdateHistograms();
      50           0 :   if (master_) {
      51           0 :     delete ts_extrapolator_;
      52             :   }
      53           0 :   delete crit_sect_;
      54           0 : }
      55             : 
      56           0 : void VCMTiming::UpdateHistograms() const {
      57           0 :   CriticalSectionScoped cs(crit_sect_);
      58           0 :   if (num_decoded_frames_ == 0) {
      59           0 :     return;
      60             :   }
      61             :   int64_t elapsed_sec =
      62           0 :       (clock_->TimeInMilliseconds() - first_decoded_frame_ms_) / 1000;
      63           0 :   if (elapsed_sec < metrics::kMinRunTimeInSeconds) {
      64           0 :     return;
      65             :   }
      66           0 :   RTC_HISTOGRAM_COUNTS_100(
      67             :       "WebRTC.Video.DecodedFramesPerSecond",
      68             :       static_cast<int>((num_decoded_frames_ / elapsed_sec) + 0.5f));
      69           0 :   RTC_HISTOGRAM_PERCENTAGE(
      70             :       "WebRTC.Video.DelayedFramesToRenderer",
      71             :       num_delayed_decoded_frames_ * 100 / num_decoded_frames_);
      72           0 :   if (num_delayed_decoded_frames_ > 0) {
      73           0 :     RTC_HISTOGRAM_COUNTS_1000(
      74             :         "WebRTC.Video.DelayedFramesToRenderer_AvgDelayInMs",
      75             :         sum_missed_render_deadline_ms_ / num_delayed_decoded_frames_);
      76             :   }
      77             : }
      78             : 
      79           0 : void VCMTiming::Reset() {
      80           0 :   CriticalSectionScoped cs(crit_sect_);
      81           0 :   ts_extrapolator_->Reset(clock_->TimeInMilliseconds());
      82           0 :   codec_timer_.reset(new VCMCodecTimer());
      83           0 :   render_delay_ms_ = kDefaultRenderDelayMs;
      84           0 :   min_playout_delay_ms_ = 0;
      85           0 :   jitter_delay_ms_ = 0;
      86           0 :   current_delay_ms_ = 0;
      87           0 :   prev_frame_timestamp_ = 0;
      88           0 : }
      89             : 
      90           0 : void VCMTiming::ResetDecodeTime() {
      91           0 :   CriticalSectionScoped lock(crit_sect_);
      92           0 :   codec_timer_.reset(new VCMCodecTimer());
      93           0 : }
      94             : 
      95           0 : void VCMTiming::set_render_delay(int render_delay_ms) {
      96           0 :   CriticalSectionScoped cs(crit_sect_);
      97           0 :   render_delay_ms_ = render_delay_ms;
      98           0 : }
      99             : 
     100           0 : void VCMTiming::set_min_playout_delay(int min_playout_delay_ms) {
     101           0 :   CriticalSectionScoped cs(crit_sect_);
     102           0 :   min_playout_delay_ms_ = min_playout_delay_ms;
     103           0 : }
     104             : 
     105           0 : int VCMTiming::min_playout_delay() {
     106           0 :   CriticalSectionScoped cs(crit_sect_);
     107           0 :   return min_playout_delay_ms_;
     108             : }
     109             : 
     110           0 : void VCMTiming::set_max_playout_delay(int max_playout_delay_ms) {
     111           0 :   CriticalSectionScoped cs(crit_sect_);
     112           0 :   max_playout_delay_ms_ = max_playout_delay_ms;
     113           0 : }
     114             : 
     115           0 : int VCMTiming::max_playout_delay() {
     116           0 :   CriticalSectionScoped cs(crit_sect_);
     117           0 :   return max_playout_delay_ms_;
     118             : }
     119             : 
     120           0 : void VCMTiming::SetJitterDelay(int jitter_delay_ms) {
     121           0 :   CriticalSectionScoped cs(crit_sect_);
     122           0 :   if (jitter_delay_ms != jitter_delay_ms_) {
     123           0 :     jitter_delay_ms_ = jitter_delay_ms;
     124             :     // When in initial state, set current delay to minimum delay.
     125           0 :     if (current_delay_ms_ == 0) {
     126           0 :       current_delay_ms_ = jitter_delay_ms_;
     127             :     }
     128             :   }
     129           0 : }
     130             : 
     131           0 : void VCMTiming::UpdateCurrentDelay(uint32_t frame_timestamp) {
     132           0 :   CriticalSectionScoped cs(crit_sect_);
     133           0 :   int target_delay_ms = TargetDelayInternal();
     134             : 
     135           0 :   if (current_delay_ms_ == 0) {
     136             :     // Not initialized, set current delay to target.
     137           0 :     current_delay_ms_ = target_delay_ms;
     138           0 :   } else if (target_delay_ms != current_delay_ms_) {
     139             :     int64_t delay_diff_ms =
     140           0 :         static_cast<int64_t>(target_delay_ms) - current_delay_ms_;
     141             :     // Never change the delay with more than 100 ms every second. If we're
     142             :     // changing the delay in too large steps we will get noticeable freezes. By
     143             :     // limiting the change we can increase the delay in smaller steps, which
     144             :     // will be experienced as the video is played in slow motion. When lowering
     145             :     // the delay the video will be played at a faster pace.
     146           0 :     int64_t max_change_ms = 0;
     147           0 :     if (frame_timestamp < 0x0000ffff && prev_frame_timestamp_ > 0xffff0000) {
     148             :       // wrap
     149           0 :       max_change_ms = kDelayMaxChangeMsPerS *
     150           0 :                       (frame_timestamp + (static_cast<int64_t>(1) << 32) -
     151           0 :                        prev_frame_timestamp_) /
     152           0 :                       90000;
     153             :     } else {
     154           0 :       max_change_ms = kDelayMaxChangeMsPerS *
     155           0 :                       (frame_timestamp - prev_frame_timestamp_) / 90000;
     156             :     }
     157             : 
     158           0 :     if (max_change_ms <= 0) {
     159             :       // Any changes less than 1 ms are truncated and
     160             :       // will be postponed. Negative change will be due
     161             :       // to reordering and should be ignored.
     162           0 :       return;
     163             :     }
     164           0 :     delay_diff_ms = std::max(delay_diff_ms, -max_change_ms);
     165           0 :     delay_diff_ms = std::min(delay_diff_ms, max_change_ms);
     166             : 
     167           0 :     current_delay_ms_ = current_delay_ms_ + delay_diff_ms;
     168             :   }
     169           0 :   prev_frame_timestamp_ = frame_timestamp;
     170             : }
     171             : 
     172           0 : void VCMTiming::UpdateCurrentDelay(int64_t render_time_ms,
     173             :                                    int64_t actual_decode_time_ms) {
     174           0 :   CriticalSectionScoped cs(crit_sect_);
     175           0 :   uint32_t target_delay_ms = TargetDelayInternal();
     176             :   int64_t delayed_ms =
     177             :       actual_decode_time_ms -
     178           0 :       (render_time_ms - RequiredDecodeTimeMs() - render_delay_ms_);
     179           0 :   if (delayed_ms < 0) {
     180           0 :     return;
     181             :   }
     182           0 :   if (current_delay_ms_ + delayed_ms <= target_delay_ms) {
     183           0 :     current_delay_ms_ += delayed_ms;
     184             :   } else {
     185           0 :     current_delay_ms_ = target_delay_ms;
     186             :   }
     187             : }
     188             : 
     189           0 : int32_t VCMTiming::StopDecodeTimer(uint32_t time_stamp,
     190             :                                    int32_t decode_time_ms,
     191             :                                    int64_t now_ms,
     192             :                                    int64_t render_time_ms) {
     193           0 :   CriticalSectionScoped cs(crit_sect_);
     194           0 :   codec_timer_->AddTiming(decode_time_ms, now_ms);
     195           0 :   assert(decode_time_ms >= 0);
     196           0 :   last_decode_ms_ = decode_time_ms;
     197             : 
     198             :   // Update stats.
     199           0 :   ++num_decoded_frames_;
     200           0 :   if (num_decoded_frames_ == 1) {
     201           0 :     first_decoded_frame_ms_ = now_ms;
     202             :   }
     203           0 :   int time_until_rendering_ms = render_time_ms - render_delay_ms_ - now_ms;
     204           0 :   if (time_until_rendering_ms < 0) {
     205           0 :     sum_missed_render_deadline_ms_ += -time_until_rendering_ms;
     206           0 :     ++num_delayed_decoded_frames_;
     207             :   }
     208           0 :   return 0;
     209             : }
     210             : 
     211           0 : void VCMTiming::IncomingTimestamp(uint32_t time_stamp, int64_t now_ms) {
     212           0 :   CriticalSectionScoped cs(crit_sect_);
     213           0 :   ts_extrapolator_->Update(now_ms, time_stamp);
     214           0 : }
     215             : 
     216           0 : int64_t VCMTiming::RenderTimeMs(uint32_t frame_timestamp,
     217             :                                 int64_t now_ms) const {
     218           0 :   CriticalSectionScoped cs(crit_sect_);
     219           0 :   const int64_t render_time_ms = RenderTimeMsInternal(frame_timestamp, now_ms);
     220           0 :   return render_time_ms;
     221             : }
     222             : 
     223           0 : int64_t VCMTiming::RenderTimeMsInternal(uint32_t frame_timestamp,
     224             :                                         int64_t now_ms) const {
     225             :   int64_t estimated_complete_time_ms =
     226           0 :       ts_extrapolator_->ExtrapolateLocalTime(frame_timestamp);
     227           0 :   if (estimated_complete_time_ms == -1) {
     228           0 :     estimated_complete_time_ms = now_ms;
     229             :   }
     230             : 
     231           0 :   if (min_playout_delay_ms_ == 0 && max_playout_delay_ms_ == 0) {
     232             :     // Render as soon as possible
     233           0 :     return now_ms;
     234             :   }
     235             : 
     236             :   // Make sure the actual delay stays in the range of |min_playout_delay_ms_|
     237             :   // and |max_playout_delay_ms_|.
     238           0 :   int actual_delay = std::max(current_delay_ms_, min_playout_delay_ms_);
     239           0 :   actual_delay = std::min(actual_delay, max_playout_delay_ms_);
     240           0 :   return estimated_complete_time_ms + actual_delay;
     241             : }
     242             : 
     243             : // Must be called from inside a critical section.
     244           0 : int VCMTiming::RequiredDecodeTimeMs() const {
     245           0 :   const int decode_time_ms = codec_timer_->RequiredDecodeTimeMs();
     246           0 :   assert(decode_time_ms >= 0);
     247           0 :   return decode_time_ms;
     248             : }
     249             : 
     250           0 : uint32_t VCMTiming::MaxWaitingTime(int64_t render_time_ms,
     251             :                                    int64_t now_ms) const {
     252           0 :   CriticalSectionScoped cs(crit_sect_);
     253             : 
     254             :   const int64_t max_wait_time_ms =
     255           0 :       render_time_ms - now_ms - RequiredDecodeTimeMs() - render_delay_ms_;
     256             : 
     257           0 :   if (max_wait_time_ms < 0) {
     258           0 :     return 0;
     259             :   }
     260           0 :   return static_cast<uint32_t>(max_wait_time_ms);
     261             : }
     262             : 
     263           0 : bool VCMTiming::EnoughTimeToDecode(
     264             :     uint32_t available_processing_time_ms) const {
     265           0 :   CriticalSectionScoped cs(crit_sect_);
     266           0 :   int64_t required_decode_time_ms = RequiredDecodeTimeMs();
     267           0 :   if (required_decode_time_ms < 0) {
     268             :     // Haven't decoded any frames yet, try decoding one to get an estimate
     269             :     // of the decode time.
     270           0 :     return true;
     271           0 :   } else if (required_decode_time_ms == 0) {
     272             :     // Decode time is less than 1, set to 1 for now since
     273             :     // we don't have any better precision. Count ticks later?
     274           0 :     required_decode_time_ms = 1;
     275             :   }
     276           0 :   return static_cast<int64_t>(available_processing_time_ms) -
     277             :              required_decode_time_ms >
     278           0 :          0;
     279             : }
     280             : 
     281           0 : int VCMTiming::TargetVideoDelay() const {
     282           0 :   CriticalSectionScoped cs(crit_sect_);
     283           0 :   return TargetDelayInternal();
     284             : }
     285             : 
     286           0 : int VCMTiming::TargetDelayInternal() const {
     287             :   return std::max(min_playout_delay_ms_,
     288           0 :                   jitter_delay_ms_ + RequiredDecodeTimeMs() + render_delay_ms_);
     289             : }
     290             : 
     291           0 : bool VCMTiming::GetTimings(int* decode_ms,
     292             :                            int* max_decode_ms,
     293             :                            int* current_delay_ms,
     294             :                            int* target_delay_ms,
     295             :                            int* jitter_buffer_ms,
     296             :                            int* min_playout_delay_ms,
     297             :                            int* render_delay_ms) const {
     298           0 :   CriticalSectionScoped cs(crit_sect_);
     299           0 :   *decode_ms = last_decode_ms_;
     300           0 :   *max_decode_ms = RequiredDecodeTimeMs();
     301           0 :   *current_delay_ms = current_delay_ms_;
     302           0 :   *target_delay_ms = TargetDelayInternal();
     303           0 :   *jitter_buffer_ms = jitter_delay_ms_;
     304           0 :   *min_playout_delay_ms = min_playout_delay_ms_;
     305           0 :   *render_delay_ms = render_delay_ms_;
     306           0 :   return (num_decoded_frames_ > 0);
     307             : }
     308             : 
     309             : }  // namespace webrtc

Generated by: LCOV version 1.13