1 /*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "screen_capture_consumer.h"
17 #include "common/common_macro.h"
18 #include "common/reflect_registration.h"
19 #include "common/sharing_log.h"
20 #include "screen_capture_def.h"
21
22 namespace OHOS {
23 namespace Sharing {
OnFrameBufferUsed()24 void ScreenCaptureConsumer::OnFrameBufferUsed()
25 {
26 ReleaseScreenBuffer();
27 }
28
HandleSpsFrame(BufferDispatcher::Ptr dispatcher,const Frame::Ptr & frame)29 void ScreenCaptureConsumer::HandleSpsFrame(BufferDispatcher::Ptr dispatcher, const Frame::Ptr &frame)
30 {
31 auto spsOld = dispatcher->GetSPS();
32 if (spsOld != nullptr && spsOld->buff != nullptr) {
33 return;
34 }
35 // set sps into buffer dispathcer
36 auto sps = std::make_shared<MediaData>();
37 sps->buff = move(frame);
38 sps->mediaType = MEDIA_TYPE_VIDEO;
39 dispatcher->SetSpsNalu(sps);
40 }
41
HandlePpsFrame(BufferDispatcher::Ptr dispatcher,const Frame::Ptr & frame)42 void ScreenCaptureConsumer::HandlePpsFrame(BufferDispatcher::Ptr dispatcher, const Frame::Ptr &frame)
43 {
44 auto ppsOld = dispatcher->GetPPS();
45 if (ppsOld != nullptr && ppsOld->buff != nullptr) {
46 return;
47 }
48 // set pps into buffer dispather
49 auto pps = std::make_shared<MediaData>();
50 pps->buff = move(frame);
51 pps->mediaType = MEDIA_TYPE_VIDEO;
52 dispatcher->SetPpsNalu(pps);
53 }
54
OnFrame(const Frame::Ptr & frame,FRAME_TYPE frameType,bool keyFrame)55 void ScreenCaptureConsumer::OnFrame(const Frame::Ptr &frame, FRAME_TYPE frameType, bool keyFrame)
56 {
57 SHARING_LOGD("trace.");
58 if (frame == nullptr) {
59 SHARING_LOGE("Screen Capture encodedBuf is null!");
60 return;
61 }
62
63 if (listener_.expired() || IsPaused()) {
64 return;
65 }
66
67 auto listener = listener_.lock();
68 BufferDispatcher::Ptr dispatcher = listener->GetDispatcher();
69 if (dispatcher) {
70 static std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
71 uint32_t len = frame->Size();
72 switch (frameType) {
73 case SPS_FRAME: {
74 SHARING_LOGD("get sps frame, size:%{public}u.", len);
75 HandleSpsFrame(dispatcher, frame);
76 break;
77 }
78 case PPS_FRAME: {
79 SHARING_LOGD("get pps frame, size:%{public}u.", len);
80 HandlePpsFrame(dispatcher, frame);
81 break;
82 }
83 case IDR_FRAME: {
84 std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
85 uint64_t pts = std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count();
86 auto mediaData = dispatcher->RequestDataBuffer(MEDIA_TYPE_VIDEO, len);
87 mediaData->mediaType = MEDIA_TYPE_VIDEO;
88 mediaData->isRaw = false;
89 mediaData->keyFrame = keyFrame;
90 mediaData->pts = pts;
91 SHARING_LOGD("[%{public}" PRId64 "] capture a video into dispatcher:%{public}u, len:%{public}u.",
92 mediaData->pts, dispatcher->GetDispatcherId(), len);
93 mediaData->buff = move(frame);
94 dispatcher->InputData(mediaData);
95 break;
96 }
97 default:
98 break;
99 }
100 }
101 }
102
ScreenCaptureConsumer()103 ScreenCaptureConsumer::ScreenCaptureConsumer()
104 {
105 SHARING_LOGD("capture consumer Id: %{public}u.", GetId());
106 }
107
~ScreenCaptureConsumer()108 ScreenCaptureConsumer::~ScreenCaptureConsumer()
109 {
110 SHARING_LOGD("~ capture consumer Id: %{public}u.", GetId());
111 Release();
112 }
113
HandleProsumerInitState(SharingEvent & event)114 void ScreenCaptureConsumer::HandleProsumerInitState(SharingEvent &event)
115 {
116 SHARING_LOGD("trace.");
117 auto pPrivateMsg = std::make_shared<ScreenCaptureSessionEventMsg>();
118 pPrivateMsg->errorCode = ERR_GENERAL_ERROR;
119
120 auto msg = ConvertEventMsg<ScreenCaptureConsumerEventMsg>(event);
121 if (msg) {
122 SHARING_LOGD("msg convert suc, vcodecId:%{public}d.", msg->videoTrack.codecId);
123 if (msg->audioTrack.codecId != CodecId::CODEC_NONE) {
124 audioTrack_ = msg->audioTrack;
125 }
126
127 if (msg->videoTrack.codecId != CodecId::CODEC_NONE) {
128 videoTrack_ = msg->videoTrack;
129 }
130
131 if (Init(msg->screenId)) {
132 pPrivateMsg->errorCode = ERR_OK;
133 }
134 } else {
135 SHARING_LOGE("msg convert fail!");
136 return;
137 }
138
139 pPrivateMsg->type = EVENT_AGENT_STATE_PROSUMER_INIT;
140 pPrivateMsg->toMgr = ModuleType::MODULE_CONTEXT;
141 pPrivateMsg->fromMgr = ModuleType::MODULE_MEDIACHANNEL;
142 pPrivateMsg->srcId = GetId();
143 pPrivateMsg->dstId = event.eventMsg->srcId;
144 pPrivateMsg->agentId = GetSinkAgentId();
145 pPrivateMsg->prosumerId = GetId();
146 pPrivateMsg->requestId = event.eventMsg->requestId;
147
148 NotifyPrivateEvent(pPrivateMsg);
149 }
150
HandleEvent(SharingEvent & event)151 int32_t ScreenCaptureConsumer::HandleEvent(SharingEvent &event)
152 {
153 SHARING_LOGD("trace.");
154 RETURN_INVALID_IF_NULL(event.eventMsg);
155
156 SHARING_LOGD("eventType: %{public}s = %{public}d, capture consumerId: %{public}u.",
157 std::string(magic_enum::enum_name(event.eventMsg->type)).c_str(), event.eventMsg->type, GetId());
158 switch (event.eventMsg->type) {
159 case EventType::EVENT_SCREEN_CAPTURE_INIT:
160 HandleProsumerInitState(event);
161 break;
162 default:
163 SHARING_LOGI("none process case.");
164 break;
165 }
166
167 return 0;
168 }
169
UpdateOperation(ProsumerStatusMsg::Ptr & statusMsg)170 void ScreenCaptureConsumer::UpdateOperation(ProsumerStatusMsg::Ptr &statusMsg)
171 {
172 SHARING_LOGD("trace.");
173 RETURN_IF_NULL(statusMsg);
174
175 SHARING_LOGD("status: %{public}s consumerId: %{public}u.",
176 std::string(magic_enum::enum_name(static_cast<ProsumerOptRunningStatus>(statusMsg->status))).c_str(),
177 GetId());
178 switch (statusMsg->status) {
179 case ProsumerOptRunningStatus::PROSUMER_INIT:
180 statusMsg->status = PROSUMER_NOTIFY_INIT_SUCCESS;
181 break;
182 case ProsumerOptRunningStatus::PROSUMER_START: {
183 paused_ = false;
184 if (isInit_ && StartCapture()) {
185 statusMsg->status = PROSUMER_NOTIFY_START_SUCCESS;
186 } else {
187 statusMsg->status = PROSUMER_NOTIFY_ERROR;
188 statusMsg->errorCode = ERR_PROSUMER_START;
189 }
190 break;
191 }
192 case ProsumerOptRunningStatus::PROSUMER_PAUSE: {
193 paused_ = true;
194 statusMsg->status = PROSUMER_NOTIFY_PAUSE_SUCCESS;
195 break;
196 }
197 case ProsumerOptRunningStatus::PROSUMER_RESUME: {
198 paused_ = false;
199 statusMsg->status = PROSUMER_NOTIFY_RESUME_SUCCESS;
200 break;
201 }
202 case ProsumerOptRunningStatus::PROSUMER_STOP: {
203 if (StopCapture()) {
204 statusMsg->status = PROSUMER_NOTIFY_STOP_SUCCESS;
205 } else {
206 statusMsg->status = PROSUMER_NOTIFY_ERROR;
207 statusMsg->errorCode = ERR_PROSUMER_STOP;
208 }
209 break;
210 }
211 case ProsumerOptRunningStatus::PROSUMER_DESTROY:
212 Release();
213 SHARING_LOGD("prosumer release success, out.");
214 statusMsg->status = PROSUMER_NOTIFY_DESTROY_SUCCESS;
215 break;
216 default:
217 SHARING_LOGI("none process case.");
218 break;
219 }
220
221 Notify(statusMsg);
222 }
223
Release()224 int32_t ScreenCaptureConsumer::Release()
225 {
226 SHARING_LOGD("trace.");
227 StopCapture();
228
229 SHARING_LOGD("consumerId: %{public}u, capture consumer release=out.", GetId());
230 return 0;
231 }
232
IsPaused()233 bool ScreenCaptureConsumer::IsPaused()
234 {
235 SHARING_LOGD("trace.");
236 return paused_;
237 }
238
ReleaseScreenBuffer()239 int32_t ScreenCaptureConsumer::ReleaseScreenBuffer()
240 {
241 SHARING_LOGD("trace.");
242 if (videoSourceScreen_ == nullptr) {
243 return ERR_GENERAL_ERROR;
244 }
245 return videoSourceScreen_->ReleaseScreenBuffer();
246 }
247
Init(uint64_t screenId)248 bool ScreenCaptureConsumer::Init(uint64_t screenId)
249 {
250 SHARING_LOGD("capture consumerId: %{public}u, codecId: %{public}d.", GetId(), videoTrack_.codecId);
251 std::lock_guard<std::mutex> lock(mutex_);
252 if ((videoTrack_.codecId != CODEC_NONE) && !InitVideoCapture(screenId)) {
253 SHARING_LOGE("capture consumerId: %{public}u, init video capture failed.", GetId());
254 return false;
255 }
256
257 SHARING_LOGD("capture consumerId: %{public}u, success.", GetId());
258 isInit_ = true;
259 return true;
260 }
261
InitVideoCapture(uint64_t screenId)262 bool ScreenCaptureConsumer::InitVideoCapture(uint64_t screenId)
263 {
264 SHARING_LOGD("consumerId: %{public}u.", GetId());
265 VideoSourceConfigure config;
266 config.srcScreenId_ = screenId;
267
268 videoSourceEncoder_ = std::make_shared<VideoSourceEncoder>(shared_from_this());
269 if (!videoSourceEncoder_->InitEncoder(config)) {
270 SHARING_LOGE("InitEncoder failed! %{public}u.", GetId());
271 OnInitVideoCaptureError();
272 return false;
273 }
274 videoSourceScreen_ = std::make_shared<VideoSourceScreen>(videoSourceEncoder_->GetEncoderSurface());
275 videoSourceScreen_->InitScreenSource(config);
276 return true;
277 }
278
InitAudioCapture() const279 bool ScreenCaptureConsumer::InitAudioCapture() const
280 {
281 SHARING_LOGD("trace.");
282 return true;
283 }
284
StartCapture()285 bool ScreenCaptureConsumer::StartCapture()
286 {
287 SHARING_LOGD("trace.");
288 std::lock_guard<std::mutex> lock(mutex_);
289 if (isRunning_ || !isInit_) {
290 return false;
291 }
292
293 isRunning_ = true;
294 if ((videoTrack_.codecId != CODEC_NONE) && !StartVideoCapture()) {
295 SHARING_LOGE("consumerId: %{public}u, start video capture failed.", GetId());
296 isRunning_ = false;
297 return false;
298 }
299
300 SHARING_LOGD("consumerId: %{public}u, success.", GetId());
301 return true;
302 }
303
StartVideoCapture()304 bool ScreenCaptureConsumer::StartVideoCapture()
305 {
306 SHARING_LOGD("trace.");
307 if (videoSourceScreen_ != nullptr) {
308 videoSourceScreen_->StartScreenSourceCapture();
309 }
310 if (videoSourceEncoder_ != nullptr) {
311 videoSourceEncoder_->StartEncoder();
312 }
313 return true;
314 }
315
StopCapture()316 bool ScreenCaptureConsumer::StopCapture()
317 {
318 SHARING_LOGD("stop capture consumer, consumerId: %{public}u.", GetId());
319 std::lock_guard<std::mutex> lock(mutex_);
320 if (!isRunning_ || !isInit_) {
321 SHARING_LOGD("stop capture consumer already stoped, consumerId: %{public}u.", GetId());
322 return true;
323 }
324
325 isRunning_ = false;
326
327 if (videoTrack_.codecId != CODEC_NONE) {
328 if (videoSourceEncoder_ != nullptr) {
329 videoSourceEncoder_->StopEncoder();
330 }
331 if (videoSourceScreen_ != nullptr) {
332 videoSourceScreen_->StopScreenSourceCapture();
333 }
334 }
335
336 return true;
337 }
338
OnInitVideoCaptureError()339 void ScreenCaptureConsumer::OnInitVideoCaptureError()
340 {
341 SHARING_LOGD("trace.");
342 auto statusMsg = std::make_shared<ProsumerStatusMsg>();
343 statusMsg->errorCode = ERR_PROSUMER_VIDEO_CAPTURE;
344 if (audioTrack_.codecId == CODEC_NONE) {
345 statusMsg->status = PROSUMER_NOTIFY_ERROR;
346 }
347
348 Notify(statusMsg);
349 }
350
351 REGISTER_CLASS_REFLECTOR(ScreenCaptureConsumer);
352 } // namespace Sharing
353 } // namespace OHOS
354