• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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