diff options
Diffstat (limited to 'remoting/ios/bridge/frame_consumer_bridge.cc')
-rw-r--r-- | remoting/ios/bridge/frame_consumer_bridge.cc | 88 |
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 |