HarmonyOS 鸿蒙Next 使用AVScreenCapture录屏取码流(C/C++),在回调OnBufferAvailable()中获取不到码流数据
使用版本:HarmonyOS 5.0.1(13)
功能描述:需要做一个录屏的功能,获取录屏的H.264的码数数据
场景描述:参考了官方例子:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/using-avscreencapture-for-buffer-V13
问题:其中,OH_AVScreenCapture_SetDataCallback(capture, OnBufferAvailable, userData); 配置获取码流的回调方法“OnBufferAvailable”没有触发回调,调试状态下打断点也没有进去。
说明:
// 开始录屏
result = OH_AVScreenCapture_StartScreenCapture(capture); 返回的参数为0(这个状态是正常的)
OH_AVScreenCapture_SetStateCallback(capture, OnStateChange, nullptr);此方法也能拿到state为
OH_SCREEN_CAPTURE_STATE_STARTED。
请问,如何才能触发“OnBufferAvailable”方法
代码:
// // Created on 2024/12/19. // // Node APIs are not fully supported. To solve the compilation error of the interface cannot be found, // please include “napi/native_api.h”.
#include "screen_capture.h"
#include "napi/native_api.h"
#include <multimedia/player_framework/native_avscreen_capture.h>
#include <multimedia/player_framework/native_avscreen_capture_base.h>
#include <multimedia/player_framework/native_avscreen_capture_errors.h>
#include <multimedia/player_framework/native_avbuffer.h>
#include <native_buffer/native_buffer.h>
#include <fcntl.h>
#include "string"
#include "unistd.h"
screen_capture::~screen_capture() { }
void OnError(OH_AVScreenCapture *capture, int32_t errorCode, void *userData) {
(void)capture;
(void)errorCode;
(void)userData;
}
void OnStateChange(struct OH_AVScreenCapture *capture, OH_AVScreenCaptureStateCode stateCode, void *userData) {
(void)capture;
if (stateCode == OH_SCREEN_CAPTURE_STATE_STARTED) {
// 处理状态变更
}
if (stateCode == OH_SCREEN_CAPTURE_STATE_STOPPED_BY_CALL ||
stateCode == OH_SCREEN_CAPTURE_STATE_STOPPED_BY_USER_SWITCHES) {
// 录屏中断状态处理
}
if (stateCode == OH_SCREEN_CAPTURE_STATE_INTERRUPTED_BY_OTHER) {
// 处理状态变更
}
(void)userData;
}
void OnBufferAvailable(OH_AVScreenCapture *capture, OH_AVBuffer *buffer,
OH_AVScreenCaptureBufferType bufferType, int64_t timestamp, void *userData) {
// 获取解码后信息 可以参考编解码接口
int bufferLen = OH_AVBuffer_GetCapacity(buffer);
OH_NativeBuffer *nativeBuffer = OH_AVBuffer_GetNativeBuffer(buffer);
OH_NativeBuffer_Config config;
OH_NativeBuffer_GetConfig(nativeBuffer, &config);
int32_t videoSize= config.height * config.width * 4;
uint8_t *buf = OH_AVBuffer_GetAddr(buffer);
if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_VIDEO) {
// 处理视频buffer
} else if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_INNER) {
// 处理内录buffer
} else if (bufferType == OH_SCREEN_CAPTURE_BUFFERTYPE_AUDIO_MIC) {
// 处理麦克风buffer
}
}
struct OH_AVScreenCapture *capture;
void screen_capture:: Screencast() {
// // 从js端获取窗口id number[]
// std::vector<int> windowIdsExclude = {};
// size_t argc = 1;
// napi_value args[1] = {nullptr};
// // 获取参数
// napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
// // 获取数组长度
// uint32_t array_length;
// napi_get_array_length(env, args[0], &array_length);
// // 读初窗口id
// for (int32_t i = 0; i < array_length; i++) {
// napi_value temp;
// napi_get_element(env, args[0], i, &temp);
// uint32_t tempValue;
// napi_get_value_uint32(env, temp, &tempValue);
// windowIdsExclude.push_back(tempValue);
// }
// 实例化ScreenCapture
capture = OH_AVScreenCapture_Create();
// 设置回调
OH_AVScreenCapture_SetErrorCallback(capture, OnError, nullptr);
OH_AVScreenCapture_SetStateCallback(capture, OnStateChange, nullptr);
OH_AVScreenCapture_SetDataCallback(capture, OnBufferAvailable, nullptr);
// 可选 配置录屏旋转,此接口在感知到手机屏幕旋转时调用,如果手机的屏幕实际上没有发生旋转,调用接口是无效的。
OH_AVScreenCapture_SetCanvasRotation(capture, true);
// 可选 [过滤音频]
OH_AVScreenCapture_ContentFilter *contentFilter= OH_AVScreenCapture_CreateContentFilter();
// 添加过滤通知音
OH_AVScreenCapture_ContentFilter_AddAudioContent(contentFilter, OH_SCREEN_CAPTURE_NOTIFICATION_AUDIO);
// 排除指定窗口id
// OH_AVScreenCapture_ContentFilter_AddWindowContent(contentFilter, &windowIdsExclude[0],
// static_cast<int32_t>(windowIdsExclude.size()));
OH_AVScreenCapture_ExcludeContent(capture, contentFilter);
// 初始化录屏,传入配置信息OH_AVScreenRecorderConfig
OH_AudioCaptureInfo miccapinfo = {.audioSampleRate = 16000, .audioChannels = 2, .audioSource = OH_MIC};
OH_VideoCaptureInfo videocapinfo = {
.videoFrameWidth = 768, .videoFrameHeight = 1280, .videoSource = OH_VIDEO_SOURCE_SURFACE_RGBA};
OH_AudioInfo audioinfo = {
.micCapInfo = miccapinfo,
};
OH_VideoInfo videoinfo = {.videoCapInfo = videocapinfo};
OH_AVScreenCaptureConfig config = {.captureMode = OH_CAPTURE_HOME_SCREEN,
.dataType = OH_ORIGINAL_STREAM,
//.audioInfo = audioinfo,
.videoInfo = videoinfo};
int result = OH_AVScreenCapture_Init(capture, config);
if (result != AV_SCREEN_CAPTURE_ERR_OK) {
}
// 可选 [Surface模式]
// 通过 MIME TYPE 创建编码器,系统会根据MIME创建最合适的编码器。
// OH_AVCodec *codec = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
// 从视频编码器获取输入Surface
// OH_AVErrCode OH_VideoEncoder_GetSurface(codec, window);
// 启动编码器
// int32_t retEnc = OH_VideoEncoder_Start(codec);
// 指定surface开始录屏
// int32_t retStart = OH_AVScreenCapture_StartScreenCaptureWithSurface(capture, window);
// 开始录屏
result = OH_AVScreenCapture_StartScreenCapture(capture);
// mic开关设置
OH_AVScreenCapture_SetMicrophoneEnabled(capture, true);
// 可选 豁免隐私窗口 需传递应用豁免子窗口和主窗口ID,传空数组取消豁免隐私窗口
// std::vector<int> windowIdsSkipPrivacy = {};
// OH_AVScreenCapture_SkipPrivacyMode(capture, &windowIdsSkipPrivacy[0],
// static_cast<int32_t>(windowIdsSkipPrivacy.size()));
// 可选 调整录屏分辨率 需在启动后调用,分辨率有范围限制 可参考avcodec编解码能力
// OH_AVScreenCapture_ResizeCanvas(capture, 768, 1280);
sleep(10); // 录制10s
// 结束录屏
OH_AVScreenCapture_StopScreenCapture(capture);
// 释放ScreenCapture
OH_AVScreenCapture_Release(capture);
// 返回调用结果,示例仅返回随意值
// napi_value sum;
// napi_create_double(env, 5, &sum);
return void(0);
}
更多关于HarmonyOS 鸿蒙Next 使用AVScreenCapture录屏取码流(C/C++),在回调OnBufferAvailable()中获取不到码流数据的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS 鸿蒙Next 使用AVScreenCapture录屏取码流(C/C++),在回调OnBufferAvailable()中获取不到码流数据的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
OH_AVScreenCapture_SetDataCallback 返回的状态也是正常的
在HarmonyOS鸿蒙Next系统中使用AVScreenCapture进行录屏并尝试在OnBufferAvailable()
回调中获取码流数据时,若未能成功获取,可能的原因及潜在解决方案包括:
-
权限检查:确保应用已正确声明并获取了录屏所需的权限,如
ohos.permission.RECORD_AUDIO
和ohos.permission.CAPTURE_VIDEO_OUTPUT
。 -
回调注册:验证
OnBufferAvailable()
回调是否已正确注册到AVScreenCapture
实例,且回调方法签名与API要求一致。 -
Buffer状态:检查传入的
MediaCodec.BufferInfo
对象是否有效,确保offset
、size
等字段正确设置,且presentationTimeUs
反映了正确的时间戳。 -
线程安全:确保回调处理逻辑不会因线程安全问题导致数据访问失败,考虑使用同步机制保护数据访问。
-
设备兼容性:确认目标设备支持当前使用的录屏功能,并检查是否有特定的硬件或软件限制。
如果上述检查后问题依旧没法解决,请访问官网客服寻求进一步帮助。官网地址是:https://www.itying.com/category-93-b0.html。