1 /*
2 * Copyright (c) 2025 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 "main.h"
17
18 using namespace std;
19 #define LOG_TAG "ScreenCaptureSample"
20
OpenFile(std::string fileName)21 void OpenFile(std::string fileName)
22 {
23 std::string filePath = "data/storage/el2/base/files/MIC_" + fileName + ".pcm";
24 micFile_ = fopen(filePath.c_str(), "wb");
25 if (micFile_ == nullptr) {
26 OH_LOG_ERROR(LOG_APP, "OpenFile micFile_ audio open failed. %{public}s", strerror(errno));
27 }
28 filePath = "data/storage/el2/base/files/INNER_" + fileName + ".pcm";
29 innerFile_ = fopen(filePath.c_str(), "wb");
30 if (innerFile_ == nullptr) {
31 OH_LOG_ERROR(LOG_APP, "OpenFile innerFile_ audio open failed. %{public}s", strerror(errno));
32 }
33 filePath = "data/storage/el2/base/files/VIDEO_" + fileName + ".yuv";
34 vFile_ = fopen(filePath.c_str(), "wb");
35 if (vFile_ == nullptr) {
36 OH_LOG_ERROR(LOG_APP, "OpenFile vFile video open failed. %{public}s", strerror(errno));
37 }
38 }
39
CloseFile(void)40 void CloseFile(void)
41 {
42 if (micFile_ != nullptr) {
43 fclose(micFile_);
44 micFile_ = nullptr;
45 }
46 if (innerFile_ != nullptr) {
47 fclose(innerFile_);
48 innerFile_ = nullptr;
49 }
50 if (vFile_ != nullptr) {
51 fclose(vFile_);
52 vFile_ = nullptr;
53 }
54 }
55
SetConfig(OH_AVScreenCaptureConfig & config)56 void SetConfig(OH_AVScreenCaptureConfig &config)
57 {
58 int32_t width = 720;
59 int32_t height = 1280;
60 OH_AudioCaptureInfo micCapInfo = {.audioSampleRate = 48000, .audioChannels = 2, .audioSource = OH_MIC};
61 OH_AudioCaptureInfo innerCapInfo = {.audioSampleRate = 48000, .audioChannels = 2, .audioSource = OH_ALL_PLAYBACK};
62 OH_AudioEncInfo audioEncInfo = {.audioBitrate = 48000, .audioCodecformat = OH_AudioCodecFormat::OH_AAC_LC};
63 OH_AudioInfo audioInfo = {.micCapInfo = micCapInfo, .innerCapInfo = innerCapInfo, .audioEncInfo = audioEncInfo};
64
65 OH_VideoCaptureInfo videoCapInfo = {
66 .videoFrameWidth = width, .videoFrameHeight = height, .videoSource = OH_VIDEO_SOURCE_SURFACE_RGBA};
67 OH_VideoEncInfo videoEncInfo = {
68 .videoCodec = OH_VideoCodecFormat::OH_H264, .videoBitrate = 2000000, .videoFrameRate = 30};
69 OH_VideoInfo videoInfo = {.videoCapInfo = videoCapInfo, .videoEncInfo = videoEncInfo};
70
71 config = {
72 .captureMode = OH_CAPTURE_HOME_SCREEN,
73 .dataType = OH_ORIGINAL_STREAM,
74 .audioInfo = audioInfo,
75 .videoInfo = videoInfo,
76 };
77 }
78
OnError(OH_AVScreenCapture * capture,int32_t errorCode,void * userData)79 void OnError(OH_AVScreenCapture *capture, int32_t errorCode, void *userData)
80 {
81 (void)capture;
82 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnError errorCode is %{public}d", errorCode);
83 (void)userData;
84 }
85
OnStateChange(struct OH_AVScreenCapture * capture,OH_AVScreenCaptureStateCode stateCode,void * userData)86 void OnStateChange(struct OH_AVScreenCapture *capture, OH_AVScreenCaptureStateCode stateCode, void *userData)
87 {
88 if (stateCode == OH_SCREEN_CAPTURE_STATE_STARTED) {
89 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnStateChange started");
90 // 处理状态变更
91 // 可选 配置录屏旋转
92 int32_t ret = OH_AVScreenCapture_SetCanvasRotation(capture, true);
93 // 可选 修改Canvas分辨率
94 ret = OH_AVScreenCapture_ResizeCanvas(g_avCapture, 768, 1280);
95 // 可选 设置是否显示光标
96 ret = OH_AVScreenCapture_ShowCursor(g_avCapture, true);
97 // 可选 设置视频最大帧率
98 ret = OH_AVScreenCapture_SetMaxVideoFrameRate(g_avCapture, 30);
99 }
100 if (stateCode == OH_SCREEN_CAPTURE_STATE_INTERRUPTED_BY_OTHER) {
101 // 处理状态变更
102 }
103 (void)userData;
104 }
105
OnBufferAvailable(OH_AVScreenCapture * capture,OH_AVBuffer * buffer,OH_AVScreenCaptureBufferType bufferType,int64_t timestamp,void * userData)106 void OnBufferAvailable(OH_AVScreenCapture *capture, OH_AVBuffer *buffer, OH_AVScreenCaptureBufferType bufferType,
107 int64_t timestamp, void *userData)
108 {
109 if (m_isRunning) {
110 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnBufferAvailable bufferType is %{public}d",
111 bufferType);
112 if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_VIDEO) {
113 // 处理视频buffer
114 OH_NativeBuffer *nativebuffer = OH_AVBuffer_GetNativeBuffer(buffer);
115 if (nativebuffer != nullptr) {
116 int bufferLen = OH_AVBuffer_GetCapacity(buffer);
117 OH_AVCodecBufferAttr info;
118 int32_t ret = OH_AVBuffer_GetBufferAttr(buffer, &info);
119 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture size %{public}d", info.size);
120 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture bufferLen %{public}d", bufferLen);
121
122 OH_NativeBuffer_Config config;
123 OH_NativeBuffer_GetConfig(nativebuffer, &config);
124 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture height %{public}d width %{public}d",
125 config.height, config.width);
126 // int32_t length = config.height * config.width * 4;
127 uint8_t *buf = OH_AVBuffer_GetAddr(buffer);
128 if (buf == nullptr) {
129 return;
130 }
131 fwrite(buf, 1, bufferLen, vFile_);
132 OH_NativeBuffer_Unreference(nativebuffer);
133 buffer = nullptr;
134 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnBufferAvailable inner audio");
135 }
136 } else if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_INNER) {
137 // 处理内录buffer
138 int bufferLen = OH_AVBuffer_GetCapacity(buffer);
139 uint8_t *buf = OH_AVBuffer_GetAddr(buffer);
140 if (buf != nullptr) {
141 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnBufferAvailable inner audio");
142 fwrite(buf, 1, bufferLen, innerFile_);
143 }
144 } else if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_MIC) {
145 // 处理麦克风buffer
146 int bufferLen = OH_AVBuffer_GetCapacity(buffer);
147 uint8_t *buf = OH_AVBuffer_GetAddr(buffer);
148 if (buf != nullptr) {
149 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnBufferAvailable mic audio");
150 fwrite(buf, 1, bufferLen, micFile_);
151 }
152 }
153 }
154 return;
155 }
156
OnDisplaySelected(struct OH_AVScreenCapture * capture,uint64_t displayId,void * userData)157 void OnDisplaySelected(struct OH_AVScreenCapture *capture, uint64_t displayId, void *userData)
158 {
159 (void)capture;
160 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnError errorCode is %{public}uld", displayId);
161 (void)userData;
162 }
163
164 // 开始录屏原始码流
StartScreenCapture_01(napi_env env,napi_callback_info info)165 static napi_value StartScreenCapture_01(napi_env env, napi_callback_info info)
166 {
167 g_avCapture = OH_AVScreenCapture_Create();
168 if (g_avCapture == nullptr) {
169 OH_LOG_ERROR(LOG_APP, "create screen capture failed");
170 }
171 OH_AVScreenCaptureConfig config_;
172 SetConfig(config_);
173 OpenFile("Demo");
174 bool isMicrophone = true;
175 OH_AVScreenCapture_SetMicrophoneEnabled(g_avCapture, isMicrophone);
176 OH_AVScreenCapture_SetErrorCallback(g_avCapture, OnError, nullptr);
177 OH_AVScreenCapture_SetStateCallback(g_avCapture, OnStateChange, nullptr);
178 OH_AVScreenCapture_SetDataCallback(g_avCapture, OnBufferAvailable, nullptr);
179 OH_AVScreenCapture_SetDisplayCallback(g_avCapture, OnDisplaySelected, nullptr);
180 // 可选,排除指定窗口/指定音频类型 start
181 struct OH_AVScreenCapture_ContentFilter *contentFilter = OH_AVScreenCapture_CreateContentFilter();
182 OH_AVScreenCapture_ContentFilter_AddAudioContent(contentFilter, OH_SCREEN_CAPTURE_NOTIFICATION_AUDIO);
183 vector<int> windowIdsExclude = { -111 };
184 OH_AVScreenCapture_ContentFilter_AddWindowContent(contentFilter,
185 &windowIdsExclude[0], static_cast<int32_t>(windowIdsExclude.size()));
186 OH_AVScreenCapture_ExcludeContent(g_avCapture, contentFilter);
187 OH_AVScreenCapture_SkipPrivacyMode(g_avCapture,
188 &windowIdsExclude[0], static_cast<int32_t>(windowIdsExclude.size()));
189 OH_AVScreenCapture_ReleaseContentFilter(contentFilter);
190 // 可选,排除指定窗口/指定音频类型 end
191 int result = OH_AVScreenCapture_Init(g_avCapture, config_);
192 if (result != AV_SCREEN_CAPTURE_ERR_OK) {
193 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OH_AVScreenCapture_Init failed %{public}d", result);
194 }
195 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OH_AVScreenCapture_Init %{public}d", result);
196
197 result = OH_AVScreenCapture_StartScreenCapture(g_avCapture);
198 if (result != AV_SCREEN_CAPTURE_ERR_OK) {
199 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started failed %{public}d", result);
200 OH_AVScreenCapture_Release(g_avCapture);
201 }
202 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started %{public}d", result);
203
204 m_isRunning = true;
205
206 napi_value res;
207 napi_create_int32(env, result, &res);
208 return res;
209 }
210
211 // 开始录屏存文件
StartScreenCapture_02(napi_env env,napi_callback_info info)212 static napi_value StartScreenCapture_02(napi_env env, napi_callback_info info)
213 {
214 g_avCapture = OH_AVScreenCapture_Create();
215 if (g_avCapture == nullptr) {
216 OH_LOG_ERROR(LOG_APP, "create screen capture failed");
217 }
218 OH_AVScreenCaptureConfig config_;
219
220 OH_RecorderInfo recorderInfo;
221 const std::string filePath = "/data/storage/el2/base/files/";
222 int32_t outputFd = open((filePath + "saving_file.mp4").c_str(), O_RDWR | O_CREAT, 0777);
223 std::string fileUrl = "fd://" + std::to_string(outputFd);
224 recorderInfo.url = const_cast<char *>(fileUrl.c_str());
225 recorderInfo.fileFormat = OH_ContainerFormatType::CFT_MPEG_4;
226 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture fileUrl %{public}s", fileUrl.c_str());
227
228 SetConfig(config_);
229 config_.captureMode = OH_CAPTURE_HOME_SCREEN;
230 config_.dataType = OH_CAPTURE_FILE;
231 config_.recorderInfo = recorderInfo;
232 bool isMicrophone = true;
233 OH_AVScreenCapture_SetMicrophoneEnabled(g_avCapture, isMicrophone);
234 OH_AVScreenCapture_SetStateCallback(g_avCapture, OnStateChange, nullptr);
235 OH_AVScreenCapture_SetDisplayCallback(g_avCapture, OnDisplaySelected, nullptr);
236 OH_AVSCREEN_CAPTURE_ErrCode result = OH_AVScreenCapture_Init(g_avCapture, config_);
237 if (result != AV_SCREEN_CAPTURE_ERR_OK) {
238 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OH_AVScreenCapture_Init failed %{public}d", result);
239 }
240 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OH_AVScreenCapture_Init %{public}d", result);
241
242 result = OH_AVScreenCapture_StartScreenRecording(g_avCapture);
243 if (result != AV_SCREEN_CAPTURE_ERR_OK) {
244 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started failed %{public}d", result);
245 OH_AVScreenCapture_Release(g_avCapture);
246 }
247 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started %{public}d", result);
248
249 m_scSaveFileIsRunning = true;
250 napi_value res;
251 napi_create_int32(env, result, &res);
252 return res;
253 }
254
255 // 开始录屏原始码流SurfaceMode
ThreadVideoRunMethod()256 void ThreadVideoRunMethod()
257 {
258 while (m_scSurfaceIsRunning) {
259 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ThreadVideoRunMethod m_scSurfaceIsRunning %{public}d",
260 m_scSurfaceIsRunning);
261 if (!isStarted_.load()) {
262 return;
263 }
264 std::unique_lock<std::mutex> lock(g_encContext->outputMutex_);
265 bool condRet = g_encContext->outputCond_.wait_for(
266 lock, 2s, [&]() { return !isStarted_.load() || !g_encContext->outputBufferInfoQueue_.empty(); });
267 if (!isStarted_.load()) {
268 return;
269 }
270 if (g_encContext->outputBufferInfoQueue_.empty()) {
271 continue;
272 }
273 CodecBufferInfo bufferInfo = g_encContext->outputBufferInfoQueue_.front();
274 g_encContext->outputBufferInfoQueue_.pop();
275 if (bufferInfo.attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
276 lock.unlock();
277 break;
278 }
279 lock.unlock();
280 if (bufferInfo.buffer != nullptr) {
281 bufferInfo.attr.pts = (bufferInfo.attr.flags & AVCODEC_BUFFER_FLAGS_CODEC_DATA)
282 ? 0
283 : (g_encContext->outputFrameCount_++ * 1000000 / sampleInfo_.frameRate);
284 g_muxer->WriteSample(reinterpret_cast<OH_AVBuffer *>(bufferInfo.buffer), bufferInfo.attr);
285 }
286 OH_VideoEncoder_FreeOutputBuffer(g_videoEnc, bufferInfo.bufferIndex);
287 }
288 }
289
SetFormat()290 int SetFormat()
291 {
292 OH_AVFormat *format = OH_AVFormat_Create();
293 // 配置视频帧速率
294 double frameRate = 30.0;
295 // 配置视频YUV值范围标志
296 bool rangeFlag = false;
297 // 配置视频原色
298 int32_t primary = static_cast<int32_t>(OH_ColorPrimary::COLOR_PRIMARY_BT709);
299 // 配置传输特性
300 int32_t transfer = static_cast<int32_t>(OH_TransferCharacteristic::TRANSFER_CHARACTERISTIC_BT709);
301 // 配置最大矩阵系数
302 int32_t matrix = static_cast<int32_t>(OH_MatrixCoefficient::MATRIX_COEFFICIENT_IDENTITY);
303 // 配置编码Profile
304 int32_t profile = static_cast<int32_t>(OH_AVCProfile::AVC_PROFILE_BASELINE);
305 // 配置编码比特率模式
306 int32_t rateMode = static_cast<int32_t>(OH_VideoEncodeBitrateMode::CBR);
307 // 配置关键帧的间隔,单位为毫秒
308 int32_t iFrameInterval = 23000;
309 // 配置所需的编码质量。只有在恒定质量模式下配置的编码器才支持此配置
310 int32_t quality = 0;
311 // 配置比特率
312 int64_t bitRate = 2000000;
313 OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
314 sampleInfo_.videoWidth = DEFAULT_WIDTH;
315 OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
316 sampleInfo_.videoHeight = DEFAULT_HEIGHT;
317 OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIXELFORMAT);
318 OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
319 sampleInfo_.frameRate = frameRate;
320 sampleInfo_.videoCodecMime = sampleInfo_.codecMime.data();
321 OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, rangeFlag);
322 OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, primary);
323 OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, transfer);
324 OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, matrix);
325 OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, iFrameInterval);
326 OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, profile);
327 OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, rateMode);
328 OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, bitRate);
329 OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, quality);
330 int result = OH_VideoEncoder_Configure(g_videoEnc, format);
331 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== OH_VideoEncoder_Configure ret=%{public}d", result);
332 OH_AVFormat_Destroy(format);
333 return result;
334 }
335
GetInputSurface()336 int GetInputSurface()
337 {
338 // 获取需要输入的Surface,以进行编码
339 OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
340 const char *name = OH_AVCapability_GetName(capability);
341 g_videoEnc = OH_VideoEncoder_CreateByName(name);
342 g_muxer = std::make_unique<Muxer>();
343 const std::string filePath = "/data/storage/el2/base/files/";
344 int32_t outputFd = open((filePath + "surface.mp4").c_str(), O_RDWR | O_CREAT, 0777);
345 g_muxer->Create(outputFd);
346 g_encContext = new CodecUserData;
347 g_encContext->sampleInfo = &sampleInfo_;
348 // 配置异步回调,调用 OH_VideoEncoder_SetCallback 接口
349 OH_VideoEncoder_RegisterCallback(g_videoEnc,
350 {SampleCallback::OnError, SampleCallback::OnStreamChanged,
351 SampleCallback::OnNeedInputBuffer, SampleCallback::OnNewOutputBuffer},
352 g_encContext);
353 (void)SetFormat();
354 // 从视频编码器获取输入Surface
355 OHNativeWindow *nativeWindow;
356 int result = OH_VideoEncoder_GetSurface(g_videoEnc, &nativeWindow);
357 if (result != AV_ERR_OK) {
358 OH_LOG_ERROR(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started OH_VideoEncoder_GetSurface ret=%{public}d",
359 result);
360 return result;
361 }
362 result = OH_VideoEncoder_Prepare(g_videoEnc);
363 g_muxer->Config(sampleInfo_);
364 g_muxer->Start();
365 // 启动编码器
366 result = OH_VideoEncoder_Start(g_videoEnc);
367 isStarted_.store(true);
368 m_scSurfaceIsRunning = true;
369 inputVideoThread_ = std::make_unique<std::thread>(ThreadVideoRunMethod);
370 // 指定surface开始录屏
371 result = OH_AVScreenCapture_StartScreenCaptureWithSurface(g_avCapture, nativeWindow);
372 if (result != AV_SCREEN_CAPTURE_ERR_OK) {
373 OH_LOG_ERROR(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started failed %{public}d", result);
374 OH_AVScreenCapture_Release(g_avCapture);
375 return result;
376 }
377 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started %{public}d", result);
378 return result;
379 }
380
StartScreenCapture_03(napi_env env,napi_callback_info info)381 static napi_value StartScreenCapture_03(napi_env env, napi_callback_info info)
382 {
383 isStarted_.store(false);
384 inputVideoThread_ = nullptr;
385 g_encContext = nullptr;
386 g_avCapture = OH_AVScreenCapture_Create();
387 if (g_avCapture == nullptr) {
388 OH_LOG_ERROR(LOG_APP, "create screen capture failed");
389 }
390 OH_AVScreenCaptureConfig config_;
391 SetConfig(config_);
392 bool isMicrophone = false;
393 OH_AVScreenCapture_SetMicrophoneEnabled(g_avCapture, isMicrophone);
394 OH_AVScreenCapture_SetErrorCallback(g_avCapture, OnError, nullptr);
395 OH_AVScreenCapture_SetStateCallback(g_avCapture, OnStateChange, nullptr);
396 OH_AVScreenCapture_SetDataCallback(g_avCapture, OnBufferAvailable, nullptr);
397 OH_AVScreenCapture_SetDisplayCallback(g_avCapture, OnDisplaySelected, nullptr);
398 int result = OH_AVScreenCapture_Init(g_avCapture, config_);
399 if (result != AV_SCREEN_CAPTURE_ERR_OK) {
400 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OH_AVScreenCapture_Init failed %{public}d", result);
401 }
402 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OH_AVScreenCapture_Init %{public}d", result);
403 (void)GetInputSurface();
404 napi_value res;
405 napi_create_int32(env, result, &res);
406 return res;
407 }
408
409 // 停止
StopScreenCapture(napi_env env,napi_callback_info info)410 static napi_value StopScreenCapture(napi_env env, napi_callback_info info)
411 {
412 OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture Stop");
413 OH_AVSCREEN_CAPTURE_ErrCode result = AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT;
414 napi_value res;
415 if (m_scSurfaceIsRunning) {
416 (void)OH_VideoEncoder_NotifyEndOfStream(g_videoEnc);
417 (void)OH_VideoEncoder_Stop(g_videoEnc);
418 (void)OH_VideoEncoder_Destroy(g_videoEnc);
419 g_videoEnc = nullptr;
420 g_muxer->Stop();
421 m_scSurfaceIsRunning = false;
422 isStarted_.store(false);
423 if (inputVideoThread_ && inputVideoThread_->joinable()) {
424 inputVideoThread_->join();
425 }
426 }
427 if (g_avCapture == nullptr) {
428 OH_LOG_ERROR(LOG_APP, "capture_ is null.");
429 }
430 if (m_scSaveFileIsRunning) {
431 result = OH_AVScreenCapture_StopScreenRecording(g_avCapture);
432 if (result != AV_SCREEN_CAPTURE_ERR_BASE) {
433 OH_LOG_ERROR(LOG_APP, "StopScreenCapture OH_AVScreenCapture_StopScreenRecording Result: %{public}d",
434 result);
435 }
436 result = OH_AVScreenCapture_Release(g_avCapture);
437 if (result != AV_SCREEN_CAPTURE_ERR_BASE) {
438 OH_LOG_ERROR(LOG_APP, "StopScreenCapture OH_AVScreenCapture_Release: %{public}d", result);
439 }
440 OH_LOG_INFO(LOG_APP, "OH_AVScreenCapture_Release success");
441 m_scSaveFileIsRunning = false;
442 } else {
443 result = OH_AVScreenCapture_StopScreenCapture(g_avCapture);
444 if (result != AV_SCREEN_CAPTURE_ERR_BASE) {
445 OH_LOG_ERROR(LOG_APP, "StopScreenCapture OH_AVScreenCapture_StopScreenCapture Result: %{public}d", result);
446 }
447 result = OH_AVScreenCapture_Release(g_avCapture);
448 if (result != AV_SCREEN_CAPTURE_ERR_BASE) {
449 OH_LOG_ERROR(LOG_APP, "StopScreenCapture OH_AVScreenCapture_Release: %{public}d", result);
450 }
451 OH_LOG_INFO(LOG_APP, "OH_AVScreenCapture_Release success");
452 CloseFile();
453 m_isRunning = false;
454 }
455 napi_create_int32(env, result, &res);
456 return res;
457 }
458
459
460 // 调用老接口,仅提供代码实现,不建议使用
MockOnAudioBufferAvailable(OH_AVScreenCapture * screenCapture,bool isReady,OH_AudioCaptureSourceType type)461 void MockOnAudioBufferAvailable(OH_AVScreenCapture *screenCapture, bool isReady, OH_AudioCaptureSourceType type)
462 {
463 if (isReady == true) {
464 OH_AudioBuffer *audioBuffer = (OH_AudioBuffer *)malloc(sizeof(OH_AudioBuffer));
465 if (audioBuffer == nullptr) {
466 OH_LOG_INFO(LOG_APP, "audio buffer is nullptr");
467 return;
468 }
469 if (OH_AVScreenCapture_AcquireAudioBuffer(screenCapture, &audioBuffer, type) == AV_SCREEN_CAPTURE_ERR_OK) {
470 if ((micFile_ != nullptr) && (audioBuffer->buf != nullptr) && (type == OH_MIC)) {
471 int32_t ret = fwrite(audioBuffer->buf, 1, audioBuffer->size, micFile_);
472 free(audioBuffer->buf);
473 audioBuffer->buf = nullptr;
474 } else if ((innerFile_ != nullptr) && (audioBuffer->buf != nullptr) && (type == OH_ALL_PLAYBACK)) {
475 int32_t ret = fwrite(audioBuffer->buf, 1, audioBuffer->size, innerFile_);
476 free(audioBuffer->buf);
477 audioBuffer->buf = nullptr;
478 }
479 free(audioBuffer);
480 audioBuffer = nullptr;
481 }
482 // do something
483 OH_AVScreenCapture_ReleaseAudioBuffer(screenCapture, type);
484 } else {
485 OH_LOG_INFO(LOG_APP, "AcquireAudioBuffer failed");
486 }
487 }
488
489 // 调用老接口,仅提供代码实现,不建议使用
MockOnVideoBufferAvailable(OH_AVScreenCapture * screenCapture,bool isReady)490 void MockOnVideoBufferAvailable(OH_AVScreenCapture *screenCapture, bool isReady)
491 {
492 if (isReady == true) {
493 int32_t fence = 0;
494 int64_t timestamp = 0;
495 int32_t size = 4;
496 OH_Rect damage;
497 OH_NativeBuffer_Config config;
498 OH_NativeBuffer *nativeBuffer =
499 OH_AVScreenCapture_AcquireVideoBuffer(screenCapture, &fence, ×tamp, &damage);
500 if (nativeBuffer != nullptr) {
501 OH_NativeBuffer_GetConfig(nativeBuffer, &config);
502 int32_t length = config.height * config.width * size;
503 OH_NativeBuffer_Unreference(nativeBuffer);
504 } else {
505 OH_LOG_INFO(LOG_APP, "AcquireVideoBuffer failed");
506 }
507 // do something
508 OH_AVScreenCapture_ReleaseVideoBuffer(screenCapture);
509 }
510 }
511
512 // 调用老接口,仅提供代码实现,不建议使用
MockOnError(OH_AVScreenCapture * screenCapture,int32_t errorCode)513 void MockOnError(OH_AVScreenCapture *screenCapture, int32_t errorCode)
514 {
515 // 错误处理
516 }
517
518 // 调用老接口,仅提供代码实现,不建议使用
SetScreenCaptureCallback()519 void SetScreenCaptureCallback()
520 {
521 struct OH_AVScreenCaptureCallback callback;
522 callback.onAudioBufferAvailable = MockOnAudioBufferAvailable;
523 callback.onVideoBufferAvailable = MockOnVideoBufferAvailable;
524 callback.onError = MockOnError;
525 OH_AVScreenCapture_SetCallback(g_avCapture, callback);
526 }
527
528 EXTERN_C_START
Init(napi_env env,napi_value exports)529 static napi_value Init(napi_env env, napi_value exports)
530 {
531 napi_property_descriptor desc[] = {
532 {"startScreenCapture", nullptr, StartScreenCapture_01, nullptr, nullptr, nullptr, napi_default, nullptr},
533 {"stopScreenCapture", nullptr, StopScreenCapture, nullptr, nullptr, nullptr, napi_default, nullptr},
534 {"startCaptureAsFile", nullptr, StartScreenCapture_02, nullptr, nullptr, nullptr, napi_default, nullptr},
535 {"startScreenCaptureWithSurface", nullptr, StartScreenCapture_03, nullptr, nullptr, nullptr, napi_default,
536 nullptr},
537 };
538 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
539 return exports;
540 }
541 EXTERN_C_END
542
543 static napi_module demoModule = {
544 .nm_version = 1,
545 .nm_flags = 0,
546 .nm_filename = nullptr,
547 .nm_register_func = Init,
548 .nm_modname = "entry",
549 .nm_priv = ((void *)0),
550 .reserved = {0},
551 };
552
RegisterScreencaptureModule(void)553 extern "C" __attribute__((constructor)) void RegisterScreencaptureModule(void) { napi_module_register(&demoModule); }
554