15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "remoting/client/software_video_renderer.h" 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <list> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/callback_helpers.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/single_thread_task_runner.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/util.h" 168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "remoting/client/frame_consumer.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/video_decoder.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/video_decoder_verbatim.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if !defined(MEDIA_DISABLE_LIBVPX) 208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "remoting/codec/video_decoder_vpx.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // !defined(MEDIA_DISABLE_LIBVPX) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/protocol/session_config.h" 234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "third_party/libyuv/include/libyuv/convert_argb.h" 247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Passed; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using remoting::protocol::ChannelConfig; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using remoting::protocol::SessionConfig; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// This class wraps a VideoDecoder and byte-swaps the pixels for compatibility 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// with the android.graphics.Bitmap class. 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// TODO(lambroslambrou): Refactor so that the VideoDecoder produces data 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// in the right byte-order, instead of swapping it here. 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class RgbToBgrVideoDecoderFilter : public VideoDecoder { 374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public: 384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) RgbToBgrVideoDecoderFilter(scoped_ptr<VideoDecoder> parent) 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : parent_(parent.Pass()) { 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual void Initialize(const webrtc::DesktopSize& screen_size) OVERRIDE { 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) parent_->Initialize(screen_size); 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual bool DecodePacket(const VideoPacket& packet) OVERRIDE { 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return parent_->DecodePacket(packet); 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual void Invalidate(const webrtc::DesktopSize& view_size, 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const webrtc::DesktopRegion& region) OVERRIDE { 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return parent_->Invalidate(view_size, region); 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual void RenderFrame(const webrtc::DesktopSize& view_size, 564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const webrtc::DesktopRect& clip_area, 574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uint8* image_buffer, 584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int image_stride, 594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) webrtc::DesktopRegion* output_region) OVERRIDE { 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) parent_->RenderFrame(view_size, clip_area, image_buffer, image_stride, 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) output_region); 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (webrtc::DesktopRegion::Iterator i(*output_region); !i.IsAtEnd(); 644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) i.Advance()) { 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) webrtc::DesktopRect rect = i.rect(); 664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uint8* pixels = image_buffer + (rect.top() * image_stride) + 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) (rect.left() * kBytesPerPixel); 684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) libyuv::ABGRToARGB(pixels, image_stride, pixels, image_stride, 694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) rect.width(), rect.height()); 704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual const webrtc::DesktopRegion* GetImageShape() OVERRIDE { 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return parent_->GetImageShape(); 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private: 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<VideoDecoder> parent_; 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}; 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class SoftwareVideoRenderer::Core { 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Core(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<FrameConsumerProxy> consumer); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~Core(); 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void Initialize(const protocol::SessionConfig& config); 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void DrawBuffer(webrtc::DesktopFrame* buffer); 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void InvalidateRegion(const webrtc::DesktopRegion& region); 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void RequestReturnBuffers(const base::Closure& done); 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SetOutputSizeAndClip( 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const webrtc::DesktopSize& view_size, 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const webrtc::DesktopRect& clip_area); 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Decodes the contents of |packet|. DecodePacket may keep a reference to 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // |packet| so the |packet| must remain alive and valid until |done| is 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // executed. 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void DecodePacket(scoped_ptr<VideoPacket> packet, const base::Closure& done); 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Paints the invalidated region to the next available buffer and returns it 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // to the consumer. 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void SchedulePaint(); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void DoPaint(); 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner_; 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<FrameConsumerProxy> consumer_; 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<VideoDecoder> decoder_; 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Remote screen size in pixels. 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) webrtc::DesktopSize source_size_; 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Vertical and horizontal DPI of the remote screen. 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) webrtc::DesktopVector source_dpi_; 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The current dimensions of the frame consumer view. 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) webrtc::DesktopSize view_size_; 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) webrtc::DesktopRect clip_area_; 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The drawing buffers supplied by the frame consumer. 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::list<webrtc::DesktopFrame*> buffers_; 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Flag used to coalesce runs of SchedulePaint()s into a single DoPaint(). 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool paint_scheduled_; 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WeakPtrFactory<Core> weak_factory_; 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SoftwareVideoRenderer::Core::Core( 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<FrameConsumerProxy> consumer) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : main_task_runner_(main_task_runner), 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decode_task_runner_(decode_task_runner), 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_(consumer), 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paint_scheduled_(false), 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_factory_(this) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SoftwareVideoRenderer::Core::~Core() { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::Core::Initialize(const SessionConfig& config) { 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(decode_task_runner_->BelongsToCurrentThread()); 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize decoder based on the selected codec. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelConfig::Codec codec = config.video_config().codec; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (codec == ChannelConfig::CODEC_VERBATIM) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_.reset(new VideoDecoderVerbatim()); 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if !defined(MEDIA_DISABLE_LIBVPX) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (codec == ChannelConfig::CODEC_VP8) { 1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) decoder_ = VideoDecoderVpx::CreateForVP8(); 1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } else if (codec == ChannelConfig::CODEC_VP9) { 1568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) decoder_ = VideoDecoderVpx::CreateForVP9(); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // !defined(MEDIA_DISABLE_LIBVPX) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "Invalid Encoding found: " << codec; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (consumer_->GetPixelFormat() == FrameConsumer::FORMAT_RGBA) { 1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<VideoDecoder> wrapper( 1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) new RgbToBgrVideoDecoderFilter(decoder_.Pass())); 1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) decoder_ = wrapper.Pass(); 1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::Core::DecodePacket(scoped_ptr<VideoPacket> packet, 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Closure& done) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(decode_task_runner_->BelongsToCurrentThread()); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool decoder_needs_reset = false; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool notify_size_or_dpi_change = false; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the packet includes screen size or DPI information, store them. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (packet->format().has_screen_width() && 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) packet->format().has_screen_height()) { 179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopSize source_size(packet->format().screen_width(), 180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) packet->format().screen_height()); 181d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!source_size_.equals(source_size)) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_size_ = source_size; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_needs_reset = true; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notify_size_or_dpi_change = true; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (packet->format().has_x_dpi() && packet->format().has_y_dpi()) { 188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopVector source_dpi(packet->format().x_dpi(), 189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) packet->format().y_dpi()); 190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!source_dpi.equals(source_dpi_)) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_dpi_ = source_dpi; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notify_size_or_dpi_change = true; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we've never seen a screen size, ignore the packet. 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (source_size_.is_empty()) { 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) main_task_runner_->PostTask(FROM_HERE, base::Bind(done)); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decoder_needs_reset) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_->Initialize(source_size_); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (notify_size_or_dpi_change) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->SetSourceSize(source_size_, source_dpi_); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (decoder_->DecodePacket(*packet.get())) { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) LOG(ERROR) << "DecodePacket() failed."; 21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) main_task_runner_->PostTask(FROM_HERE, base::Bind(done)); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::Core::SchedulePaint() { 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(decode_task_runner_->BelongsToCurrentThread()); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (paint_scheduled_) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paint_scheduled_ = true; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decode_task_runner_->PostTask( 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, base::Bind(&SoftwareVideoRenderer::Core::DoPaint, 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_factory_.GetWeakPtr())); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::Core::DoPaint() { 2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(decode_task_runner_->BelongsToCurrentThread()); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(paint_scheduled_); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) paint_scheduled_ = false; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the view size is empty or we have no output buffers ready, return. 232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (buffers_.empty() || view_size_.is_empty()) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If no Decoder is initialized, or the host dimensions are empty, return. 236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!decoder_.get() || source_size_.is_empty()) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Draw the invalidated region to the buffer. 2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch webrtc::DesktopFrame* buffer = buffers_.front(); 241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion output_region; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_->RenderFrame(view_size_, clip_area_, 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) buffer->data(), buffer->stride(), &output_region); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notify the consumer that painting is done. 246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!output_region.is_empty()) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffers_.pop_front(); 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) consumer_->ApplyBuffer(view_size_, clip_area_, buffer, output_region, 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *decoder_->GetImageShape()); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::Core::RequestReturnBuffers( 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::Closure& done) { 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(decode_task_runner_->BelongsToCurrentThread()); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!buffers_.empty()) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->ReturnBuffer(buffers_.front()); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffers_.pop_front(); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!done.is_null()) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Run(); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::Core::DrawBuffer(webrtc::DesktopFrame* buffer) { 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(decode_task_runner_->BelongsToCurrentThread()); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(clip_area_.width() <= buffer->size().width() && 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clip_area_.height() <= buffer->size().height()); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffers_.push_back(buffer); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::Core::InvalidateRegion( 276d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRegion& region) { 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(decode_task_runner_->BelongsToCurrentThread()); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decoder_.get()) { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_->Invalidate(view_size_, region); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::Core::SetOutputSizeAndClip( 286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopSize& view_size, 287d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const webrtc::DesktopRect& clip_area) { 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(decode_task_runner_->BelongsToCurrentThread()); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The whole frame needs to be repainted if the scaling factor has changed. 291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!view_size_.equals(view_size) && decoder_.get()) { 292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) webrtc::DesktopRegion region; 293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) region.AddRect(webrtc::DesktopRect::MakeSize(view_size)); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_->Invalidate(view_size, region); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 297d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (!view_size_.equals(view_size) || 298d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) !clip_area_.equals(clip_area)) { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_size_ = view_size; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clip_area_ = clip_area; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return buffers that are smaller than needed to the consumer for 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reuse/reallocation. 3047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch std::list<webrtc::DesktopFrame*>::iterator i = buffers_.begin(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (i != buffers_.end()) { 3067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if ((*i)->size().width() < clip_area_.width() || 3077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch (*i)->size().height() < clip_area_.height()) { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) consumer_->ReturnBuffer(*i); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = buffers_.erase(i); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SoftwareVideoRenderer::SoftwareVideoRenderer( 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<FrameConsumerProxy> consumer) 3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : decode_task_runner_(decode_task_runner), 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) core_(new Core(main_task_runner, decode_task_runner, consumer)), 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) latest_sequence_number_(0), 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_factory_(this) { 3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(CalledOnValidThread()); 328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SoftwareVideoRenderer::~SoftwareVideoRenderer() { 3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) decode_task_runner_->DeleteSoon(FROM_HERE, core_.release()); 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::Initialize( 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const protocol::SessionConfig& config) { 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) decode_task_runner_->PostTask( 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, base::Bind(&SoftwareVideoRenderer::Core::Initialize, 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(core_.get()), config)); 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ChromotingStats* SoftwareVideoRenderer::GetStats() { 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return &stats_; 3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::ProcessVideoPacket(scoped_ptr<VideoPacket> packet, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& done) { 3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(CalledOnValidThread()); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the video packet is empty then drop it. Empty packets are used to 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // maintain activity on the network. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!packet->has_data() || packet->data().size() == 0) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Run(); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add one frame to the counter. 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stats_.video_frame_rate()->Record(1); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record other statistics received from host. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stats_.video_bandwidth()->Record(packet->data().size()); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (packet->has_capture_time_ms()) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stats_.video_capture_ms()->Record(packet->capture_time_ms()); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (packet->has_encode_time_ms()) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stats_.video_encode_ms()->Record(packet->encode_time_ms()); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (packet->has_client_sequence_number() && 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) packet->client_sequence_number() > latest_sequence_number_) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) latest_sequence_number_ = packet->client_sequence_number(); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta round_trip_latency = 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time::Now() - 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time::FromInternalValue(packet->client_sequence_number()); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stats_.round_trip_ms()->Record(round_trip_latency.InMilliseconds()); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Measure the latency between the last packet being received and presented. 378d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Time decode_start = base::Time::Now(); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Closure decode_done = base::Bind(&SoftwareVideoRenderer::OnPacketDone, 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_factory_.GetWeakPtr(), 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) decode_start, done); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decode_task_runner_->PostTask(FROM_HERE, base::Bind( 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &SoftwareVideoRenderer::Core::DecodePacket, 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(core_.get()), base::Passed(&packet), decode_done)); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::DrawBuffer(webrtc::DesktopFrame* buffer) { 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) decode_task_runner_->PostTask( 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, base::Bind(&SoftwareVideoRenderer::Core::DrawBuffer, 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(core_.get()), buffer)); 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::InvalidateRegion( 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const webrtc::DesktopRegion& region) { 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) decode_task_runner_->PostTask( 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, base::Bind(&SoftwareVideoRenderer::Core::InvalidateRegion, 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(core_.get()), region)); 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::RequestReturnBuffers(const base::Closure& done) { 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) decode_task_runner_->PostTask( 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&SoftwareVideoRenderer::Core::RequestReturnBuffers, 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(core_.get()), done)); 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::SetOutputSizeAndClip( 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const webrtc::DesktopSize& view_size, 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const webrtc::DesktopRect& clip_area) { 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) decode_task_runner_->PostTask( 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FROM_HERE, 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&SoftwareVideoRenderer::Core::SetOutputSizeAndClip, 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(core_.get()), view_size, clip_area)); 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void SoftwareVideoRenderer::OnPacketDone(base::Time decode_start, 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Closure& done) { 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(CalledOnValidThread()); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 422d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Record the latency between the packet being received and presented. 423d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) stats_.video_decode_ms()->Record( 424d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) (base::Time::Now() - decode_start).InMilliseconds()); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Run(); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 430