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