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