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