Home | History | Annotate | Download | only in bridge
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "remoting/ios/bridge/frame_consumer_bridge.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/logging.h"
      9 #include "base/synchronization/waitable_event.h"
     10 #include "remoting/base/util.h"
     11 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
     12 
     13 namespace remoting {
     14 
     15 FrameConsumerBridge::FrameConsumerBridge(OnFrameCallback callback)
     16     : callback_(callback), frame_producer_(NULL) {}
     17 
     18 FrameConsumerBridge::~FrameConsumerBridge() {
     19   // The producer should now return any pending buffers. At this point, however,
     20   // the buffers are returned via tasks which may not be scheduled before the
     21   // producer, so we free all the buffers once the producer's queue is empty.
     22   // And the scheduled tasks will die quietly.
     23   if (frame_producer_) {
     24     base::WaitableEvent done_event(true, false);
     25     frame_producer_->RequestReturnBuffers(base::Bind(
     26         &base::WaitableEvent::Signal, base::Unretained(&done_event)));
     27     done_event.Wait();
     28   }
     29 }
     30 
     31 void FrameConsumerBridge::Initialize(FrameProducer* producer) {
     32   DCHECK(!frame_producer_);
     33   frame_producer_ = producer;
     34   DCHECK(frame_producer_);
     35 }
     36 
     37 void FrameConsumerBridge::ApplyBuffer(const webrtc::DesktopSize& view_size,
     38                                       const webrtc::DesktopRect& clip_area,
     39                                       webrtc::DesktopFrame* buffer,
     40                                       const webrtc::DesktopRegion& region,
     41                                       const webrtc::DesktopRegion& shape) {
     42   DCHECK(frame_producer_);
     43   if (!view_size_.equals(view_size)) {
     44     // Drop the frame, since the data belongs to the previous generation,
     45     // before SetSourceSize() called SetOutputSizeAndClip().
     46     ReturnBuffer(buffer);
     47     return;
     48   }
     49 
     50   // This call completes synchronously.
     51   callback_.Run(view_size, buffer, region);
     52 
     53   // Recycle |buffer| by returning it to |frame_producer_| as the next buffer
     54   frame_producer_->DrawBuffer(buffer);
     55 }
     56 
     57 void FrameConsumerBridge::ReturnBuffer(webrtc::DesktopFrame* buffer) {
     58   DCHECK(frame_producer_);
     59   ScopedVector<webrtc::DesktopFrame>::iterator it =
     60       std::find(buffers_.begin(), buffers_.end(), buffer);
     61 
     62   DCHECK(it != buffers_.end());
     63   buffers_.erase(it);
     64 }
     65 
     66 void FrameConsumerBridge::SetSourceSize(const webrtc::DesktopSize& source_size,
     67                                         const webrtc::DesktopVector& dpi) {
     68   DCHECK(frame_producer_);
     69   view_size_ = source_size;
     70   webrtc::DesktopRect clip_area = webrtc::DesktopRect::MakeSize(view_size_);
     71   frame_producer_->SetOutputSizeAndClip(view_size_, clip_area);
     72 
     73   // Now that the size is well known, ask the producer to start drawing
     74   DrawWithNewBuffer();
     75 }
     76 
     77 FrameConsumerBridge::PixelFormat FrameConsumerBridge::GetPixelFormat() {
     78   return FORMAT_RGBA;
     79 }
     80 
     81 void FrameConsumerBridge::DrawWithNewBuffer() {
     82   DCHECK(frame_producer_);
     83   webrtc::DesktopFrame* buffer = new webrtc::BasicDesktopFrame(view_size_);
     84   buffers_.push_back(buffer);
     85   frame_producer_->DrawBuffer(buffer);
     86 }
     87 
     88 }  // namespace remoting
     89