1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97

fuchsia_web / webengine / browser / receiver_session_client.cc [blame]

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "fuchsia_web/webengine/browser/receiver_session_client.h"

#include "base/functional/bind.h"
#include "components/cast/message_port/fuchsia/message_port_fuchsia.h"
#include "components/cast/message_port/message_port.h"
#include "components/cast_streaming/browser/public/receiver_config.h"
#include "components/cast_streaming/browser/public/receiver_session.h"
#include "components/cast_streaming/common/public/mojom/demuxer_connector.mojom.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/video_decoder_config.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/size.h"

namespace {
constexpr size_t kMaxFrameRate = 30;
}  // namespace

ReceiverSessionClient::ReceiverSessionClient(
    fidl::InterfaceRequest<fuchsia::web::MessagePort> message_port_request,
    bool video_only_receiver)
    : message_port_request_(std::move(message_port_request)),
      video_only_receiver_(video_only_receiver) {
  DCHECK(message_port_request_);
}

ReceiverSessionClient::~ReceiverSessionClient() = default;

void ReceiverSessionClient::SetMojoEndpoints(
    mojo::AssociatedRemote<cast_streaming::mojom::DemuxerConnector>
        demuxer_connector,
    mojo::AssociatedRemote<cast_streaming::mojom::RendererController>
        renderer_controller) {
  DCHECK(message_port_request_);

  // TODO: Add streaming session Constraints based on system capabilities
  // (see crbug.com/1013412) and DisplayDescription (see crbug.com/1087520).
  // TODO(crbug.com/40185682): Only populate codecs corresponding to those
  // called out by build flags.
  std::vector<media::VideoCodec> video_codecs;
  std::vector<media::AudioCodec> audio_codecs;

  // Codecs are set in order of preference for the receiver, i.e. H264 is
  // preferred above VP8 in the below code.
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
  video_codecs.push_back(media::VideoCodec::kH264);
#endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
  video_codecs.push_back(media::VideoCodec::kVP8);

  if (!video_only_receiver_) {
    audio_codecs.push_back(media::AudioCodec::kOpus);
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
    audio_codecs.push_back(media::AudioCodec::kAAC);
#endif  // BUILDFLAG(USE_PROPRIETARY_CODECS)
  }

  // TODO(crbug.com/40241121): Set config.remoting to expose the device as a
  // valid remoting endpoint when |renderer_controller| is set.
  cast_streaming::ReceiverConfig config(std::move(video_codecs),
                                        std::move(audio_codecs));

  gfx::Size display_resolution =
      display::Screen::GetScreen()->GetPrimaryDisplay().bounds().size();
  config.video_limits.push_back(cast_streaming::ReceiverConfig::VideoLimits{
      .max_pixels_per_second =
          static_cast<int>(display_resolution.width() *
                           display_resolution.height() * kMaxFrameRate),
      .max_dimensions = gfx::Rect(display_resolution),
      .max_frame_rate = kMaxFrameRate});
  config.display_description = cast_streaming::ReceiverConfig::Display{
      .dimensions = gfx::Rect(display_resolution),
      .max_frame_rate = kMaxFrameRate,
      .can_scale_content = true};

  receiver_session_ = cast_streaming::ReceiverSession::Create(
      config,
      base::BindOnce(
          [](fidl::InterfaceRequest<fuchsia::web::MessagePort> port)
              -> std::unique_ptr<cast_api_bindings::MessagePort> {
            return cast_api_bindings::MessagePortFuchsia::Create(
                std::move(port));
          },
          std::move(message_port_request_)));
  if (renderer_controller) {
    receiver_session_->StartStreamingAsync(std::move(demuxer_connector),
                                           std::move(renderer_controller));
  } else {
    receiver_session_->StartStreamingAsync(std::move(demuxer_connector));
  }
}

bool ReceiverSessionClient::HasReceiverSession() {
  return !!receiver_session_;
}