1 /*
2 * Copyright (c) 2023-2024 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 {
24 static std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
OnFrame(const Frame::Ptr & frame)25 void ScreenCaptureConsumer::AudioEncoderReceiver::OnFrame(const Frame::Ptr &frame)
26 {
27 auto parent = parent_.lock();
28 if (parent && !parent->listener_.expired()) {
29 auto listener = parent->listener_.lock();
30 auto dispatcher = listener->GetDispatcher();
31 if (dispatcher) {
32 auto mediaData = dispatcher->RequestDataBuffer(MEDIA_TYPE_AUDIO, frame->Size());
33 if (mediaData == nullptr) {
34 SHARING_LOGE("mediaData read failed.");
35 return;
36 }
37 mediaData->mediaType = MEDIA_TYPE_AUDIO;
38 mediaData->codecId = frame->GetCodecId();
39 mediaData->isRaw = false;
40 mediaData->keyFrame = false;
41 mediaData->pts = frame->Pts();
42 MEDIA_LOGD("recv audio encode data: codec:%{public}d size: %{public}d & put into dispatcher: %{public}u.",
43 mediaData->codecId, frame->Size(), dispatcher->GetDispatcherId());
44 mediaData->buff = move(frame);
45 dispatcher->InputData(mediaData);
46 }
47 }
48 }
49
OnFrameBufferUsed()50 void ScreenCaptureConsumer::OnFrameBufferUsed()
51 {
52 ReleaseScreenBuffer();
53 }
54
HandleSpsFrame(BufferDispatcher::Ptr dispatcher,const Frame::Ptr & frame)55 void ScreenCaptureConsumer::HandleSpsFrame(BufferDispatcher::Ptr dispatcher, const Frame::Ptr &frame)
56 {
57 RETURN_IF_NULL(dispatcher);
58 auto spsOld = dispatcher->GetSPS();
59 if (spsOld != nullptr && spsOld->buff != nullptr) {
60 return;
61 }
62 // set sps into buffer dispathcer
63 auto sps = std::make_shared<MediaData>();
64 sps->buff = move(frame);
65 sps->mediaType = MEDIA_TYPE_VIDEO;
66 dispatcher->SetSpsNalu(sps);
67 }
68
HandlePpsFrame(BufferDispatcher::Ptr dispatcher,const Frame::Ptr & frame)69 void ScreenCaptureConsumer::HandlePpsFrame(BufferDispatcher::Ptr dispatcher, const Frame::Ptr &frame)
70 {
71 RETURN_IF_NULL(dispatcher);
72 auto ppsOld = dispatcher->GetPPS();
73 if (ppsOld != nullptr && ppsOld->buff != nullptr) {
74 return;
75 }
76 // set pps into buffer dispather
77 auto pps = std::make_shared<MediaData>();
78 pps->buff = move(frame);
79 pps->mediaType = MEDIA_TYPE_VIDEO;
80 dispatcher->SetPpsNalu(pps);
81 }
82
OnFrame(const Frame::Ptr & frame,FRAME_TYPE frameType,bool keyFrame)83 void ScreenCaptureConsumer::OnFrame(const Frame::Ptr &frame, FRAME_TYPE frameType, bool keyFrame)
84 {
85 SHARING_LOGD("trace.");
86 if (frame == nullptr) {
87 SHARING_LOGE("Screen Capture encodedBuf is null!");
88 return;
89 }
90
91 if (listener_.expired() || IsPaused()) {
92 return;
93 }
94
95 auto listener = listener_.lock();
96 BufferDispatcher::Ptr dispatcher = listener->GetDispatcher();
97 if (dispatcher) {
98 uint32_t len = (uint32_t)frame->Size();
99 switch (frameType) {
100 case SPS_FRAME: {
101 SHARING_LOGD("get sps frame, size:%{public}u.", len);
102 HandleSpsFrame(dispatcher, frame);
103 break;
104 }
105 case PPS_FRAME: {
106 SHARING_LOGD("get pps frame, size:%{public}u.", len);
107 HandlePpsFrame(dispatcher, frame);
108 break;
109 }
110 case IDR_FRAME: {
111 std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
112 uint64_t pts =
113 static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count());
114 auto mediaData = dispatcher->RequestDataBuffer(MEDIA_TYPE_VIDEO, len);
115 if (mediaData == nullptr) {
116 SHARING_LOGE("RequestDataBuffer get null!");
117 break;
118 }
119 mediaData->mediaType = MEDIA_TYPE_VIDEO;
120 mediaData->isRaw = false;
121 mediaData->keyFrame = keyFrame;
122 mediaData->pts = pts;
123 SHARING_LOGD("[%{public}" PRId64 "] capture a video into dispatcher:%{public}u, len:%{public}u.",
124 mediaData->pts, dispatcher->GetDispatcherId(), len);
125 mediaData->buff = move(frame);
126 dispatcher->InputData(mediaData);
127 break;
128 }
129 default:
130 break;
131 }
132 }
133 }
134
ScreenCaptureConsumer()135 ScreenCaptureConsumer::ScreenCaptureConsumer()
136 {
137 SHARING_LOGD("capture consumer Id: %{public}u.", GetId());
138 }
139
~ScreenCaptureConsumer()140 ScreenCaptureConsumer::~ScreenCaptureConsumer()
141 {
142 SHARING_LOGD("~ capture consumer Id: %{public}u.", GetId());
143 Release();
144 }
145
HandleProsumerInitState(SharingEvent & event)146 void ScreenCaptureConsumer::HandleProsumerInitState(SharingEvent &event)
147 {
148 SHARING_LOGD("trace.");
149 auto pPrivateMsg = std::make_shared<ScreenCaptureSessionEventMsg>();
150 pPrivateMsg->errorCode = ERR_GENERAL_ERROR;
151 pPrivateMsg->errorCode = ERR_OK;
152 pPrivateMsg->type = EVENT_AGENT_STATE_PROSUMER_INIT;
153 pPrivateMsg->toMgr = ModuleType::MODULE_CONTEXT;
154 pPrivateMsg->fromMgr = ModuleType::MODULE_MEDIACHANNEL;
155 pPrivateMsg->srcId = GetId();
156 pPrivateMsg->dstId = event.eventMsg->srcId;
157 pPrivateMsg->agentId = GetSinkAgentId();
158 pPrivateMsg->prosumerId = GetId();
159 pPrivateMsg->requestId = event.eventMsg->requestId;
160
161 NotifyPrivateEvent(pPrivateMsg);
162 }
163
HandleProsumerPlay(SharingEvent & event)164 void ScreenCaptureConsumer::HandleProsumerPlay(SharingEvent &event)
165 {
166 SHARING_LOGD("trace.");
167
168 auto msg = ConvertEventMsg<ScreenCaptureConsumerEventMsg>(event);
169 if (msg) {
170 SHARING_LOGI("msg convert suc, vcodecId:%{public}d, acodecId:%{public}d.",
171 msg->videoTrack.codecId, msg->audioTrack.codecId);
172 if (msg->audioTrack.codecId != CodecId::CODEC_NONE) {
173 audioTrack_ = msg->audioTrack;
174 }
175
176 if (msg->videoTrack.codecId != CodecId::CODEC_NONE) {
177 videoTrack_ = msg->videoTrack;
178 }
179
180 if (isInit_) {
181 SHARING_LOGD("Capture already inited!");
182 return;
183 }
184 if (!InitCapture(msg->screenId)) {
185 SHARING_LOGD("InitCapture failed!");
186 return;
187 }
188 if (!StartCapture()) {
189 SHARING_LOGD("StartCapture failed!");
190 return;
191 }
192 } else {
193 SHARING_LOGE("msg convert fail!");
194 }
195 }
196
HandleEvent(SharingEvent & event)197 int32_t ScreenCaptureConsumer::HandleEvent(SharingEvent &event)
198 {
199 SHARING_LOGD("trace.");
200 RETURN_INVALID_IF_NULL(event.eventMsg);
201
202 SHARING_LOGD("eventType: %{public}s = %{public}d, capture consumerId: %{public}u.",
203 std::string(magic_enum::enum_name(event.eventMsg->type)).c_str(), event.eventMsg->type, GetId());
204 switch (event.eventMsg->type) {
205 case EventType::EVENT_SCREEN_CAPTURE_INIT:
206 HandleProsumerInitState(event);
207 break;
208 case EventType::EVENT_WFD_NOTIFY_RTSP_PLAYED:
209 HandleProsumerPlay(event);
210 break;
211 default:
212 SHARING_LOGI("none process case.");
213 break;
214 }
215
216 return 0;
217 }
218
UpdateOperation(ProsumerStatusMsg::Ptr & statusMsg)219 void ScreenCaptureConsumer::UpdateOperation(ProsumerStatusMsg::Ptr &statusMsg)
220 {
221 SHARING_LOGD("trace.");
222 RETURN_IF_NULL(statusMsg);
223
224 SHARING_LOGD("status: %{public}s consumerId: %{public}u.",
225 std::string(magic_enum::enum_name(static_cast<ProsumerOptRunningStatus>(statusMsg->status))).c_str(),
226 GetId());
227 switch (statusMsg->status) {
228 case ProsumerOptRunningStatus::PROSUMER_INIT:
229 statusMsg->status = PROSUMER_NOTIFY_INIT_SUCCESS;
230 break;
231 case ProsumerOptRunningStatus::PROSUMER_START: {
232 paused_ = false;
233 statusMsg->status = PROSUMER_NOTIFY_START_SUCCESS;
234 break;
235 }
236 case ProsumerOptRunningStatus::PROSUMER_PAUSE: {
237 paused_ = true;
238 statusMsg->status = PROSUMER_NOTIFY_PAUSE_SUCCESS;
239 break;
240 }
241 case ProsumerOptRunningStatus::PROSUMER_RESUME: {
242 paused_ = false;
243 statusMsg->status = PROSUMER_NOTIFY_RESUME_SUCCESS;
244 break;
245 }
246 case ProsumerOptRunningStatus::PROSUMER_STOP: {
247 if (StopCapture()) {
248 statusMsg->status = PROSUMER_NOTIFY_STOP_SUCCESS;
249 } else {
250 statusMsg->status = PROSUMER_NOTIFY_ERROR;
251 statusMsg->errorCode = ERR_PROSUMER_STOP;
252 }
253 break;
254 }
255 case ProsumerOptRunningStatus::PROSUMER_DESTROY:
256 Release();
257 SHARING_LOGD("prosumer release success, out.");
258 statusMsg->status = PROSUMER_NOTIFY_DESTROY_SUCCESS;
259 break;
260 default:
261 SHARING_LOGI("none process case.");
262 break;
263 }
264
265 Notify(statusMsg);
266 }
267
Release()268 int32_t ScreenCaptureConsumer::Release()
269 {
270 SHARING_LOGD("trace.");
271 StopCapture();
272
273 SHARING_LOGD("consumerId: %{public}u, capture consumer release=out.", GetId());
274 return 0;
275 }
276
IsPaused()277 bool ScreenCaptureConsumer::IsPaused()
278 {
279 SHARING_LOGD("trace.");
280 return paused_;
281 }
282
ReleaseScreenBuffer()283 int32_t ScreenCaptureConsumer::ReleaseScreenBuffer()
284 {
285 SHARING_LOGD("trace.");
286 if (videoSourceScreen_ == nullptr) {
287 return ERR_GENERAL_ERROR;
288 }
289 return videoSourceScreen_->ReleaseScreenBuffer();
290 }
291
InitCapture(uint64_t screenId)292 bool ScreenCaptureConsumer::InitCapture(uint64_t screenId)
293 {
294 SHARING_LOGD("capture consumerId: %{public}u, viddeo codecId: %{public}d, audio codecId: %{public}d.", GetId(),
295 videoTrack_.codecId, audioTrack_.codecId);
296 std::lock_guard<std::mutex> lock(mutex_);
297 if (audioTrack_.codecId != CODEC_NONE) {
298 if (!InitAudioEncoder()) {
299 SHARING_LOGE("capture consumerId: %{public}u, init audio encoder failed.", GetId());
300 return false;
301 }
302
303 if (!InitAudioCapture()) {
304 SHARING_LOGE("capture consumerId: %{public}u, init audio capture failed.", GetId());
305 return false;
306 }
307 }
308
309 if ((videoTrack_.codecId != CODEC_NONE) && !InitVideoCapture(screenId)) {
310 SHARING_LOGE("capture consumerId: %{public}u, init video capture failed.", GetId());
311 return false;
312 }
313
314 SHARING_LOGD("capture consumerId: %{public}u, success.", GetId());
315 isInit_ = true;
316 return true;
317 }
318
InitVideoCapture(uint64_t screenId)319 bool ScreenCaptureConsumer::InitVideoCapture(uint64_t screenId)
320 {
321 SHARING_LOGD("consumerId: %{public}u.", GetId());
322 VideoSourceConfigure config;
323 config.srcScreenId_ = screenId;
324
325 videoSourceEncoder_ = std::make_shared<VideoSourceEncoder>(shared_from_this());
326 if (!videoSourceEncoder_->InitEncoder(config)) {
327 SHARING_LOGE("InitEncoder failed! %{public}u.", GetId());
328 OnInitVideoCaptureError();
329 return false;
330 }
331 videoSourceScreen_ = std::make_shared<VideoSourceScreen>(videoSourceEncoder_->GetEncoderSurface());
332 videoSourceScreen_->InitScreenSource(config);
333 return true;
334 }
335
InitAudioCapture()336 bool ScreenCaptureConsumer::InitAudioCapture()
337 {
338 SHARING_LOGD("trace.");
339
340 if (audioEncoder_ == nullptr) {
341 SHARING_LOGE("InitAudioCapture failed, audioEncoder_ is null! %{public}u.", GetId());
342 return false;
343 }
344 audioSourceCapturer_ = std::make_shared<AudioSourceCapturer>(audioEncoder_);
345 return audioSourceCapturer_->InitAudioCapture();
346 }
347
InitAudioEncoder()348 bool ScreenCaptureConsumer::InitAudioEncoder()
349 {
350 SHARING_LOGD("trace.");
351 audioEncoder_ = CodecFactory::CreateAudioEncoder(audioTrack_.codecId);
352 if (!audioEncoder_) {
353 SHARING_LOGE("create audio encoder failed.");
354 return false;
355 }
356
357 audioEncoder_->Init(AUDIO_CHANNEL_STEREO, AUDIO_SAMPLE_BIT_S16LE, AUDIO_SAMPLE_RATE_48000);
358 audioEncoderReceiver_ = std::make_shared<AudioEncoderReceiver>(shared_from_this());
359 audioEncoder_->AddAudioDestination(audioEncoderReceiver_);
360 return true;
361 }
362
StartCapture()363 bool ScreenCaptureConsumer::StartCapture()
364 {
365 SHARING_LOGD("trace.");
366 std::lock_guard<std::mutex> lock(mutex_);
367 if (isRunning_ || !isInit_) {
368 return false;
369 }
370
371 isRunning_ = true;
372 if ((videoTrack_.codecId != CODEC_NONE) && !StartVideoCapture()) {
373 SHARING_LOGE("consumerId: %{public}u, start video capture failed.", GetId());
374 isRunning_ = false;
375 return false;
376 }
377
378 if ((audioTrack_.codecId != CODEC_NONE) && !StartAudioCapture()) {
379 SHARING_LOGE("consumerId: %{public}u, start audio capture failed, only viedo works!", GetId());
380 }
381
382 SHARING_LOGD("consumerId: %{public}u, success.", GetId());
383 return true;
384 }
385
StartAudioCapture()386 bool ScreenCaptureConsumer::StartAudioCapture()
387 {
388 SHARING_LOGD("trace.");
389
390 if (audioSourceCapturer_ == nullptr) {
391 SHARING_LOGE("start capture fail - capturer is null, consumerId: %{public}u.", GetId());
392 return false;
393 }
394 return audioSourceCapturer_->StartAudioCapture();
395 }
396
StartVideoCapture()397 bool ScreenCaptureConsumer::StartVideoCapture()
398 {
399 SHARING_LOGD("trace.");
400 if (videoSourceScreen_ != nullptr) {
401 videoSourceScreen_->StartScreenSourceCapture();
402 }
403 if (videoSourceEncoder_ != nullptr) {
404 videoSourceEncoder_->StartEncoder();
405 }
406 return true;
407 }
408
StopCapture()409 bool ScreenCaptureConsumer::StopCapture()
410 {
411 SHARING_LOGD("stop capture consumer, consumerId: %{public}u.", GetId());
412 std::lock_guard<std::mutex> lock(mutex_);
413 if (!isRunning_ || !isInit_) {
414 SHARING_LOGD("capture consumer already stoped, consumerId: %{public}u.", GetId());
415 return true;
416 }
417
418 isRunning_ = false;
419 StopAudioCapture();
420 StopVideoCapture();
421
422 return true;
423 }
424
StopAudioCapture()425 bool ScreenCaptureConsumer::StopAudioCapture()
426 {
427 SHARING_LOGD("trace.");
428
429 if (audioSourceCapturer_ == nullptr) {
430 SHARING_LOGE("stop capture fail - capturer is null, consumerId: %{public}u.", GetId());
431 return false;
432 }
433 return audioSourceCapturer_->StopAudioCapture();
434 }
435
StopVideoCapture()436 bool ScreenCaptureConsumer::StopVideoCapture()
437 {
438 SHARING_LOGD("trace.");
439 if (videoTrack_.codecId != CODEC_NONE) {
440 if (videoSourceEncoder_ != nullptr) {
441 videoSourceEncoder_->StopEncoder();
442 }
443 if (videoSourceScreen_ != nullptr) {
444 videoSourceScreen_->StopScreenSourceCapture();
445 }
446 }
447 return true;
448 }
449
OnInitVideoCaptureError()450 void ScreenCaptureConsumer::OnInitVideoCaptureError()
451 {
452 SHARING_LOGD("trace.");
453 auto statusMsg = std::make_shared<ProsumerStatusMsg>();
454 statusMsg->errorCode = ERR_PROSUMER_VIDEO_CAPTURE;
455 if (audioTrack_.codecId == CODEC_NONE) {
456 statusMsg->status = PROSUMER_NOTIFY_ERROR;
457 }
458
459 Notify(statusMsg);
460 }
461
462 REGISTER_CLASS_REFLECTOR(ScreenCaptureConsumer);
463 } // namespace Sharing
464 } // namespace OHOS
465