1 /*
2 * Copyright (C) 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 <cinttypes>
17 #include "image_log.h"
18 #include "image_utils.h"
19 #include "media_errors.h"
20 #include "native_image.h"
21
22 #undef LOG_DOMAIN
23 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
24
25 #undef LOG_TAG
26 #define LOG_TAG "NativeImage"
27
28 namespace {
29 constexpr int32_t NUMI_0 = 0;
30 constexpr uint32_t NUM_0 = 0;
31 constexpr uint32_t NUM_1 = 1;
32 constexpr uint32_t NUM_2 = 2;
33 const std::string DATA_SIZE_TAG = "dataSize";
34 }
35
36 namespace OHOS {
37 namespace Media {
NativeImage(sptr<SurfaceBuffer> buffer,std::shared_ptr<IBufferProcessor> releaser)38 NativeImage::NativeImage(sptr<SurfaceBuffer> buffer,
39 std::shared_ptr<IBufferProcessor> releaser) : buffer_(buffer), releaser_(releaser), timestamp_(0)
40 {}
41
NativeImage(sptr<SurfaceBuffer> buffer,std::shared_ptr<IBufferProcessor> releaser,int64_t timestamp)42 NativeImage::NativeImage(sptr<SurfaceBuffer> buffer, std::shared_ptr<IBufferProcessor> releaser,
43 int64_t timestamp) : buffer_(buffer), releaser_(releaser), timestamp_(timestamp)
44 {}
45
46 struct YUVData {
47 std::vector<uint8_t> y;
48 std::vector<uint8_t> u;
49 std::vector<uint8_t> v;
50 uint64_t ySize;
51 uint64_t uvSize;
52 };
53
DataSwap(uint8_t * a,uint8_t * b,bool flip)54 static inline void DataSwap(uint8_t* a, uint8_t* b, bool flip)
55 {
56 if (flip) {
57 *a = *b;
58 } else {
59 *b = *a;
60 }
61 }
62
IsYUV422SPFormat(int32_t format)63 static inline bool IsYUV422SPFormat(int32_t format)
64 {
65 if (format == int32_t(ImageFormat::YCBCR_422_SP) ||
66 format == int32_t(GRAPHIC_PIXEL_FMT_YCBCR_422_SP)) {
67 return true;
68 }
69 return false;
70 }
71
YUV422SPDataCopy(uint8_t * buffer,uint64_t size,YUVData & data,bool flip)72 static void YUV422SPDataCopy(uint8_t* buffer, uint64_t size, YUVData &data, bool flip)
73 {
74 uint64_t ui = NUM_0;
75 uint64_t vi = NUM_0;
76 for (uint64_t i = NUM_0; i < size; i++) {
77 if (i < data.ySize) {
78 DataSwap(&(buffer[i]), &(data.y[i]), flip);
79 continue;
80 }
81 if (vi >= data.uvSize || ui >= data.uvSize) {
82 // Over write buffer size.
83 continue;
84 }
85 if (i % NUM_2 == NUM_1) {
86 DataSwap(&(buffer[i]), &(data.v[vi]), flip);
87 vi++;
88 } else {
89 DataSwap(&(buffer[i]), &(data.u[ui]), flip);
90 ui++;
91 }
92 }
93 }
GetSurfaceBufferAddr()94 uint8_t* NativeImage::GetSurfaceBufferAddr()
95 {
96 if (buffer_ != nullptr) {
97 return static_cast<uint8_t*>(buffer_->GetVirAddr());
98 }
99 return nullptr;
100 }
SplitYUV422SPComponent()101 int32_t NativeImage::SplitYUV422SPComponent()
102 {
103 auto rawBuffer = GetSurfaceBufferAddr();
104 if (rawBuffer == nullptr) {
105 IMAGE_LOGE("SurfaceBuffer viraddr is nullptr");
106 return ERR_MEDIA_NULL_POINTER;
107 }
108
109 uint64_t surfaceSize = NUM_0;
110 auto res = GetDataSize(surfaceSize);
111 if (res != SUCCESS || surfaceSize == NUM_0) {
112 IMAGE_LOGE("S size is 0");
113 return ERR_MEDIA_DATA_UNSUPPORT;
114 }
115
116 int32_t width = NUM_0;
117 int32_t height = NUM_0;
118 res = GetSize(width, height);
119 if (res != SUCCESS || width <= NUMI_0 || height <= NUMI_0) {
120 IMAGE_LOGE("Invaild width %{public}" PRId32 " height %{public}" PRId32, width, height);
121 return ERR_MEDIA_DATA_UNSUPPORT;
122 }
123
124 struct YUVData yuv;
125 uint64_t uvStride = static_cast<uint64_t>((width + NUM_1) / NUM_2);
126 if (ImageUtils::CheckMulOverflow(width, height)) {
127 IMAGE_LOGE("Invalid width %{public}" PRId32 " height %{public}" PRId32, width, height);
128 return ERR_MEDIA_DATA_UNSUPPORT;
129 }
130 yuv.ySize = static_cast<uint64_t>(width) * static_cast<uint64_t>(height);
131 yuv.uvSize = static_cast<uint64_t>(height) * uvStride;
132 if (surfaceSize < (yuv.ySize + yuv.uvSize * NUM_2)) {
133 IMAGE_LOGE("S size %{public}" PRIu64 " < y plane %{public}" PRIu64
134 " + uv plane %{public}" PRIu64, surfaceSize, yuv.ySize, yuv.uvSize * NUM_2);
135 return ERR_MEDIA_DATA_UNSUPPORT;
136 }
137
138 NativeComponent* y = CreateComponent(int32_t(ComponentType::YUV_Y), yuv.ySize, width, NUM_1, nullptr);
139 NativeComponent* u = CreateComponent(int32_t(ComponentType::YUV_U), yuv.uvSize, uvStride, NUM_2, nullptr);
140 NativeComponent* v = CreateComponent(int32_t(ComponentType::YUV_V), yuv.uvSize, uvStride, NUM_2, nullptr);
141 if ((y == nullptr) || (u == nullptr) || (v == nullptr)) {
142 IMAGE_LOGE("Create Component failed");
143 return ERR_MEDIA_DATA_UNSUPPORT;
144 }
145 yuv.y = y->raw;
146 yuv.u = u->raw;
147 yuv.v = v->raw;
148 YUV422SPDataCopy(rawBuffer, surfaceSize, yuv, false);
149 return SUCCESS;
150 }
151
SplitSurfaceToComponent()152 int32_t NativeImage::SplitSurfaceToComponent()
153 {
154 int32_t format = NUM_0;
155 auto res = GetFormat(format);
156 if (res != SUCCESS) {
157 return res;
158 }
159 switch (format) {
160 case int32_t(ImageFormat::YCBCR_422_SP):
161 case int32_t(GRAPHIC_PIXEL_FMT_YCBCR_422_SP):
162 return SplitYUV422SPComponent();
163 case int32_t(ImageFormat::JPEG):
164 bool cond = CreateCombineComponent(int32_t(ComponentType::JPEG)) != nullptr;
165 CHECK_ERROR_RETURN_RET(cond, SUCCESS);
166 }
167 // Unsupport split component
168 return ERR_MEDIA_DATA_UNSUPPORT;
169 }
170
CombineYUVComponents()171 int32_t NativeImage::CombineYUVComponents()
172 {
173 int32_t format = NUM_0;
174 auto res = GetFormat(format);
175 if (res != SUCCESS) {
176 return res;
177 }
178 if (!IsYUV422SPFormat(format)) {
179 IMAGE_LOGI("No need to combine components for NO YUV format now");
180 return SUCCESS;
181 }
182
183 auto y = GetComponent(int32_t(ComponentType::YUV_Y));
184 auto u = GetComponent(int32_t(ComponentType::YUV_U));
185 auto v = GetComponent(int32_t(ComponentType::YUV_V));
186 bool cond = (y == nullptr) || (u == nullptr) || (v == nullptr);
187 CHECK_ERROR_RETURN_RET_LOG(cond, ERR_MEDIA_DATA_UNSUPPORT, "No component need to combine");
188 YUVData data;
189 data.ySize = y->raw.size();
190 data.uvSize = u->raw.size();
191 data.y = y->raw;
192 data.u = u->raw;
193 data.v = v->raw;
194
195 uint64_t bufferSize = NUM_0;
196 GetDataSize(bufferSize);
197
198 YUV422SPDataCopy(GetSurfaceBufferAddr(), bufferSize, data, true);
199 return SUCCESS;
200 }
201
BuildComponent(size_t size,int32_t row,int32_t pixel,uint8_t * vir)202 static std::unique_ptr<NativeComponent> BuildComponent(size_t size, int32_t row, int32_t pixel, uint8_t* vir)
203 {
204 if (size == NUM_0 && vir == nullptr) {
205 IMAGE_LOGE("Could't create 0 size component data");
206 return nullptr;
207 }
208 std::unique_ptr<NativeComponent> component = std::make_unique<NativeComponent>();
209 component->pixelStride = pixel;
210 component->rowStride = row;
211 component->size = size;
212 if (vir != nullptr) {
213 component->virAddr = vir;
214 } else {
215 component->raw.resize(size);
216 }
217 return component;
218 }
219
GetCachedComponent(int32_t type)220 NativeComponent* NativeImage::GetCachedComponent(int32_t type)
221 {
222 auto iter = components_.find(type);
223 if (iter != components_.end()) {
224 return iter->second.get();
225 }
226 return nullptr;
227 }
228
CreateComponent(int32_t type,size_t size,int32_t row,int32_t pixel,uint8_t * vir)229 NativeComponent* NativeImage::CreateComponent(int32_t type, size_t size, int32_t row,
230 int32_t pixel, uint8_t* vir)
231 {
232 NativeComponent* res = GetCachedComponent(type);
233 if (res != nullptr) {
234 IMAGE_LOGD("Component %{public}d already exist. No need create", type);
235 return res;
236 }
237
238 std::unique_ptr<NativeComponent> component = BuildComponent(size, row, pixel, vir);
239 if (component == nullptr) {
240 return nullptr;
241 }
242 components_.insert(std::map<int32_t, std::unique_ptr<NativeComponent>>::value_type(type,
243 std::move(component)));
244
245 return GetCachedComponent(type);
246 }
247
CreateCombineComponent(int32_t type)248 NativeComponent* NativeImage::CreateCombineComponent(int32_t type)
249 {
250 uint64_t size = NUM_0;
251 GetDataSize(size);
252 return CreateComponent(type, static_cast<size_t>(size), buffer_->GetStride(), NUM_1, GetSurfaceBufferAddr());
253 }
GetSize(int32_t & width,int32_t & height)254 int32_t NativeImage::GetSize(int32_t &width, int32_t &height)
255 {
256 if (buffer_ == nullptr) {
257 return ERR_MEDIA_DEAD_OBJECT;
258 }
259 width = buffer_->GetWidth();
260 height = buffer_->GetHeight();
261 return SUCCESS;
262 }
263
GetDataSize(uint64_t & size)264 int32_t NativeImage::GetDataSize(uint64_t &size)
265 {
266 if (buffer_ == nullptr) {
267 return ERR_MEDIA_DEAD_OBJECT;
268 }
269
270 size = static_cast<uint64_t>(buffer_->GetSize());
271 auto extraData = buffer_->GetExtraData();
272 if (extraData == nullptr) {
273 IMAGE_LOGI("Nullptr s extra data. return buffer size %{public}" PRIu64, size);
274 return SUCCESS;
275 }
276
277 int32_t extraDataSize = NUMI_0;
278 auto res = extraData->ExtraGet(DATA_SIZE_TAG, extraDataSize);
279 if (res != NUM_0) {
280 IMAGE_LOGI("S ExtraGet dataSize error %{public}d", res);
281 } else if (extraDataSize <= NUMI_0) {
282 IMAGE_LOGI("S ExtraGet dataSize Ok, but size <= 0");
283 } else if (static_cast<uint64_t>(extraDataSize) > size) {
284 IMAGE_LOGI("S ExtraGet dataSize Ok,but dataSize %{public}d is bigger than bufferSize %{public}" PRIu64,
285 extraDataSize, size);
286 } else {
287 IMAGE_LOGD("S ExtraGet dataSize %{public}d", extraDataSize);
288 size = extraDataSize;
289 }
290 return SUCCESS;
291 }
292
GetFormat(int32_t & format)293 int32_t NativeImage::GetFormat(int32_t &format)
294 {
295 if (buffer_ == nullptr) {
296 return ERR_MEDIA_DEAD_OBJECT;
297 }
298 format = buffer_->GetFormat();
299 return SUCCESS;
300 }
301
GetTimestamp(int64_t & timestamp)302 int32_t NativeImage::GetTimestamp(int64_t ×tamp)
303 {
304 if (buffer_ == nullptr) {
305 return ERR_MEDIA_DEAD_OBJECT;
306 }
307 timestamp = timestamp_;
308 return SUCCESS;
309 }
310
GetComponent(int32_t type)311 NativeComponent* NativeImage::GetComponent(int32_t type)
312 {
313 if (buffer_ == nullptr) {
314 return nullptr;
315 }
316
317 // Find type if it has exist.
318 auto component = GetCachedComponent(type);
319 if (component != nullptr) {
320 return component;
321 }
322
323 int32_t format = NUM_0;
324 if (GetFormat(format) == SUCCESS && type == format) {
325 return CreateCombineComponent(type);
326 }
327 SplitSurfaceToComponent();
328 // Try again
329 component = GetCachedComponent(type);
330
331 #ifdef COMPONENT_STRICT_CHECK
332 return component;
333 #else // We don't check the input type anymore, return raw format component!!
334 if (component == nullptr && GetFormat(format) == SUCCESS) {
335 return CreateCombineComponent(format);
336 }
337 return nullptr;
338 #endif
339 }
340
release()341 void NativeImage::release()
342 {
343 if (buffer_ == nullptr) {
344 return;
345 }
346 IMAGE_LOGD("NativeImage release");
347 if (components_.size() > 0) {
348 components_.clear();
349 }
350 if (releaser_ != nullptr && buffer_ != nullptr) {
351 releaser_->BufferRelease(buffer_);
352 }
353 releaser_ = nullptr;
354 buffer_ = nullptr;
355 }
356 } // namespace Media
357 } // namespace OHOS
358