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