| Index: trunk/src/content/renderer/media/video_frame_compositor.cc
|
| ===================================================================
|
| --- trunk/src/content/renderer/media/video_frame_compositor.cc (revision 266950)
|
| +++ trunk/src/content/renderer/media/video_frame_compositor.cc (working copy)
|
| @@ -4,6 +4,11 @@
|
|
|
| #include "content/renderer/media/video_frame_compositor.h"
|
|
|
| +#include "base/bind.h"
|
| +#include "base/location.h"
|
| +#include "base/single_thread_task_runner.h"
|
| +#include "cc/layers/video_frame_provider.h"
|
| +#include "content/renderer/render_thread_impl.h"
|
| #include "media/base/video_frame.h"
|
|
|
| namespace content {
|
| @@ -27,52 +32,141 @@
|
| return false;
|
| }
|
|
|
| +class VideoFrameCompositor::Internal : public cc::VideoFrameProvider {
|
| + public:
|
| + Internal(
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner,
|
| + const base::Callback<void(gfx::Size)>& natural_size_changed_cb,
|
| + const base::Callback<void(bool)>& opacity_changed_cb)
|
| + : compositor_task_runner_(compositor_task_runner),
|
| + natural_size_changed_cb_(natural_size_changed_cb),
|
| + opacity_changed_cb_(opacity_changed_cb),
|
| + client_(NULL),
|
| + compositor_notification_pending_(false),
|
| + frames_dropped_before_compositor_was_notified_(0) {}
|
| +
|
| + virtual ~Internal() {
|
| + if (client_)
|
| + client_->StopUsingProvider();
|
| + }
|
| +
|
| + void DeleteSoon() {
|
| + compositor_task_runner_->DeleteSoon(FROM_HERE, this);
|
| + }
|
| +
|
| + void UpdateCurrentFrame(const scoped_refptr<media::VideoFrame>& frame) {
|
| + base::AutoLock auto_lock(lock_);
|
| +
|
| + if (current_frame_ &&
|
| + current_frame_->natural_size() != frame->natural_size()) {
|
| + natural_size_changed_cb_.Run(frame->natural_size());
|
| + }
|
| +
|
| + if (!current_frame_ || IsOpaque(current_frame_) != IsOpaque(frame)) {
|
| + opacity_changed_cb_.Run(IsOpaque(frame));
|
| + }
|
| +
|
| + current_frame_ = frame;
|
| +
|
| + // Count frames as dropped if and only if we updated the frame but didn't
|
| + // finish notifying the compositor for the previous frame.
|
| + if (compositor_notification_pending_) {
|
| + if (frames_dropped_before_compositor_was_notified_ < kuint32max)
|
| + ++frames_dropped_before_compositor_was_notified_;
|
| + return;
|
| + }
|
| +
|
| + compositor_notification_pending_ = true;
|
| + compositor_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&Internal::NotifyCompositorOfNewFrame,
|
| + base::Unretained(this)));
|
| + }
|
| +
|
| + uint32 GetFramesDroppedBeforeCompositorWasNotified() {
|
| + base::AutoLock auto_lock(lock_);
|
| + return frames_dropped_before_compositor_was_notified_;
|
| + }
|
| +
|
| + void SetFramesDroppedBeforeCompositorWasNotifiedForTesting(
|
| + uint32 dropped_frames) {
|
| + base::AutoLock auto_lock(lock_);
|
| + frames_dropped_before_compositor_was_notified_ = dropped_frames;
|
| + }
|
| +
|
| + // cc::VideoFrameProvider implementation.
|
| + virtual void SetVideoFrameProviderClient(
|
| + cc::VideoFrameProvider::Client* client) OVERRIDE {
|
| + if (client_)
|
| + client_->StopUsingProvider();
|
| + client_ = client;
|
| + }
|
| +
|
| + virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE {
|
| + base::AutoLock auto_lock(lock_);
|
| + return current_frame_;
|
| + }
|
| +
|
| + virtual void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame)
|
| + OVERRIDE {}
|
| +
|
| + private:
|
| + void NotifyCompositorOfNewFrame() {
|
| + base::AutoLock auto_lock(lock_);
|
| + compositor_notification_pending_ = false;
|
| + if (client_)
|
| + client_->DidReceiveFrame();
|
| + }
|
| +
|
| + scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
|
| + base::Callback<void(gfx::Size)> natural_size_changed_cb_;
|
| + base::Callback<void(bool)> opacity_changed_cb_;
|
| +
|
| + cc::VideoFrameProvider::Client* client_;
|
| +
|
| + base::Lock lock_;
|
| + scoped_refptr<media::VideoFrame> current_frame_;
|
| + bool compositor_notification_pending_;
|
| + uint32 frames_dropped_before_compositor_was_notified_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Internal);
|
| +};
|
| +
|
| VideoFrameCompositor::VideoFrameCompositor(
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner,
|
| const base::Callback<void(gfx::Size)>& natural_size_changed_cb,
|
| const base::Callback<void(bool)>& opacity_changed_cb)
|
| - : natural_size_changed_cb_(natural_size_changed_cb),
|
| - opacity_changed_cb_(opacity_changed_cb),
|
| - client_(NULL) {
|
| + : internal_(new Internal(compositor_task_runner,
|
| + natural_size_changed_cb,
|
| + opacity_changed_cb)) {
|
| }
|
|
|
| VideoFrameCompositor::~VideoFrameCompositor() {
|
| - if (client_)
|
| - client_->StopUsingProvider();
|
| + internal_->DeleteSoon();
|
| }
|
|
|
| -void VideoFrameCompositor::SetVideoFrameProviderClient(
|
| - cc::VideoFrameProvider::Client* client) {
|
| - if (client_)
|
| - client_->StopUsingProvider();
|
| - client_ = client;
|
| +cc::VideoFrameProvider* VideoFrameCompositor::GetVideoFrameProvider() {
|
| + return internal_;
|
| }
|
|
|
| +void VideoFrameCompositor::UpdateCurrentFrame(
|
| + const scoped_refptr<media::VideoFrame>& frame) {
|
| + internal_->UpdateCurrentFrame(frame);
|
| +}
|
| +
|
| scoped_refptr<media::VideoFrame> VideoFrameCompositor::GetCurrentFrame() {
|
| - base::AutoLock auto_lock(lock_);
|
| - return current_frame_;
|
| + return internal_->GetCurrentFrame();
|
| }
|
|
|
| -void VideoFrameCompositor::PutCurrentFrame(
|
| - const scoped_refptr<media::VideoFrame>& frame) {
|
| +uint32 VideoFrameCompositor::GetFramesDroppedBeforeCompositorWasNotified() {
|
| + return internal_->GetFramesDroppedBeforeCompositorWasNotified();
|
| }
|
|
|
| -void VideoFrameCompositor::UpdateCurrentFrame(
|
| - const scoped_refptr<media::VideoFrame>& frame) {
|
| - base::AutoLock auto_lock(lock_);
|
| -
|
| - if (current_frame_ &&
|
| - current_frame_->natural_size() != frame->natural_size()) {
|
| - natural_size_changed_cb_.Run(frame->natural_size());
|
| - }
|
| -
|
| - if (!current_frame_ || IsOpaque(current_frame_) != IsOpaque(frame)) {
|
| - opacity_changed_cb_.Run(IsOpaque(frame));
|
| - }
|
| -
|
| - current_frame_ = frame;
|
| -
|
| - if (client_)
|
| - client_->DidReceiveFrame();
|
| +void
|
| +VideoFrameCompositor::SetFramesDroppedBeforeCompositorWasNotifiedForTesting(
|
| + uint32 dropped_frames) {
|
| + internal_->SetFramesDroppedBeforeCompositorWasNotifiedForTesting(
|
| + dropped_frames);
|
| }
|
|
|
| } // namespace content
|
|
|