xref: /aosp_15_r20/external/openscreen/cast/standalone_receiver/streaming_playback_controller.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1 // Copyright 2019 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 
5 #include "cast/standalone_receiver/streaming_playback_controller.h"
6 
7 #include <string>
8 
9 #if defined(CAST_STANDALONE_RECEIVER_HAVE_EXTERNAL_LIBS)
10 #include "cast/standalone_receiver/sdl_audio_player.h"  // nogncheck
11 #include "cast/standalone_receiver/sdl_glue.h"          // nogncheck
12 #include "cast/standalone_receiver/sdl_video_player.h"  // nogncheck
13 #else
14 #include "cast/standalone_receiver/dummy_player.h"  // nogncheck
15 #endif  // defined(CAST_STANDALONE_RECEIVER_HAVE_EXTERNAL_LIBS)
16 
17 #include "util/trace_logging.h"
18 
19 namespace openscreen {
20 namespace cast {
21 
22 StreamingPlaybackController::Client::~Client() = default;
23 
24 #if defined(CAST_STANDALONE_RECEIVER_HAVE_EXTERNAL_LIBS)
StreamingPlaybackController(TaskRunner * task_runner,StreamingPlaybackController::Client * client)25 StreamingPlaybackController::StreamingPlaybackController(
26     TaskRunner* task_runner,
27     StreamingPlaybackController::Client* client)
28     : task_runner_(task_runner),
29       client_(client),
30       sdl_event_loop_(task_runner_, [this] {
31         client_->OnPlaybackError(this,
32                                  Error{Error::Code::kOperationCancelled,
33                                        std::string("SDL event loop closed.")});
34       }) {
35   OSP_DCHECK(task_runner_ != nullptr);
36   OSP_DCHECK(client_ != nullptr);
37   constexpr int kDefaultWindowWidth = 1280;
38   constexpr int kDefaultWindowHeight = 720;
39   window_ = MakeUniqueSDLWindow(
40       "Cast Streaming Receiver Demo",
41       SDL_WINDOWPOS_UNDEFINED /* initial X position */,
42       SDL_WINDOWPOS_UNDEFINED /* initial Y position */, kDefaultWindowWidth,
43       kDefaultWindowHeight, SDL_WINDOW_RESIZABLE);
44   OSP_CHECK(window_) << "Failed to create SDL window: " << SDL_GetError();
45   renderer_ = MakeUniqueSDLRenderer(window_.get(), -1, 0);
46   OSP_CHECK(renderer_) << "Failed to create SDL renderer: " << SDL_GetError();
47 
48   sdl_event_loop_.RegisterForKeyboardEvent(
__anonbb8123350202(const SDL_KeyboardEvent& event) 49       [this](const SDL_KeyboardEvent& event) {
50         this->HandleKeyboardEvent(event);
51       });
52 }
53 #else
StreamingPlaybackController(TaskRunner * task_runner,StreamingPlaybackController::Client * client)54 StreamingPlaybackController::StreamingPlaybackController(
55     TaskRunner* task_runner,
56     StreamingPlaybackController::Client* client)
57     : task_runner_(task_runner), client_(client) {
58   OSP_DCHECK(task_runner_ != nullptr);
59   OSP_DCHECK(client_ != nullptr);
60 }
61 #endif  // defined(CAST_STANDALONE_RECEIVER_HAVE_EXTERNAL_LIBS)
62 
OnNegotiated(const ReceiverSession * session,ReceiverSession::ConfiguredReceivers receivers)63 void StreamingPlaybackController::OnNegotiated(
64     const ReceiverSession* session,
65     ReceiverSession::ConfiguredReceivers receivers) {
66   TRACE_DEFAULT_SCOPED(TraceCategory::kStandaloneReceiver);
67   Initialize(receivers);
68 }
69 
OnRemotingNegotiated(const ReceiverSession * session,ReceiverSession::RemotingNegotiation negotiation)70 void StreamingPlaybackController::OnRemotingNegotiated(
71     const ReceiverSession* session,
72     ReceiverSession::RemotingNegotiation negotiation) {
73   remoting_receiver_ =
74       std::make_unique<SimpleRemotingReceiver>(negotiation.messenger);
75   remoting_receiver_->SendInitializeMessage(
76       [this, receivers = negotiation.receivers](AudioCodec audio_codec,
77                                                 VideoCodec video_codec) {
78         // The configurations in |negotiation| do not have the actual codecs,
79         // only REMOTE_AUDIO and REMOTE_VIDEO. Once we receive the
80         // initialization callback method, we can override with the actual
81         // codecs here.
82         auto mutable_receivers = receivers;
83         mutable_receivers.audio_config.codec = audio_codec;
84         mutable_receivers.video_config.codec = video_codec;
85         Initialize(mutable_receivers);
86       });
87 }
88 
OnReceiversDestroying(const ReceiverSession * session,ReceiversDestroyingReason reason)89 void StreamingPlaybackController::OnReceiversDestroying(
90     const ReceiverSession* session,
91     ReceiversDestroyingReason reason) {
92   OSP_LOG_INFO << "Receivers are currently destroying, resetting SDL players.";
93   audio_player_.reset();
94   video_player_.reset();
95 }
96 
OnError(const ReceiverSession * session,Error error)97 void StreamingPlaybackController::OnError(const ReceiverSession* session,
98                                           Error error) {
99   client_->OnPlaybackError(this, error);
100 }
101 
Initialize(ReceiverSession::ConfiguredReceivers receivers)102 void StreamingPlaybackController::Initialize(
103     ReceiverSession::ConfiguredReceivers receivers) {
104 #if defined(CAST_STANDALONE_RECEIVER_HAVE_EXTERNAL_LIBS)
105   OSP_LOG_INFO << "Successfully negotiated a session, creating SDL players.";
106   if (receivers.audio_receiver) {
107     audio_player_ = std::make_unique<SDLAudioPlayer>(
108         &Clock::now, task_runner_, receivers.audio_receiver,
109         receivers.audio_config.codec, [this] {
110           client_->OnPlaybackError(this, audio_player_->error_status());
111         });
112   }
113   if (receivers.video_receiver) {
114     video_player_ = std::make_unique<SDLVideoPlayer>(
115         &Clock::now, task_runner_, receivers.video_receiver,
116         receivers.video_config.codec, renderer_.get(), [this] {
117           client_->OnPlaybackError(this, video_player_->error_status());
118         });
119   }
120 #else
121   if (receivers.audio_receiver) {
122     audio_player_ = std::make_unique<DummyPlayer>(receivers.audio_receiver);
123   }
124 
125   if (receivers.video_receiver) {
126     video_player_ = std::make_unique<DummyPlayer>(receivers.video_receiver);
127   }
128 #endif  // defined(CAST_STANDALONE_RECEIVER_HAVE_EXTERNAL_LIBS)
129 }
130 
131 #if defined(CAST_STANDALONE_RECEIVER_HAVE_EXTERNAL_LIBS)
HandleKeyboardEvent(const SDL_KeyboardEvent & event)132 void StreamingPlaybackController::HandleKeyboardEvent(
133     const SDL_KeyboardEvent& event) {
134   // We only handle keyboard events if we are remoting.
135   if (!remoting_receiver_) {
136     return;
137   }
138 
139   switch (event.keysym.sym) {
140     // See codes here: https://wiki.libsdl.org/SDL_Scancode
141     case SDLK_KP_SPACE:  // fallthrough, "Keypad Space"
142     case SDLK_SPACE:     // "Space"
143       is_playing_ = !is_playing_;
144       remoting_receiver_->SendPlaybackRateMessage(is_playing_ ? 1.0 : 0.0);
145       break;
146   }
147 }
148 #endif
149 
150 }  // namespace cast
151 }  // namespace openscreen
152