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