• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 ? 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 }
100 
~PlanesLockGuard()101 PlanesLockGuard::~PlanesLockGuard() {
102   if (getStatus() != OK || mHwBuffer == nullptr) {
103     return;
104   }
105   AHardwareBuffer_unlock(mHwBuffer.get(), /*fence=*/nullptr);
106 }
107 
getStatus() const108 int PlanesLockGuard::getStatus() const {
109   return mLockStatus;
110 }
111 
operator *() const112 const AHardwareBuffer_Planes& PlanesLockGuard::operator*() const {
113   LOG_ALWAYS_FATAL_IF(getStatus() != OK,
114                       "Dereferencing unlocked PlanesLockGuard, status is %s",
115                       statusToString(mLockStatus).c_str());
116   return mPlanes;
117 }
118 
importFence(const NativeHandle & aidlHandle)119 sp<Fence> importFence(const NativeHandle& aidlHandle) {
120   if (aidlHandle.fds.size() != 1) {
121     return sp<Fence>::make();
122   }
123 
124   return sp<Fence>::make(::dup(aidlHandle.fds[0].get()));
125 }
126 
isPixelFormatSupportedForInput(const Format format)127 bool isPixelFormatSupportedForInput(const Format format) {
128   return std::find(kSupportedFormats.begin(), kSupportedFormats.end(),
129                    format) != kSupportedFormats.end();
130 }
131 
132 // Returns true if specified format is supported for virtual camera input.
isFormatSupportedForInput(const int width,const int height,const Format format,const int maxFps)133 bool isFormatSupportedForInput(const int width, const int height,
134                                const Format format, const int maxFps) {
135   if (!isPixelFormatSupportedForInput(format)) {
136     return false;
137   }
138 
139   int maxTextureSize = getMaximumTextureSize();
140   if (width <= 0 || height <= 0 || width > maxTextureSize ||
141       height > maxTextureSize) {
142     return false;
143   }
144 
145   if (maxFps <= 0 || maxFps > kMaxFpsUpperLimit) {
146     return false;
147   }
148 
149   return true;
150 }
151 
operator <<(std::ostream & os,const Resolution & resolution)152 std::ostream& operator<<(std::ostream& os, const Resolution& resolution) {
153   return os << resolution.width << "x" << resolution.height;
154 }
155 
156 }  // namespace virtualcamera
157 }  // namespace companion
158 }  // namespace android
159