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
FrameConsumerBridge(OnFrameCallback callback)15 FrameConsumerBridge::FrameConsumerBridge(OnFrameCallback callback)
16 : callback_(callback), frame_producer_(NULL) {}
17
~FrameConsumerBridge()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
Initialize(FrameProducer * producer)31 void FrameConsumerBridge::Initialize(FrameProducer* producer) {
32 DCHECK(!frame_producer_);
33 frame_producer_ = producer;
34 DCHECK(frame_producer_);
35 }
36
ApplyBuffer(const webrtc::DesktopSize & view_size,const webrtc::DesktopRect & clip_area,webrtc::DesktopFrame * buffer,const webrtc::DesktopRegion & region,const webrtc::DesktopRegion & shape)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
ReturnBuffer(webrtc::DesktopFrame * buffer)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
SetSourceSize(const webrtc::DesktopSize & source_size,const webrtc::DesktopVector & dpi)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
GetPixelFormat()77 FrameConsumerBridge::PixelFormat FrameConsumerBridge::GetPixelFormat() {
78 return FORMAT_RGBA;
79 }
80
DrawWithNewBuffer()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