summaryrefslogtreecommitdiff
path: root/remoting/ios/bridge/frame_consumer_bridge.cc
diff options
context:
space:
mode:
Diffstat (limited to 'remoting/ios/bridge/frame_consumer_bridge.cc')
-rw-r--r--remoting/ios/bridge/frame_consumer_bridge.cc88
1 files changed, 88 insertions, 0 deletions
diff --git a/remoting/ios/bridge/frame_consumer_bridge.cc b/remoting/ios/bridge/frame_consumer_bridge.cc
new file mode 100644
index 0000000000..fbc96066d3
--- /dev/null
+++ b/remoting/ios/bridge/frame_consumer_bridge.cc
@@ -0,0 +1,88 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/ios/bridge/frame_consumer_bridge.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/synchronization/waitable_event.h"
+#include "remoting/base/util.h"
+#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
+
+namespace remoting {
+
+FrameConsumerBridge::FrameConsumerBridge(OnFrameCallback callback)
+ : callback_(callback), frame_producer_(NULL) {}
+
+FrameConsumerBridge::~FrameConsumerBridge() {
+ // The producer should now return any pending buffers. At this point, however,
+ // the buffers are returned via tasks which may not be scheduled before the
+ // producer, so we free all the buffers once the producer's queue is empty.
+ // And the scheduled tasks will die quietly.
+ if (frame_producer_) {
+ base::WaitableEvent done_event(true, false);
+ frame_producer_->RequestReturnBuffers(base::Bind(
+ &base::WaitableEvent::Signal, base::Unretained(&done_event)));
+ done_event.Wait();
+ }
+}
+
+void FrameConsumerBridge::Initialize(FrameProducer* producer) {
+ DCHECK(!frame_producer_);
+ frame_producer_ = producer;
+ DCHECK(frame_producer_);
+}
+
+void FrameConsumerBridge::ApplyBuffer(const webrtc::DesktopSize& view_size,
+ const webrtc::DesktopRect& clip_area,
+ webrtc::DesktopFrame* buffer,
+ const webrtc::DesktopRegion& region,
+ const webrtc::DesktopRegion& shape) {
+ DCHECK(frame_producer_);
+ if (!view_size_.equals(view_size)) {
+ // Drop the frame, since the data belongs to the previous generation,
+ // before SetSourceSize() called SetOutputSizeAndClip().
+ ReturnBuffer(buffer);
+ return;
+ }
+
+ // This call completes synchronously.
+ callback_.Run(view_size, buffer, region);
+
+ // Recycle |buffer| by returning it to |frame_producer_| as the next buffer
+ frame_producer_->DrawBuffer(buffer);
+}
+
+void FrameConsumerBridge::ReturnBuffer(webrtc::DesktopFrame* buffer) {
+ DCHECK(frame_producer_);
+ ScopedVector<webrtc::DesktopFrame>::iterator it =
+ std::find(buffers_.begin(), buffers_.end(), buffer);
+
+ DCHECK(it != buffers_.end());
+ buffers_.erase(it);
+}
+
+void FrameConsumerBridge::SetSourceSize(const webrtc::DesktopSize& source_size,
+ const webrtc::DesktopVector& dpi) {
+ DCHECK(frame_producer_);
+ view_size_ = source_size;
+ webrtc::DesktopRect clip_area = webrtc::DesktopRect::MakeSize(view_size_);
+ frame_producer_->SetOutputSizeAndClip(view_size_, clip_area);
+
+ // Now that the size is well known, ask the producer to start drawing
+ DrawWithNewBuffer();
+}
+
+FrameConsumerBridge::PixelFormat FrameConsumerBridge::GetPixelFormat() {
+ return FORMAT_RGBA;
+}
+
+void FrameConsumerBridge::DrawWithNewBuffer() {
+ DCHECK(frame_producer_);
+ webrtc::DesktopFrame* buffer = new webrtc::BasicDesktopFrame(view_size_);
+ buffers_.push_back(buffer);
+ frame_producer_->DrawBuffer(buffer);
+}
+
+} // namespace remoting