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