Home | History | Annotate | Download | only in video_engine
      1 /*
      2  *  Copyright (c) 2012 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/video_engine/vie_frame_provider_base.h"
     12 
     13 #include <algorithm>
     14 
     15 #include "webrtc/common_video/interface/i420_video_frame.h"
     16 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
     17 #include "webrtc/system_wrappers/interface/logging.h"
     18 #include "webrtc/system_wrappers/interface/tick_util.h"
     19 #include "webrtc/video_engine/vie_defines.h"
     20 
     21 namespace webrtc {
     22 
     23 ViEFrameProviderBase::ViEFrameProviderBase(int Id, int engine_id)
     24     : id_(Id),
     25       engine_id_(engine_id),
     26       provider_cs_(CriticalSectionWrapper::CreateCriticalSection()),
     27       frame_delay_(0) {
     28 }
     29 
     30 ViEFrameProviderBase::~ViEFrameProviderBase() {
     31   if (frame_callbacks_.size() > 0) {
     32     LOG_F(LS_WARNING) << "FrameCallbacks still exist when Provider deleted: "
     33                       << frame_callbacks_.size();
     34   }
     35 
     36   for (FrameCallbacks::iterator it = frame_callbacks_.begin();
     37        it != frame_callbacks_.end(); ++it) {
     38     (*it)->ProviderDestroyed(id_);
     39   }
     40   frame_callbacks_.clear();
     41 }
     42 
     43 int ViEFrameProviderBase::Id() {
     44   return id_;
     45 }
     46 
     47 void ViEFrameProviderBase::DeliverFrame(
     48     I420VideoFrame* video_frame,
     49     int num_csrcs,
     50     const uint32_t CSRC[kRtpCsrcSize]) {
     51 #ifdef DEBUG_
     52   const TickTime start_process_time = TickTime::Now();
     53 #endif
     54   CriticalSectionScoped cs(provider_cs_.get());
     55 
     56   // Deliver the frame to all registered callbacks.
     57   if (frame_callbacks_.size() > 0) {
     58     if (frame_callbacks_.size() == 1) {
     59       // We don't have to copy the frame.
     60       frame_callbacks_.front()->DeliverFrame(id_, video_frame, num_csrcs, CSRC);
     61     } else {
     62       for (FrameCallbacks::iterator it = frame_callbacks_.begin();
     63            it != frame_callbacks_.end(); ++it) {
     64         if (video_frame->native_handle() != NULL) {
     65           (*it)->DeliverFrame(id_, video_frame, num_csrcs, CSRC);
     66         } else {
     67           // Make a copy of the frame for all callbacks.
     68           if (!extra_frame_.get()) {
     69             extra_frame_.reset(new I420VideoFrame());
     70           }
     71           extra_frame_->CopyFrame(*video_frame);
     72           (*it)->DeliverFrame(id_, extra_frame_.get(), num_csrcs, CSRC);
     73         }
     74       }
     75     }
     76   }
     77 #ifdef DEBUG_
     78   const int process_time =
     79       static_cast<int>((TickTime::Now() - start_process_time).Milliseconds());
     80   if (process_time > 25) {
     81     // Warn if the delivery time is too long.
     82     LOG(LS_WARNING) << "Too long time delivering frame " << process_time;
     83   }
     84 #endif
     85 }
     86 
     87 void ViEFrameProviderBase::SetFrameDelay(int frame_delay) {
     88   CriticalSectionScoped cs(provider_cs_.get());
     89   frame_delay_ = frame_delay;
     90 
     91   for (FrameCallbacks::iterator it = frame_callbacks_.begin();
     92        it != frame_callbacks_.end(); ++it) {
     93     (*it)->DelayChanged(id_, frame_delay);
     94   }
     95 }
     96 
     97 int ViEFrameProviderBase::FrameDelay() {
     98   return frame_delay_;
     99 }
    100 
    101 int ViEFrameProviderBase::GetBestFormat(int* best_width,
    102                                         int* best_height,
    103                                         int* best_frame_rate) {
    104   int largest_width = 0;
    105   int largest_height = 0;
    106   int highest_frame_rate = 0;
    107 
    108   CriticalSectionScoped cs(provider_cs_.get());
    109   for (FrameCallbacks::iterator it = frame_callbacks_.begin();
    110        it != frame_callbacks_.end(); ++it) {
    111     int prefered_width = 0;
    112     int prefered_height = 0;
    113     int prefered_frame_rate = 0;
    114     if ((*it)->GetPreferedFrameSettings(&prefered_width, &prefered_height,
    115                                         &prefered_frame_rate) == 0) {
    116       if (prefered_width > largest_width) {
    117         largest_width = prefered_width;
    118       }
    119       if (prefered_height > largest_height) {
    120         largest_height = prefered_height;
    121       }
    122       if (prefered_frame_rate > highest_frame_rate) {
    123         highest_frame_rate = prefered_frame_rate;
    124       }
    125     }
    126   }
    127   *best_width = largest_width;
    128   *best_height = largest_height;
    129   *best_frame_rate = highest_frame_rate;
    130   return 0;
    131 }
    132 
    133 int ViEFrameProviderBase::RegisterFrameCallback(
    134     int observer_id, ViEFrameCallback* callback_object) {
    135   assert(callback_object);
    136   {
    137     CriticalSectionScoped cs(provider_cs_.get());
    138     if (std::find(frame_callbacks_.begin(), frame_callbacks_.end(),
    139                   callback_object) != frame_callbacks_.end()) {
    140       assert(false && "frameObserver already registered");
    141       return -1;
    142     }
    143     frame_callbacks_.push_back(callback_object);
    144   }
    145   // Report current capture delay.
    146   callback_object->DelayChanged(id_, frame_delay_);
    147 
    148   // Notify implementer of this class that the callback list have changed.
    149   FrameCallbackChanged();
    150   return 0;
    151 }
    152 
    153 int ViEFrameProviderBase::DeregisterFrameCallback(
    154     const ViEFrameCallback* callback_object) {
    155   assert(callback_object);
    156   CriticalSectionScoped cs(provider_cs_.get());
    157 
    158   FrameCallbacks::iterator it = std::find(frame_callbacks_.begin(),
    159                                           frame_callbacks_.end(),
    160                                           callback_object);
    161   if (it == frame_callbacks_.end()) {
    162     return -1;
    163   }
    164   frame_callbacks_.erase(it);
    165 
    166   // Notify implementer of this class that the callback list have changed.
    167   FrameCallbackChanged();
    168   return 0;
    169 }
    170 
    171 bool ViEFrameProviderBase::IsFrameCallbackRegistered(
    172     const ViEFrameCallback* callback_object) {
    173   assert(callback_object);
    174 
    175   CriticalSectionScoped cs(provider_cs_.get());
    176   return std::find(frame_callbacks_.begin(), frame_callbacks_.end(),
    177                    callback_object) != frame_callbacks_.end();
    178 }
    179 
    180 int ViEFrameProviderBase::NumberOfRegisteredFrameCallbacks() {
    181   CriticalSectionScoped cs(provider_cs_.get());
    182   return frame_callbacks_.size();
    183 }
    184 }  // namespac webrtc
    185