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