1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/vie_frame_provider_base.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <algorithm>
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
15281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/common_video/interface/i420_video_frame.h"
16281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
17022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org#include "webrtc/system_wrappers/interface/logging.h"
18281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/tick_util.h"
19281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/vie_defines.h"
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc {
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgViEFrameProviderBase::ViEFrameProviderBase(int Id, int engine_id)
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    : id_(Id),
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      engine_id_(engine_id),
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      provider_cs_(CriticalSectionWrapper::CreateCriticalSection()),
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      frame_delay_(0) {
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgViEFrameProviderBase::~ViEFrameProviderBase() {
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (frame_callbacks_.size() > 0) {
32022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org    LOG_F(LS_WARNING) << "FrameCallbacks still exist when Provider deleted: "
33022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org                      << frame_callbacks_.size();
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (FrameCallbacks::iterator it = frame_callbacks_.begin();
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       it != frame_callbacks_.end(); ++it) {
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    (*it)->ProviderDestroyed(id_);
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  frame_callbacks_.clear();
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEFrameProviderBase::Id() {
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return id_;
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEFrameProviderBase::DeliverFrame(
483bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    I420VideoFrame* video_frame,
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int num_csrcs,
5067879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    const uint32_t CSRC[kRtpCsrcSize]) {
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef DEBUG_
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const TickTime start_process_time = TickTime::Now();
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(provider_cs_.get());
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Deliver the frame to all registered callbacks.
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (frame_callbacks_.size() > 0) {
58ea7b33ee032bd2d1528384e26ba079dee0d280fbwu@webrtc.org    if (frame_callbacks_.size() == 1 || video_frame->native_handle() != NULL) {
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // We don't have to copy the frame.
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      frame_callbacks_.front()->DeliverFrame(id_, video_frame, num_csrcs, CSRC);
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    } else {
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      // Make a copy of the frame for all callbacks.callback
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      for (FrameCallbacks::iterator it = frame_callbacks_.begin();
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org           it != frame_callbacks_.end(); ++it) {
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        if (!extra_frame_.get()) {
663bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org          extra_frame_.reset(new I420VideoFrame());
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        }
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        extra_frame_->CopyFrame(*video_frame);
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        (*it)->DeliverFrame(id_, extra_frame_.get(), num_csrcs, CSRC);
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef DEBUG_
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const int process_time =
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      static_cast<int>((TickTime::Now() - start_process_time).Milliseconds());
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (process_time > 25) {
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Warn if the delivery time is too long.
78022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org    LOG(LS_WARNING) << "Too long time delivering frame " << process_time;
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEFrameProviderBase::SetFrameDelay(int frame_delay) {
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(provider_cs_.get());
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  frame_delay_ = frame_delay;
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (FrameCallbacks::iterator it = frame_callbacks_.begin();
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       it != frame_callbacks_.end(); ++it) {
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    (*it)->DelayChanged(id_, frame_delay);
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEFrameProviderBase::FrameDelay() {
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return frame_delay_;
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEFrameProviderBase::GetBestFormat(int* best_width,
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                        int* best_height,
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                        int* best_frame_rate) {
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int largest_width = 0;
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int largest_height = 0;
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int highest_frame_rate = 0;
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(provider_cs_.get());
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (FrameCallbacks::iterator it = frame_callbacks_.begin();
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       it != frame_callbacks_.end(); ++it) {
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int prefered_width = 0;
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int prefered_height = 0;
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int prefered_frame_rate = 0;
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if ((*it)->GetPreferedFrameSettings(&prefered_width, &prefered_height,
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                        &prefered_frame_rate) == 0) {
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (prefered_width > largest_width) {
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        largest_width = prefered_width;
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (prefered_height > largest_height) {
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        largest_height = prefered_height;
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (prefered_frame_rate > highest_frame_rate) {
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        highest_frame_rate = prefered_frame_rate;
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *best_width = largest_width;
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *best_height = largest_height;
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *best_frame_rate = highest_frame_rate;
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEFrameProviderBase::RegisterFrameCallback(
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int observer_id, ViEFrameCallback* callback_object) {
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(callback_object);
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped cs(provider_cs_.get());
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (std::find(frame_callbacks_.begin(), frame_callbacks_.end(),
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                  callback_object) != frame_callbacks_.end()) {
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      assert(false && "frameObserver already registered");
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return -1;
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    frame_callbacks_.push_back(callback_object);
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Report current capture delay.
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  callback_object->DelayChanged(id_, frame_delay_);
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Notify implementer of this class that the callback list have changed.
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FrameCallbackChanged();
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEFrameProviderBase::DeregisterFrameCallback(
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const ViEFrameCallback* callback_object) {
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(callback_object);
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(provider_cs_.get());
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FrameCallbacks::iterator it = std::find(frame_callbacks_.begin(),
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                          frame_callbacks_.end(),
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                          callback_object);
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (it == frame_callbacks_.end()) {
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  frame_callbacks_.erase(it);
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Notify implementer of this class that the callback list have changed.
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FrameCallbackChanged();
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool ViEFrameProviderBase::IsFrameCallbackRegistered(
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const ViEFrameCallback* callback_object) {
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(callback_object);
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(provider_cs_.get());
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return std::find(frame_callbacks_.begin(), frame_callbacks_.end(),
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   callback_object) != frame_callbacks_.end();
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEFrameProviderBase::NumberOfRegisteredFrameCallbacks() {
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(provider_cs_.get());
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return frame_callbacks_.size();
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespac webrtc
181