// Copyright 2015 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/protocol/webrtc_video_renderer_adapter.h" #include #include "base/bind.h" #include "base/callback.h" #include "base/location.h" #include "base/memory/scoped_ptr.h" #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" #include "remoting/protocol/frame_consumer.h" #include "third_party/libyuv/include/libyuv/video_common.h" #include "third_party/webrtc/media/base/videoframe.h" #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" namespace remoting { namespace protocol { WebrtcVideoRendererAdapter::WebrtcVideoRendererAdapter( scoped_refptr media_stream, FrameConsumer* frame_consumer) : media_stream_(std::move(media_stream)), frame_consumer_(frame_consumer), output_format_fourcc_(frame_consumer_->GetPixelFormat() == FrameConsumer::FORMAT_BGRA ? libyuv::FOURCC_ARGB : libyuv::FOURCC_ABGR), task_runner_(base::ThreadTaskRunnerHandle::Get()), weak_factory_(this) { webrtc::VideoTrackVector video_tracks = media_stream_->GetVideoTracks(); if (video_tracks.empty()) { LOG(ERROR) << "Received media stream with no video tracks."; return; } if (video_tracks.size() > 1U) { LOG(WARNING) << "Received media stream with multiple video tracks."; } video_tracks[0]->AddOrUpdateSink(this, rtc::VideoSinkWants()); } WebrtcVideoRendererAdapter::~WebrtcVideoRendererAdapter() { DCHECK(task_runner_->BelongsToCurrentThread()); } void WebrtcVideoRendererAdapter::OnFrame(const cricket::VideoFrame& frame) { // TODO(sergeyu): WebRTC calls OnFrame on a separate thread it creates. // FrameConsumer normally expects to be called on the network thread, so we // cannot call FrameConsumer::AllocateFrame() here and instead // BasicDesktopFrame is created directly. This will not work correctly with // all FrameConsumer implementations. Fix this somehow. scoped_ptr rgb_frame(new webrtc::BasicDesktopFrame( webrtc::DesktopSize(frame.GetWidth(), frame.GetHeight()))); frame.ConvertToRgbBuffer( output_format_fourcc_, rgb_frame->data(), std::abs(rgb_frame->stride()) * rgb_frame->size().height(), rgb_frame->stride()); rgb_frame->mutable_updated_region()->AddRect( webrtc::DesktopRect::MakeSize(rgb_frame->size())); task_runner_->PostTask( FROM_HERE, base::Bind(&WebrtcVideoRendererAdapter::DrawFrame, weak_factory_.GetWeakPtr(), base::Passed(&rgb_frame))); } void WebrtcVideoRendererAdapter::DrawFrame( scoped_ptr frame) { DCHECK(task_runner_->BelongsToCurrentThread()); frame_consumer_->DrawFrame(std::move(frame), base::Closure()); } } // namespace remoting } // namespace protocol