1e0dac50fSopenharmony_ci/*
2e0dac50fSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3e0dac50fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e0dac50fSopenharmony_ci * you may not use this file except in compliance with the License.
5e0dac50fSopenharmony_ci * You may obtain a copy of the License at
6e0dac50fSopenharmony_ci *
7e0dac50fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e0dac50fSopenharmony_ci *
9e0dac50fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e0dac50fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e0dac50fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e0dac50fSopenharmony_ci * See the License for the specific language governing permissions and
13e0dac50fSopenharmony_ci * limitations under the License.
14e0dac50fSopenharmony_ci */
15e0dac50fSopenharmony_ci
16e0dac50fSopenharmony_ci#include "surface_reader.h"
17e0dac50fSopenharmony_ci#include "sync_fence.h"
18e0dac50fSopenharmony_ci#include "window_manager_hilog.h"
19e0dac50fSopenharmony_ci#include "unique_fd.h"
20e0dac50fSopenharmony_ci
21e0dac50fSopenharmony_ci#include <securec.h>
22e0dac50fSopenharmony_ci
23e0dac50fSopenharmony_ciusing namespace OHOS::Media;
24e0dac50fSopenharmony_ci
25e0dac50fSopenharmony_cinamespace OHOS {
26e0dac50fSopenharmony_cinamespace Rosen {
27e0dac50fSopenharmony_cinamespace {
28e0dac50fSopenharmony_ciconstexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SurfaceReader"};
29e0dac50fSopenharmony_ci} // namespace
30e0dac50fSopenharmony_ciconst int BPP = 4; // bytes per pixel
31e0dac50fSopenharmony_ci
32e0dac50fSopenharmony_ciSurfaceReader::SurfaceReader()
33e0dac50fSopenharmony_ci{
34e0dac50fSopenharmony_ci}
35e0dac50fSopenharmony_ci
36e0dac50fSopenharmony_ciSurfaceReader::~SurfaceReader()
37e0dac50fSopenharmony_ci{
38e0dac50fSopenharmony_ci    if (csurface_ != nullptr) {
39e0dac50fSopenharmony_ci        csurface_->UnregisterConsumerListener();
40e0dac50fSopenharmony_ci    }
41e0dac50fSopenharmony_ci    psurface_ = nullptr;
42e0dac50fSopenharmony_ci    csurface_ = nullptr;
43e0dac50fSopenharmony_ci}
44e0dac50fSopenharmony_ci
45e0dac50fSopenharmony_cibool SurfaceReader::Init()
46e0dac50fSopenharmony_ci{
47e0dac50fSopenharmony_ci    csurface_ = IConsumerSurface::Create();
48e0dac50fSopenharmony_ci    if (csurface_ == nullptr) {
49e0dac50fSopenharmony_ci        return false;
50e0dac50fSopenharmony_ci    }
51e0dac50fSopenharmony_ci
52e0dac50fSopenharmony_ci    auto producer = csurface_->GetProducer();
53e0dac50fSopenharmony_ci    psurface_ = Surface::CreateSurfaceAsProducer(producer);
54e0dac50fSopenharmony_ci    if (psurface_ == nullptr) {
55e0dac50fSopenharmony_ci        return false;
56e0dac50fSopenharmony_ci    }
57e0dac50fSopenharmony_ci
58e0dac50fSopenharmony_ci    listener_ = new BufferListener(*this);
59e0dac50fSopenharmony_ci    SurfaceError ret = csurface_->RegisterConsumerListener(listener_);
60e0dac50fSopenharmony_ci    if (ret != SURFACE_ERROR_OK) {
61e0dac50fSopenharmony_ci        return false;
62e0dac50fSopenharmony_ci    }
63e0dac50fSopenharmony_ci    return true;
64e0dac50fSopenharmony_ci}
65e0dac50fSopenharmony_ci
66e0dac50fSopenharmony_civoid SurfaceReader::OnVsync()
67e0dac50fSopenharmony_ci{
68e0dac50fSopenharmony_ci    WLOGI("SurfaceReader::OnVsync");
69e0dac50fSopenharmony_ci
70e0dac50fSopenharmony_ci    sptr<SurfaceBuffer> cbuffer = nullptr;
71e0dac50fSopenharmony_ci    int32_t fence = -1;
72e0dac50fSopenharmony_ci    int64_t timestamp = 0;
73e0dac50fSopenharmony_ci    Rect damage;
74e0dac50fSopenharmony_ci    auto sret = csurface_->AcquireBuffer(cbuffer, fence, timestamp, damage);
75e0dac50fSopenharmony_ci    sptr<SyncFence> acquireFence = new SyncFence(fence);
76e0dac50fSopenharmony_ci    acquireFence->Wait(3000); // 3000ms
77e0dac50fSopenharmony_ci    if (cbuffer == nullptr || sret != OHOS::SURFACE_ERROR_OK) {
78e0dac50fSopenharmony_ci        WLOGFE("SurfaceReader::OnVsync: surface buffer is null");
79e0dac50fSopenharmony_ci        return;
80e0dac50fSopenharmony_ci    }
81e0dac50fSopenharmony_ci
82e0dac50fSopenharmony_ci    if (!ProcessBuffer(cbuffer)) {
83e0dac50fSopenharmony_ci        WLOGFE("SurfaceReader::OnVsync: ProcessBuffer failed");
84e0dac50fSopenharmony_ci        return;
85e0dac50fSopenharmony_ci    }
86e0dac50fSopenharmony_ci
87e0dac50fSopenharmony_ci    if (cbuffer != prevBuffer_) {
88e0dac50fSopenharmony_ci        if (prevBuffer_ != nullptr) {
89e0dac50fSopenharmony_ci            SurfaceError ret = csurface_->ReleaseBuffer(prevBuffer_, -1);
90e0dac50fSopenharmony_ci            if (ret != SURFACE_ERROR_OK) {
91e0dac50fSopenharmony_ci                WLOGFE("SurfaceReader::OnVsync: release buffer error");
92e0dac50fSopenharmony_ci                return;
93e0dac50fSopenharmony_ci            }
94e0dac50fSopenharmony_ci        }
95e0dac50fSopenharmony_ci
96e0dac50fSopenharmony_ci        prevBuffer_ = cbuffer;
97e0dac50fSopenharmony_ci    }
98e0dac50fSopenharmony_ci}
99e0dac50fSopenharmony_ci
100e0dac50fSopenharmony_cisptr<Surface> SurfaceReader::GetSurface() const
101e0dac50fSopenharmony_ci{
102e0dac50fSopenharmony_ci    return psurface_;
103e0dac50fSopenharmony_ci}
104e0dac50fSopenharmony_ci
105e0dac50fSopenharmony_civoid SurfaceReader::SetHandler(sptr<SurfaceReaderHandler> handler)
106e0dac50fSopenharmony_ci{
107e0dac50fSopenharmony_ci    handler_ = handler;
108e0dac50fSopenharmony_ci}
109e0dac50fSopenharmony_ci
110e0dac50fSopenharmony_cibool SurfaceReader::ProcessBuffer(const sptr<SurfaceBuffer>& buf)
111e0dac50fSopenharmony_ci{
112e0dac50fSopenharmony_ci    if (handler_ == nullptr) {
113e0dac50fSopenharmony_ci        WLOGFE("SurfaceReaderHandler not set");
114e0dac50fSopenharmony_ci        return false;
115e0dac50fSopenharmony_ci    }
116e0dac50fSopenharmony_ci
117e0dac50fSopenharmony_ci    BufferHandle *bufferHandle =  buf->GetBufferHandle();
118e0dac50fSopenharmony_ci    if (bufferHandle == nullptr) {
119e0dac50fSopenharmony_ci        WLOGFE("bufferHandle nullptr");
120e0dac50fSopenharmony_ci        return false;
121e0dac50fSopenharmony_ci    }
122e0dac50fSopenharmony_ci
123e0dac50fSopenharmony_ci    uint32_t width = static_cast<uint32_t>(bufferHandle->width);
124e0dac50fSopenharmony_ci    uint32_t height = static_cast<uint32_t>(bufferHandle->height);
125e0dac50fSopenharmony_ci    uint32_t stride = static_cast<uint32_t>(bufferHandle->stride);
126e0dac50fSopenharmony_ci    uint8_t *addr = (uint8_t *)buf->GetVirAddr();
127e0dac50fSopenharmony_ci
128e0dac50fSopenharmony_ci    auto data = (uint8_t *)malloc(width * height * BPP);
129e0dac50fSopenharmony_ci    if (data == nullptr) {
130e0dac50fSopenharmony_ci        WLOGFE("data malloc failed");
131e0dac50fSopenharmony_ci        return false;
132e0dac50fSopenharmony_ci    }
133e0dac50fSopenharmony_ci    for (uint32_t i = 0; i < height; i++) {
134e0dac50fSopenharmony_ci        errno_t ret = memcpy_s(data + width * i * BPP,  width * BPP, addr + stride * i, width * BPP);
135e0dac50fSopenharmony_ci        if (ret != EOK) {
136e0dac50fSopenharmony_ci            WLOGFE("memcpy failed");
137e0dac50fSopenharmony_ci            free(data);
138e0dac50fSopenharmony_ci            return false;
139e0dac50fSopenharmony_ci        }
140e0dac50fSopenharmony_ci    }
141e0dac50fSopenharmony_ci
142e0dac50fSopenharmony_ci    Media::InitializationOptions opts;
143e0dac50fSopenharmony_ci    opts.size.width = static_cast<int32_t>(width);
144e0dac50fSopenharmony_ci    opts.size.height = static_cast<int32_t>(height);
145e0dac50fSopenharmony_ci    std::unique_ptr<Media::PixelMap> pixelMapPtr = Media::PixelMap::Create(opts);
146e0dac50fSopenharmony_ci    sptr<Media::PixelMap> pixelMap(pixelMapPtr.release());
147e0dac50fSopenharmony_ci    if (pixelMap == nullptr) {
148e0dac50fSopenharmony_ci        WLOGFE("create pixelMap failed");
149e0dac50fSopenharmony_ci        free(data);
150e0dac50fSopenharmony_ci        return false;
151e0dac50fSopenharmony_ci    }
152e0dac50fSopenharmony_ci
153e0dac50fSopenharmony_ci    ImageInfo info;
154e0dac50fSopenharmony_ci    info.size.width = static_cast<int32_t>(width);
155e0dac50fSopenharmony_ci    info.size.height = static_cast<int32_t>(height);
156e0dac50fSopenharmony_ci    info.pixelFormat = OHOS::Media::PixelFormat::RGBA_8888;
157e0dac50fSopenharmony_ci    info.colorSpace = ColorSpace::SRGB;
158e0dac50fSopenharmony_ci    pixelMap->SetImageInfo(info);
159e0dac50fSopenharmony_ci
160e0dac50fSopenharmony_ci    pixelMap->SetPixelsAddr(data, nullptr, width * height, AllocatorType::HEAP_ALLOC, nullptr);
161e0dac50fSopenharmony_ci
162e0dac50fSopenharmony_ci    handler_->OnImageAvailable(pixelMap);
163e0dac50fSopenharmony_ci    return true;
164e0dac50fSopenharmony_ci}
165e0dac50fSopenharmony_ci}
166e0dac50fSopenharmony_ci}
167