1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "host/frontend/webrtc/libdevice/recording_manager.h"
17
18 #include <thread>
19 #include <vector>
20
21 #include <android-base/logging.h>
22 #include <rtc_base/time_utils.h>
23
24 #include "common/libs/fs/shared_buf.h"
25 #include "common/libs/fs/shared_fd.h"
26 #include "common/libs/utils/files.h"
27 #include "host/frontend/webrtc/libdevice/local_recorder.h"
28 #include "host/libs/config/cuttlefish_config.h"
29
30 namespace cuttlefish {
31 namespace webrtc_streaming {
32
RecordingManager()33 RecordingManager::RecordingManager() {
34 auto cvd_config = cuttlefish::CuttlefishConfig::Get();
35 CHECK(cvd_config);
36 auto instance = cvd_config->ForDefaultInstance();
37
38 instance_name_ = instance.instance_name();
39 recording_directory_ = instance.PerInstancePath("recording/");
40 recording_ = false;
41 }
42
AddSource(size_t width,size_t height,std::shared_ptr<webrtc::VideoTrackSourceInterface> video,const std::string & label)43 void RecordingManager::AddSource(
44 size_t width, size_t height,
45 std::shared_ptr<webrtc::VideoTrackSourceInterface> video,
46 const std::string& label) {
47 LOG(VERBOSE) << "Display source is initiated in recording_manager. ";
48
49 std::lock_guard<std::mutex> lock(mutex_);
50
51 auto source = std::make_unique<Source>();
52 source->width_ = width;
53 source->height_ = height;
54 source->video_ = video;
55 sources_[label] = std::move(source);
56
57 if (recording_) {
58 StartSingleRecorder(label);
59 }
60 video_source_ready_signal_.notify_one();
61 }
62
RemoveSource(const std::string & label)63 void RecordingManager::RemoveSource(const std::string& label) {
64 LOG(VERBOSE) << "Display source is removed in recording_manager. ";
65 std::lock_guard<std::mutex> lock(mutex_);
66
67 auto existing_recorder = local_recorders_.find(label);
68 if (existing_recorder != local_recorders_.end()) {
69 existing_recorder->second->Stop();
70 local_recorders_.erase(existing_recorder);
71 }
72
73 sources_.erase(label);
74 video_source_ready_signal_.notify_one();
75 }
76
Start()77 void RecordingManager::Start() {
78 std::lock_guard<std::mutex> lock(mutex_);
79 if (recording_) {
80 LOG(VERBOSE) << "Video recording has been started! ";
81 return;
82 }
83
84 for (auto& [label, source] : sources_) {
85 StartSingleRecorder(label);
86 }
87 recording_ = true;
88 }
89
Stop()90 void RecordingManager::Stop() {
91 std::lock_guard<std::mutex> lock(mutex_);
92 if (!recording_) {
93 LOG(VERBOSE) << "Video recording is not started, do noting in Stop.";
94 return;
95 }
96
97 for (auto& [label, local_recorder] : local_recorders_) {
98 local_recorder->Stop();
99 }
100 recording_ = false;
101
102 local_recorders_.clear();
103 };
104
WaitForSources(size_t num_sources)105 void RecordingManager::WaitForSources(size_t num_sources) {
106 std::unique_lock<std::mutex> lock(mutex_);
107 while (sources_.size() < num_sources) {
108 video_source_ready_signal_.wait(lock);
109 }
110 }
111
StartSingleRecorder(const std::string & label)112 void RecordingManager::StartSingleRecorder(const std::string& label) {
113 auto existing_source = sources_.find(label);
114 if (existing_source == sources_.end()) {
115 LOG(WARNING) << "Video recording is failed, no video source for: " << label;
116 return;
117 }
118
119 int recording_time = rtc::TimeMillis();
120 std::string recording_path = fmt::format("{}recording_{}_{}_{}.webm", recording_directory_,
121 instance_name_, label, recording_time);
122 std::unique_ptr<cuttlefish::webrtc_streaming::LocalRecorder> local_recorder =
123 LocalRecorder::Create(recording_path);
124 CHECK(local_recorder) << "Could not create local recorder";
125 local_recorder->AddDisplay(label, existing_source->second->width_,
126 existing_source->second->height_, existing_source->second->video_);
127 local_recorders_[label] = std::move(local_recorder);
128 }
129
130 } // namespace webrtc_streaming
131 } // namespace cuttlefish
132