OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/client/rectangle_update_decoder.h" | 5 #include "remoting/client/rectangle_update_decoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/location.h" | 10 #include "base/location.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
13 #include "remoting/base/util.h" | 13 #include "remoting/base/util.h" |
14 #include "remoting/codec/video_decoder.h" | 14 #include "remoting/codec/video_decoder.h" |
15 #include "remoting/codec/video_decoder_verbatim.h" | 15 #include "remoting/codec/video_decoder_verbatim.h" |
16 #include "remoting/codec/video_decoder_vp8.h" | 16 #include "remoting/codec/video_decoder_vp8.h" |
17 #include "remoting/client/frame_consumer.h" | 17 #include "remoting/client/frame_consumer.h" |
18 #include "remoting/protocol/session_config.h" | 18 #include "remoting/protocol/session_config.h" |
| 19 #include "third_party/libyuv/include/libyuv/convert_argb.h" |
19 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" | 20 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
20 | 21 |
21 using base::Passed; | 22 using base::Passed; |
22 using remoting::protocol::ChannelConfig; | 23 using remoting::protocol::ChannelConfig; |
23 using remoting::protocol::SessionConfig; | 24 using remoting::protocol::SessionConfig; |
24 | 25 |
25 namespace remoting { | 26 namespace remoting { |
26 | 27 |
| 28 class RgbToBgrVideoDecoderFilter : public VideoDecoder { |
| 29 public: |
| 30 RgbToBgrVideoDecoderFilter(scoped_ptr<VideoDecoder> parent) |
| 31 : parent_(parent.Pass()) { |
| 32 } |
| 33 |
| 34 virtual void Initialize(const SkISize& screen_size) OVERRIDE { |
| 35 parent_->Initialize(screen_size); |
| 36 } |
| 37 |
| 38 virtual bool DecodePacket(const VideoPacket& packet) OVERRIDE { |
| 39 return parent_->DecodePacket(packet); |
| 40 } |
| 41 |
| 42 virtual void Invalidate(const SkISize& view_size, |
| 43 const SkRegion& region) OVERRIDE { |
| 44 return parent_->Invalidate(view_size, region); |
| 45 } |
| 46 |
| 47 virtual void RenderFrame(const SkISize& view_size, |
| 48 const SkIRect& clip_area, |
| 49 uint8* image_buffer, |
| 50 int image_stride, |
| 51 SkRegion* output_region) OVERRIDE { |
| 52 parent_->RenderFrame(view_size, clip_area, image_buffer, image_stride, |
| 53 output_region); |
| 54 |
| 55 // Byte-swap the pixels for compatibility with the android.graphics.Bitmap |
| 56 // class. |
| 57 // TODO(lambroslambrou): Refactor so that the VideoDecoder produces data |
| 58 // in the right byte-order, instead of swapping it here. |
| 59 for (SkRegion::Iterator i(*output_region); !i.done(); i.next()) { |
| 60 SkIRect rect = i.rect(); |
| 61 uint8* pixels = image_buffer + (rect.top() * image_stride) + |
| 62 (rect.left() * kBytesPerPixel); |
| 63 libyuv::ABGRToARGB(pixels, image_stride, pixels, image_stride, |
| 64 rect.width(), rect.height()); |
| 65 } |
| 66 } |
| 67 |
| 68 virtual const SkRegion* GetImageShape() OVERRIDE { |
| 69 return parent_->GetImageShape(); |
| 70 } |
| 71 |
| 72 private: |
| 73 scoped_ptr<VideoDecoder> parent_; |
| 74 }; |
| 75 |
27 RectangleUpdateDecoder::RectangleUpdateDecoder( | 76 RectangleUpdateDecoder::RectangleUpdateDecoder( |
28 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 77 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
29 scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, | 78 scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, |
30 scoped_refptr<FrameConsumerProxy> consumer) | 79 scoped_refptr<FrameConsumerProxy> consumer) |
31 : main_task_runner_(main_task_runner), | 80 : main_task_runner_(main_task_runner), |
32 decode_task_runner_(decode_task_runner), | 81 decode_task_runner_(decode_task_runner), |
33 consumer_(consumer), | 82 consumer_(consumer), |
34 source_size_(SkISize::Make(0, 0)), | 83 source_size_(SkISize::Make(0, 0)), |
35 source_dpi_(SkIPoint::Make(0, 0)), | 84 source_dpi_(SkIPoint::Make(0, 0)), |
36 view_size_(SkISize::Make(0, 0)), | 85 view_size_(SkISize::Make(0, 0)), |
37 clip_area_(SkIRect::MakeEmpty()), | 86 clip_area_(SkIRect::MakeEmpty()), |
38 paint_scheduled_(false), | 87 paint_scheduled_(false), |
39 latest_sequence_number_(0) { | 88 latest_sequence_number_(0) { |
40 } | 89 } |
41 | 90 |
42 RectangleUpdateDecoder::~RectangleUpdateDecoder() { | 91 RectangleUpdateDecoder::~RectangleUpdateDecoder() { |
43 } | 92 } |
44 | 93 |
45 void RectangleUpdateDecoder::Initialize(const SessionConfig& config) { | 94 void RectangleUpdateDecoder::Initialize(const SessionConfig& config) { |
46 // Initialize decoder based on the selected codec. | 95 // Initialize decoder based on the selected codec. |
47 ChannelConfig::Codec codec = config.video_config().codec; | 96 ChannelConfig::Codec codec = config.video_config().codec; |
48 if (codec == ChannelConfig::CODEC_VERBATIM) { | 97 if (codec == ChannelConfig::CODEC_VERBATIM) { |
49 decoder_.reset(new VideoDecoderVerbatim()); | 98 decoder_.reset(new VideoDecoderVerbatim()); |
50 } else if (codec == ChannelConfig::CODEC_VP8) { | 99 } else if (codec == ChannelConfig::CODEC_VP8) { |
51 decoder_.reset(new VideoDecoderVp8()); | 100 decoder_.reset(new VideoDecoderVp8()); |
52 } else { | 101 } else { |
53 NOTREACHED() << "Invalid Encoding found: " << codec; | 102 NOTREACHED() << "Invalid Encoding found: " << codec; |
54 } | 103 } |
| 104 |
| 105 if (consumer_->GetPixelFormat() == FrameConsumer::FORMAT_RGBA) { |
| 106 scoped_ptr<VideoDecoder> wrapper( |
| 107 new RgbToBgrVideoDecoderFilter(decoder_.Pass())); |
| 108 decoder_ = wrapper.Pass(); |
| 109 } |
55 } | 110 } |
56 | 111 |
57 void RectangleUpdateDecoder::DecodePacket(scoped_ptr<VideoPacket> packet, | 112 void RectangleUpdateDecoder::DecodePacket(scoped_ptr<VideoPacket> packet, |
58 const base::Closure& done) { | 113 const base::Closure& done) { |
59 DCHECK(decode_task_runner_->BelongsToCurrentThread()); | 114 DCHECK(decode_task_runner_->BelongsToCurrentThread()); |
60 | 115 |
61 base::ScopedClosureRunner done_runner(done); | 116 base::ScopedClosureRunner done_runner(done); |
62 | 117 |
63 bool decoder_needs_reset = false; | 118 bool decoder_needs_reset = false; |
64 bool notify_size_or_dpi_change = false; | 119 bool notify_size_or_dpi_change = false; |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 | 332 |
278 done.Run(); | 333 done.Run(); |
279 } | 334 } |
280 | 335 |
281 ChromotingStats* RectangleUpdateDecoder::GetStats() { | 336 ChromotingStats* RectangleUpdateDecoder::GetStats() { |
282 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 337 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
283 return &stats_; | 338 return &stats_; |
284 } | 339 } |
285 | 340 |
286 } // namespace remoting | 341 } // namespace remoting |
OLD | NEW |