software_video_renderer.cc 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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
  3. // found in the LICENSE file.
  4. #include "remoting/client/software_video_renderer.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/callback.h"
  9. #include "base/callback_helpers.h"
  10. #include "base/location.h"
  11. #include "base/logging.h"
  12. #include "base/memory/ptr_util.h"
  13. #include "base/task/single_thread_task_runner.h"
  14. #include "base/task/task_runner_util.h"
  15. #include "remoting/base/util.h"
  16. #include "remoting/client/client_context.h"
  17. #include "remoting/codec/video_decoder.h"
  18. #include "remoting/codec/video_decoder_verbatim.h"
  19. #include "remoting/codec/video_decoder_vpx.h"
  20. #include "remoting/proto/video.pb.h"
  21. #include "remoting/protocol/frame_consumer.h"
  22. #include "remoting/protocol/frame_stats.h"
  23. #include "remoting/protocol/performance_tracker.h"
  24. #include "remoting/protocol/session_config.h"
  25. #include "third_party/libyuv/include/libyuv/convert_argb.h"
  26. #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
  27. using remoting::protocol::ChannelConfig;
  28. using remoting::protocol::SessionConfig;
  29. namespace remoting {
  30. namespace {
  31. std::unique_ptr<webrtc::DesktopFrame> DoDecodeFrame(
  32. VideoDecoder* decoder,
  33. std::unique_ptr<VideoPacket> packet,
  34. std::unique_ptr<webrtc::DesktopFrame> frame) {
  35. if (!decoder->DecodePacket(*packet, frame.get()))
  36. frame.reset();
  37. return frame;
  38. }
  39. } // namespace
  40. SoftwareVideoRenderer::SoftwareVideoRenderer(protocol::FrameConsumer* consumer)
  41. : consumer_(consumer) {
  42. thread_checker_.DetachFromThread();
  43. }
  44. SoftwareVideoRenderer::SoftwareVideoRenderer(
  45. std::unique_ptr<protocol::FrameConsumer> consumer)
  46. : SoftwareVideoRenderer(consumer.get()) {
  47. owned_consumer_ = std::move(consumer);
  48. }
  49. SoftwareVideoRenderer::~SoftwareVideoRenderer() {
  50. DCHECK(thread_checker_.CalledOnValidThread());
  51. if (decoder_)
  52. decode_task_runner_->DeleteSoon(FROM_HERE, decoder_.release());
  53. }
  54. bool SoftwareVideoRenderer::Initialize(
  55. const ClientContext& client_context,
  56. protocol::FrameStatsConsumer* stats_consumer) {
  57. DCHECK(thread_checker_.CalledOnValidThread());
  58. decode_task_runner_ = client_context.decode_task_runner();
  59. stats_consumer_ = stats_consumer;
  60. return true;
  61. }
  62. void SoftwareVideoRenderer::OnSessionConfig(
  63. const protocol::SessionConfig& config) {
  64. DCHECK(thread_checker_.CalledOnValidThread());
  65. // Initialize decoder based on the selected codec.
  66. ChannelConfig::Codec codec = config.video_config().codec;
  67. if (codec == ChannelConfig::CODEC_VERBATIM) {
  68. decoder_ = std::make_unique<VideoDecoderVerbatim>();
  69. } else if (codec == ChannelConfig::CODEC_VP8) {
  70. decoder_ = VideoDecoderVpx::CreateForVP8();
  71. } else if (codec == ChannelConfig::CODEC_VP9) {
  72. decoder_ = VideoDecoderVpx::CreateForVP9();
  73. } else if (codec == ChannelConfig::CODEC_H264) {
  74. NOTIMPLEMENTED() << "H264 software decoding is not supported.";
  75. } else {
  76. NOTREACHED() << "Invalid Encoding found: " << codec;
  77. }
  78. decoder_->SetPixelFormat(
  79. (consumer_->GetPixelFormat() == protocol::FrameConsumer::FORMAT_BGRA)
  80. ? VideoDecoder::PixelFormat::BGRA
  81. : VideoDecoder::PixelFormat::RGBA);
  82. }
  83. protocol::VideoStub* SoftwareVideoRenderer::GetVideoStub() {
  84. DCHECK(thread_checker_.CalledOnValidThread());
  85. return this;
  86. }
  87. protocol::FrameConsumer* SoftwareVideoRenderer::GetFrameConsumer() {
  88. return consumer_;
  89. }
  90. protocol::FrameStatsConsumer* SoftwareVideoRenderer::GetFrameStatsConsumer() {
  91. return stats_consumer_;
  92. }
  93. void SoftwareVideoRenderer::ProcessVideoPacket(
  94. std::unique_ptr<VideoPacket> packet,
  95. base::OnceClosure done) {
  96. DCHECK(thread_checker_.CalledOnValidThread());
  97. base::ScopedClosureRunner done_runner(std::move(done));
  98. std::unique_ptr<protocol::FrameStats> frame_stats(new protocol::FrameStats());
  99. frame_stats->host_stats =
  100. protocol::HostFrameStats::GetForVideoPacket(*packet);
  101. frame_stats->client_stats.time_received = base::TimeTicks::Now();
  102. // If the video packet is empty then there is nothing to decode. Empty packets
  103. // are used to maintain activity on the network. Stats for such packets still
  104. // need to be reported.
  105. if (!packet->has_data() || packet->data().size() == 0) {
  106. if (stats_consumer_)
  107. stats_consumer_->OnVideoFrameStats(*frame_stats);
  108. return;
  109. }
  110. if (packet->format().has_screen_width() &&
  111. packet->format().has_screen_height()) {
  112. source_size_.set(packet->format().screen_width(),
  113. packet->format().screen_height());
  114. }
  115. if (packet->format().has_x_dpi() && packet->format().has_y_dpi()) {
  116. webrtc::DesktopVector source_dpi(packet->format().x_dpi(),
  117. packet->format().y_dpi());
  118. if (!source_dpi.equals(source_dpi_)) {
  119. source_dpi_ = source_dpi;
  120. }
  121. }
  122. if (source_size_.is_empty()) {
  123. LOG(ERROR) << "Received VideoPacket with unknown size.";
  124. return;
  125. }
  126. std::unique_ptr<webrtc::DesktopFrame> frame =
  127. consumer_->AllocateFrame(source_size_);
  128. frame->set_dpi(source_dpi_);
  129. base::PostTaskAndReplyWithResult(
  130. decode_task_runner_.get(), FROM_HERE,
  131. base::BindOnce(&DoDecodeFrame, decoder_.get(), std::move(packet),
  132. std::move(frame)),
  133. base::BindOnce(&SoftwareVideoRenderer::RenderFrame,
  134. weak_factory_.GetWeakPtr(), std::move(frame_stats),
  135. done_runner.Release()));
  136. }
  137. void SoftwareVideoRenderer::RenderFrame(
  138. std::unique_ptr<protocol::FrameStats> stats,
  139. base::OnceClosure done,
  140. std::unique_ptr<webrtc::DesktopFrame> frame) {
  141. DCHECK(thread_checker_.CalledOnValidThread());
  142. stats->client_stats.time_decoded = base::TimeTicks::Now();
  143. if (!frame) {
  144. if (done)
  145. std::move(done).Run();
  146. return;
  147. }
  148. consumer_->DrawFrame(std::move(frame),
  149. base::BindOnce(&SoftwareVideoRenderer::OnFrameRendered,
  150. weak_factory_.GetWeakPtr(),
  151. std::move(stats), std::move(done)));
  152. }
  153. void SoftwareVideoRenderer::OnFrameRendered(
  154. std::unique_ptr<protocol::FrameStats> stats,
  155. base::OnceClosure done) {
  156. DCHECK(thread_checker_.CalledOnValidThread());
  157. stats->client_stats.time_rendered = base::TimeTicks::Now();
  158. if (stats_consumer_)
  159. stats_consumer_->OnVideoFrameStats(*stats);
  160. if (done)
  161. std::move(done).Run();
  162. }
  163. } // namespace remoting