Home | History | Annotate | Download | only in source
      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_processing/main/interface/video_processing.h"
     12 #include "webrtc/modules/video_processing/main/source/video_decimator.h"
     13 #include "webrtc/system_wrappers/interface/tick_util.h"
     14 
     15 #define VD_MIN(a, b) ((a) < (b)) ? (a) : (b)
     16 
     17 namespace webrtc {
     18 
     19 VPMVideoDecimator::VPMVideoDecimator() {
     20   Reset();
     21 }
     22 
     23 VPMVideoDecimator::~VPMVideoDecimator() {}
     24 
     25 void VPMVideoDecimator::Reset()  {
     26   overshoot_modifier_ = 0;
     27   drop_count_ = 0;
     28   keep_count_ = 0;
     29   target_frame_rate_ = 30;
     30   incoming_frame_rate_ = 0.0f;
     31   memset(incoming_frame_times_, 0, sizeof(incoming_frame_times_));
     32   enable_temporal_decimation_ = true;
     33 }
     34 
     35 void VPMVideoDecimator::EnableTemporalDecimation(bool enable) {
     36   enable_temporal_decimation_ = enable;
     37 }
     38 
     39 int32_t VPMVideoDecimator::SetTargetFramerate(uint32_t frame_rate) {
     40   if (frame_rate == 0) return VPM_PARAMETER_ERROR;
     41 
     42   target_frame_rate_ = frame_rate;
     43   return VPM_OK;
     44 }
     45 
     46 bool VPMVideoDecimator::DropFrame() {
     47   if (!enable_temporal_decimation_) return false;
     48 
     49   if (incoming_frame_rate_ <= 0) return false;
     50 
     51   const uint32_t incomingframe_rate =
     52       static_cast<uint32_t>(incoming_frame_rate_ + 0.5f);
     53 
     54   if (target_frame_rate_ == 0) return true;
     55 
     56   bool drop = false;
     57   if (incomingframe_rate > target_frame_rate_) {
     58     int32_t overshoot =
     59         overshoot_modifier_ + (incomingframe_rate - target_frame_rate_);
     60     if (overshoot < 0) {
     61       overshoot = 0;
     62       overshoot_modifier_ = 0;
     63     }
     64 
     65     if (overshoot && 2 * overshoot < (int32_t) incomingframe_rate) {
     66       if (drop_count_) {  // Just got here so drop to be sure.
     67           drop_count_ = 0;
     68           return true;
     69       }
     70       const uint32_t dropVar = incomingframe_rate / overshoot;
     71 
     72       if (keep_count_ >= dropVar) {
     73           drop = true;
     74           overshoot_modifier_ = -((int32_t) incomingframe_rate % overshoot) / 3;
     75           keep_count_ = 1;
     76       } else {
     77           keep_count_++;
     78       }
     79     } else {
     80       keep_count_ = 0;
     81       const uint32_t dropVar = overshoot / target_frame_rate_;
     82       if (drop_count_ < dropVar) {
     83           drop = true;
     84           drop_count_++;
     85       } else {
     86           overshoot_modifier_ = overshoot % target_frame_rate_;
     87           drop = false;
     88           drop_count_ = 0;
     89       }
     90     }
     91   }
     92   return drop;
     93 }
     94 
     95 
     96 uint32_t VPMVideoDecimator::Decimatedframe_rate() {
     97 ProcessIncomingframe_rate(TickTime::MillisecondTimestamp());
     98   if (!enable_temporal_decimation_) {
     99     return static_cast<uint32_t>(incoming_frame_rate_ + 0.5f);
    100   }
    101   return VD_MIN(target_frame_rate_,
    102       static_cast<uint32_t>(incoming_frame_rate_ + 0.5f));
    103 }
    104 
    105 uint32_t VPMVideoDecimator::Inputframe_rate() {
    106   ProcessIncomingframe_rate(TickTime::MillisecondTimestamp());
    107   return static_cast<uint32_t>(incoming_frame_rate_ + 0.5f);
    108 }
    109 
    110 void VPMVideoDecimator::UpdateIncomingframe_rate() {
    111   int64_t now = TickTime::MillisecondTimestamp();
    112   if (incoming_frame_times_[0] == 0) {
    113     // First no shift.
    114   } else {
    115     // Shift.
    116     for (int i = kFrameCountHistory_size - 2; i >= 0; i--) {
    117         incoming_frame_times_[i+1] = incoming_frame_times_[i];
    118     }
    119   }
    120   incoming_frame_times_[0] = now;
    121   ProcessIncomingframe_rate(now);
    122 }
    123 
    124 void VPMVideoDecimator::ProcessIncomingframe_rate(int64_t now) {
    125   int32_t num = 0;
    126   int32_t nrOfFrames = 0;
    127   for (num = 1; num < (kFrameCountHistory_size - 1); num++) {
    128     // Don't use data older than 2sec.
    129     if (incoming_frame_times_[num] <= 0 ||
    130         now - incoming_frame_times_[num] > kFrameHistoryWindowMs) {
    131       break;
    132     } else {
    133       nrOfFrames++;
    134     }
    135   }
    136   if (num > 1) {
    137     int64_t diff = now - incoming_frame_times_[num-1];
    138     incoming_frame_rate_ = 1.0;
    139     if (diff > 0) {
    140       incoming_frame_rate_ = nrOfFrames * 1000.0f / static_cast<float>(diff);
    141     }
    142   } else {
    143     incoming_frame_rate_ = static_cast<float>(nrOfFrames);
    144   }
    145 }
    146 
    147 }  // namespace webrtc
    148