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