[*] 屏幕采集
This commit is contained in:
@@ -13,15 +13,15 @@
|
||||
{
|
||||
"name": "default",
|
||||
"material": {
|
||||
"keyAlias" : "debugKey",
|
||||
"signAlg" : "SHA256withECDSA",
|
||||
"signAlg" : "SHA256withECDSA",
|
||||
"keyAlias": "debugKey",
|
||||
"keyPassword" : "0000001BEC83FE5E74E20C2BD84F2E7C3C00A1038029C6F2FE0121CA85487C1C334AFF202964F02D800AEC",
|
||||
"storePassword": "0000001B2C10F7CA3C261A3B5F8DE65A4E13A65E37B6C298C3FD3C9A3ACCD5E10DF1F475F5370DF7996519",
|
||||
"profile" : "C:/Users/acgis/.ohos/config/openharmony/default_taoyao_RrmPaKOZ5zMCU4QlpK1kz_6UoyvfsA4RcQxqexSUJ_8=.p7b",
|
||||
"certpath" : "C:/Users/acgis/.ohos/config/openharmony/default_taoyao_RrmPaKOZ5zMCU4QlpK1kz_6UoyvfsA4RcQxqexSUJ_8=.cer",
|
||||
"storeFile": "C:/Users/acgis/.ohos/config/openharmony/default_taoyao_RrmPaKOZ5zMCU4QlpK1kz_6UoyvfsA4RcQxqexSUJ_8=.p12",
|
||||
"keyPassword" : "0000001BD55750CF879F40EE4EA1B96386BD83692A36E1776974D52D7439FEEEFCB8D2EC5C798FC7C815AE",
|
||||
"storePassword": "0000001B2AC157AB2A1227E77D5E4925A0B59DE84E94B4D146D9C4DA5EAB030537941F0436A3C3E9F26424"
|
||||
"storeFile": "C:/Users/acgis/.ohos/config/openharmony/default_taoyao_RrmPaKOZ5zMCU4QlpK1kz_6UoyvfsA4RcQxqexSUJ_8=.p12"
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
"modules": [
|
||||
|
||||
@@ -4,11 +4,6 @@
|
||||
"@ohos/hvigor-ohos-plugin": "3.2.4"
|
||||
},
|
||||
"execution": {
|
||||
// "daemon" : true,
|
||||
// "analyze" : "default",
|
||||
// "parallel" : true,
|
||||
// "typeCheck" : false,
|
||||
// "incremental": true,
|
||||
},
|
||||
"logging": {
|
||||
"level": "debug"
|
||||
|
||||
@@ -38,14 +38,15 @@ add_library(
|
||||
media/LocalClient.cpp
|
||||
media/RemoteClient.cpp
|
||||
media/MediaManager.cpp
|
||||
media/VideoDecoder.cpp
|
||||
media/VideoEncoder.cpp
|
||||
media/Player.cpp
|
||||
media/AudioPlayer.cpp
|
||||
media/VideoPlayer.cpp
|
||||
media/VideoDecoder.cpp
|
||||
media/Capturer.cpp
|
||||
media/VideoEncoder.cpp
|
||||
media/AudioCapturer.cpp
|
||||
media/VideoCapturer.cpp
|
||||
media/CameraCapturer.cpp
|
||||
media/ScreenCapturer.cpp
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
@@ -83,6 +84,8 @@ target_link_libraries(
|
||||
libnative_media_venc.so
|
||||
libnative_media_core.so
|
||||
libnative_media_codecbase.so
|
||||
# 屏幕录制
|
||||
libnative_avscreen_capture.so
|
||||
# libmediasoupclient
|
||||
mediasoupclient
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#define TAOYAO_CAPTURER_HPP
|
||||
|
||||
// 本地音频采集
|
||||
#define __TAOYAO_AUDIO_LOCAL__ true
|
||||
#define __TAOYAO_AUDIO_LOCAL__ false
|
||||
// 本地视频采集
|
||||
#define __TAOYAO_VIDEO_LOCAL__ true
|
||||
|
||||
@@ -49,6 +49,10 @@
|
||||
#include <ohaudio/native_audiocapturer.h>
|
||||
#include <ohaudio/native_audiostreambuilder.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>
|
||||
|
||||
namespace acgist {
|
||||
|
||||
/**
|
||||
@@ -114,7 +118,22 @@ public:
|
||||
/**
|
||||
* 视频采集器
|
||||
*/
|
||||
class VideoCapturer: public Capturer<acgist::TaoyaoVideoTrackSource> {
|
||||
class VideoCapturer : public Capturer<acgist::TaoyaoVideoTrackSource> {
|
||||
|
||||
public:
|
||||
VideoCapturer() {};
|
||||
virtual ~VideoCapturer() override {};
|
||||
|
||||
public:
|
||||
virtual bool start() override = 0;
|
||||
virtual bool stop() override = 0;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 相机采集器
|
||||
*/
|
||||
class CameraCapturer : public VideoCapturer {
|
||||
|
||||
public:
|
||||
// ================ OpenGL ES ================
|
||||
@@ -153,8 +172,8 @@ public:
|
||||
Camera_OutputCapability* cameraOutputCapability = nullptr;
|
||||
|
||||
public:
|
||||
VideoCapturer();
|
||||
virtual ~VideoCapturer() override;
|
||||
CameraCapturer();
|
||||
virtual ~CameraCapturer() override;
|
||||
|
||||
public:
|
||||
// 加载OpenGL ES
|
||||
@@ -166,6 +185,24 @@ public:
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 屏幕采集器
|
||||
*/
|
||||
class ScreenCapturer : public VideoCapturer {
|
||||
|
||||
public:
|
||||
OH_AVScreenCapture* avScreenCapture = nullptr;
|
||||
|
||||
public:
|
||||
ScreenCapturer();
|
||||
virtual ~ScreenCapturer() override;
|
||||
|
||||
public:
|
||||
virtual bool start() override;
|
||||
virtual bool stop() override;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // TAOYAO_CAPTURER_HPP
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
#include "api/peer_connection_interface.h"
|
||||
|
||||
#define TAOYAO_VIDEO_SOURCE_SCREEN true
|
||||
#define TAOYAO_VIDEO_SOURCE_CAMERA false
|
||||
|
||||
namespace acgist {
|
||||
|
||||
/**
|
||||
|
||||
@@ -76,12 +76,6 @@ static int32_t OnError(OH_AudioCapturer* capturer, void* userData, OH_AudioStrea
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
// TODO: 删除
|
||||
static std::ofstream outfile("/data/storage/el2/base/haps/media/files/audio.pcm");
|
||||
|
||||
static int32_t OnReadData(OH_AudioCapturer* capturer, void* userData, void* buffer, int32_t length) {
|
||||
OH_LOG_DEBUG(LOG_APP, "音频帧数据采集回调:%{public}d", length);
|
||||
if(userData == nullptr) {
|
||||
@@ -96,7 +90,6 @@ static int32_t OnReadData(OH_AudioCapturer* capturer, void* userData, void* buff
|
||||
// 字节数量 * 8 / 位深 / 通道数量
|
||||
size_t number_of_frames = length / 2;
|
||||
// size_t number_of_frames = length * 8 / 16 / 2;
|
||||
outfile.write((char*) buffer, length);
|
||||
audioCapturer->source->OnData((uint16_t*) buffer, acgist::bitsPerSample, acgist::samplingRate, acgist::channelCount, number_of_frames);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ static void onFrame(void* context);
|
||||
// 检查EGL扩展
|
||||
static bool CheckEglExtension(const char* extensions, const char* extension);
|
||||
|
||||
acgist::VideoCapturer::VideoCapturer() {
|
||||
acgist::CameraCapturer::CameraCapturer() {
|
||||
initOpenGLES();
|
||||
Camera_ErrorCode ret = OH_Camera_GetCameraManager(&this->cameraManager);
|
||||
TAOYAO_VIDEO_RET_LOG("配置相机管理:%{public}d", ret);
|
||||
@@ -108,7 +108,7 @@ acgist::VideoCapturer::VideoCapturer() {
|
||||
// OH_CaptureSession_SetZoomRatio(this->cameraCaptureSession, 0.5F);
|
||||
}
|
||||
|
||||
acgist::VideoCapturer::~VideoCapturer() {
|
||||
acgist::CameraCapturer::~CameraCapturer() {
|
||||
releaseOpenGLES();
|
||||
CaptureSession_Callbacks captureSession_Callbacks = { onSessionFocusStateChange, onSessionError };
|
||||
Camera_ErrorCode ret = OH_CaptureSession_UnregisterCallback(this->cameraCaptureSession, &captureSession_Callbacks);
|
||||
@@ -148,7 +148,7 @@ acgist::VideoCapturer::~VideoCapturer() {
|
||||
TAOYAO_VIDEO_RET_LOG("释放相机管理:%{public}d", ret);
|
||||
}
|
||||
|
||||
bool acgist::VideoCapturer::start() {
|
||||
bool acgist::CameraCapturer::start() {
|
||||
std::lock_guard<std::recursive_mutex> videoLock(videoMutex);
|
||||
if (this->running) {
|
||||
return true;
|
||||
@@ -176,7 +176,7 @@ bool acgist::VideoCapturer::start() {
|
||||
return ret = Camera_ErrorCode::CAMERA_OK;
|
||||
}
|
||||
|
||||
bool acgist::VideoCapturer::stop() {
|
||||
bool acgist::CameraCapturer::stop() {
|
||||
std::lock_guard<std::recursive_mutex> videoLock(videoMutex);
|
||||
if (!this->running) {
|
||||
return true;
|
||||
@@ -204,7 +204,7 @@ bool acgist::VideoCapturer::stop() {
|
||||
return ret = Camera_ErrorCode::CAMERA_OK;
|
||||
}
|
||||
|
||||
void acgist::VideoCapturer::initOpenGLES() {
|
||||
void acgist::CameraCapturer::initOpenGLES() {
|
||||
// EGL
|
||||
static const char* EGL_EXT_PLATFORM_WAYLAND = "EGL_EXT_platform_wayland";
|
||||
static const char* EGL_KHR_PLATFORM_WAYLAND = "EGL_KHR_platform_wayland";
|
||||
@@ -257,14 +257,16 @@ void acgist::VideoCapturer::initOpenGLES() {
|
||||
this->eglContext = eglCreateContext(this->eglDisplay, config, EGL_NO_CONTEXT, context_attribs);
|
||||
}
|
||||
const EGLint surfaceAttr[] = {
|
||||
EGL_WIDTH, 1980,
|
||||
EGL_HEIGHT, 1080,
|
||||
// EGL_WIDTH, acgist::width,
|
||||
// EGL_HEIGHT, acgist::height,
|
||||
EGL_LARGEST_PBUFFER, EGL_TRUE,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
this->eglSurface = eglCreatePbufferSurface(this->eglDisplay, config, surfaceAttr);
|
||||
|
||||
// OH_NativeWindow_CreateNativeWindow(this->eglSurface);
|
||||
|
||||
eglMakeCurrent(this->eglDisplay, this->eglSurface, this->eglSurface, this->eglContext);
|
||||
|
||||
// IMAGE WINDOW
|
||||
@@ -278,7 +280,7 @@ void acgist::VideoCapturer::initOpenGLES() {
|
||||
OH_LOG_INFO(LOG_APP, "视频采集SurfaceId:%{public}lld", this->surfaceId);
|
||||
}
|
||||
|
||||
void acgist::VideoCapturer::releaseOpenGLES() {
|
||||
void acgist::CameraCapturer::releaseOpenGLES() {
|
||||
if(this->textureId != 0) {
|
||||
glDeleteTextures(this->textureSize, &this->textureId);
|
||||
this->textureId = 0;
|
||||
@@ -342,21 +344,20 @@ static void onSessionFocusStateChange(Camera_CaptureSession* session, Camera_Foc
|
||||
|
||||
static void onFrame(void* context) {
|
||||
OH_LOG_DEBUG(LOG_APP, "视频帧数据采集回调:%{public}d", 1);
|
||||
acgist::VideoCapturer* videoCapturer = (acgist::VideoCapturer*) context;
|
||||
// OH_NativeImage_UpdateSurfaceImage(videoCapturer->nativeImage);
|
||||
acgist::CameraCapturer* cameraCapturer = (acgist::CameraCapturer*) context;
|
||||
// OH_NativeImage_UpdateSurfaceImage(cameraCapturer->nativeImage);
|
||||
// 更新内容到OpenGL纹理。
|
||||
uint32_t ret = OH_NativeImage_UpdateSurfaceImage(videoCapturer->nativeImage);
|
||||
uint32_t ret = OH_NativeImage_UpdateSurfaceImage(cameraCapturer->nativeImage);
|
||||
if (ret != 0) {
|
||||
}
|
||||
// 获取最近调用OH_NativeImage_UpdateSurfaceImage的纹理图像的时间戳和变化矩阵。
|
||||
int64_t timeStamp = OH_NativeImage_GetTimestamp(videoCapturer->nativeImage);
|
||||
int64_t timeStamp = OH_NativeImage_GetTimestamp(cameraCapturer->nativeImage);
|
||||
float matrix[16];
|
||||
ret = OH_NativeImage_GetTransformMatrix(videoCapturer->nativeImage, matrix);
|
||||
ret = OH_NativeImage_GetTransformMatrix(cameraCapturer->nativeImage, matrix);
|
||||
if (ret != 0) {
|
||||
}
|
||||
|
||||
// 对update绑定到对应textureId的纹理做对应的opengl后处理后,将纹理上屏
|
||||
EGLBoolean eglRet = eglSwapBuffers(videoCapturer->eglDisplay, videoCapturer->eglSurface);
|
||||
EGLBoolean eglRet = eglSwapBuffers(cameraCapturer->eglDisplay, cameraCapturer->eglSurface);
|
||||
if (eglRet == EGL_FALSE) {
|
||||
}
|
||||
//HWTEST_F(NativeImageTest, OHNativeImageSetOnFrameAvailableListener001, Function | MediumTest | Level1)
|
||||
@@ -396,7 +397,7 @@ if (eglRet == EGL_FALSE) {
|
||||
// ret = OH_NativeImage_UpdateSurfaceImage(image);
|
||||
// ASSERT_EQ(ret, SURFACE_ERROR_OK);
|
||||
//}
|
||||
// OHNativeWindow* nativeWindow = OH_NativeImage_AcquireNativeWindow(videoCapturer->nativeImage);
|
||||
// OHNativeWindow* nativeWindow = OH_NativeImage_AcquireNativeWindow(cameraCapturer->nativeImage);
|
||||
// int code = SET_BUFFER_GEOMETRY;
|
||||
// int32_t width = 800;
|
||||
// int32_t height = 600;
|
||||
@@ -411,30 +412,30 @@ if (eglRet == EGL_FALSE) {
|
||||
//// 通过OH_NativeWindow_NativeWindowFlushBuffer 提交给消费者使用,例如:显示在屏幕上。
|
||||
//OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, buffer, fenceFd, region);
|
||||
// // 更新内容到OpenGL纹理。
|
||||
// ret = OH_NativeImage_UpdateSurfaceImage(videoCapturer->nativeImage);
|
||||
// ret = OH_NativeImage_UpdateSurfaceImage(cameraCapturer->nativeImage);
|
||||
//if (ret != 0) {
|
||||
//}
|
||||
//// 获取最近调用OH_NativeImage_UpdateSurfaceImage的纹理图像的时间戳和变化矩阵。
|
||||
//int64_t timeStamp = OH_NativeImage_GetTimestamp(videoCapturer->nativeImage);
|
||||
//int64_t timeStamp = OH_NativeImage_GetTimestamp(cameraCapturer->nativeImage);
|
||||
//float matrix[16];
|
||||
//ret = OH_NativeImage_GetTransformMatrix(videoCapturer->nativeImage, matrix);
|
||||
//ret = OH_NativeImage_GetTransformMatrix(cameraCapturer->nativeImage, matrix);
|
||||
//if (ret != 0) {
|
||||
//}
|
||||
//
|
||||
//// 对update绑定到对应textureId的纹理做对应的opengl后处理后,将纹理上屏
|
||||
//EGLBoolean eglRet = eglSwapBuffers(videoCapturer->eglDisplay, videoCapturer->eglSurface);
|
||||
//EGLBoolean eglRet = eglSwapBuffers(cameraCapturer->eglDisplay, cameraCapturer->eglSurface);
|
||||
//if (eglRet == EGL_FALSE) {
|
||||
//}
|
||||
|
||||
// eglMakeCurrent(videoCapturer->eglDisplay, videoCapturer->eglSurface, videoCapturer->eglSurface, videoCapturer->eglContext);
|
||||
// OH_NativeImage_UpdateSurfaceImage(videoCapturer->nativeImage);
|
||||
// OH_NativeImage_GetTimestamp(videoCapturer->nativeImage);
|
||||
// eglMakeCurrent(cameraCapturer->eglDisplay, cameraCapturer->eglSurface, cameraCapturer->eglSurface, cameraCapturer->eglContext);
|
||||
// OH_NativeImage_UpdateSurfaceImage(cameraCapturer->nativeImage);
|
||||
// OH_NativeImage_GetTimestamp(cameraCapturer->nativeImage);
|
||||
// float matrix[16];
|
||||
// OH_NativeImage_GetTransformMatrix(videoCapturer->nativeImage, matrix);
|
||||
// eglSwapBuffers(videoCapturer->eglDisplay, videoCapturer->eglSurface);
|
||||
// OH_NativeImage_GetTransformMatrix(cameraCapturer->nativeImage, matrix);
|
||||
// eglSwapBuffers(cameraCapturer->eglDisplay, cameraCapturer->eglSurface);
|
||||
// char* chars = new char[1024];
|
||||
// eglQueryNativePixmapNV(videoCapturer->eglDisplay, videoCapturer->eglSurface, &pixmap);
|
||||
// EGLBoolean ret = eglCopyBuffers(videoCapturer->eglDisplay, videoCapturer->eglSurface, (EGLNativePixmapType) chars);
|
||||
// eglQueryNativePixmapNV(cameraCapturer->eglDisplay, cameraCapturer->eglSurface, &pixmap);
|
||||
// EGLBoolean ret = eglCopyBuffers(cameraCapturer->eglDisplay, cameraCapturer->eglSurface, (EGLNativePixmapType) chars);
|
||||
// char buffer[1024];
|
||||
// glReadPixels(0, 0, 10, 10, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
||||
// OH_LOG_DEBUG(LOG_APP, "视频帧数据采集回调读取:%{public}d", ret);
|
||||
@@ -447,7 +448,7 @@ if (eglRet == EGL_FALSE) {
|
||||
// webrtc::VideoFrame::Builder builder;
|
||||
// webrtc::VideoFrame videoFrame =
|
||||
// builder.set_timestamp_ms(rtc::TimeMillis()).set_video_frame_buffer(videoFrameBuffer).build();
|
||||
// for (auto iterator = videoCapturer->map.begin(); iterator != videoCapturer->map.end(); ++iterator) {
|
||||
// for (auto iterator = cameraCapturer->map.begin(); iterator != cameraCapturer->map.end(); ++iterator) {
|
||||
// iterator->second->OnFrame(videoFrame);
|
||||
// }
|
||||
// // TODO: 释放webrtc
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
acgist::LocalClient::LocalClient(acgist::MediaManager* mediaManager) : acgist::RoomClient(mediaManager) {
|
||||
this->mediaManager->newLocalClient();
|
||||
this->audioTrack = this->mediaManager->getAudioTrack();
|
||||
// this->videoTrack = this->mediaManager->getVideoTrack();
|
||||
// this->audioTrack = this->mediaManager->getAudioTrack();
|
||||
this->videoTrack = this->mediaManager->getVideoTrack();
|
||||
}
|
||||
|
||||
acgist::LocalClient::~LocalClient() {
|
||||
|
||||
@@ -109,8 +109,8 @@ int acgist::MediaManager::releaseLocalClient() {
|
||||
}
|
||||
|
||||
bool acgist::MediaManager::startCapture() {
|
||||
this->startAudioCapture();
|
||||
// this->startVideoCapture();
|
||||
// this->startAudioCapture();
|
||||
this->startVideoCapture();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -130,10 +130,10 @@ bool acgist::MediaManager::startAudioCapture() {
|
||||
if(this->audioTrackSource == nullptr) {
|
||||
OH_LOG_INFO(LOG_APP, "设置音频来源");
|
||||
cricket::AudioOptions options;
|
||||
options.highpass_filter = true;
|
||||
options.auto_gain_control = true;
|
||||
options.echo_cancellation = true;
|
||||
options.noise_suppression = true;
|
||||
// options.highpass_filter = true;
|
||||
// options.auto_gain_control = true;
|
||||
// options.echo_cancellation = true;
|
||||
// options.noise_suppression = true;
|
||||
this->audioTrackSource = this->peerConnectionFactory->CreateAudioSource(options);
|
||||
}
|
||||
#endif
|
||||
@@ -143,7 +143,14 @@ bool acgist::MediaManager::startAudioCapture() {
|
||||
bool acgist::MediaManager::startVideoCapture() {
|
||||
if(this->videoCapturer == nullptr) {
|
||||
OH_LOG_INFO(LOG_APP, "开始视频采集");
|
||||
this->videoCapturer = new acgist::VideoCapturer();
|
||||
#if TAOYAO_VIDEO_SOURCE_SCREEN
|
||||
OH_LOG_INFO(LOG_APP, "开始屏幕采集");
|
||||
this->videoCapturer = new acgist::ScreenCapturer();
|
||||
#endif
|
||||
#if TAOYAO_VIDEO_SOURCE_CAMERA
|
||||
OH_LOG_INFO(LOG_APP, "开始相机采集");
|
||||
this->videoCapturer = new acgist::CameraCapturer();
|
||||
#endif
|
||||
this->videoCapturer->start();
|
||||
}
|
||||
if(this->videoTrackSource == nullptr) {
|
||||
|
||||
@@ -118,10 +118,10 @@ int acgist::Room::produceMedia() {
|
||||
this->createRecvTransport();
|
||||
}
|
||||
if(this->audioProduce) {
|
||||
this->produceAudio();
|
||||
// this->produceAudio();
|
||||
}
|
||||
if(this->videoProduce) {
|
||||
// this->produceVideo();
|
||||
this->produceVideo();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
#include "../include/Capturer.hpp"
|
||||
|
||||
#include <hilog/log.h>
|
||||
|
||||
#include "api/video/nv12_buffer.h"
|
||||
#include "api/video/i420_buffer.h"
|
||||
|
||||
// 没法
|
||||
static acgist::ScreenCapturer* screenCapturer = nullptr;
|
||||
|
||||
static void OnError(OH_AVScreenCapture* capture, int32_t errorCode) {
|
||||
OH_LOG_ERROR(LOG_APP, "屏幕采集异常:%{public}d", errorCode);
|
||||
}
|
||||
|
||||
static void OnAudioBufferAvailable(OH_AVScreenCapture* capture, bool isReady, OH_AudioCaptureSourceType type) {
|
||||
// OH_LOG_DEBUG(LOG_APP, "屏幕采集音频数据帧");
|
||||
if (isReady) {
|
||||
OH_AudioBuffer* buffer = new OH_AudioBuffer;
|
||||
int32_t ret = OH_AVScreenCapture_AcquireAudioBuffer(capture, &buffer, type);
|
||||
(void) buffer->buf;
|
||||
(void) buffer->size;
|
||||
(void) buffer->timestamp;
|
||||
delete buffer;
|
||||
buffer = nullptr;
|
||||
OH_AVScreenCapture_ReleaseAudioBuffer(capture, type);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnVideoBufferAvailable(OH_AVScreenCapture* capture, bool isReady) {
|
||||
OH_LOG_DEBUG(LOG_APP, "屏幕采集视频数据帧");
|
||||
if (isReady) {
|
||||
int32_t fence = 0;
|
||||
int64_t timestamp = 0;
|
||||
OH_Rect damage;
|
||||
OH_NativeBuffer* buffer = OH_AVScreenCapture_AcquireVideoBuffer(capture, &fence, ×tamp, &damage);
|
||||
void* virAddr = nullptr;
|
||||
OH_NativeBuffer_Map(buffer, &virAddr);
|
||||
OH_NativeBuffer_Config config;
|
||||
OH_NativeBuffer_GetConfig(buffer, &config);
|
||||
// rtc::scoped_refptr<webrtc::I420Buffer> videoFrameBuffer = webrtc::I420Buffer::Copy(config.width, config.height, (uint8_t*) virAddr, 0, (uint8_t*) virAddr, 0, (uint8_t*) virAddr, 0);
|
||||
// webrtc::VideoFrame::Builder builder;
|
||||
// webrtc::VideoFrame videoFrame = builder.set_timestamp_ms(timestamp).set_video_frame_buffer(videoFrameBuffer).build();
|
||||
// screenCapturer->source->OnData(videoFrame);
|
||||
OH_NativeBuffer_Unmap(buffer);
|
||||
OH_AVScreenCapture_ReleaseVideoBuffer(capture);
|
||||
}
|
||||
}
|
||||
|
||||
acgist::ScreenCapturer::ScreenCapturer() {
|
||||
this->avScreenCapture = OH_AVScreenCapture_Create();
|
||||
OH_AVScreenCaptureCallback callback;
|
||||
callback.onError = OnError;
|
||||
callback.onAudioBufferAvailable = OnAudioBufferAvailable;
|
||||
callback.onVideoBufferAvailable = OnVideoBufferAvailable;
|
||||
OH_AVScreenCapture_SetCallback(this->avScreenCapture, callback);
|
||||
OH_AudioCaptureInfo audioCaptureInfo = {
|
||||
.audioSampleRate = acgist::samplingRate,
|
||||
.audioChannels = acgist::channelCount,
|
||||
.audioSource = OH_MIC
|
||||
};
|
||||
OH_AudioInfo audioInfo = {
|
||||
.micCapInfo = audioCaptureInfo,
|
||||
};
|
||||
OH_VideoCaptureInfo videoCaptureInfo = {
|
||||
// .videoFrameWidth = static_cast<int32_t>(acgist::width),
|
||||
// .videoFrameHeight = static_cast<int32_t>(acgist::height),
|
||||
.videoFrameWidth = static_cast<int32_t>(800),
|
||||
.videoFrameHeight = static_cast<int32_t>(1280),
|
||||
.videoSource = OH_VIDEO_SOURCE_SURFACE_RGBA
|
||||
// .videoSource = OH_VIDEO_SOURCE_SURFACE_YUV
|
||||
};
|
||||
// OH_VideoEncInfo videoEncInfo = {
|
||||
// .videoCodec = OH_VideoCodecFormat::OH_H264,
|
||||
// .videoBitrate = acgist::bitrate,
|
||||
// .videoFrameRate = acgist::frameRate
|
||||
// };
|
||||
OH_VideoInfo videoInfo = {
|
||||
.videoCapInfo = videoCaptureInfo,
|
||||
// .videoEncInfo = videoEncInfo
|
||||
};
|
||||
OH_AVScreenCaptureConfig config = {
|
||||
.captureMode = OH_CAPTURE_HOME_SCREEN,
|
||||
.dataType = OH_ORIGINAL_STREAM,
|
||||
.audioInfo = audioInfo,
|
||||
.videoInfo = videoInfo,
|
||||
};
|
||||
OH_AVScreenCapture_Init(this->avScreenCapture, config);
|
||||
OH_AVScreenCapture_SetMicrophoneEnabled(this->avScreenCapture, false);
|
||||
screenCapturer = this;
|
||||
}
|
||||
|
||||
bool acgist::ScreenCapturer::start() {
|
||||
OH_LOG_INFO(LOG_APP, "打开屏幕采集");
|
||||
OH_AVScreenCapture_StartScreenCapture(this->avScreenCapture);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool acgist::ScreenCapturer::stop() {
|
||||
OH_LOG_INFO(LOG_APP, "关闭屏幕采集");
|
||||
OH_AVScreenCapture_StopScreenCapture(this->avScreenCapture);
|
||||
return true;
|
||||
}
|
||||
|
||||
acgist::ScreenCapturer::~ScreenCapturer() {
|
||||
OH_AVScreenCapture_Release(this->avScreenCapture);
|
||||
this->avScreenCapture = nullptr;
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
namespace acgist {
|
||||
|
||||
uint32_t width = 720;
|
||||
uint32_t width = 640;
|
||||
uint32_t height = 480;
|
||||
uint64_t bitrate = 3'000'000L;
|
||||
uint32_t iFrameInterval = 5'000;
|
||||
double frameRate = 30.0;
|
||||
double frameRate = 10.0;
|
||||
int32_t samplingRate = 48'000;
|
||||
int32_t channelCount = 2;
|
||||
int32_t bitsPerSample = 16;
|
||||
|
||||
@@ -13,6 +13,8 @@ const permissions: Array<Permissions> = [
|
||||
"ohos.permission.MICROPHONE",
|
||||
"ohos.permission.READ_MEDIA",
|
||||
"ohos.permission.WRITE_MEDIA",
|
||||
"ohos.permission.CAPTURE_SCREEN",
|
||||
"ohos.permission.CAPTURE_VOICE_DOWNLINK_AUDIO",
|
||||
];
|
||||
|
||||
function reqPermissionsFromUser(permissions: Array<Permissions>, context: common.UIAbilityContext) {
|
||||
|
||||
@@ -38,37 +38,47 @@
|
||||
"name": "ohos.permission.CAMERA",
|
||||
"reason": "$string:app_name",
|
||||
"usedScene": {
|
||||
"when": "inuse"
|
||||
"when": "inuse",
|
||||
"abilities": [ "EntryAbility" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.INTERNET",
|
||||
"reason": "$string:app_name",
|
||||
"usedScene": {
|
||||
"when": "always"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.MICROPHONE",
|
||||
"reason": "$string:app_name",
|
||||
"usedScene": {
|
||||
"when": "inuse"
|
||||
"when": "inuse",
|
||||
"abilities": [ "EntryAbility" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.READ_MEDIA",
|
||||
"reason": "$string:app_name",
|
||||
"usedScene": {
|
||||
"when": "always"
|
||||
"when": "always",
|
||||
"abilities": [ "EntryAbility" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.WRITE_MEDIA",
|
||||
"reason": "$string:app_name",
|
||||
"usedScene": {
|
||||
"when": "always"
|
||||
"when": "always",
|
||||
"abilities": [ "EntryAbility" ]
|
||||
}
|
||||
},
|
||||
// 🤡🤡🤡🤡
|
||||
{
|
||||
"name": "ohos.permission.CAPTURE_SCREEN",
|
||||
"reason": "$string:app_name",
|
||||
},
|
||||
{
|
||||
"name": "ohos.permission.CAPTURE_VOICE_DOWNLINK_AUDIO",
|
||||
"reason": "$string:app_name",
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user