1 /*
2  * Copyright (c) 2023 Huawei Device 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_adapter_impl.h"
17 
18 #include "foundation/multimedia/player_framework/interfaces/inner_api/native/media_errors.h"
19 #include "nweb_log.h"
20 #include "surface_adapter_impl.h"
21 
22 namespace OHOS::NWeb {
23 namespace {
GetOHCaptureMode(const CaptureModeAdapter & mode)24 OHOS::Media::CaptureMode GetOHCaptureMode(const CaptureModeAdapter& mode)
25 {
26     switch (mode) {
27         case CaptureModeAdapter::CAPTURE_HOME_SCREEN:
28             return OHOS::Media::CaptureMode::CAPTURE_HOME_SCREEN;
29         case CaptureModeAdapter::CAPTURE_SPECIFIED_SCREEN:
30             return OHOS::Media::CaptureMode::CAPTURE_SPECIFIED_SCREEN;
31         case CaptureModeAdapter::CAPTURE_SPECIFIED_WINDOW:
32             return OHOS::Media::CaptureMode::CAPTURE_SPECIFIED_WINDOW;
33         default:
34             return OHOS::Media::CaptureMode::CAPTURE_INVAILD;
35     }
36     return OHOS::Media::CaptureMode::CAPTURE_INVAILD;
37 }
38 
GetOHDataType(const DataTypeAdapter & type)39 OHOS::Media::DataType GetOHDataType(const DataTypeAdapter& type)
40 {
41     switch (type) {
42         case DataTypeAdapter::ORIGINAL_STREAM_DATA_TYPE:
43             return OHOS::Media::DataType::ORIGINAL_STREAM;
44         case DataTypeAdapter::ENCODED_STREAM_DATA_TYPE:
45             return OHOS::Media::DataType::ENCODED_STREAM;
46         case DataTypeAdapter::CAPTURE_FILE_DATA_TYPE:
47             return OHOS::Media::DataType::CAPTURE_FILE;
48         default:
49             return OHOS::Media::DataType::INVAILD;
50     }
51     return OHOS::Media::DataType::INVAILD;
52 }
53 
GetOHAudioCaptureSourceType(const AudioCaptureSourceTypeAdapter & type)54 OHOS::Media::AudioCaptureSourceType GetOHAudioCaptureSourceType(const AudioCaptureSourceTypeAdapter& type)
55 {
56     switch (type) {
57         case AudioCaptureSourceTypeAdapter::SOURCE_DEFAULT:
58             return OHOS::Media::AudioCaptureSourceType::SOURCE_DEFAULT;
59         case AudioCaptureSourceTypeAdapter::MIC:
60             return OHOS::Media::AudioCaptureSourceType::MIC;
61         case AudioCaptureSourceTypeAdapter::ALL_PLAYBACK:
62             return OHOS::Media::AudioCaptureSourceType::ALL_PLAYBACK;
63         case AudioCaptureSourceTypeAdapter::APP_PLAYBACK:
64             return OHOS::Media::AudioCaptureSourceType::APP_PLAYBACK;
65         default:
66             return OHOS::Media::AudioCaptureSourceType::SOURCE_INVALID;
67     }
68     return OHOS::Media::AudioCaptureSourceType::SOURCE_INVALID;
69 }
70 
GetAudioCaptureSourceTypeAdapter(const OHOS::Media::AudioCaptureSourceType & type)71 AudioCaptureSourceTypeAdapter GetAudioCaptureSourceTypeAdapter(const OHOS::Media::AudioCaptureSourceType& type)
72 {
73     switch (type) {
74         case OHOS::Media::AudioCaptureSourceType::SOURCE_DEFAULT:
75             return AudioCaptureSourceTypeAdapter::SOURCE_DEFAULT;
76         case OHOS::Media::AudioCaptureSourceType::MIC:
77             return AudioCaptureSourceTypeAdapter::MIC;
78         case OHOS::Media::AudioCaptureSourceType::ALL_PLAYBACK:
79             return AudioCaptureSourceTypeAdapter::ALL_PLAYBACK;
80         case OHOS::Media::AudioCaptureSourceType::APP_PLAYBACK:
81             return AudioCaptureSourceTypeAdapter::APP_PLAYBACK;
82         default:
83             return AudioCaptureSourceTypeAdapter::SOURCE_INVALID;
84     }
85     return AudioCaptureSourceTypeAdapter::SOURCE_INVALID;
86 }
87 
GetOHAudioCodecFormat(const AudioCodecFormatAdapter & format)88 OHOS::Media::AudioCodecFormat GetOHAudioCodecFormat(const AudioCodecFormatAdapter& format)
89 {
90     switch (format) {
91         case AudioCodecFormatAdapter::AUDIO_DEFAULT:
92             return OHOS::Media::AudioCodecFormat::AUDIO_DEFAULT;
93         case AudioCodecFormatAdapter::AAC_LC:
94             return OHOS::Media::AudioCodecFormat::AAC_LC;
95         default:
96             return OHOS::Media::AudioCodecFormat::AUDIO_CODEC_FORMAT_BUTT;
97     }
98     return OHOS::Media::AudioCodecFormat::AUDIO_CODEC_FORMAT_BUTT;
99 }
100 
GetOHVideoSourceType(const VideoSourceTypeAdapter & type)101 OHOS::Media::VideoSourceType GetOHVideoSourceType(const VideoSourceTypeAdapter& type)
102 {
103     switch (type) {
104         case VideoSourceTypeAdapter::VIDEO_SOURCE_SURFACE_YUV:
105             return OHOS::Media::VideoSourceType::VIDEO_SOURCE_SURFACE_YUV;
106         case VideoSourceTypeAdapter::VIDEO_SOURCE_SURFACE_ES:
107             return OHOS::Media::VideoSourceType::VIDEO_SOURCE_SURFACE_ES;
108         case VideoSourceTypeAdapter::VIDEO_SOURCE_SURFACE_RGBA:
109             return OHOS::Media::VideoSourceType::VIDEO_SOURCE_SURFACE_RGBA;
110         default:
111             return OHOS::Media::VideoSourceType::VIDEO_SOURCE_BUTT;
112     }
113     return OHOS::Media::VideoSourceType::VIDEO_SOURCE_BUTT;
114 }
115 
GetOHVideoCodecFormat(const VideoCodecFormatAdapter & format)116 OHOS::Media::VideoCodecFormat GetOHVideoCodecFormat(const VideoCodecFormatAdapter& format)
117 {
118     switch (format) {
119         case VideoCodecFormatAdapter::VIDEO_DEFAULT:
120             return OHOS::Media::VideoCodecFormat::VIDEO_DEFAULT;
121         case VideoCodecFormatAdapter::H264:
122             return OHOS::Media::VideoCodecFormat::H264;
123         case VideoCodecFormatAdapter::MPEG4:
124             return OHOS::Media::VideoCodecFormat::MPEG4;
125         default:
126             return OHOS::Media::VideoCodecFormat::VIDEO_CODEC_FORMAT_BUTT;
127     }
128     return OHOS::Media::VideoCodecFormat::VIDEO_CODEC_FORMAT_BUTT;
129 }
130 
GetOHContainerFormatType(const ContainerFormatTypeAdapter & type)131 std::string GetOHContainerFormatType(const ContainerFormatTypeAdapter& type)
132 {
133     switch (type) {
134         case ContainerFormatTypeAdapter::CFT_MPEG_4A_TYPE:
135             return std::string(OHOS::Media::ContainerFormatType::CFT_MPEG_4A);
136         default:
137             return std::string(OHOS::Media::ContainerFormatType::CFT_MPEG_4);
138     }
139     return std::string(OHOS::Media::ContainerFormatType::CFT_MPEG_4);
140 }
141 
ConvertScreenCaptureConfig(const std::shared_ptr<ScreenCaptureConfigAdapter> config)142 OHOS::Media::AVScreenCaptureConfig ConvertScreenCaptureConfig(const std::shared_ptr<ScreenCaptureConfigAdapter> config)
143 {
144     OHOS::Media::AVScreenCaptureConfig avConfig;
145 
146     if (!config) {
147         WVLOG_I("ConvertScreenCaptureConfig config is null");
148         return avConfig;
149     }
150 
151     avConfig.captureMode = GetOHCaptureMode(config->GetCaptureMode());
152     avConfig.dataType = GetOHDataType(config->GetDataType());
153 
154     if (config->GetAudioInfo() && config->GetAudioInfo()->GetMicCapInfo()) {
155         avConfig.audioInfo.micCapInfo.audioSampleRate = config->GetAudioInfo()->GetMicCapInfo()->GetAudioSampleRate();
156         avConfig.audioInfo.micCapInfo.audioChannels = config->GetAudioInfo()->GetMicCapInfo()->GetAudioChannels();
157         avConfig.audioInfo.micCapInfo.audioSource =
158             GetOHAudioCaptureSourceType(config->GetAudioInfo()->GetMicCapInfo()->GetAudioSource());
159     }
160 
161     if (config->GetAudioInfo() && config->GetAudioInfo()->GetInnerCapInfo()) {
162         avConfig.audioInfo.innerCapInfo.audioSampleRate =
163             config->GetAudioInfo()->GetInnerCapInfo()->GetAudioSampleRate();
164         avConfig.audioInfo.innerCapInfo.audioChannels = config->GetAudioInfo()->GetInnerCapInfo()->GetAudioChannels();
165         avConfig.audioInfo.innerCapInfo.audioSource =
166             GetOHAudioCaptureSourceType(config->GetAudioInfo()->GetInnerCapInfo()->GetAudioSource());
167     }
168 
169     if (config->GetAudioInfo() && config->GetAudioInfo()->GetAudioEncInfo()) {
170         avConfig.audioInfo.audioEncInfo.audioBitrate = config->GetAudioInfo()->GetAudioEncInfo()->GetAudioBitrate();
171         avConfig.audioInfo.audioEncInfo.audioCodecformat =
172             GetOHAudioCodecFormat(config->GetAudioInfo()->GetAudioEncInfo()->GetAudioCodecformat());
173     }
174 
175     if (config->GetVideoInfo() && config->GetVideoInfo()->GetVideoCapInfo()) {
176         avConfig.videoInfo.videoCapInfo.displayId = config->GetVideoInfo()->GetVideoCapInfo()->GetDisplayId();
177         avConfig.videoInfo.videoCapInfo.taskIDs = config->GetVideoInfo()->GetVideoCapInfo()->GetTaskIDs();
178         avConfig.videoInfo.videoCapInfo.videoFrameWidth =
179             config->GetVideoInfo()->GetVideoCapInfo()->GetVideoFrameWidth();
180         avConfig.videoInfo.videoCapInfo.videoFrameHeight =
181             config->GetVideoInfo()->GetVideoCapInfo()->GetVideoFrameHeight();
182         avConfig.videoInfo.videoCapInfo.videoSource =
183             GetOHVideoSourceType(config->GetVideoInfo()->GetVideoCapInfo()->GetVideoSourceType());
184     }
185 
186     if (config->GetVideoInfo() && config->GetVideoInfo()->GetVideoEncInfo()) {
187         avConfig.videoInfo.videoEncInfo.videoCodec =
188             GetOHVideoCodecFormat(config->GetVideoInfo()->GetVideoEncInfo()->GetVideoCodecFormat());
189         avConfig.videoInfo.videoEncInfo.videoBitrate = config->GetVideoInfo()->GetVideoEncInfo()->GetVideoBitrate();
190         avConfig.videoInfo.videoEncInfo.videoFrameRate = config->GetVideoInfo()->GetVideoEncInfo()->GetVideoFrameRate();
191     }
192 
193     if (config->GetDataType() == DataTypeAdapter::CAPTURE_FILE_DATA_TYPE && config->GetRecorderInfo()) {
194         avConfig.recorderInfo.url = config->GetRecorderInfo()->GetUrl();
195         avConfig.recorderInfo.fileFormat = GetOHContainerFormatType(config->GetRecorderInfo()->GetFileFormat());
196     }
197 
198     return avConfig;
199 }
200 
GetScreenCaptureStateCodeAdapter(const OHOS::Media::AVScreenCaptureStateCode & stateCode)201 ScreenCaptureStateCodeAdapter GetScreenCaptureStateCodeAdapter(const OHOS::Media::AVScreenCaptureStateCode& stateCode)
202 {
203     switch (stateCode) {
204         case OHOS::Media::AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_STARTED:
205             return ScreenCaptureStateCodeAdapter::SCREEN_CAPTURE_STATE_STARTED;
206         case OHOS::Media::AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_CANCELED:
207             return ScreenCaptureStateCodeAdapter::SCREEN_CAPTURE_STATE_CANCELED;
208         case OHOS::Media::AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_STOPPED_BY_USER:
209             return ScreenCaptureStateCodeAdapter::SCREEN_CAPTURE_STATE_STOPPED_BY_USER;
210         case OHOS::Media::AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_INTERRUPTED_BY_OTHER:
211             return ScreenCaptureStateCodeAdapter::SCREEN_CAPTURE_STATE_INTERRUPTED_BY_OTHER;
212         case OHOS::Media::AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_STOPPED_BY_CALL:
213             return ScreenCaptureStateCodeAdapter::SCREEN_CAPTURE_STATE_STOPPED_BY_CALL;
214         case OHOS::Media::AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_MIC_UNAVAILABLE:
215             return ScreenCaptureStateCodeAdapter::SCREEN_CAPTURE_STATE_MIC_UNAVAILABLE;
216         case OHOS::Media::AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_MIC_MUTED_BY_USER:
217             return ScreenCaptureStateCodeAdapter::SCREEN_CAPTURE_STATE_MIC_MUTED_BY_USER;
218         case OHOS::Media::AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_MIC_UNMUTED_BY_USER:
219             return ScreenCaptureStateCodeAdapter::SCREEN_CAPTURE_STATE_MIC_UNMUTED_BY_USER;
220         case OHOS::Media::AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_ENTER_PRIVATE_SCENE:
221             return ScreenCaptureStateCodeAdapter::SCREEN_CAPTURE_STATE_ENTER_PRIVATE_SCENE;
222         case OHOS::Media::AVScreenCaptureStateCode::SCREEN_CAPTURE_STATE_EXIT_PRIVATE_SCENE:
223             return ScreenCaptureStateCodeAdapter::SCREEN_CAPTURE_STATE_EXIT_PRIVATE_SCENE;
224         default:
225             return ScreenCaptureStateCodeAdapter::SCREEN_CAPTURE_STATE_INVLID;
226     }
227     return ScreenCaptureStateCodeAdapter::SCREEN_CAPTURE_STATE_INVLID;
228 }
229 } // namespace
230 
OnError(OHOS::Media::ScreenCaptureErrorType errorType,int32_t errorCode)231 void OHScreenCaptureCallback::OnError(OHOS::Media::ScreenCaptureErrorType errorType, int32_t errorCode)
232 {
233     WVLOG_I("OnError() is called, errorType %{public}d, errorCode %{public}d", errorType, errorCode);
234     if (callback_) {
235         callback_->OnError(errorCode);
236     }
237 }
238 
OnAudioBufferAvailable(bool isReady,OHOS::Media::AudioCaptureSourceType type)239 void OHScreenCaptureCallback::OnAudioBufferAvailable(bool isReady, OHOS::Media::AudioCaptureSourceType type)
240 {
241     if (callback_) {
242         callback_->OnAudioBufferAvailable(isReady, GetAudioCaptureSourceTypeAdapter(type));
243     }
244 }
245 
OnVideoBufferAvailable(bool isReady)246 void OHScreenCaptureCallback::OnVideoBufferAvailable(bool isReady)
247 {
248     if (callback_) {
249         callback_->OnVideoBufferAvailable(isReady);
250     }
251 }
252 
OnStateChange(OHOS::Media::AVScreenCaptureStateCode stateCode)253 void OHScreenCaptureCallback::OnStateChange(OHOS::Media::AVScreenCaptureStateCode stateCode)
254 {
255     WVLOG_I("OnStateChange() is called, stateCode %{public}d", stateCode);
256     if (callback_) {
257         callback_->OnStateChange(GetScreenCaptureStateCodeAdapter(stateCode));
258     }
259 }
260 
~ScreenCaptureAdapterImpl()261 ScreenCaptureAdapterImpl::~ScreenCaptureAdapterImpl()
262 {
263     Release();
264 }
265 
Init(const std::shared_ptr<ScreenCaptureConfigAdapter> config)266 int32_t ScreenCaptureAdapterImpl::Init(const std::shared_ptr<ScreenCaptureConfigAdapter> config)
267 {
268     if (screenCapture_) {
269         return 0;
270     }
271     screenCapture_ = OHOS::Media::ScreenCaptureFactory::CreateScreenCapture();
272     if (!screenCapture_) {
273         WVLOG_E("CreateScreenCapture create failed");
274         return -1;
275     }
276 
277     if (!config) {
278         WVLOG_E("config is null");
279         return -1;
280     }
281 
282     int32_t ret = screenCapture_->Init(ConvertScreenCaptureConfig(config));
283     if (ret != Media::MSERR_OK) {
284         WVLOG_E("OH_AVScreenCapture init failed, ret = %{public}d", ret);
285         Release();
286         return -1;
287     }
288     return 0;
289 }
290 
Release()291 void ScreenCaptureAdapterImpl::Release()
292 {
293     if (!screenCapture_) {
294         return;
295     }
296     screenCaptureCallback_ = nullptr;
297     int32_t ret = screenCapture_->Release();
298     if (ret != Media::MSERR_OK) {
299         WVLOG_E("OH_AVScreenCapture release failed, ret = %{public}d", ret);
300     }
301     screenCapture_ = nullptr;
302 }
303 
SetMicrophoneEnable(bool enable)304 int32_t ScreenCaptureAdapterImpl::SetMicrophoneEnable(bool enable)
305 {
306     if (!screenCapture_) {
307         WVLOG_E("not init");
308         return -1;
309     }
310     int32_t ret = screenCapture_->SetMicrophoneEnabled(enable);
311     if (ret != Media::MSERR_OK) {
312         WVLOG_E("set microphone enabled failed, ret = %{public}d", ret);
313         return -1;
314     }
315     return 0;
316 }
317 
StartCapture()318 int32_t ScreenCaptureAdapterImpl::StartCapture()
319 {
320     if (!screenCapture_) {
321         WVLOG_E("not init");
322         return -1;
323     }
324     int32_t ret = screenCapture_->SetPrivacyAuthorityEnabled();
325     if (ret != Media::MSERR_OK) {
326         WVLOG_E("start capture SetPrivacyAuthorityEnabled failed, ret = %{public}d", ret);
327         return -1;
328     }
329     ret = screenCapture_->SetCanvasRotation(true);
330     if (ret != Media::MSERR_OK) {
331         WVLOG_E("start capture SetCanvasRotation failed, ret = %{public}d", ret);
332     }
333     ret = screenCapture_->StartScreenCapture();
334     if (ret != Media::MSERR_OK) {
335         WVLOG_E("start capture failed, ret = %{public}d", ret);
336         return -1;
337     }
338     return 0;
339 }
340 
StopCapture()341 int32_t ScreenCaptureAdapterImpl::StopCapture()
342 {
343     if (!screenCapture_) {
344         WVLOG_E("not init");
345         return -1;
346     }
347     int32_t ret = screenCapture_->StopScreenCapture();
348     if (ret != Media::MSERR_OK) {
349         WVLOG_E("stop capture failed, ret = %{public}d", ret);
350         return -1;
351     }
352     return 0;
353 }
354 
SetCaptureCallback(const std::shared_ptr<ScreenCaptureCallbackAdapter> callback)355 int32_t ScreenCaptureAdapterImpl::SetCaptureCallback(const std::shared_ptr<ScreenCaptureCallbackAdapter> callback)
356 {
357     if (!screenCapture_ || !callback || screenCaptureCallback_) {
358         WVLOG_E("not init or param error");
359         return -1;
360     }
361     screenCaptureCallback_ = std::make_shared<OHScreenCaptureCallback>(callback);
362     if (!screenCaptureCallback_) {
363         WVLOG_E("make_shared failed");
364         return -1;
365     }
366     int32_t ret = screenCapture_->SetScreenCaptureCallback(screenCaptureCallback_);
367     if (ret != Media::MSERR_OK) {
368         WVLOG_E("set callback failed, ret = %{public}d", ret);
369         screenCaptureCallback_ = nullptr;
370         return -1;
371     }
372     return 0;
373 }
374 
AcquireVideoBuffer()375 std::shared_ptr<SurfaceBufferAdapter> ScreenCaptureAdapterImpl::AcquireVideoBuffer()
376 {
377     if (!screenCapture_) {
378         WVLOG_E("not init");
379         return nullptr;
380     }
381     int32_t fence;
382     int64_t timestamp;
383     OHOS::Rect region;
384     sptr<OHOS::SurfaceBuffer> surfaceBuffer = screenCapture_->AcquireVideoBuffer(fence, timestamp, region);
385     if (surfaceBuffer == nullptr) {
386         WVLOG_E("acquire video buffer failed");
387         return nullptr;
388     }
389     auto surfaceBufferImpl = std::make_shared<SurfaceBufferAdapterImpl>(surfaceBuffer);
390     if (!surfaceBufferImpl) {
391         WVLOG_E("make_unique failed");
392         (void)ReleaseVideoBuffer();
393         return nullptr;
394     }
395     return std::move(surfaceBufferImpl);
396 }
397 
ReleaseVideoBuffer()398 int32_t ScreenCaptureAdapterImpl::ReleaseVideoBuffer()
399 {
400     if (!screenCapture_) {
401         WVLOG_E("not init");
402         return -1;
403     }
404     int32_t ret = screenCapture_->ReleaseVideoBuffer();
405     if (ret != Media::MSERR_OK) {
406         WVLOG_E("release video buffer failed, ret = %{public}d", ret);
407         return -1;
408     }
409     return 0;
410 }
411 } // namespace OHOS::NWeb
412