add ScreenRecord demo

Signed-off-by: Grady <yangguangwei4@huawei.com>
Change-Id: Ic9f6f94bd615e8def87d33f36d62e94def46a472
This commit is contained in:
Grady
2022-02-21 09:37:07 +08:00
parent eeb73277f8
commit 41e3401433
8 changed files with 471 additions and 0 deletions
+26
View File
@@ -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") {
+97
View File
@@ -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;
}
+3
View File
@@ -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",
]
+66
View File
@@ -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
+34
View File
@@ -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
+152
View File
@@ -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;
}
}
}
+54
View File
@@ -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_;
}
}
}