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