diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/README_zh.md b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/README_zh.md index 8ac7552432f4590dd73d8845a9699bc54cf4b2da..7139ec22084ec5c12c2213b3a760b77e728073ee 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/README_zh.md +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/README_zh.md @@ -1,10 +1,10 @@ -# 录屏 Sample +# 录屏Sample ## 介绍 -录屏 Sample 调用了媒体 AVScreenCapture 组件提供的接口能力,提供屏幕捕获的功能,包含: +录屏Sample调用了媒体AVScreenCapture组件提供的接口能力,提供屏幕捕获的功能,包含: - 录屏存文件 - 录屏取原始码流 -- 录屏取原始码流 Surface 模式 +- 录屏取原始码流Surface模式 ## 效果预览 | 获取录音权限 | 应用主界面 | 隐私弹窗 | 录制过程界面 | @@ -14,18 +14,18 @@ 使用说明 1. 启动应用,首次启动需要用户授予访问麦克风的权限。 -2. 选择对应的功能页签,点击 Start 按钮,启动屏幕录制。 +2. 选择对应的功能页签,点击Start按钮,启动屏幕录制。 3. 启动录制后会弹出隐私弹窗,告知用户将被录屏。 4. 选择允许后,启动录制后会弹出录制悬浮胶囊,并显示录制时间计时,此时可以操作屏幕,屏幕上的操作过程会被录制下来。 5. 需要停止录屏时,点击应用停止按钮或点击悬浮半透明的红色按钮,屏幕录制停止。 -6. 录屏存储的文件保存在沙箱目录。 +6. 录屏存储的文件保存在沙箱目录,录制结果与设备支持的编码格式有关。 ## 工程目录 仓目录结构如下: ``` -entry/src/main # 录屏demo业务代码 +entry/src/main # 录屏Sample业务代码 │ module.json5 # 编译相关文件 ├─cpp # ndk相关文件 │ │ CMakeLists.txt @@ -39,13 +39,13 @@ entry/src/main # 录屏demo业务代码 ├─ets # 页面相关实现 │ ├─entryability │ ├─entrybackupability -│ └─pages # ets 页面实现 +│ └─pages # ets页面实现 │ Index.ets # 首页 │ Menu.ets # 列表文件 │ Scene1.ets # 录屏存文件场景 │ Scene2.ets # 录屏取码流场景 │ Scene3.ets # 录屏取码流Surface场景 -│ Scene4.ets # 其他场景 +│ Scene4.ets # 录屏存文件js接口 │ └─resources # 资源文件 ``` @@ -53,7 +53,9 @@ entry/src/main # 录屏demo业务代码 ## 相关权限 ohos.permission.MICROPHONE + ohos.permission.KEEP_BACKGROUND_RUNNING + ohos.permission.WRITE_MEDIA ## 依赖 @@ -76,6 +78,6 @@ ohos.permission.WRITE_MEDIA git init git config core.sparsecheckout true echo code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/ > .git/info/sparse-checkout -git remote add origin OpenHarmony/applications_app_samples +git remote add origin https://gitee.com/openharmony/applications_app_samples.git git pull origin master ``` \ No newline at end of file diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/build-profile.json5 b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/build-profile.json5 index 01bed8940ff6f2d5843f8d1d7e184725f59be699..6125a7467db0b8ece6e5cbf1fabff87bbdcc3999 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/build-profile.json5 +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/build-profile.json5 @@ -20,6 +20,10 @@ "path": "./src/main/cpp/CMakeLists.txt", "arguments": "", "cppFlags": "", + "abiFilters": [ + "armeabi-v7a", + "arm64-v8a" + ] } }, "buildOptionSet": [ diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/muxer.cpp b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/muxer.cpp index 83b830fbd2ab50726f8d62cf5a35291f5f06426d..6eeb60c28671e04b4776ea22f81113ae40f982e3 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/muxer.cpp +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/muxer.cpp @@ -37,7 +37,7 @@ int32_t Muxer::Create(int32_t fd) int32_t Muxer::Config(SampleInfo &sampleInfo) { - OH_LOG_INFO(LOG_APP, "==DEMO== Config"); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== Config"); OH_AVFormat *formatVideo = OH_AVFormat_CreateVideoFormat(sampleInfo.codecMime.data(), sampleInfo.videoWidth, sampleInfo.videoHeight); @@ -48,7 +48,7 @@ int32_t Muxer::Config(SampleInfo &sampleInfo) int32_t ret = OH_AVMuxer_AddTrack(muxer_, &videoTrackId_, formatVideo); OH_AVFormat_Destroy(formatVideo); - OH_LOG_INFO(LOG_APP, "==DEMO== Config End"); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== Config End"); return 0; } diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/napi_init.cpp b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/napi_init.cpp index 999058144c72cf0fa80c3f5b33a1e7707820b41c..27b60e4b76f1819e71bb7a8cffef959d6e96e87a 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/napi_init.cpp +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/napi_init.cpp @@ -16,51 +16,29 @@ #include "main.h" using namespace std; -#define LOG_TAG "MY_TAG" +#define LOG_TAG "ScreenCaptureSample" -static napi_value Add(napi_env env, napi_callback_info info) { - size_t requireArgc = 2; - size_t argc = 2; - napi_value args[2] = {nullptr}; - - napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - - napi_valuetype valuetype0; - napi_typeof(env, args[0], &valuetype0); - - napi_valuetype valuetype1; - napi_typeof(env, args[1], &valuetype1); - - double value0; - napi_get_value_double(env, args[0], &value0); - - double value1; - napi_get_value_double(env, args[1], &value1); - - napi_value sum; - napi_create_double(env, value0 + value1, &sum); - return sum; -} - -void OpenFile(std::string filename_) { - snprintf(filename, sizeof(filename), "data/storage/el2/base/files/MIC_%s.pcm", filename_.c_str()); - micFile_ = fopen(filename, "wb"); +void OpenFile(std::string fileName) +{ + std::string filePath = "data/storage/el2/base/files/MIC_" + fileName + ".pcm"; + micFile_ = fopen(filePath.c_str(), "wb"); if (micFile_ == nullptr) { - // OH_LOG_ERROR(LOG_APP, "OpenFile micFile_ audio open failed. %{public}s", strerror(errno)); + OH_LOG_ERROR(LOG_APP, "OpenFile micFile_ audio open failed. %{public}s", strerror(errno)); } - snprintf(filename, sizeof(filename), "data/storage/el2/base/files/INNER_%s.pcm", filename_.c_str()); - innerFile_ = fopen(filename, "wb"); + filePath = "data/storage/el2/base/files/INNER_" + fileName + ".pcm"; + innerFile_ = fopen(filePath.c_str(), "wb"); if (innerFile_ == nullptr) { - // OH_LOG_ERROR(LOG_APP, "OpenFile innerFile_ audio open failed. %{public}s", strerror(errno)); + OH_LOG_ERROR(LOG_APP, "OpenFile innerFile_ audio open failed. %{public}s", strerror(errno)); } - snprintf(filename, sizeof(filename), "data/storage/el2/base/files/VIDEO_%s.yuv", filename_.c_str()); - vFile_ = fopen(filename, "wb"); + filePath = "data/storage/el2/base/files/VIDEO_" + fileName + ".yuv"; + vFile_ = fopen(filePath.c_str(), "wb"); if (vFile_ == nullptr) { - // OH_LOG_ERROR(LOG_APP, "OpenFile vFile video open failed. %{public}s", strerror(errno)); + OH_LOG_ERROR(LOG_APP, "OpenFile vFile video open failed. %{public}s", strerror(errno)); } } -void CloseFile(void) { +void CloseFile(void) +{ if (micFile_ != nullptr) { fclose(micFile_); micFile_ = nullptr; @@ -75,7 +53,8 @@ void CloseFile(void) { } } -void SetConfig(OH_AVScreenCaptureConfig &config) { +void SetConfig(OH_AVScreenCaptureConfig &config) +{ int32_t width = 720; int32_t height = 1280; OH_AudioCaptureInfo micCapInfo = {.audioSampleRate = 48000, .audioChannels = 2, .audioSource = OH_MIC}; @@ -97,15 +76,17 @@ void SetConfig(OH_AVScreenCaptureConfig &config) { }; } -void OnError(OH_AVScreenCapture *capture, int32_t errorCode, void *userData) { +void OnError(OH_AVScreenCapture *capture, int32_t errorCode, void *userData) +{ (void)capture; - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OnError errorCode is %{public}d", errorCode); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnError errorCode is %{public}d", errorCode); (void)userData; } -void OnStateChange(struct OH_AVScreenCapture *capture, OH_AVScreenCaptureStateCode stateCode, void *userData) { +void OnStateChange(struct OH_AVScreenCapture *capture, OH_AVScreenCaptureStateCode stateCode, void *userData) +{ if (stateCode == OH_SCREEN_CAPTURE_STATE_STARTED) { - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OnStateChange started"); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnStateChange started"); // 处理状态变更 // 可选 配置录屏旋转 int32_t ret = OH_AVScreenCapture_SetCanvasRotation(capture, true); @@ -123,9 +104,11 @@ void OnStateChange(struct OH_AVScreenCapture *capture, OH_AVScreenCaptureStateCo } void OnBufferAvailable(OH_AVScreenCapture *capture, OH_AVBuffer *buffer, OH_AVScreenCaptureBufferType bufferType, - int64_t timestamp, void *userData) { + int64_t timestamp, void *userData) +{ if (m_isRunning) { - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OnBufferAvailable bufferType is %{public}d", bufferType); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnBufferAvailable bufferType is %{public}d", + bufferType); if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_VIDEO) { // 处理视频buffer OH_NativeBuffer *nativebuffer = OH_AVBuffer_GetNativeBuffer(buffer); @@ -133,13 +116,13 @@ void OnBufferAvailable(OH_AVScreenCapture *capture, OH_AVBuffer *buffer, OH_AVSc int bufferLen = OH_AVBuffer_GetCapacity(buffer); OH_AVCodecBufferAttr info; int32_t ret = OH_AVBuffer_GetBufferAttr(buffer, &info); - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture size %{public}d", info.size); - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture bufferLen %{public}d", bufferLen); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture size %{public}d", info.size); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture bufferLen %{public}d", bufferLen); OH_NativeBuffer_Config config; OH_NativeBuffer_GetConfig(nativebuffer, &config); - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture height %{public}d width %{public}d", config.height, - config.width); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture height %{public}d width %{public}d", + config.height, config.width); // int32_t length = config.height * config.width * 4; uint8_t *buf = OH_AVBuffer_GetAddr(buffer); if (buf == nullptr) { @@ -148,14 +131,14 @@ void OnBufferAvailable(OH_AVScreenCapture *capture, OH_AVBuffer *buffer, OH_AVSc fwrite(buf, 1, bufferLen, vFile_); OH_NativeBuffer_Unreference(nativebuffer); buffer = nullptr; - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OnBufferAvailable inner audio"); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnBufferAvailable inner audio"); } } else if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_INNER) { // 处理内录buffer int bufferLen = OH_AVBuffer_GetCapacity(buffer); uint8_t *buf = OH_AVBuffer_GetAddr(buffer); if (buf != nullptr) { - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OnBufferAvailable inner audio"); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnBufferAvailable inner audio"); fwrite(buf, 1, bufferLen, innerFile_); } } else if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_MIC) { @@ -163,7 +146,7 @@ void OnBufferAvailable(OH_AVScreenCapture *capture, OH_AVBuffer *buffer, OH_AVSc int bufferLen = OH_AVBuffer_GetCapacity(buffer); uint8_t *buf = OH_AVBuffer_GetAddr(buffer); if (buf != nullptr) { - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OnBufferAvailable mic audio"); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnBufferAvailable mic audio"); fwrite(buf, 1, bufferLen, micFile_); } } @@ -174,12 +157,13 @@ void OnBufferAvailable(OH_AVScreenCapture *capture, OH_AVBuffer *buffer, OH_AVSc void OnDisplaySelected(struct OH_AVScreenCapture *capture, uint64_t displayId, void *userData) { (void)capture; - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OnError errorCode is %{public}uld", displayId); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OnError errorCode is %{public}uld", displayId); (void)userData; } // 开始录屏原始码流 -static napi_value StartScreenCapture_01(napi_env env, napi_callback_info info) { +static napi_value StartScreenCapture_01(napi_env env, napi_callback_info info) +{ g_avCapture = OH_AVScreenCapture_Create(); if (g_avCapture == nullptr) { OH_LOG_ERROR(LOG_APP, "create screen capture failed"); @@ -206,16 +190,16 @@ static napi_value StartScreenCapture_01(napi_env env, napi_callback_info info) { // 可选,排除指定窗口/指定音频类型 end int result = OH_AVScreenCapture_Init(g_avCapture, config_); if (result != AV_SCREEN_CAPTURE_ERR_OK) { - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OH_AVScreenCapture_Init failed %{public}d", result); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OH_AVScreenCapture_Init failed %{public}d", result); } - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OH_AVScreenCapture_Init %{public}d", result); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OH_AVScreenCapture_Init %{public}d", result); result = OH_AVScreenCapture_StartScreenCapture(g_avCapture); if (result != AV_SCREEN_CAPTURE_ERR_OK) { - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture Started failed %{public}d", result); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started failed %{public}d", result); OH_AVScreenCapture_Release(g_avCapture); } - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture Started %{public}d", result); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started %{public}d", result); m_isRunning = true; @@ -225,7 +209,8 @@ static napi_value StartScreenCapture_01(napi_env env, napi_callback_info info) { } // 开始录屏存文件 -static napi_value StartScreenCapture_02(napi_env env, napi_callback_info info) { +static napi_value StartScreenCapture_02(napi_env env, napi_callback_info info) +{ g_avCapture = OH_AVScreenCapture_Create(); if (g_avCapture == nullptr) { OH_LOG_ERROR(LOG_APP, "create screen capture failed"); @@ -233,12 +218,12 @@ static napi_value StartScreenCapture_02(napi_env env, napi_callback_info info) { OH_AVScreenCaptureConfig config_; OH_RecorderInfo recorderInfo; - const std::string SCREEN_CAPTURE_ROOT = "/data/storage/el2/base/files/"; - int32_t outputFd = open((SCREEN_CAPTURE_ROOT + "saving_file.mp4").c_str(), O_RDWR | O_CREAT, 0777); + const std::string filePath = "/data/storage/el2/base/files/"; + int32_t outputFd = open((filePath + "saving_file.mp4").c_str(), O_RDWR | O_CREAT, 0777); std::string fileUrl = "fd://" + std::to_string(outputFd); recorderInfo.url = const_cast(fileUrl.c_str()); recorderInfo.fileFormat = OH_ContainerFormatType::CFT_MPEG_4; - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture fileUrl %{public}s", fileUrl.c_str()); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture fileUrl %{public}s", fileUrl.c_str()); SetConfig(config_); config_.captureMode = OH_CAPTURE_HOME_SCREEN; @@ -250,16 +235,16 @@ static napi_value StartScreenCapture_02(napi_env env, napi_callback_info info) { OH_AVScreenCapture_SetDisplayCallback(g_avCapture, OnDisplaySelected, nullptr); OH_AVSCREEN_CAPTURE_ErrCode result = OH_AVScreenCapture_Init(g_avCapture, config_); if (result != AV_SCREEN_CAPTURE_ERR_OK) { - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OH_AVScreenCapture_Init failed %{public}d", result); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OH_AVScreenCapture_Init failed %{public}d", result); } - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OH_AVScreenCapture_Init %{public}d", result); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OH_AVScreenCapture_Init %{public}d", result); result = OH_AVScreenCapture_StartScreenRecording(g_avCapture); if (result != AV_SCREEN_CAPTURE_ERR_OK) { - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture Started failed %{public}d", result); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started failed %{public}d", result); OH_AVScreenCapture_Release(g_avCapture); } - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture Started %{public}d", result); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started %{public}d", result); m_scSaveFileIsRunning = true; napi_value res; @@ -268,9 +253,11 @@ static napi_value StartScreenCapture_02(napi_env env, napi_callback_info info) { } // 开始录屏原始码流SurfaceMode -void ThreadVideoRunMethod() { +void ThreadVideoRunMethod() +{ while (m_scSurfaceIsRunning) { - OH_LOG_INFO(LOG_APP, "==DEMO== ThreadVideoRunMethod m_scSurfaceIsRunning %{public}d", m_scSurfaceIsRunning); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ThreadVideoRunMethod m_scSurfaceIsRunning %{public}d", + m_scSurfaceIsRunning); if (!isStarted_.load()) { return; } @@ -300,43 +287,8 @@ void ThreadVideoRunMethod() { } } -static napi_value StartScreenCapture_03(napi_env env, napi_callback_info info) { - isStarted_.store(false); - inputVideoThread_ = nullptr; - g_encContext = nullptr; - g_avCapture = OH_AVScreenCapture_Create(); - if (g_avCapture == nullptr) { - OH_LOG_ERROR(LOG_APP, "create screen capture failed"); - } - OH_AVScreenCaptureConfig config_; - SetConfig(config_); - bool isMicrophone = false; - OH_AVScreenCapture_SetMicrophoneEnabled(g_avCapture, isMicrophone); - OH_AVScreenCapture_SetErrorCallback(g_avCapture, OnError, nullptr); - OH_AVScreenCapture_SetStateCallback(g_avCapture, OnStateChange, nullptr); - OH_AVScreenCapture_SetDataCallback(g_avCapture, OnBufferAvailable, nullptr); - OH_AVScreenCapture_SetDisplayCallback(g_avCapture, OnDisplaySelected, nullptr); - int result = OH_AVScreenCapture_Init(g_avCapture, config_); - if (result != AV_SCREEN_CAPTURE_ERR_OK) { - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OH_AVScreenCapture_Init failed %{public}d", result); - } - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture OH_AVScreenCapture_Init %{public}d", result); - - // 获取需要输入的Surface,以进行编码 - OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true); - const char *name = OH_AVCapability_GetName(capability); - g_videoEnc = OH_VideoEncoder_CreateByName(name); - g_muxer = std::make_unique(); - const std::string SCREEN_CAPTURE_ROOT = "/data/storage/el2/base/files/"; - int32_t outputFd = open((SCREEN_CAPTURE_ROOT + "surface.mp4").c_str(), O_RDWR | O_CREAT, 0777); - g_muxer->Create(outputFd); - g_encContext = new CodecUserData; - g_encContext->sampleInfo = &sampleInfo_; - // 配置异步回调,调用 OH_VideoEncoder_SetCallback 接口 - OH_VideoEncoder_RegisterCallback(g_videoEnc, - {SampleCallback::OnError, SampleCallback::OnStreamChanged, - SampleCallback::OnNeedInputBuffer, SampleCallback::OnNewOutputBuffer}, - g_encContext); +int SetFormat() +{ OH_AVFormat *format = OH_AVFormat_Create(); // 配置视频帧速率 double frameRate = 30.0; @@ -357,7 +309,7 @@ static napi_value StartScreenCapture_03(napi_env env, napi_callback_info info) { // 配置所需的编码质量。只有在恒定质量模式下配置的编码器才支持此配置 int32_t quality = 0; // 配置比特率 - int64_t bitRate = 3000000; + int64_t bitRate = 2000000; OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH); sampleInfo_.videoWidth = DEFAULT_WIDTH; OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT); @@ -375,54 +327,95 @@ static napi_value StartScreenCapture_03(napi_env env, napi_callback_info info) { OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, rateMode); OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, bitRate); OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, quality); - result = OH_VideoEncoder_Configure(g_videoEnc, format); - OH_LOG_INFO(LOG_APP, "==DEMO== OH_VideoEncoder_Configure ret=%{public}d", result); + int result = OH_VideoEncoder_Configure(g_videoEnc, format); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== OH_VideoEncoder_Configure ret=%{public}d", result); OH_AVFormat_Destroy(format); + return result; +} +int GetInputSurface() +{ + // 获取需要输入的Surface,以进行编码 + OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true); + const char *name = OH_AVCapability_GetName(capability); + g_videoEnc = OH_VideoEncoder_CreateByName(name); + g_muxer = std::make_unique(); + const std::string filePath = "/data/storage/el2/base/files/"; + int32_t outputFd = open((filePath + "surface.mp4").c_str(), O_RDWR | O_CREAT, 0777); + g_muxer->Create(outputFd); + g_encContext = new CodecUserData; + g_encContext->sampleInfo = &sampleInfo_; + // 配置异步回调,调用 OH_VideoEncoder_SetCallback 接口 + OH_VideoEncoder_RegisterCallback(g_videoEnc, + {SampleCallback::OnError, SampleCallback::OnStreamChanged, + SampleCallback::OnNeedInputBuffer, SampleCallback::OnNewOutputBuffer}, + g_encContext); + (void)SetFormat(); // 从视频编码器获取输入Surface OHNativeWindow *nativeWindow; - result = OH_VideoEncoder_GetSurface(g_videoEnc, &nativeWindow); + int result = OH_VideoEncoder_GetSurface(g_videoEnc, &nativeWindow); if (result != AV_ERR_OK) { - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture Started OH_VideoEncoder_GetSurface ret=%{public}d", result); + OH_LOG_ERROR(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started OH_VideoEncoder_GetSurface ret=%{public}d", + result); + return result; } result = OH_VideoEncoder_Prepare(g_videoEnc); g_muxer->Config(sampleInfo_); g_muxer->Start(); // 启动编码器 - int32_t retEnc = OH_VideoEncoder_Start(g_videoEnc); + result = OH_VideoEncoder_Start(g_videoEnc); isStarted_.store(true); m_scSurfaceIsRunning = true; inputVideoThread_ = std::make_unique(ThreadVideoRunMethod); // 指定surface开始录屏 result = OH_AVScreenCapture_StartScreenCaptureWithSurface(g_avCapture, nativeWindow); if (result != AV_SCREEN_CAPTURE_ERR_OK) { - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture Started failed %{public}d", result); + OH_LOG_ERROR(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started failed %{public}d", result); OH_AVScreenCapture_Release(g_avCapture); + return result; } - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture Started %{public}d", result); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture Started %{public}d", result); + return result; +} + +static napi_value StartScreenCapture_03(napi_env env, napi_callback_info info) +{ + isStarted_.store(false); + inputVideoThread_ = nullptr; + g_encContext = nullptr; + g_avCapture = OH_AVScreenCapture_Create(); + if (g_avCapture == nullptr) { + OH_LOG_ERROR(LOG_APP, "create screen capture failed"); + } + OH_AVScreenCaptureConfig config_; + SetConfig(config_); + bool isMicrophone = false; + OH_AVScreenCapture_SetMicrophoneEnabled(g_avCapture, isMicrophone); + OH_AVScreenCapture_SetErrorCallback(g_avCapture, OnError, nullptr); + OH_AVScreenCapture_SetStateCallback(g_avCapture, OnStateChange, nullptr); + OH_AVScreenCapture_SetDataCallback(g_avCapture, OnBufferAvailable, nullptr); + OH_AVScreenCapture_SetDisplayCallback(g_avCapture, OnDisplaySelected, nullptr); + int result = OH_AVScreenCapture_Init(g_avCapture, config_); + if (result != AV_SCREEN_CAPTURE_ERR_OK) { + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OH_AVScreenCapture_Init failed %{public}d", result); + } + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture OH_AVScreenCapture_Init %{public}d", result); + (void)GetInputSurface(); napi_value res; napi_create_int32(env, result, &res); return res; } // 停止 -static napi_value StopScreenCapture(napi_env env, napi_callback_info info) { - OH_LOG_INFO(LOG_APP, "==DEMO== ScreenCapture Stop"); +static napi_value StopScreenCapture(napi_env env, napi_callback_info info) +{ + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== ScreenCapture Stop"); OH_AVSCREEN_CAPTURE_ErrCode result = AV_SCREEN_CAPTURE_ERR_OPERATE_NOT_PERMIT; napi_value res; if (m_scSurfaceIsRunning) { - int32_t ret = OH_VideoEncoder_NotifyEndOfStream(g_videoEnc); - if (ret != AV_ERR_OK) { - // 异常处理 - } - ret = OH_VideoEncoder_Stop(g_videoEnc); - if (ret != AV_ERR_OK) { - // 异常处理 - } - ret = OH_VideoEncoder_Destroy(g_videoEnc); - if (ret != AV_ERR_OK) { - // 异常处理 - } + (void)OH_VideoEncoder_NotifyEndOfStream(g_videoEnc); + (void)OH_VideoEncoder_Stop(g_videoEnc); + (void)OH_VideoEncoder_Destroy(g_videoEnc); g_videoEnc = nullptr; g_muxer->Stop(); m_scSurfaceIsRunning = false; @@ -431,16 +424,15 @@ static napi_value StopScreenCapture(napi_env env, napi_callback_info info) { inputVideoThread_->join(); } } - + if (g_avCapture == nullptr) { + OH_LOG_ERROR(LOG_APP, "capture_ is null."); + } if (m_scSaveFileIsRunning) { - if (g_avCapture == nullptr) { - OH_LOG_ERROR(LOG_APP, "capture_ is null."); - } result = OH_AVScreenCapture_StopScreenRecording(g_avCapture); if (result != AV_SCREEN_CAPTURE_ERR_BASE) { - OH_LOG_ERROR(LOG_APP, "StopScreenCapture OH_AVScreenCapture_StopScreenCapture Result: %{public}d", result); + OH_LOG_ERROR(LOG_APP, "StopScreenCapture OH_AVScreenCapture_StopScreenRecording Result: %{public}d", + result); } - OH_LOG_INFO(LOG_APP, "StopScreenCapture OH_AVScreenCapture_StopScreenCapture"); result = OH_AVScreenCapture_Release(g_avCapture); if (result != AV_SCREEN_CAPTURE_ERR_BASE) { OH_LOG_ERROR(LOG_APP, "StopScreenCapture OH_AVScreenCapture_Release: %{public}d", result); @@ -448,31 +440,25 @@ static napi_value StopScreenCapture(napi_env env, napi_callback_info info) { OH_LOG_INFO(LOG_APP, "OH_AVScreenCapture_Release success"); m_scSaveFileIsRunning = false; } else { - if (g_avCapture == nullptr) { - OH_LOG_ERROR(LOG_APP, "capture_ is null."); - } result = OH_AVScreenCapture_StopScreenCapture(g_avCapture); if (result != AV_SCREEN_CAPTURE_ERR_BASE) { OH_LOG_ERROR(LOG_APP, "StopScreenCapture OH_AVScreenCapture_StopScreenCapture Result: %{public}d", result); } - OH_LOG_INFO(LOG_APP, "StopScreenCapture OH_AVScreenCapture_StopScreenCapture"); result = OH_AVScreenCapture_Release(g_avCapture); if (result != AV_SCREEN_CAPTURE_ERR_BASE) { OH_LOG_ERROR(LOG_APP, "StopScreenCapture OH_AVScreenCapture_Release: %{public}d", result); } OH_LOG_INFO(LOG_APP, "OH_AVScreenCapture_Release success"); CloseFile(); - OH_LOG_INFO(LOG_APP, "CloseFile success"); m_isRunning = false; } - napi_create_int32(env, result, &res); return res; } // 调用老接口,仅提供代码实现,不建议使用 -void MockOnAudioBufferAvailable(OH_AVScreenCapture *screenCapture, bool isReady, OH_AudioCaptureSourceType type) +void MockOnAudioBufferAvailable(OH_AVScreenCapture *screenCapture, bool isReady, OH_AudioCaptureSourceType type) { if (isReady == true) { OH_AudioBuffer *audioBuffer = (OH_AudioBuffer *)malloc(sizeof(OH_AudioBuffer)); @@ -540,9 +526,9 @@ void SetScreenCaptureCallback() } EXTERN_C_START -static napi_value Init(napi_env env, napi_value exports) { +static napi_value Init(napi_env env, napi_value exports) +{ napi_property_descriptor desc[] = { - {"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr}, {"startScreenCapture", nullptr, StartScreenCapture_01, nullptr, nullptr, nullptr, napi_default, nullptr}, {"stopScreenCapture", nullptr, StopScreenCapture, nullptr, nullptr, nullptr, napi_default, nullptr}, {"startCaptureAsFile", nullptr, StartScreenCapture_02, nullptr, nullptr, nullptr, napi_default, nullptr}, diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/sample_callback.cpp b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/sample_callback.cpp index b1383676595a839ab1f0cc3a9741e04807c1e956..28df10fbd9eec9092bdeeb72899defb825583140 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/sample_callback.cpp +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/sample_callback.cpp @@ -40,7 +40,7 @@ void SampleCallback::OnStreamChanged(OH_AVCodec *codec, OH_AVFormat *format, voi // 设置 OH_AVCodecOnNeedInputBuffer 回调函数,编码输入帧送入数据队列 void SampleCallback::OnNeedInputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData) { // surface模式下,该回调函数无作用,用户通过获取的surface输入数据 - OH_LOG_INFO(LOG_APP, "==DEMO== Video OnNeedInputBuffer"); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== Video OnNeedInputBuffer"); (void)userData; (void)index; (void)buffer; @@ -60,7 +60,7 @@ void SampleCallback::OnNewOutputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVB // 完成帧的数据buffer送入outBufferQueue队列 // 数据处理,请参考: // - 释放编码帧 - OH_LOG_INFO(LOG_APP, "==DEMO== Video OnNewOutputBuffer"); + OH_LOG_INFO(LOG_APP, "==ScreenCaptureSample== Video OnNewOutputBuffer"); if (userData == nullptr) { return; } diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/types/libentry/Index.d.ts b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/types/libentry/Index.d.ts index 8aadf80908aa25ce2e97e01548efe592451457de..d6f4abe9e642cb35006c2e81467cc29c7418a670 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/types/libentry/Index.d.ts +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/cpp/types/libentry/Index.d.ts @@ -13,7 +13,6 @@ * limitations under the License. */ -export const add: (a: number, b: number) => number; export const startScreenCapture: () => number; export const stopScreenCapture: () => number; export const startCaptureAsFile: () => number; diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Index.ets b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Index.ets index 9e32ea0a8ed31190566f148f39cac4931e943967..fbe0919d380f721d010ca9b262273b3f495760c8 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Index.ets +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Index.ets @@ -56,6 +56,13 @@ struct Index { this.pageInfos.pushPathByName('Scene1', ''); }) } + ListItem() { + Button($r('app.string.js_saving_file_desc')) + .width('80%') + .onClick(() => { + this.pageInfos.pushPathByName('Scene4', ''); + }) + } ListItem() { Text($r('app.string.streaming_desc')) .fontSize(20) @@ -75,7 +82,7 @@ struct Index { }) } } - .width("100%") + .width('100%') .margin({ top: 12 }) .alignListItem(ListItemAlign.Center) .divider(this.egDivider) diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Menu.ets b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Menu.ets index 615b016994f395f9805a9b3879aa0a098b6f868e..2151e9c0572131227218807d72408d6718c0a857 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Menu.ets +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Menu.ets @@ -24,7 +24,7 @@ export struct MenuSCComponent { MenuItemGroup({ header: $r('app.string.list_desc') }) { MenuItem({ content: $r('app.string.index_desc') }) .onChange((selected) => { - console.info("menuItem select" + selected); + console.info('menuItem select' + selected); router.pushUrl({ url: 'pages/Index' // 目标url }, router.RouterMode.Single, (err) => { @@ -74,23 +74,18 @@ export struct MenuSCComponent { console.info('Invoke pushUrl succeeded.'); }); }) - } - MenuItemGroup({ header: $r('app.string.other_mode_desc') }) { - MenuItem({ content: $r('app.string.all_mode_desc') }) + MenuItem({ content: $r('app.string.js_saving_file_desc')}) .onChange((selected) => { - router.pushUrl({ - url: 'pages/Scene4' // 目标url - }, router.RouterMode.Single, (err) => { - if (err) { - console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`); - return; - } - console.info('Invoke pushUrl succeeded.'); - }); - }) - MenuItem({ - content: $r('app.string.all_mode_desc'), + router.pushUrl({ + url: 'pages/Scene4' // 目标url + }, router.RouterMode.Single, (err) => { + if (err) { + console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`); + return; + } + console.info('Invoke pushUrl succeeded.'); + }); }) } } diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene1.ets b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene1.ets index abc85d576aec7905e36b8caff40f6c9c24435f6e..0d93162c36f3c5c6af2644764c6c650cdb66a61f 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene1.ets +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene1.ets @@ -29,9 +29,6 @@ export struct Scene1 { Text($r('app.string.saving_file_desc')) .fontSize(30) .fontWeight(FontWeight.Bold) - .onClick(() => { - hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3)); - }) } .width('100%') .height('20%') diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene2.ets b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene2.ets index 095b230a1f7fb1c58af5f38bbb610655a7f10978..16e5b0d412496ac84f5de61c566b2b52fb427594 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene2.ets +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene2.ets @@ -30,9 +30,6 @@ export struct Scene2 { Text($r('app.string.streaming_desc')) .fontSize(30) .fontWeight(FontWeight.Bold) - .onClick(() => { - hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3)); - }) } .width('100%') .height('20%') diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene3.ets b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene3.ets index 8912dba01f4a690f650878ecc4cfc07704d0e8f5..9bc43d97fb18957357050872353fb9b1725943e3 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene3.ets +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene3.ets @@ -19,7 +19,6 @@ import testNapi from 'libentry.so'; @Entry({ routeName : 'Scene3' }) @Component export struct Scene3 { - @State message: string = '录屏取码流Surface模式'; @State isCapturing: boolean = false; @Consume('pageInfos') pageInfos: NavPathStack; @@ -28,12 +27,9 @@ export struct Scene3 { Column({ space: 15 }) { Column() { - Text(this.message) + Text($r('app.string.streaming_surface_mode_desc')) .fontSize(30) .fontWeight(FontWeight.Bold) - .onClick(() => { - hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3)); - }) } .width('100%') .height('20%') @@ -75,6 +71,6 @@ export struct Scene3 { } .width('100%') } - .title($r('app.string.other_mode_desc')) + .title($r('app.string.streaming_surface_mode_desc')) } } \ No newline at end of file diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene4.ets b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene4.ets index 86edb413cf5efd28c1a0f0f2a001aa6a806f2fee..be6c6ce618bb8fcc6bddf8454cdcf9324c361aff 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene4.ets +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/ets/pages/Scene4.ets @@ -13,150 +13,230 @@ * limitations under the License. */ -import { hilog } from '@kit.PerformanceAnalysisKit'; -import testNapi from 'libentry.so'; -import {MenuSCComponent} from './Menu'; +import { BusinessError } from '@ohos.base'; +import { media } from '@kit.MediaKit'; +import fs from '@ohos.file.fs'; +import { deviceInfo } from '@kit.BasicServicesKit'; +import { display } from '@kit.ArkUI'; -@Entry({ routeName : 'Scene4' }) @Component export struct Scene4 { - @State isCapturing: boolean = false; @Consume('pageInfos') pageInfos: NavPathStack; + private lastSaveTime: string = ''; + private saveIndex: number = 0; + private outputFd: number | null = null; + private avScreenCaptureRecorder?: media.AVScreenCaptureRecorder; + private displayId:number = 0; + private isStarted: boolean = false; + private filepathSC: string = ''; + @State text: string = 'PRESERVE_ASPECT_RATIO' + private displayWidth: number = 0; + private displayHeight: number = 0; - build() { - NavDestination() { + private initDeviceResolution(): void { + try { + let currentDisplay: display.Display = + this.displayId? display.getDisplayByIdSync(this.displayId as number): display.getDefaultDisplaySync(); + this.displayWidth = currentDisplay.width; + this.displayHeight = currentDisplay.height; + console.info('ScreenCaptureSample displayWidth: ' + this.displayWidth + ', displayHeight: ' + this.displayHeight); + } catch (err) { + console.error('ScreenCaptureSample initDeviceResolution failed, code is ${err.code}, message is ${err.message}'); + } + } + checkName(name: string): string { + if (this.lastSaveTime == name) { + this.saveIndex += 1; + return `${name}_${this.saveIndex}` + } + this.lastSaveTime = name; + this.saveIndex = 0; + return name; + } - Column({ space: 15 }) { - Column() { - MenuSCComponent() - Text($r('app.string.all_mode_desc')) - .fontSize(25) - .fontWeight(FontWeight.Bold) - } - .width('100%') - .height('10%').border({ width: 1 }) + StopRecording() { + if (!this.avScreenCaptureRecorder) { + return; + } + this.avScreenCaptureRecorder?.stopRecording(); + if (this.outputFd != undefined && this.outputFd?.valueOf() > 0) { + fs.close(this.outputFd); + } + this.avScreenCaptureRecorder?.release(); + this.isStarted = false; + this.outputFd = -1; + } - Column() { - Text($r('app.string.saving_file_eng_desc')) - .fontSize(20) - .fontWeight(FontWeight.Bold) - .onClick(() => { - hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3)); - }) - List({ space: 40 }) { - ListItem() { - Button($r('app.string.start_desc'), { type: ButtonType.Circle, stateEffect: true }) - .backgroundColor(0xF55A42) - .width(90) - .height(90) - .onClick(() => { - if (testNapi.startCaptureAsFile() == 0) { - this.isCapturing = true; - } - }) - } + async createVideoFd(): Promise { + console.info('==ScreenCaptureSample== the value of the deviceType in'); + let deviceTypeInfo: string = deviceInfo.deviceType; + console.info('==ScreenCaptureSample== the value of the deviceType is :' + deviceTypeInfo); - ListItem() { - } + const displayName = 'js_saving_file.mp4'; + let videoFd: number = 0; + console.info('==ScreenCaptureSample== the value of the deviceType in'); + this.filepathSC = '/data/storage/el2/base/files/' + displayName; + await fs.open(this.filepathSC, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE).then((file) => { + videoFd = file.fd; + console.info('==ScreenCaptureSample== the value of the deviceType in'); + }).catch((err: BusinessError) => { + fs.unlinkSync(this.filepathSC); + console.error('open file failed, code is ${err.code}, message is ${err.message}'); + }) + console.info('==ScreenCaptureSample== the value of the deviceType in'); + console.info('==ScreenCaptureSample== createVideoFd videoFd: ' + videoFd); + return videoFd; + } - ListItem() { - Button($r('app.string.stop_desc'), { type: ButtonType.Normal, stateEffect: true }) - .backgroundColor(0x000000) - .width(85) - .height(85) - .shadow({ radius: 10 }) - .onClick(() => { - if (this.isCapturing) { - testNapi.stopScreenCapture(); - this.isCapturing = false; - } - }) - } - }.listDirection(Axis.Horizontal).lanes({ minLength: 200, maxLength: 300 }) - } - .width('100%') - .height('20%').border({ width: 1 }) + async StartRecording(): Promise { + if (this.isStarted === true) { + console.info('==ScreenCaptureSample== isStarted: ' + this.outputFd); + return; + } + this.outputFd = await this.createVideoFd() + console.info('==ScreenCaptureSample== outputFd: ' + this.outputFd); + if (this.outputFd != 0) { + console.info('selectOutputFilePath outputFd: ' + this.outputFd ); + this.initDeviceResolution(); + let avCaptureConfig: media.AVScreenCaptureRecordConfig = { + fd: this.outputFd, + frameWidth: this.displayWidth, + frameHeight: this.displayHeight, + videoBitrate: 10000000, + audioSampleRate: 48000, + audioChannelCount: 2, + audioBitrate: 96001, + displayId: this.displayId, + preset: media.AVScreenCaptureRecordPreset.SCREEN_RECORD_PRESET_H264_AAC_MP4, + }; + this.avScreenCaptureRecorder = await media.createAVScreenCaptureRecorder(); + await this.avScreenCaptureRecorder.init(avCaptureConfig).then(() => { + console.info('==ScreenCaptureSample== Succeeded in init avScreenCaptureRecorder'); + }).catch((err: BusinessError) => { + fs.unlinkSync(this.filepathSC); + console.error('==ScreenCaptureSample== Failed to init avScreenCaptureRecorder, code is ${err.code},' + + 'message is ${err.message}'); + }) - Column() { - Text($r('app.string.streaming_eng_desc')) - .fontSize(20) - .fontWeight(FontWeight.Bold) - .onClick(() => { - hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3)); - }) - List({ space: 40 }) { - ListItem() { - Button($r('app.string.start_desc'), { type: ButtonType.Circle, stateEffect: true }) - .backgroundColor(0xF55A42) - .width(90) - .height(90) - .onClick(() => { - if (testNapi.startScreenCapture() == 0) { - this.isCapturing = true; - } - }) - } - ListItem() { - } - ListItem() { - Button($r('app.string.stop_desc'), { type: ButtonType.Normal, stateEffect: true }) - .backgroundColor(0x000000) - .width(85) - .height(85) - .shadow({ radius: 10 }) - .onClick(() => { - if (this.isCapturing) { - testNapi.stopScreenCapture(); - this.isCapturing = false; - } - }) - } - }.listDirection(Axis.Horizontal).lanes({ minLength: 200, maxLength: 300 }) - } - .width('100%') - .height('20%').border({ width: 1 }) + this.avScreenCaptureRecorder.setMicEnabled(true).then(() => { + console.info('==ScreenCaptureSample== Succeeded in setMicEnabled avScreenCaptureRecorder'); + }).catch((err: BusinessError) => { + console.error('==ScreenCaptureSample== Failed to setMicEnabled avScreenCaptureRecorder, code is ${err.code},' + + 'message is ${err.message}'); + }) + + this.avScreenCaptureRecorder.on('error', (err: BusinessError) => { + console.error('==ScreenCaptureSample== avScreenCaptureRecorder stateChange to:' + err.message); + fs.unlinkSync(this.filepathSC); + }) - Column() { - Text($r('app.string.streaming_surface_mode_eng_desc')) - .fontSize(20) - .fontWeight(FontWeight.Bold) - .onClick(() => { - hilog.info(0x0000, 'testTag', 'Test NAPI 2 + 3 = %{public}d', testNapi.add(2, 3)); - }) - List({ space: 40 }) { - ListItem() { - Button($r('app.string.start_desc'), { type: ButtonType.Circle, stateEffect: true }) - .backgroundColor(0xF55A42) - .width(90) - .height(90) - .onClick(() => { - if (testNapi.startScreenCaptureWithSurface() == 0) { - this.isCapturing = true; - } - }) - } - ListItem() { - } - ListItem() { - Button($r('app.string.stop_desc'), { type: ButtonType.Normal, stateEffect: true }) - .backgroundColor(0x000000) - .width(85) - .height(85) - .shadow({ radius: 10 }) - .onClick(() => { - if (this.isCapturing) { - testNapi.stopScreenCapture(); - this.isCapturing = false; - } - }) - } - }.listDirection(Axis.Horizontal).lanes({ minLength: 200, maxLength: 300 }) + this.avScreenCaptureRecorder!.on('stateChange', async (state: media.AVScreenCaptureStateCode) => { + console.info('==ScreenCaptureSample== 2 avScreenCaptureRecorder stateChange to ' + state); + switch (state) { + case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_STARTED: + console.info('==ScreenCaptureSample== screen capture started'); + break; + case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_CANCELED: + this.avScreenCaptureRecorder?.release(); + this.avScreenCaptureRecorder = undefined; + console.info('==ScreenCaptureSample== delete filepathSC uri: ' + this.filepathSC); + fs.unlinkSync(this.filepathSC); + console.info('==ScreenCaptureSample== screen capture canceled'); + break; + case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_STOPPED_BY_USER: + this.avScreenCaptureRecorder?.stopRecording(); + this.avScreenCaptureRecorder?.release(); + this.avScreenCaptureRecorder = undefined; + console.info('==ScreenCaptureSample== screen capture stopped by user'); + break; + case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_INTERRUPTED_BY_OTHER: + console.info('==ScreenCaptureSample== screen capture stopped by other'); + break; + case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_STOPPED_BY_CALL: + console.info('==ScreenCaptureSample== screen capture stopped by call'); + break; + case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_MIC_UNAVAILABLE: + console.info('==ScreenCaptureSample== screen capture mic unavailable'); + break; + case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_MIC_MUTED_BY_USER: + console.info('==ScreenCaptureSample== screen capture mic muted by user'); + break; + case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_MIC_UNMUTED_BY_USER: + console.info('==ScreenCaptureSample== screen capture mic unmuted by user'); + break; + case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_ENTER_PRIVATE_SCENE: + console.info('==ScreenCaptureSample== screen capture enter private scene'); + break; + case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_EXIT_PRIVATE_SCENE: + console.info('==ScreenCaptureSample== screen capture exit private scene'); + break; + case media.AVScreenCaptureStateCode.SCREENCAPTURE_STATE_STOPPED_BY_USER_SWITCHES: + console.info('==ScreenCaptureSample== screen capture stopped by user switches'); + break; + default: + break; + } + }) + await this.avScreenCaptureRecorder?.startRecording().then(() => { + console.info('==ScreenCaptureSample== Succeeded in starting avScreenCaptureRecorder'); + this.isStarted = true; + }).catch((err: BusinessError) => { + console.error('==ScreenCaptureSample== Failed to start avScreenCaptureRecorder, code is ${err.code}, message is ${err.message}'); + }) + + } + } + + build() { + NavDestination() { + Column({ space: 15 }) { + Column() { + Text($r('app.string.js_saving_file_desc')) + .fontSize(30) + .fontWeight(FontWeight.Bold) + } + .width('100%') + .height('20%') + + Column() { + List({ space: 40 }) { + ListItem() { + Button($r('app.string.start_desc'), { type: ButtonType.Circle, stateEffect: true }) + .id(getContext().resourceManager.getStringSync($r('app.string.start_desc'))) + .backgroundColor(0xF55A42) + .width(90) + .height(90) + .onClick(() => { + this.StopRecording(); + this.StartRecording() + }) + } + ListItem() { + Button($r('app.string.stop_desc'), { type: ButtonType.Normal, stateEffect: true }) + .id(getContext().resourceManager.getStringSync($r('app.string.stop_desc'))) + .backgroundColor(0x000000) + .width(85) + .height(85) + .shadow({ radius: 10 }) + .onClick(() => { + this.StopRecording(); + }) + } + }.listDirection(Axis.Horizontal).lanes({ minLength: 200, maxLength: 300 }) + } + .width('100%') + .height('20%') + + Text($r('app.string.display_id_desc')) + TextInput({ + text:'0' + }).onChange((value)=>{ + console.info('==ScreenCaptureSample== displayId:' + value); + this.displayId = parseInt(value); + }) } .width('100%') - .height('20%').border({ width: 1 }) - } - .height('100%') } - .title($r('app.string.all_mode_desc')) + .title($r('app.string.js_saving_file_desc')) } } \ No newline at end of file diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/resources/base/element/string.json b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/resources/base/element/string.json index 0423a79e1a85f6e1a2827e5b5dab97e8433afb69..330b8321a773cc6dffa6c6959772b1021eaa135d 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/resources/base/element/string.json +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/main/resources/base/element/string.json @@ -67,6 +67,18 @@ { "name": "all_mode_desc", "value": "全量" + }, + { + "name": "js_saving_file_desc", + "value": "js-录屏存文件" + }, + { + "name": "display_id_desc", + "value": "Display Id" + }, + { + "name": "allow_desc", + "value": "允许" } ] } \ No newline at end of file diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/ohosTest/ets/test/Ability.test.ets b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/ohosTest/ets/test/Ability.test.ets index 0f8ce9a2c012f8fe36114cef65216ef0b6254f41..6756d456e14a632688d863ab85339126bad92bcd 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/ohosTest/ets/test/Ability.test.ets +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/entry/src/ohosTest/ets/test/Ability.test.ets @@ -13,8 +13,15 @@ * limitations under the License. */ -import { hilog } from '@kit.PerformanceAnalysisKit'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import Base from '@ohos.base'; +import { Driver, ON } from '@ohos.UiTest'; +import fs from '@ohos.file.fs'; + +const TAG = 'abilityTest'; +const domain: number = 0x0000; export default function abilityTest() { describe('ActsAbilityTest', () => { @@ -37,14 +44,35 @@ export default function abilityTest() { // Presets a clear action, which is performed after all test cases of the test suite end. // This API supports only one parameter: clear action function. }) - it('assertContain', 0, () => { + it('assertContain', 0, async () => { // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. - hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); - let a = 'abc'; - let b = 'b'; - // Defines a variety of assertion methods, which are used to declare expected boolean conditions. - expect(a).assertContain(b); - expect(a).assertEqual(a); + let want: Want = { + bundleName: 'com.sample.screencapturesample', + abilityName: 'EntryAbility' + }; + let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + abilityDelegator.startAbility(want, (err: Base.BusinessError) => { + hilog.info(domain, TAG, 'StartAbility get err ' + JSON.stringify(err)); + expect(err).assertNull(); + }) + let driver = await Driver.create(); + await driver.delayMs(2000); + let allowBtn1 = await driver.findComponent(ON.text(getContext().resourceManager.getStringSync($r('app.string.allow_desc')))); + await allowBtn1.click(); + let allowBtn2 = await driver.findComponent(ON.text(getContext().resourceManager.getStringSync($r('app.string.allow_desc')))); + await allowBtn2.click(); + let btn3 = await driver.findComponent(ON.text(getContext().resourceManager.getStringSync($r('app.string.js_saving_file_desc')))); + await btn3.click(); + let btn4 = await driver.findComponent(ON.text(getContext().resourceManager.getStringSync($r('app.string.start_desc')))); + await btn4.click(); + await driver.delayMs(2000); + let allowBtn3 = await driver.findComponent(ON.text(getContext().resourceManager.getStringSync($r('app.string.allow_desc')))); + await allowBtn3.click(); + await driver.delayMs(5000); + let btn5 = await driver.findComponent(ON.text(getContext().resourceManager.getStringSync($r('app.string.stop_desc')))); + await btn5.click(); + let files: string[] = fs.listFileSync('/data/storage/el2/base/files/'); + expect(files).assertContain('js_saving_file.mp4'); }) }) } \ No newline at end of file diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/log.txt b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/log.txt deleted file mode 100644 index 17cc32bea3df5e26a9a01a62cbdb5efc7e74cc25..0000000000000000000000000000000000000000 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/log.txt +++ /dev/null @@ -1,520 +0,0 @@ -18:20:09:121 log task queue not empty -18:20:09:121 log task size: 1 -18:20:09:121 log before pop task size: 1 -18:20:09:121 log after task size: 0 -18:20:09:631 log timer task size: 1 -18:20:10:396 log task queue not empty -18:20:10:396 log task size: 1 -18:20:10:396 log before pop task size: 1 -18:20:10:396 log after task size: 0 -18:20:10:904 log timer task size: 1 -19:13:41:986 log task queue not empty -19:13:41:986 log task size: 1 -19:13:41:986 log before pop task size: 1 -19:13:41:987 log after task size: 0 -19:13:42:494 log timer task size: 1 -19:13:42:962 log task queue not empty -19:13:42:962 log task size: 1 -19:13:42:962 log before pop task size: 1 -19:13:42:962 log after task size: 0 -19:13:43:334 log task queue not empty -19:13:43:336 log task size: 1 -19:13:43:337 log before pop task size: 1 -19:13:43:337 log after task size: 0 -19:13:43:465 log timer task size: 1 -19:13:43:733 log task queue not empty -19:13:43:734 log task size: 1 -19:13:43:734 log before pop task size: 1 -19:13:43:734 log after task size: 0 -19:13:43:852 log timer task size: 1 -19:13:44:077 log task queue not empty -19:13:44:077 log task size: 1 -19:13:44:077 log before pop task size: 1 -19:13:44:077 log after task size: 0 -19:13:44:208 log task queue not empty -19:13:44:209 log task size: 1 -19:13:44:209 log before pop task size: 1 -19:13:44:209 log after task size: 0 -19:13:44:236 log timer task size: 1 -19:13:44:592 log timer task size: 1 -19:13:44:716 log timer task size: 1 -19:13:47:615 log task queue not empty -19:13:47:615 log task size: 1 -19:13:47:615 log before pop task size: 1 -19:13:47:615 log after task size: 0 -19:13:47:897 log task queue not empty -19:13:47:897 log task size: 1 -19:13:47:898 log before pop task size: 1 -19:13:47:898 log after task size: 0 -19:13:47:965 log task queue not empty -19:13:47:966 log task size: 1 -19:13:47:966 log before pop task size: 1 -19:13:47:966 log after task size: 0 -19:13:48:120 log timer task size: 1 -19:13:48:413 log timer task size: 1 -19:13:48:474 log timer task size: 1 -19:13:48:691 log task queue not empty -19:13:48:691 log task size: 1 -19:13:48:691 log before pop task size: 1 -19:13:48:691 log after task size: 0 -19:13:49:013 log task queue not empty -19:13:49:013 log task size: 1 -19:13:49:013 log before pop task size: 1 -19:13:49:014 log after task size: 0 -19:13:49:077 log task queue not empty -19:13:49:077 log task size: 1 -19:13:49:077 log before pop task size: 1 -19:13:49:077 log after task size: 0 -19:13:49:201 log timer task size: 1 -19:13:49:524 log timer task size: 1 -19:13:49:587 log timer task size: 1 -19:13:51:414 log task queue not empty -19:13:51:414 log task size: 1 -19:13:51:414 log before pop task size: 1 -19:13:51:415 log after task size: 0 -19:13:51:904 log task queue not empty -19:13:51:904 log task size: 1 -19:13:51:904 log before pop task size: 1 -19:13:51:904 log after task size: 0 -19:13:51:918 log timer task size: 1 -19:13:52:203 log task queue not empty -19:13:52:203 log task size: 1 -19:13:52:203 log before pop task size: 1 -19:13:52:203 log after task size: 0 -19:13:52:268 log task queue not empty -19:13:52:268 log task size: 1 -19:13:52:268 log before pop task size: 1 -19:13:52:268 log after task size: 0 -19:13:52:413 log timer task size: 1 -19:13:52:706 log timer task size: 1 -19:13:52:783 log timer task size: 1 -19:13:52:836 log task queue not empty -19:13:52:837 log task size: 1 -19:13:52:837 log before pop task size: 1 -19:13:52:837 log after task size: 0 -19:13:52:886 log task queue not empty -19:13:52:886 log task size: 1 -19:13:52:886 log before pop task size: 1 -19:13:52:886 log after task size: 0 -19:13:53:338 log timer task size: 1 -19:13:53:400 log timer task size: 1 -19:13:55:319 log task queue not empty -19:13:55:319 log task size: 1 -19:13:55:319 log before pop task size: 1 -19:13:55:319 log after task size: 0 -19:13:55:729 log task queue not empty -19:13:55:730 log task size: 1 -19:13:55:730 log before pop task size: 1 -19:13:55:730 log after task size: 0 -19:13:55:821 log timer task size: 1 -19:13:55:975 log task queue not empty -19:13:55:975 log task size: 1 -19:13:55:976 log before pop task size: 1 -19:13:55:976 log after task size: 0 -19:13:56:238 log timer task size: 1 -19:13:56:485 log timer task size: 1 -19:13:56:775 log task queue not empty -19:13:56:776 log task size: 1 -19:13:56:776 log before pop task size: 1 -19:13:56:776 log after task size: 0 -19:13:56:841 log task queue not empty -19:13:56:841 log task size: 1 -19:13:56:841 log before pop task size: 1 -19:13:56:841 log after task size: 0 -19:13:57:287 log timer task size: 1 -19:13:57:349 log timer task size: 1 -19:14:14:524 log task queue not empty -19:14:14:524 log task size: 1 -19:14:14:524 log before pop task size: 1 -19:14:14:524 log after task size: 0 -19:14:15:039 log timer task size: 1 -19:14:16:166 log task queue not empty -19:14:16:166 log task size: 1 -19:14:16:166 log before pop task size: 1 -19:14:16:166 log after task size: 0 -19:14:16:673 log timer task size: 1 -19:14:36:030 log task queue not empty -19:14:36:030 log task size: 1 -19:14:36:030 log before pop task size: 1 -19:14:36:030 log after task size: 0 -19:14:36:514 log task queue not empty -19:14:36:514 log task size: 1 -19:14:36:514 log before pop task size: 1 -19:14:36:514 log after task size: 0 -19:14:36:534 log timer task size: 1 -19:14:37:022 log timer task size: 1 -19:15:12:978 log task queue not empty -19:15:12:978 log task size: 1 -19:15:12:978 log before pop task size: 1 -19:15:12:978 log after task size: 0 -19:15:13:483 log timer task size: 1 -19:15:18:387 log task queue not empty -19:15:18:387 log task size: 1 -19:15:18:387 log before pop task size: 1 -19:15:18:387 log after task size: 0 -19:15:18:388 log task queue not empty -19:15:18:388 log task size: 1 -19:15:18:388 log before pop task size: 1 -19:15:18:388 log after task size: 0 -19:15:18:487 log task queue not empty -19:15:18:487 log task size: 1 -19:15:18:487 log before pop task size: 1 -19:15:18:487 log after task size: 0 -19:15:18:868 log task queue not empty -19:15:18:868 log task size: 1 -19:15:18:868 log before pop task size: 1 -19:15:18:868 log after task size: 0 -19:15:18:903 log timer task size: 1 -19:15:18:996 log timer task size: 1 -19:15:19:013 log task queue not empty -19:15:19:013 log task size: 1 -19:15:19:013 log before pop task size: 1 -19:15:19:013 log after task size: 0 -19:15:19:371 log timer task size: 1 -19:15:19:428 log task queue not empty -19:15:19:429 log task size: 1 -19:15:19:429 log before pop task size: 1 -19:15:19:429 log after task size: 0 -19:15:19:496 log task queue not empty -19:15:19:496 log task size: 1 -19:15:19:496 log before pop task size: 1 -19:15:19:496 log after task size: 0 -19:15:19:524 log timer task size: 1 -19:15:19:931 log timer task size: 1 -19:15:20:011 log timer task size: 1 -19:15:20:324 log task queue not empty -19:15:20:324 log task size: 1 -19:15:20:324 log before pop task size: 1 -19:15:20:324 log after task size: 0 -19:15:20:834 log timer task size: 1 -19:15:21:268 log task queue not empty -19:15:21:269 log task size: 1 -19:15:21:269 log before pop task size: 1 -19:15:21:269 log after task size: 0 -19:15:21:697 log task queue not empty -19:15:21:697 log task size: 1 -19:15:21:697 log before pop task size: 1 -19:15:21:697 log after task size: 0 -19:15:21:780 log timer task size: 1 -19:15:22:205 log timer task size: 1 -19:15:22:261 log task queue not empty -19:15:22:261 log task size: 1 -19:15:22:261 log before pop task size: 1 -19:15:22:261 log after task size: 0 -19:15:22:621 log task queue not empty -19:15:22:621 log task size: 1 -19:15:22:621 log before pop task size: 1 -19:15:22:621 log after task size: 0 -19:15:22:766 log timer task size: 1 -19:15:22:975 log task queue not empty -19:15:22:975 log task size: 1 -19:15:22:975 log before pop task size: 1 -19:15:22:975 log after task size: 0 -19:15:23:127 log timer task size: 1 -19:15:23:315 log task queue not empty -19:15:23:315 log task size: 1 -19:15:23:315 log before pop task size: 1 -19:15:23:315 log after task size: 0 -19:15:23:381 log task queue not empty -19:15:23:381 log task size: 1 -19:15:23:381 log before pop task size: 1 -19:15:23:381 log after task size: 0 -19:15:23:488 log timer task size: 1 -19:15:23:817 log timer task size: 1 -19:15:23:894 log timer task size: 1 -19:15:33:945 log task queue not empty -19:15:33:945 log task size: 1 -19:15:33:946 log before pop task size: 1 -19:15:33:946 log after task size: 0 -19:15:34:056 log task queue not empty -19:15:34:056 log task size: 1 -19:15:34:056 log before pop task size: 1 -19:15:34:056 log after task size: 0 -19:15:34:457 log timer task size: 1 -19:15:34:569 log timer task size: 1 -19:15:36:076 log task queue not empty -19:15:36:076 log task size: 1 -19:15:36:076 log before pop task size: 1 -19:15:36:076 log after task size: 0 -19:15:36:586 log timer task size: 1 -19:15:36:636 log task queue not empty -19:15:36:636 log task size: 1 -19:15:36:636 log before pop task size: 1 -19:15:36:636 log after task size: 0 -19:15:37:146 log timer task size: 1 -19:15:38:352 log task queue not empty -19:15:38:352 log task size: 1 -19:15:38:352 log before pop task size: 1 -19:15:38:352 log after task size: 0 -19:15:38:497 log task queue not empty -19:15:38:498 log task size: 1 -19:15:38:498 log before pop task size: 1 -19:15:38:498 log after task size: 0 -19:15:38:858 log timer task size: 1 -19:15:39:014 log timer task size: 1 -19:15:39:541 log task queue not empty -19:15:39:541 log task size: 1 -19:15:39:542 log before pop task size: 1 -19:15:39:542 log after task size: 0 -19:15:39:740 log task queue not empty -19:15:39:740 log task size: 1 -19:15:39:740 log before pop task size: 1 -19:15:39:740 log after task size: 0 -19:15:39:837 log task queue not empty -19:15:39:837 log task size: 1 -19:15:39:837 log before pop task size: 1 -19:15:39:837 log after task size: 0 -19:15:40:009 log task queue not empty -19:15:40:009 log task size: 1 -19:15:40:009 log before pop task size: 1 -19:15:40:009 log after task size: 0 -19:15:40:044 log timer task size: 1 -19:15:40:137 log task queue not empty -19:15:40:137 log task size: 1 -19:15:40:137 log before pop task size: 1 -19:15:40:137 log after task size: 0 -19:15:40:246 log timer task size: 1 -19:15:40:353 log timer task size: 1 -19:15:40:463 log task queue not empty -19:15:40:463 log task size: 1 -19:15:40:463 log before pop task size: 1 -19:15:40:463 log after task size: 0 -19:15:40:522 log timer task size: 1 -19:15:40:645 log timer task size: 1 -19:15:40:973 log timer task size: 1 -19:15:41:472 log task queue not empty -19:15:41:474 log task size: 1 -19:15:41:474 log before pop task size: 1 -19:15:41:474 log after task size: 0 -19:15:41:986 log timer task size: 1 -19:17:34:364 log task queue not empty -19:17:34:364 log task size: 1 -19:17:34:364 log before pop task size: 1 -19:17:34:364 log after task size: 0 -19:17:34:874 log timer task size: 1 -19:17:35:177 log task queue not empty -19:17:35:178 log task size: 1 -19:17:35:178 log before pop task size: 1 -19:17:35:178 log after task size: 0 -19:17:35:178 log task queue not empty -19:17:35:178 log task size: 1 -19:17:35:178 log before pop task size: 1 -19:17:35:178 log after task size: 0 -19:17:35:179 log task queue not empty -19:17:35:179 log task size: 1 -19:17:35:179 log before pop task size: 1 -19:17:35:179 log after task size: 0 -19:17:35:180 log task queue not empty -19:17:35:180 log task size: 1 -19:17:35:180 log before pop task size: 1 -19:17:35:180 log after task size: 0 -19:17:35:180 log task queue not empty -19:17:35:180 log task size: 1 -19:17:35:180 log before pop task size: 1 -19:17:35:180 log after task size: 0 -19:17:35:181 log task queue not empty -19:17:35:181 log task size: 1 -19:17:35:181 log before pop task size: 1 -19:17:35:181 log after task size: 0 -19:17:35:682 log timer task size: 1 -19:17:35:682 log timer task size: 1 -19:17:35:682 log timer task size: 1 -19:17:36:217 log task queue not empty -19:17:36:217 log task size: 1 -19:17:36:218 log before pop task size: 1 -19:17:36:218 log after task size: 0 -19:17:36:726 log timer task size: 1 -19:17:38:953 log task queue not empty -19:17:38:953 log task size: 1 -19:17:38:953 log before pop task size: 1 -19:17:38:953 log after task size: 0 -19:17:39:465 log timer task size: 1 -19:17:39:529 log task queue not empty -19:17:39:529 log task size: 1 -19:17:39:530 log before pop task size: 1 -19:17:39:530 log after task size: 0 -19:17:39:530 log task queue not empty -19:17:39:530 log task size: 1 -19:17:39:530 log before pop task size: 1 -19:17:39:530 log after task size: 0 -19:17:39:531 log task queue not empty -19:17:39:531 log task size: 1 -19:17:39:531 log before pop task size: 1 -19:17:39:531 log after task size: 0 -19:17:39:531 log task queue not empty -19:17:39:532 log task size: 1 -19:17:39:532 log before pop task size: 1 -19:17:39:532 log after task size: 0 -19:17:39:532 log task queue not empty -19:17:39:532 log task size: 1 -19:17:39:532 log before pop task size: 1 -19:17:39:532 log after task size: 0 -19:17:39:533 log task queue not empty -19:17:39:533 log task size: 1 -19:17:39:533 log before pop task size: 1 -19:17:39:533 log after task size: 0 -19:17:39:533 log task queue not empty -19:17:39:533 log task size: 1 -19:17:39:533 log before pop task size: 1 -19:17:39:534 log after task size: 0 -19:17:39:534 log task queue not empty -19:17:39:534 log task size: 1 -19:17:39:534 log before pop task size: 1 -19:17:39:534 log after task size: 0 -19:17:39:535 log task queue not empty -19:17:39:535 log task size: 1 -19:17:39:535 log before pop task size: 1 -19:17:39:535 log after task size: 0 -19:17:39:535 log task queue not empty -19:17:39:535 log task size: 1 -19:17:39:535 log before pop task size: 1 -19:17:39:535 log after task size: 0 -19:17:39:536 log task queue not empty -19:17:39:536 log task size: 1 -19:17:39:536 log before pop task size: 1 -19:17:39:536 log after task size: 0 -19:17:39:536 log task queue not empty -19:17:39:537 log task size: 1 -19:17:39:537 log before pop task size: 1 -19:17:39:537 log after task size: 0 -19:17:39:537 log task queue not empty -19:17:39:537 log task size: 1 -19:17:39:537 log before pop task size: 1 -19:17:39:537 log after task size: 0 -19:17:39:538 log task queue not empty -19:17:39:538 log task size: 1 -19:17:39:538 log before pop task size: 1 -19:17:39:538 log after task size: 0 -19:17:39:538 log task queue not empty -19:17:39:538 log task size: 1 -19:17:39:539 log before pop task size: 1 -19:17:39:539 log after task size: 0 -19:17:40:031 log timer task size: 1 -19:17:40:047 log timer task size: 1 -19:17:40:047 log timer task size: 1 -19:17:40:047 log timer task size: 1 -19:17:40:047 log timer task size: 1 -19:17:40:047 log timer task size: 1 -19:17:40:047 log timer task size: 1 -19:17:40:583 log task queue not empty -19:17:40:583 log task size: 1 -19:17:40:583 log before pop task size: 1 -19:17:40:583 log after task size: 0 -19:17:41:096 log timer task size: 1 -19:17:41:417 log task queue not empty -19:17:41:417 log task size: 1 -19:17:41:417 log before pop task size: 1 -19:17:41:417 log after task size: 0 -19:17:41:627 log task queue not empty -19:17:41:627 log task size: 1 -19:17:41:627 log before pop task size: 1 -19:17:41:627 log after task size: 0 -19:17:41:919 log timer task size: 1 -19:17:42:139 log timer task size: 1 -19:17:42:197 log task queue not empty -19:17:42:197 log task size: 1 -19:17:42:197 log before pop task size: 1 -19:17:42:197 log after task size: 0 -19:17:42:198 log task queue not empty -19:17:42:198 log task size: 1 -19:17:42:198 log before pop task size: 1 -19:17:42:198 log after task size: 0 -19:17:42:199 log task queue not empty -19:17:42:199 log task size: 1 -19:17:42:199 log before pop task size: 1 -19:17:42:199 log after task size: 0 -19:17:42:199 log task queue not empty -19:17:42:199 log task size: 1 -19:17:42:199 log before pop task size: 1 -19:17:42:199 log after task size: 0 -19:17:42:200 log task queue not empty -19:17:42:200 log task size: 1 -19:17:42:200 log before pop task size: 1 -19:17:42:200 log after task size: 0 -19:17:42:613 log task queue not empty -19:17:42:613 log task size: 1 -19:17:42:613 log before pop task size: 1 -19:17:42:613 log after task size: 0 -19:17:42:614 log task queue not empty -19:17:42:614 log task size: 1 -19:17:42:614 log before pop task size: 1 -19:17:42:614 log after task size: 0 -19:17:42:615 log task queue not empty -19:17:42:615 log task size: 1 -19:17:42:615 log before pop task size: 1 -19:17:42:615 log after task size: 0 -19:17:42:615 log task queue not empty -19:17:42:615 log task size: 1 -19:17:42:616 log before pop task size: 1 -19:17:42:616 log after task size: 0 -19:17:42:616 log task queue not empty -19:17:42:616 log task size: 1 -19:17:42:616 log before pop task size: 1 -19:17:42:616 log after task size: 0 -19:17:42:617 log task queue not empty -19:17:42:617 log task size: 1 -19:17:42:617 log before pop task size: 1 -19:17:42:617 log after task size: 0 -19:17:42:617 log task queue not empty -19:17:42:617 log task size: 1 -19:17:42:617 log before pop task size: 1 -19:17:42:617 log after task size: 0 -19:17:42:618 log task queue not empty -19:17:42:618 log task size: 1 -19:17:42:618 log before pop task size: 1 -19:17:42:618 log after task size: 0 -19:17:42:618 log task queue not empty -19:17:42:618 log task size: 1 -19:17:42:618 log before pop task size: 1 -19:17:42:618 log after task size: 0 -19:17:42:619 log task queue not empty -19:17:42:619 log task size: 1 -19:17:42:619 log before pop task size: 1 -19:17:42:619 log after task size: 0 -19:17:42:619 log task queue not empty -19:17:42:619 log task size: 1 -19:17:42:619 log before pop task size: 1 -19:17:42:619 log after task size: 0 -19:17:42:620 log task queue not empty -19:17:42:620 log task size: 1 -19:17:42:620 log before pop task size: 1 -19:17:42:620 log after task size: 0 -19:17:42:620 log task queue not empty -19:17:42:621 log task size: 1 -19:17:42:621 log before pop task size: 1 -19:17:42:621 log after task size: 0 -19:17:42:621 log task queue not empty -19:17:42:621 log task size: 1 -19:17:42:621 log before pop task size: 1 -19:17:42:621 log after task size: 0 -19:17:42:622 log task queue not empty -19:17:42:622 log task size: 1 -19:17:42:622 log before pop task size: 1 -19:17:42:622 log after task size: 0 -19:17:42:622 log task queue not empty -19:17:42:622 log task size: 1 -19:17:42:622 log before pop task size: 1 -19:17:42:622 log after task size: 0 -19:17:42:623 log task queue not empty -19:17:42:623 log task size: 1 -19:17:42:623 log before pop task size: 1 -19:17:42:623 log after task size: 0 -19:17:42:699 log timer task size: 1 -19:17:42:700 log timer task size: 1 -19:17:42:714 log timer task size: 1 -19:17:42:714 log timer task size: 1 -19:17:43:061 log task queue not empty -19:17:43:062 log task size: 1 -19:17:43:062 log before pop task size: 1 -19:17:43:062 log after task size: 0 -19:17:43:117 log timer task size: 1 -19:17:43:117 log timer task size: 1 -19:17:43:117 log timer task size: 1 -19:17:43:117 log timer task size: 1 -19:17:43:132 log timer task size: 1 -19:17:43:132 log timer task size: 1 -19:17:43:132 log timer task size: 1 -19:17:43:132 log timer task size: 1 -19:17:43:132 log timer task size: 1 -19:17:43:132 log timer task size: 1 -19:17:43:570 log timer task size: 1 diff --git a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/ohosTest.md b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/ohosTest.md index 102b4caae37c69dfc96fba377b1d14ebdd27d19b..cf80279843f81ae436eb2295e3b1475713081219 100644 --- a/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/ohosTest.md +++ b/code/DocsSample/Media/ScreenCapture/ScreenCaptureSample/ohosTest.md @@ -4,7 +4,8 @@ | 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | |----------------|-----------|---------------------------------------------------------|---------------------------|------|------| -| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass | -| 录屏存文件功能 | 进入示例应用 | 1. 点击录屏存文件按钮
2. 点击Start
3. 一段时间后点击Stop | 生成录屏文件 | 是 | Pass | -| 录屏取码流功能 | 进入示例应用 | 1. 点击录屏取码流按钮
2. 点击Start
3. 一段时间后点击Stop | 生成录屏码流文件、麦克风音频文件和设备内录音频文件 | 是 | Pass | -| 录屏取码流Surface模式 | 进入示例应用 | 1. 点击录屏取码流Surface模式按钮
2. 点击Start
3. 一段时间后点击Stop | 生成录屏文件 | 是 | Pass | +| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 否 | Pass | +| 录屏存文件功能 | 进入示例应用 | 1. 点击“录屏存文件”按钮
2. 点击Start
3. 一段时间后点击Stop | 生成录屏文件 | 否 | Pass | +| 录屏取码流功能 | 进入示例应用 | 1. 点击“录屏取码流”按钮
2. 点击Start
3. 一段时间后点击Stop | 生成录屏码流文件、麦克风音频文件和设备内录音频文件 | 否 | Pass | +| 录屏取码流Surface模式 | 进入示例应用 | 1. 点击“录屏取码流Surface模式”按钮
2. 点击Start
3. 一段时间后点击Stop | 生成录屏文件 | 否 | Pass | +| js接口录屏存文件功能 | 设备正常运行 | 运行ohosTest中的assertContain用例 | 用例执行通过,生成录屏文件 | 是 | Pass |