xref: /aosp_15_r20/frameworks/av/services/camera/virtualcamera/util/Util.cc (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "Util.h"
18 
19 #include <unistd.h>
20 
21 #include <algorithm>
22 #include <array>
23 #include <cstdint>
24 #include <memory>
25 
26 #include "EglUtil.h"
27 #include "android/hardware_buffer.h"
28 #include "jpeglib.h"
29 #include "ui/GraphicBuffer.h"
30 #include "utils/Errors.h"
31 
32 namespace android {
33 namespace companion {
34 namespace virtualcamera {
35 
36 using ::aidl::android::companion::virtualcamera::Format;
37 using ::aidl::android::hardware::common::NativeHandle;
38 
39 constexpr int kMaxFpsUpperLimit = 60;
40 
41 constexpr std::array<Format, 2> kSupportedFormats{Format::YUV_420_888,
42                                                   Format::RGBA_8888};
43 
YCbCrLockGuard(std::shared_ptr<AHardwareBuffer> hwBuffer,const uint32_t usageFlags)44 YCbCrLockGuard::YCbCrLockGuard(std::shared_ptr<AHardwareBuffer> hwBuffer,
45                                const uint32_t usageFlags)
46     : mHwBuffer(hwBuffer) {
47   GraphicBuffer* gBuffer = GraphicBuffer::fromAHardwareBuffer(mHwBuffer.get());
48   if (gBuffer == nullptr) {
49     ALOGE("%s: Attempting to lock nullptr buffer.", __func__);
50     return;
51   }
52   mLockStatus = gBuffer->lockYCbCr(usageFlags, &mYCbCr);
53   if (mLockStatus != OK) {
54     ALOGE("%s: Failed to lock graphic buffer: %s", __func__,
55           statusToString(mLockStatus).c_str());
56   }
57 }
58 
~YCbCrLockGuard()59 YCbCrLockGuard::~YCbCrLockGuard() {
60   if (getStatus() != OK) {
61     return;
62   }
63 
64   GraphicBuffer* gBuffer = GraphicBuffer::fromAHardwareBuffer(mHwBuffer.get());
65   if (gBuffer == nullptr) {
66     return;
67   }
68   status_t status = gBuffer->unlock();
69   if (status != NO_ERROR) {
70     ALOGE("Failed to unlock graphic buffer: %s", statusToString(status).c_str());
71   }
72 }
73 
getStatus() const74 status_t YCbCrLockGuard::getStatus() const {
75   return mLockStatus;
76 }
77 
operator *() const78 const android_ycbcr& YCbCrLockGuard::operator*() const {
79   LOG_ALWAYS_FATAL_IF(getStatus() != OK,
80                       "Dereferencing unlocked YCbCrLockGuard, status is %s",
81                       statusToString(mLockStatus).c_str());
82   return mYCbCr;
83 }
84 
PlanesLockGuard(std::shared_ptr<AHardwareBuffer> hwBuffer,const uint64_t usageFlags,sp<Fence> fence)85 PlanesLockGuard::PlanesLockGuard(std::shared_ptr<AHardwareBuffer> hwBuffer,
86                                  const uint64_t usageFlags, sp<Fence> fence) {
87   if (hwBuffer == nullptr) {
88     ALOGE("%s: Attempting to lock nullptr buffer.", __func__);
89     return;
90   }
91 
92   const int32_t rawFence = fence != nullptr ? dup(fence->get()) : -1;
93   mLockStatus = static_cast<status_t>(AHardwareBuffer_lockPlanes(
94       hwBuffer.get(), usageFlags, rawFence, nullptr, &mPlanes));
95   if (mLockStatus != OK) {
96     ALOGE("%s: Failed to lock graphic buffer: %s", __func__,
97           statusToString(mLockStatus).c_str());
98   }
99   if (rawFence >= 0) {
100     close(rawFence);
101   }
102 }
103 
~PlanesLockGuard()104 PlanesLockGuard::~PlanesLockGuard() {
105   if (getStatus() != OK || mHwBuffer == nullptr) {
106     return;
107   }
108   AHardwareBuffer_unlock(mHwBuffer.get(), /*fence=*/nullptr);
109 }
110 
getStatus() const111 int PlanesLockGuard::getStatus() const {
112   return mLockStatus;
113 }
114 
operator *() const115 const AHardwareBuffer_Planes& PlanesLockGuard::operator*() const {
116   LOG_ALWAYS_FATAL_IF(getStatus() != OK,
117                       "Dereferencing unlocked PlanesLockGuard, status is %s",
118                       statusToString(mLockStatus).c_str());
119   return mPlanes;
120 }
121 
importFence(const NativeHandle & aidlHandle)122 sp<Fence> importFence(const NativeHandle& aidlHandle) {
123   if (aidlHandle.fds.size() != 1) {
124     return sp<Fence>::make();
125   }
126 
127   return sp<Fence>::make(::dup(aidlHandle.fds[0].get()));
128 }
129 
isPixelFormatSupportedForInput(const Format format)130 bool isPixelFormatSupportedForInput(const Format format) {
131   return std::find(kSupportedFormats.begin(), kSupportedFormats.end(),
132                    format) != kSupportedFormats.end();
133 }
134 
135 // Returns true if specified format is supported for virtual camera input.
isFormatSupportedForInput(const int width,const int height,const Format format,const int maxFps)136 bool isFormatSupportedForInput(const int width, const int height,
137                                const Format format, const int maxFps) {
138   if (!isPixelFormatSupportedForInput(format)) {
139     return false;
140   }
141 
142   int maxTextureSize = getMaximumTextureSize();
143   if (width <= 0 || height <= 0 || width > maxTextureSize ||
144       height > maxTextureSize) {
145     return false;
146   }
147 
148   if (maxFps <= 0 || maxFps > kMaxFpsUpperLimit) {
149     return false;
150   }
151 
152   return true;
153 }
154 
operator <<(std::ostream & os,const Resolution & resolution)155 std::ostream& operator<<(std::ostream& os, const Resolution& resolution) {
156   return os << resolution.width << "x" << resolution.height;
157 }
158 
159 }  // namespace virtualcamera
160 }  // namespace companion
161 }  // namespace android
162