| // Copyright 2017 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 "platform/graphics/VideoFrameSubmitter.h" |
| |
| #include "cc/base/filter_operations.h" |
| #include "cc/scheduler/video_frame_controller.h" |
| #include "components/viz/common/surfaces/local_surface_id_allocator.h" |
| #include "media/base/video_frame.h" |
| #include "public/platform/InterfaceProvider.h" |
| #include "public/platform/Platform.h" |
| #include "public/platform/modules/offscreencanvas/offscreen_canvas_surface.mojom-blink.h" |
| #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h" |
| |
| namespace blink { |
| |
| VideoFrameSubmitter::VideoFrameSubmitter( |
| cc::VideoFrameProvider* provider, |
| WebContextProviderCallback context_provider_callback) |
| : provider_(provider), |
| binding_(this), |
| context_provider_callback_(std::move(context_provider_callback)), |
| is_rendering_(false) { |
| current_local_surface_id_ = local_surface_id_allocator_.GenerateId(); |
| } |
| |
| VideoFrameSubmitter::~VideoFrameSubmitter() {} |
| |
| void VideoFrameSubmitter::StopUsingProvider() { |
| if (is_rendering_) |
| StopRendering(); |
| provider_ = nullptr; |
| } |
| |
| void VideoFrameSubmitter::StopRendering() { |
| DCHECK(is_rendering_); |
| viz::BeginFrameAck current_begin_frame_ack = |
| viz::BeginFrameAck::CreateManualAckWithDamage(); |
| SubmitFrame(current_begin_frame_ack); |
| is_rendering_ = false; |
| compositor_frame_sink_->SetNeedsBeginFrame(false); |
| } |
| |
| void VideoFrameSubmitter::DidReceiveFrame() { |
| if (!is_rendering_) { |
| viz::BeginFrameAck current_begin_frame_ack = |
| viz::BeginFrameAck::CreateManualAckWithDamage(); |
| SubmitFrame(current_begin_frame_ack); |
| } |
| } |
| |
| void VideoFrameSubmitter::StartRendering() { |
| DCHECK(!is_rendering_); |
| compositor_frame_sink_->SetNeedsBeginFrame(true); |
| is_rendering_ = true; |
| } |
| |
| void VideoFrameSubmitter::StartSubmitting(const viz::FrameSinkId& id) { |
| DCHECK(id.is_valid()); |
| |
| resource_provider_ = |
| std::make_unique<VideoFrameResourceProvider>(context_provider_callback_); |
| |
| // Class to be renamed. |
| mojom::blink::OffscreenCanvasProviderPtr canvas_provider; |
| Platform::Current()->GetInterfaceProvider()->GetInterface( |
| mojo::MakeRequest(&canvas_provider)); |
| |
| viz::mojom::blink::CompositorFrameSinkClientPtr client; |
| binding_.Bind(mojo::MakeRequest(&client)); |
| canvas_provider->CreateCompositorFrameSink( |
| id, std::move(client), mojo::MakeRequest(&compositor_frame_sink_)); |
| } |
| |
| void VideoFrameSubmitter::SubmitFrame(viz::BeginFrameAck begin_frame_ack) { |
| DCHECK(compositor_frame_sink_); |
| if (!provider_) |
| return; |
| |
| viz::CompositorFrame compositor_frame; |
| scoped_refptr<media::VideoFrame> video_frame = provider_->GetCurrentFrame(); |
| |
| std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create(); |
| |
| // TODO(lethalantidote): Replace with true size. Current is just for test. |
| gfx::Size viewport_size(10000, 10000); |
| render_pass->SetNew(50, gfx::Rect(viewport_size), gfx::Rect(viewport_size), |
| gfx::Transform()); |
| render_pass->filters = cc::FilterOperations(); |
| resource_provider_->AppendQuads(*render_pass); |
| compositor_frame.render_pass_list.push_back(std::move(render_pass)); |
| compositor_frame.metadata.begin_frame_ack = begin_frame_ack; |
| compositor_frame.metadata.device_scale_factor = 1; |
| compositor_frame.metadata.may_contain_video = true; |
| |
| // TODO(lethalantidote): Address third/fourth arg in SubmitCompositorFrame. |
| compositor_frame_sink_->SubmitCompositorFrame( |
| current_local_surface_id_, std::move(compositor_frame), nullptr, 0); |
| provider_->PutCurrentFrame(); |
| } |
| |
| void VideoFrameSubmitter::OnBeginFrame(const viz::BeginFrameArgs& args) { |
| viz::BeginFrameAck current_begin_frame_ack = |
| viz::BeginFrameAck(args.source_id, args.sequence_number, false); |
| if (args.type == viz::BeginFrameArgs::MISSED) { |
| compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack); |
| return; |
| } |
| |
| current_begin_frame_ack.has_damage = true; |
| |
| if (!provider_ || |
| !provider_->UpdateCurrentFrame(args.frame_time + args.interval, |
| args.frame_time + 2 * args.interval) || |
| !is_rendering_) { |
| compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack); |
| return; |
| } |
| |
| SubmitFrame(current_begin_frame_ack); |
| } |
| |
| void VideoFrameSubmitter::DidReceiveCompositorFrameAck( |
| const WTF::Vector<viz::ReturnedResource>& resources) {} |
| |
| void VideoFrameSubmitter::DidPresentCompositorFrame( |
| uint32_t presentation_token, |
| ::mojo::common::mojom::blink::TimeTicksPtr time, |
| WTF::TimeDelta refresh, |
| uint32_t flags) {} |
| |
| void VideoFrameSubmitter::DidDiscardCompositorFrame( |
| uint32_t presentation_token) {} |
| } // namespace blink |