• 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     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