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 || video_frame->native_handle() != NULL) {
     59       // We don't have to copy the frame.
     60       frame_callbacks_.front()->DeliverFrame(id_, video_frame, num_csrcs, CSRC);
     61     } else {
     62       // Make a copy of the frame for all callbacks.callback
     63       for (FrameCallbacks::iterator it = frame_callbacks_.begin();
     64            it != frame_callbacks_.end(); ++it) {
     65         if (!extra_frame_.get()) {
     66           extra_frame_.reset(new I420VideoFrame());
     67         }
     68         extra_frame_->CopyFrame(*video_frame);
     69         (*it)->DeliverFrame(id_, extra_frame_.get(), num_csrcs, CSRC);
     70       }
     71     }
     72   }
     73 #ifdef DEBUG_
     74   const int process_time =
     75       static_cast<int>((TickTime::Now() - start_process_time).Milliseconds());
     76   if (process_time > 25) {
     77     // Warn if the delivery time is too long.
     78     LOG(LS_WARNING) << "Too long time delivering frame " << process_time;
     79   }
     80 #endif
     81 }
     82 
     83 void ViEFrameProviderBase::SetFrameDelay(int frame_delay) {
     84   CriticalSectionScoped cs(provider_cs_.get());
     85   frame_delay_ = frame_delay;
     86 
     87   for (FrameCallbacks::iterator it = frame_callbacks_.begin();
     88        it != frame_callbacks_.end(); ++it) {
     89     (*it)->DelayChanged(id_, frame_delay);
     90   }
     91 }
     92 
     93 int ViEFrameProviderBase::FrameDelay() {
     94   return frame_delay_;
     95 }
     96 
     97 int ViEFrameProviderBase::GetBestFormat(int* best_width,
     98                                         int* best_height,
     99                                         int* best_frame_rate) {
    100   int largest_width = 0;
    101   int largest_height = 0;
    102   int highest_frame_rate = 0;
    103 
    104   CriticalSectionScoped cs(provider_cs_.get());
    105   for (FrameCallbacks::iterator it = frame_callbacks_.begin();
    106        it != frame_callbacks_.end(); ++it) {
    107     int prefered_width = 0;
    108     int prefered_height = 0;
    109     int prefered_frame_rate = 0;
    110     if ((*it)->GetPreferedFrameSettings(&prefered_width, &prefered_height,
    111                                         &prefered_frame_rate) == 0) {
    112       if (prefered_width > largest_width) {
    113         largest_width = prefered_width;
    114       }
    115       if (prefered_height > largest_height) {
    116         largest_height = prefered_height;
    117       }
    118       if (prefered_frame_rate > highest_frame_rate) {
    119         highest_frame_rate = prefered_frame_rate;
    120       }
    121     }
    122   }
    123   *best_width = largest_width;
    124   *best_height = largest_height;
    125   *best_frame_rate = highest_frame_rate;
    126   return 0;
    127 }
    128 
    129 int ViEFrameProviderBase::RegisterFrameCallback(
    130     int observer_id, ViEFrameCallback* callback_object) {
    131   assert(callback_object);
    132   {
    133     CriticalSectionScoped cs(provider_cs_.get());
    134     if (std::find(frame_callbacks_.begin(), frame_callbacks_.end(),
    135                   callback_object) != frame_callbacks_.end()) {
    136       assert(false && "frameObserver already registered");
    137       return -1;
    138     }
    139     frame_callbacks_.push_back(callback_object);
    140   }
    141   // Report current capture delay.
    142   callback_object->DelayChanged(id_, frame_delay_);
    143 
    144   // Notify implementer of this class that the callback list have changed.
    145   FrameCallbackChanged();
    146   return 0;
    147 }
    148 
    149 int ViEFrameProviderBase::DeregisterFrameCallback(
    150     const ViEFrameCallback* callback_object) {
    151   assert(callback_object);
    152   CriticalSectionScoped cs(provider_cs_.get());
    153 
    154   FrameCallbacks::iterator it = std::find(frame_callbacks_.begin(),
    155                                           frame_callbacks_.end(),
    156                                           callback_object);
    157   if (it == frame_callbacks_.end()) {
    158     return -1;
    159   }
    160   frame_callbacks_.erase(it);
    161 
    162   // Notify implementer of this class that the callback list have changed.
    163   FrameCallbackChanged();
    164   return 0;
    165 }
    166 
    167 bool ViEFrameProviderBase::IsFrameCallbackRegistered(
    168     const ViEFrameCallback* callback_object) {
    169   assert(callback_object);
    170 
    171   CriticalSectionScoped cs(provider_cs_.get());
    172   return std::find(frame_callbacks_.begin(), frame_callbacks_.end(),
    173                    callback_object) != frame_callbacks_.end();
    174 }
    175 
    176 int ViEFrameProviderBase::NumberOfRegisteredFrameCallbacks() {
    177   CriticalSectionScoped cs(provider_cs_.get());
    178   return frame_callbacks_.size();
    179 }
    180 }  // namespac webrtc
    181