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 23using namespace OHOS::Media; 24 25namespace OHOS { 26namespace Rosen { 27namespace { 28constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SurfaceReader"}; 29} // namespace 30const int BPP = 4; // bytes per pixel 31 32SurfaceReader::SurfaceReader() 33{ 34} 35 36SurfaceReader::~SurfaceReader() 37{ 38 if (csurface_ != nullptr) { 39 csurface_->UnregisterConsumerListener(); 40 } 41 psurface_ = nullptr; 42 csurface_ = nullptr; 43} 44 45bool 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 66void 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 100sptr<Surface> SurfaceReader::GetSurface() const 101{ 102 return psurface_; 103} 104 105void SurfaceReader::SetHandler(sptr<SurfaceReaderHandler> handler) 106{ 107 handler_ = handler; 108} 109 110bool 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