blob: fbc96066d38fcd91276278dc888ced77f76d0e7d [file] [log] [blame]
// 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