| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/software_video_renderer.h" | 5 #include "remoting/client/software_video_renderer.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| 11 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 12 #include "base/location.h" | 12 #include "base/location.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/memory/ptr_util.h" |
| 14 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
| 15 #include "base/task_runner_util.h" | 16 #include "base/task_runner_util.h" |
| 16 #include "remoting/base/util.h" | 17 #include "remoting/base/util.h" |
| 17 #include "remoting/codec/video_decoder.h" | 18 #include "remoting/codec/video_decoder.h" |
| 18 #include "remoting/codec/video_decoder_verbatim.h" | 19 #include "remoting/codec/video_decoder_verbatim.h" |
| 19 #include "remoting/codec/video_decoder_vpx.h" | 20 #include "remoting/codec/video_decoder_vpx.h" |
| 20 #include "remoting/proto/video.pb.h" | 21 #include "remoting/proto/video.pb.h" |
| 21 #include "remoting/protocol/frame_consumer.h" | 22 #include "remoting/protocol/frame_consumer.h" |
| 22 #include "remoting/protocol/session_config.h" | 23 #include "remoting/protocol/session_config.h" |
| 23 #include "third_party/libyuv/include/libyuv/convert_argb.h" | 24 #include "third_party/libyuv/include/libyuv/convert_argb.h" |
| 24 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" | 25 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
| 25 | 26 |
| 26 using remoting::protocol::ChannelConfig; | 27 using remoting::protocol::ChannelConfig; |
| 27 using remoting::protocol::SessionConfig; | 28 using remoting::protocol::SessionConfig; |
| 28 | 29 |
| 29 namespace remoting { | 30 namespace remoting { |
| 30 | 31 |
| 31 namespace { | 32 namespace { |
| 32 | 33 |
| 33 // This class wraps a VideoDecoder and byte-swaps the pixels for compatibility | 34 // This class wraps a VideoDecoder and byte-swaps the pixels for compatibility |
| 34 // with the android.graphics.Bitmap class. | 35 // with the android.graphics.Bitmap class. |
| 35 // TODO(lambroslambrou): Refactor so that the VideoDecoder produces data | 36 // TODO(lambroslambrou): Refactor so that the VideoDecoder produces data |
| 36 // in the right byte-order, instead of swapping it here. | 37 // in the right byte-order, instead of swapping it here. |
| 37 class RgbToBgrVideoDecoderFilter : public VideoDecoder { | 38 class RgbToBgrVideoDecoderFilter : public VideoDecoder { |
| 38 public: | 39 public: |
| 39 RgbToBgrVideoDecoderFilter(scoped_ptr<VideoDecoder> parent) | 40 RgbToBgrVideoDecoderFilter(std::unique_ptr<VideoDecoder> parent) |
| 40 : parent_(std::move(parent)) {} | 41 : parent_(std::move(parent)) {} |
| 41 | 42 |
| 42 bool DecodePacket(const VideoPacket& packet, | 43 bool DecodePacket(const VideoPacket& packet, |
| 43 webrtc::DesktopFrame* frame) override { | 44 webrtc::DesktopFrame* frame) override { |
| 44 if (!parent_->DecodePacket(packet, frame)) | 45 if (!parent_->DecodePacket(packet, frame)) |
| 45 return false; | 46 return false; |
| 46 for (webrtc::DesktopRegion::Iterator i(frame->updated_region()); | 47 for (webrtc::DesktopRegion::Iterator i(frame->updated_region()); |
| 47 !i.IsAtEnd(); i.Advance()) { | 48 !i.IsAtEnd(); i.Advance()) { |
| 48 webrtc::DesktopRect rect = i.rect(); | 49 webrtc::DesktopRect rect = i.rect(); |
| 49 uint8_t* pixels = frame->data() + (rect.top() * frame->stride()) + | 50 uint8_t* pixels = frame->data() + (rect.top() * frame->stride()) + |
| 50 (rect.left() * webrtc::DesktopFrame::kBytesPerPixel); | 51 (rect.left() * webrtc::DesktopFrame::kBytesPerPixel); |
| 51 libyuv::ABGRToARGB(pixels, frame->stride(), pixels, frame->stride(), | 52 libyuv::ABGRToARGB(pixels, frame->stride(), pixels, frame->stride(), |
| 52 rect.width(), rect.height()); | 53 rect.width(), rect.height()); |
| 53 } | 54 } |
| 54 | 55 |
| 55 return true; | 56 return true; |
| 56 } | 57 } |
| 57 | 58 |
| 58 private: | 59 private: |
| 59 scoped_ptr<VideoDecoder> parent_; | 60 std::unique_ptr<VideoDecoder> parent_; |
| 60 }; | 61 }; |
| 61 | 62 |
| 62 scoped_ptr<webrtc::DesktopFrame> DoDecodeFrame( | 63 std::unique_ptr<webrtc::DesktopFrame> DoDecodeFrame( |
| 63 VideoDecoder* decoder, | 64 VideoDecoder* decoder, |
| 64 scoped_ptr<VideoPacket> packet, | 65 std::unique_ptr<VideoPacket> packet, |
| 65 scoped_ptr<webrtc::DesktopFrame> frame) { | 66 std::unique_ptr<webrtc::DesktopFrame> frame) { |
| 66 if (!decoder->DecodePacket(*packet, frame.get())) | 67 if (!decoder->DecodePacket(*packet, frame.get())) |
| 67 frame.reset(); | 68 frame.reset(); |
| 68 return frame; | 69 return frame; |
| 69 } | 70 } |
| 70 | 71 |
| 71 } // namespace | 72 } // namespace |
| 72 | 73 |
| 73 SoftwareVideoRenderer::SoftwareVideoRenderer( | 74 SoftwareVideoRenderer::SoftwareVideoRenderer( |
| 74 scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, | 75 scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner, |
| 75 protocol::FrameConsumer* consumer, | 76 protocol::FrameConsumer* consumer, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 95 } else if (codec == ChannelConfig::CODEC_VP8) { | 96 } else if (codec == ChannelConfig::CODEC_VP8) { |
| 96 decoder_ = VideoDecoderVpx::CreateForVP8(); | 97 decoder_ = VideoDecoderVpx::CreateForVP8(); |
| 97 } else if (codec == ChannelConfig::CODEC_VP9) { | 98 } else if (codec == ChannelConfig::CODEC_VP9) { |
| 98 decoder_ = VideoDecoderVpx::CreateForVP9(); | 99 decoder_ = VideoDecoderVpx::CreateForVP9(); |
| 99 } else { | 100 } else { |
| 100 NOTREACHED() << "Invalid Encoding found: " << codec; | 101 NOTREACHED() << "Invalid Encoding found: " << codec; |
| 101 } | 102 } |
| 102 | 103 |
| 103 if (consumer_->GetPixelFormat() == protocol::FrameConsumer::FORMAT_RGBA) { | 104 if (consumer_->GetPixelFormat() == protocol::FrameConsumer::FORMAT_RGBA) { |
| 104 decoder_ = | 105 decoder_ = |
| 105 make_scoped_ptr(new RgbToBgrVideoDecoderFilter(std::move(decoder_))); | 106 base::WrapUnique(new RgbToBgrVideoDecoderFilter(std::move(decoder_))); |
| 106 } | 107 } |
| 107 } | 108 } |
| 108 | 109 |
| 109 protocol::VideoStub* SoftwareVideoRenderer::GetVideoStub() { | 110 protocol::VideoStub* SoftwareVideoRenderer::GetVideoStub() { |
| 110 DCHECK(thread_checker_.CalledOnValidThread()); | 111 DCHECK(thread_checker_.CalledOnValidThread()); |
| 111 return this; | 112 return this; |
| 112 } | 113 } |
| 113 | 114 |
| 114 protocol::FrameConsumer* SoftwareVideoRenderer::GetFrameConsumer() { | 115 protocol::FrameConsumer* SoftwareVideoRenderer::GetFrameConsumer() { |
| 115 return consumer_; | 116 return consumer_; |
| 116 } | 117 } |
| 117 | 118 |
| 118 void SoftwareVideoRenderer::ProcessVideoPacket(scoped_ptr<VideoPacket> packet, | 119 void SoftwareVideoRenderer::ProcessVideoPacket( |
| 119 const base::Closure& done) { | 120 std::unique_ptr<VideoPacket> packet, |
| 121 const base::Closure& done) { |
| 120 DCHECK(thread_checker_.CalledOnValidThread()); | 122 DCHECK(thread_checker_.CalledOnValidThread()); |
| 121 | 123 |
| 122 base::ScopedClosureRunner done_runner(done); | 124 base::ScopedClosureRunner done_runner(done); |
| 123 | 125 |
| 124 if (perf_tracker_) | 126 if (perf_tracker_) |
| 125 perf_tracker_->RecordVideoPacketStats(*packet); | 127 perf_tracker_->RecordVideoPacketStats(*packet); |
| 126 | 128 |
| 127 // If the video packet is empty then drop it. Empty packets are used to | 129 // If the video packet is empty then drop it. Empty packets are used to |
| 128 // maintain activity on the network. | 130 // maintain activity on the network. |
| 129 if (!packet->has_data() || packet->data().size() == 0) { | 131 if (!packet->has_data() || packet->data().size() == 0) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 142 if (!source_dpi.equals(source_dpi_)) { | 144 if (!source_dpi.equals(source_dpi_)) { |
| 143 source_dpi_ = source_dpi; | 145 source_dpi_ = source_dpi; |
| 144 } | 146 } |
| 145 } | 147 } |
| 146 | 148 |
| 147 if (source_size_.is_empty()) { | 149 if (source_size_.is_empty()) { |
| 148 LOG(ERROR) << "Received VideoPacket with unknown size."; | 150 LOG(ERROR) << "Received VideoPacket with unknown size."; |
| 149 return; | 151 return; |
| 150 } | 152 } |
| 151 | 153 |
| 152 scoped_ptr<webrtc::DesktopFrame> frame = | 154 std::unique_ptr<webrtc::DesktopFrame> frame = |
| 153 consumer_->AllocateFrame(source_size_); | 155 consumer_->AllocateFrame(source_size_); |
| 154 frame->set_dpi(source_dpi_); | 156 frame->set_dpi(source_dpi_); |
| 155 | 157 |
| 156 int32_t frame_id = packet->frame_id(); | 158 int32_t frame_id = packet->frame_id(); |
| 157 base::PostTaskAndReplyWithResult( | 159 base::PostTaskAndReplyWithResult( |
| 158 decode_task_runner_.get(), FROM_HERE, | 160 decode_task_runner_.get(), FROM_HERE, |
| 159 base::Bind(&DoDecodeFrame, decoder_.get(), base::Passed(&packet), | 161 base::Bind(&DoDecodeFrame, decoder_.get(), base::Passed(&packet), |
| 160 base::Passed(&frame)), | 162 base::Passed(&frame)), |
| 161 base::Bind(&SoftwareVideoRenderer::RenderFrame, | 163 base::Bind(&SoftwareVideoRenderer::RenderFrame, |
| 162 weak_factory_.GetWeakPtr(), frame_id, done_runner.Release())); | 164 weak_factory_.GetWeakPtr(), frame_id, done_runner.Release())); |
| 163 } | 165 } |
| 164 | 166 |
| 165 void SoftwareVideoRenderer::RenderFrame( | 167 void SoftwareVideoRenderer::RenderFrame( |
| 166 int32_t frame_id, | 168 int32_t frame_id, |
| 167 const base::Closure& done, | 169 const base::Closure& done, |
| 168 scoped_ptr<webrtc::DesktopFrame> frame) { | 170 std::unique_ptr<webrtc::DesktopFrame> frame) { |
| 169 DCHECK(thread_checker_.CalledOnValidThread()); | 171 DCHECK(thread_checker_.CalledOnValidThread()); |
| 170 | 172 |
| 171 if (perf_tracker_) | 173 if (perf_tracker_) |
| 172 perf_tracker_->OnFrameDecoded(frame_id); | 174 perf_tracker_->OnFrameDecoded(frame_id); |
| 173 | 175 |
| 174 if (!frame) { | 176 if (!frame) { |
| 175 if (!done.is_null()) | 177 if (!done.is_null()) |
| 176 done.Run(); | 178 done.Run(); |
| 177 return; | 179 return; |
| 178 } | 180 } |
| 179 | 181 |
| 180 consumer_->DrawFrame(std::move(frame), | 182 consumer_->DrawFrame(std::move(frame), |
| 181 base::Bind(&SoftwareVideoRenderer::OnFrameRendered, | 183 base::Bind(&SoftwareVideoRenderer::OnFrameRendered, |
| 182 weak_factory_.GetWeakPtr(), frame_id, done)); | 184 weak_factory_.GetWeakPtr(), frame_id, done)); |
| 183 } | 185 } |
| 184 | 186 |
| 185 void SoftwareVideoRenderer::OnFrameRendered(int32_t frame_id, | 187 void SoftwareVideoRenderer::OnFrameRendered(int32_t frame_id, |
| 186 const base::Closure& done) { | 188 const base::Closure& done) { |
| 187 DCHECK(thread_checker_.CalledOnValidThread()); | 189 DCHECK(thread_checker_.CalledOnValidThread()); |
| 188 | 190 |
| 189 if (perf_tracker_) | 191 if (perf_tracker_) |
| 190 perf_tracker_->OnFramePainted(frame_id); | 192 perf_tracker_->OnFramePainted(frame_id); |
| 191 | 193 |
| 192 if (!done.is_null()) | 194 if (!done.is_null()) |
| 193 done.Run(); | 195 done.Run(); |
| 194 } | 196 } |
| 195 | 197 |
| 196 } // namespace remoting | 198 } // namespace remoting |
| OLD | NEW |