mirror of
https://github.com/openharmony/windowmanager.git
synced 2026-07-20 01:13:32 -04:00
add ScreenRecord demo
Signed-off-by: Grady <yangguangwei4@huawei.com> Change-Id: Ic9f6f94bd615e8def87d33f36d62e94def46a472
This commit is contained in:
@@ -43,6 +43,32 @@ ohos_executable("snapshot_display") {
|
||||
subsystem_name = "window"
|
||||
}
|
||||
|
||||
ohos_executable("snapshot_virtual_screen") {
|
||||
install_enable = false
|
||||
sources = [
|
||||
"snapshot_utils.cpp",
|
||||
"snapshot_virtual_screen.cpp",
|
||||
]
|
||||
|
||||
configs = [ ":snapshot_config" ]
|
||||
|
||||
deps = [
|
||||
"//foundation/graphic/standard/rosen/modules/render_service_client:librender_service_client",
|
||||
"//foundation/windowmanager/dm:libdm",
|
||||
"//foundation/windowmanager/utils:libwmutil",
|
||||
"//foundation/windowmanager/wm:libwm",
|
||||
"//third_party/libpng:libpng", # png
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"multimedia_image_standard:image_native",
|
||||
"utils_base:utils",
|
||||
]
|
||||
|
||||
part_name = "window_manager"
|
||||
subsystem_name = "window"
|
||||
}
|
||||
|
||||
## Build snapshot }}}
|
||||
|
||||
group("test") {
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <ctime>
|
||||
|
||||
#include "snapshot_utils.h"
|
||||
#include "screen_manager.h"
|
||||
#include "surface_reader.h"
|
||||
#include "surface_reader_handler_impl.h"
|
||||
|
||||
using namespace OHOS;
|
||||
using namespace OHOS::Rosen;
|
||||
using namespace OHOS::Media;
|
||||
|
||||
namespace {
|
||||
const int SLEEP_US = 10 * 1000; // 10ms
|
||||
const int MAX_SNAPSHOT_COUNT = 10;
|
||||
const int MAX_WAIT_COUNT = 200;
|
||||
const float DEFAULT_DENSITY = 2.0;
|
||||
const std::string FILE_NAME = "/data/snapshot_virtual_screen";
|
||||
}
|
||||
|
||||
static VirtualScreenOption InitOption(ScreenId mainId, SurfaceReader& surfaceReader)
|
||||
{
|
||||
auto defaultScreen = ScreenManager::GetInstance().GetScreenById(mainId);
|
||||
VirtualScreenOption option = {
|
||||
.name_ = "virtualScreen",
|
||||
.width_ = defaultScreen->GetWidth(),
|
||||
.height_ = defaultScreen->GetHeight(),
|
||||
.density_ = DEFAULT_DENSITY,
|
||||
.surface_ = surfaceReader.GetSurface(),
|
||||
.flags_ = 0,
|
||||
.isForShot_ = true,
|
||||
};
|
||||
return option;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SurfaceReader surfaceReader;
|
||||
sptr<SurfaceReaderHandlerImpl> surfaceReaderHandler = new SurfaceReaderHandlerImpl();
|
||||
if (!surfaceReader.Init()) {
|
||||
printf("surfaceReader init failed!\n");
|
||||
return 0;
|
||||
}
|
||||
surfaceReader.SetHandler(surfaceReaderHandler);
|
||||
ScreenId mainId = static_cast<ScreenId>(DisplayManager::GetInstance().GetDefaultDisplayId());
|
||||
VirtualScreenOption option = InitOption(mainId, surfaceReader);
|
||||
ScreenId virtualScreenId = ScreenManager::GetInstance().CreateVirtualScreen(option);
|
||||
std::vector<ScreenId> mirrorIds;
|
||||
mirrorIds.push_back(virtualScreenId);
|
||||
ScreenManager::GetInstance().MakeMirror(mainId, mirrorIds);
|
||||
int fileIndex = 1;
|
||||
auto startTime = time(nullptr);
|
||||
while (time(nullptr) - startTime < MAX_SNAPSHOT_COUNT) {
|
||||
int waitCount = 0;
|
||||
while (!surfaceReaderHandler->IsImageOk()) {
|
||||
waitCount++;
|
||||
if (waitCount >= MAX_WAIT_COUNT) {
|
||||
printf("wait image overtime\n");
|
||||
break;
|
||||
}
|
||||
usleep(SLEEP_US);
|
||||
}
|
||||
if (waitCount >= MAX_WAIT_COUNT) {
|
||||
continue;
|
||||
}
|
||||
auto pixelMap = surfaceReaderHandler->GetPixelMap();
|
||||
bool ret = SnapShotUtils::WriteToPngWithPixelMap(FILE_NAME + std::to_string(fileIndex) + ".png", *pixelMap);
|
||||
if (ret) {
|
||||
printf("snapshot %" PRIu64 ", write to %s as png\n",
|
||||
mainId, (FILE_NAME + std::to_string(fileIndex)).c_str());
|
||||
} else {
|
||||
printf("snapshot %" PRIu64 " write to %s failed!\n",
|
||||
mainId, (FILE_NAME + std::to_string(fileIndex)).c_str());
|
||||
}
|
||||
surfaceReaderHandler->ResetFlag();
|
||||
fileIndex++;
|
||||
}
|
||||
ScreenManager::GetInstance().DestroyVirtualScreen(virtualScreenId);
|
||||
printf("DestroyVirtualScreen %" PRIu64 "\n", virtualScreenId);
|
||||
return 0;
|
||||
}
|
||||
@@ -34,6 +34,8 @@ ohos_shared_library("libwmutil") {
|
||||
"src/screen_group_info.cpp",
|
||||
"src/screen_info.cpp",
|
||||
"src/singleton_container.cpp",
|
||||
"src/surface_reader.cpp",
|
||||
"src/surface_reader_handler_impl.cpp",
|
||||
"src/window_property.cpp",
|
||||
"src/wm_trace.cpp",
|
||||
]
|
||||
@@ -49,6 +51,7 @@ ohos_shared_library("libwmutil") {
|
||||
"graphic_standard:surface",
|
||||
"hilog_native:libhilog",
|
||||
"ipc:ipc_core",
|
||||
"multimedia_image_standard:image_native",
|
||||
"utils_base:utils",
|
||||
]
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SURFACE_READER_H
|
||||
#define SURFACE_READER_H
|
||||
|
||||
#include "refbase.h"
|
||||
|
||||
#include <surface.h>
|
||||
|
||||
#include "surface_reader_handler.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Rosen {
|
||||
class SurfaceReader {
|
||||
public:
|
||||
SurfaceReader();
|
||||
virtual ~SurfaceReader();
|
||||
|
||||
bool Init();
|
||||
void DeInit();
|
||||
|
||||
sptr<Surface> GetSurface() const;
|
||||
void SetHandler(sptr<SurfaceReaderHandler> handler);
|
||||
private:
|
||||
class BufferListener : public IBufferConsumerListener {
|
||||
public:
|
||||
explicit BufferListener(SurfaceReader &surfaceReader): surfaceReader_(surfaceReader)
|
||||
{
|
||||
}
|
||||
~BufferListener() noexcept override = default;
|
||||
void OnBufferAvailable() override
|
||||
{
|
||||
surfaceReader_.OnVsync();
|
||||
}
|
||||
|
||||
private:
|
||||
SurfaceReader &surfaceReader_;
|
||||
};
|
||||
friend class BufferListener;
|
||||
|
||||
void OnVsync();
|
||||
bool ProcessBuffer(const sptr<SurfaceBuffer> &buf);
|
||||
|
||||
sptr<IBufferConsumerListener> listener_ = nullptr;
|
||||
sptr<Surface> csurface_ = nullptr; // cosumer surface
|
||||
sptr<Surface> psurface_ = nullptr; // producer surface
|
||||
sptr<SurfaceBuffer> prevBuffer_ = nullptr;
|
||||
sptr<SurfaceReaderHandler> handler_ = nullptr;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SURFACE_READER_H
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SURFACE_READER_HANDLER_H
|
||||
#define SURFACE_READER_HANDLER_H
|
||||
|
||||
#include "pixel_map.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Rosen {
|
||||
class SurfaceReaderHandler : public RefBase {
|
||||
public:
|
||||
SurfaceReaderHandler() {}
|
||||
virtual ~SurfaceReaderHandler() noexcept
|
||||
{
|
||||
}
|
||||
virtual bool OnImageAvalible(sptr<Media::PixelMap> pixleMap) = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // IMAGE_READER_HANDLER_H
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef SURFACE_READER_HANDLER_IMPL_H
|
||||
#define SURFACE_READER_HANDLER_IMPL_H
|
||||
|
||||
#include <mutex>
|
||||
#include "surface_reader_handler.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Rosen {
|
||||
class SurfaceReaderHandlerImpl : public SurfaceReaderHandler {
|
||||
public:
|
||||
bool OnImageAvalible(sptr<Media::PixelMap> pixleMap) override;
|
||||
bool IsImageOk();
|
||||
void ResetFlag();
|
||||
sptr<Media::PixelMap> GetPixelMap();
|
||||
|
||||
private:
|
||||
bool flag_ = false;
|
||||
sptr<Media::PixelMap> pixleMap_ = nullptr;
|
||||
std::recursive_mutex mutex_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SURFACE_READER_HANDLER_IMPL_H
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "surface_reader.h"
|
||||
#include "window_manager_hilog.h"
|
||||
#include "unique_fd.h"
|
||||
|
||||
#include <securec.h>
|
||||
|
||||
using namespace OHOS::Media;
|
||||
|
||||
namespace OHOS {
|
||||
namespace Rosen {
|
||||
namespace {
|
||||
constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SurfaceReader"};
|
||||
} // namespace
|
||||
const int BPP = 4; // bytes per pixel
|
||||
|
||||
SurfaceReader::SurfaceReader()
|
||||
{
|
||||
}
|
||||
|
||||
SurfaceReader::~SurfaceReader()
|
||||
{
|
||||
if (csurface_ != nullptr) {
|
||||
csurface_->UnregisterConsumerListener();
|
||||
}
|
||||
psurface_ = nullptr;
|
||||
csurface_ = nullptr;
|
||||
}
|
||||
|
||||
bool SurfaceReader::Init()
|
||||
{
|
||||
csurface_ = Surface::CreateSurfaceAsConsumer();
|
||||
if (csurface_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto producer = csurface_->GetProducer();
|
||||
psurface_ = Surface::CreateSurfaceAsProducer(producer);
|
||||
if (psurface_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
listener_ = new BufferListener(*this);
|
||||
SurfaceError ret = csurface_->RegisterConsumerListener(listener_);
|
||||
if (ret != SURFACE_ERROR_OK) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SurfaceReader::OnVsync()
|
||||
{
|
||||
WLOGFI("SurfaceReader::OnVsync");
|
||||
|
||||
sptr<SurfaceBuffer> cbuffer = nullptr;
|
||||
int32_t fence = -1;
|
||||
int64_t timestamp = 0;
|
||||
Rect damage;
|
||||
auto sret = csurface_->AcquireBuffer(cbuffer, fence, timestamp, damage);
|
||||
if (cbuffer == nullptr || sret != OHOS::SURFACE_ERROR_OK) {
|
||||
WLOGFE("SurfaceReader::OnVsync: surface buffer is null");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ProcessBuffer(cbuffer)) {
|
||||
WLOGFE("SurfaceReader::OnVsync: ProcessBuffer failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cbuffer != prevBuffer_) {
|
||||
if (prevBuffer_ != nullptr) {
|
||||
SurfaceError ret = csurface_->ReleaseBuffer(prevBuffer_, -1);
|
||||
if (ret != SURFACE_ERROR_OK) {
|
||||
WLOGFE("SurfaceReader::OnVsync: release buffer error");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
prevBuffer_ = cbuffer;
|
||||
}
|
||||
}
|
||||
|
||||
sptr<Surface> SurfaceReader::GetSurface() const
|
||||
{
|
||||
return psurface_;
|
||||
}
|
||||
|
||||
void SurfaceReader::SetHandler(sptr<SurfaceReaderHandler> handler)
|
||||
{
|
||||
handler_ = handler;
|
||||
}
|
||||
|
||||
bool SurfaceReader::ProcessBuffer(const sptr<SurfaceBuffer> &buf)
|
||||
{
|
||||
if (handler_ == nullptr) {
|
||||
WLOGFE("SurfaceReaderHandler not set");
|
||||
return false;
|
||||
}
|
||||
|
||||
BufferHandle *bufferHandle = buf->GetBufferHandle();
|
||||
if (bufferHandle == nullptr) {
|
||||
WLOGFE("bufferHandle nullptr");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t width = bufferHandle->width;
|
||||
uint32_t height = bufferHandle->height;
|
||||
uint32_t stride = bufferHandle->stride;
|
||||
uint8_t *addr = (uint8_t *)buf->GetVirAddr();
|
||||
|
||||
auto data = (uint8_t *)malloc(width * height * BPP);
|
||||
if (data == nullptr) {
|
||||
WLOGFE("data malloc failed");
|
||||
return false;
|
||||
}
|
||||
for (uint32_t i = 0; i < height; i++) {
|
||||
errno_t ret = memcpy_s(data + width * i * BPP, width * BPP, addr + stride * i, width * BPP);
|
||||
if (ret != EOK) {
|
||||
WLOGFE("memcpy failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sptr<PixelMap> pixelMap = new PixelMap();
|
||||
ImageInfo info;
|
||||
info.size.width = width;
|
||||
info.size.height = height;
|
||||
info.pixelFormat = PixelFormat::RGBA_8888;
|
||||
info.colorSpace = ColorSpace::SRGB;
|
||||
pixelMap->SetImageInfo(info);
|
||||
|
||||
pixelMap->SetPixelsAddr(data, nullptr, width * height, AllocatorType::HEAP_ALLOC, nullptr);
|
||||
|
||||
handler_->OnImageAvalible(pixelMap);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "surface_reader_handler_impl.h"
|
||||
#include "window_manager_hilog.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Rosen {
|
||||
namespace {
|
||||
constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SurfaceReaderHandlerImpl"};
|
||||
} // namespace
|
||||
bool SurfaceReaderHandlerImpl::OnImageAvalible(sptr<Media::PixelMap> pixleMap)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> locl(mutex_);
|
||||
if (!flag_) {
|
||||
flag_ = true;
|
||||
pixleMap_ = pixleMap;
|
||||
WLOGFI("Get an Image!");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SurfaceReaderHandlerImpl::IsImageOk()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
return flag_;
|
||||
}
|
||||
|
||||
void SurfaceReaderHandlerImpl::ResetFlag()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
if (flag_) {
|
||||
flag_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
sptr<Media::PixelMap> SurfaceReaderHandlerImpl::GetPixelMap()
|
||||
{
|
||||
return pixleMap_;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user