• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 "format_helper.h"
17 
18 #include "effect_log.h"
19 
20 namespace {
21     const float YUV_BYTES_PER_PIXEL = 1.5f;
22     const int32_t RGBA_BYTES_PER_PIXEL = 4;
23     const int32_t P10_BYTES_PER_LUMA = 2;
24     const int32_t R = 0;
25     const int32_t G = 1;
26     const int32_t B = 2;
27     const int32_t A = 3;
28     const int32_t UV_SPLIT_FACTOR = 2;
29 }
30 
31 namespace OHOS {
32 namespace Media {
33 namespace Effect {
34 
35 void ConvertRGBAToNV12(FormatConverterInfo &src, FormatConverterInfo &dst);
36 void ConvertRGBAToNV21(FormatConverterInfo &src, FormatConverterInfo &dst);
37 void ConvertNV12ToRGBA(FormatConverterInfo &src, FormatConverterInfo &dst);
38 void ConvertNV21ToRGBA(FormatConverterInfo &src, FormatConverterInfo &dst);
39 
40 using FormatConverterFunc = std::function<void(FormatConverterInfo &src, FormatConverterInfo &dst)>;
41 
42 struct FormatConverter {
43     IEffectFormat srcFormat;
44     IEffectFormat dstFormat;
45     FormatConverterFunc converterFunc;
46 };
47 
48 static const std::vector<FormatConverter> FORMAT_CONVERTER = {
49     FormatConverter{ IEffectFormat::RGBA8888, IEffectFormat::YUVNV12, ConvertRGBAToNV12 },
50     FormatConverter{ IEffectFormat::RGBA8888, IEffectFormat::YUVNV21, ConvertRGBAToNV21 },
51     FormatConverter{ IEffectFormat::YUVNV12, IEffectFormat::RGBA8888, ConvertNV12ToRGBA },
52     FormatConverter{ IEffectFormat::YUVNV21, IEffectFormat::RGBA8888, ConvertNV21ToRGBA },
53 };
54 
55 static const std::unordered_set<IEffectFormat> SUPPORTED_FORMATS = {
56     IEffectFormat::RGBA8888,
57     IEffectFormat::YUVNV12,
58     IEffectFormat::YUVNV21,
59     IEffectFormat::RGBA_1010102,
60     IEffectFormat::YCRCB_P010,
61     IEffectFormat::YCBCR_P010,
62 };
63 
CalculateDataRowCount(uint32_t height,IEffectFormat format)64 uint32_t FormatHelper::CalculateDataRowCount(uint32_t height, IEffectFormat format)
65 {
66     switch (format) {
67         case IEffectFormat::RGBA8888:
68         case IEffectFormat::RGBA_1010102:
69             return height;
70         case IEffectFormat::YUVNV12:
71         case IEffectFormat::YUVNV21:
72         case IEffectFormat::YCBCR_P010:
73         case IEffectFormat::YCRCB_P010:
74             return static_cast<uint32_t>(height * YUV_BYTES_PER_PIXEL);
75         default:
76             return height;
77     }
78 }
79 
CalculateRowStride(uint32_t width,IEffectFormat format)80 uint32_t FormatHelper::CalculateRowStride(uint32_t width, IEffectFormat format)
81 {
82     switch (format) {
83         case IEffectFormat::RGBA8888:
84         case IEffectFormat::RGBA_1010102:
85             return width * RGBA_BYTES_PER_PIXEL;
86         case IEffectFormat::YUVNV12:
87         case IEffectFormat::YUVNV21:
88             return width;
89         case IEffectFormat::YCRCB_P010:
90         case IEffectFormat::YCBCR_P010:
91             return width * P10_BYTES_PER_LUMA;
92         default:
93             return width;
94     }
95 }
96 
CalculateSize(uint32_t width,uint32_t height,IEffectFormat format)97 uint32_t FormatHelper::CalculateSize(uint32_t width, uint32_t height, IEffectFormat format)
98 {
99     return CalculateDataRowCount(height, format) * CalculateRowStride(width, format);
100 }
101 
GetAllSupportedFormats()102 std::unordered_set<IEffectFormat> FormatHelper::GetAllSupportedFormats()
103 {
104     return SUPPORTED_FORMATS;
105 }
106 
IsSupportConvert(IEffectFormat srcFormat,IEffectFormat dstFormat)107 bool FormatHelper::IsSupportConvert(IEffectFormat srcFormat, IEffectFormat dstFormat)
108 {
109     return std::any_of(FORMAT_CONVERTER.begin(), FORMAT_CONVERTER.end(), [=](const FormatConverter &converter) {
110         return converter.srcFormat == srcFormat && converter.dstFormat == dstFormat;
111     });
112 }
113 
GetFormatConverterFunc(IEffectFormat srcFormat,IEffectFormat dstFormat)114 FormatConverterFunc GetFormatConverterFunc(IEffectFormat srcFormat, IEffectFormat dstFormat)
115 {
116     for (const auto &converter : FORMAT_CONVERTER) {
117         if (converter.srcFormat == srcFormat && converter.dstFormat == dstFormat) {
118             return converter.converterFunc;
119         }
120     }
121 
122     return nullptr;
123 }
124 
CheckConverterInfo(FormatConverterInfo & src,FormatConverterInfo & dst)125 ErrorCode CheckConverterInfo(FormatConverterInfo &src, FormatConverterInfo &dst)
126 {
127     CHECK_AND_RETURN_RET_LOG(src.buffer != nullptr && dst.buffer != nullptr, ErrorCode::ERR_PARAM_INVALID,
128         "CheckConverterInfo: invalid buffer!");
129 
130     BufferInfo &srcBuffInfo = src.bufferInfo;
131     BufferInfo &dstBuffInfo = dst.bufferInfo;
132     if (srcBuffInfo.width_ != dstBuffInfo.width_ || srcBuffInfo.height_ != dstBuffInfo.height_) {
133         EFFECT_LOGW("CheckConverterInfo: diff size! srcW=%{public}d, srcH=%{public}d, dstW=%{public}d, dstH=%{public}d",
134             srcBuffInfo.width_, srcBuffInfo.height_, dstBuffInfo.width_, dstBuffInfo.height_);
135     }
136 
137     EFFECT_LOGD("CheckConverterInfo: src{w=%{public}d h=%{public}d format=%{public}d len=%{public}d stride=%{public}d},"
138         " dts={w=%{public}d h=%{public}d format=%{public}d len=%{public}d stride=%{public}d}",
139         srcBuffInfo.width_, srcBuffInfo.height_, srcBuffInfo.formatType_, srcBuffInfo.len_, srcBuffInfo.rowStride_,
140         dstBuffInfo.width_, dstBuffInfo.height_, dstBuffInfo.formatType_, dstBuffInfo.len_, dstBuffInfo.rowStride_);
141 
142     uint32_t minSrcRowStride = FormatHelper::CalculateRowStride(srcBuffInfo.width_, srcBuffInfo.formatType_);
143     uint32_t minDstRowStride = FormatHelper::CalculateRowStride(dstBuffInfo.width_, dstBuffInfo.formatType_);
144     uint32_t minSrcLen = FormatHelper::CalculateSize(srcBuffInfo.width_, srcBuffInfo.height_, srcBuffInfo.formatType_);
145     uint32_t minDstLen = FormatHelper::CalculateSize(dstBuffInfo.width_, dstBuffInfo.height_, dstBuffInfo.formatType_);
146     CHECK_AND_RETURN_RET_LOG(minSrcRowStride <= srcBuffInfo.rowStride_ && minDstRowStride <= dstBuffInfo.rowStride_ &&
147         minSrcLen <= srcBuffInfo.len_ && minDstLen <= dstBuffInfo.len_, ErrorCode::ERR_PARAM_INVALID,
148         "CheckConverterInfo: invalid size! src{%{public}d %{public}d %{public}d %{public}d %{public}d}, "
149         "dst{%{public}d %{public}d %{public}d %{public}d %{public}d}",
150         srcBuffInfo.width_, srcBuffInfo.height_, srcBuffInfo.formatType_, srcBuffInfo.len_, srcBuffInfo.rowStride_,
151         dstBuffInfo.width_, dstBuffInfo.height_, dstBuffInfo.formatType_, dstBuffInfo.len_, dstBuffInfo.rowStride_);
152 
153     return ErrorCode::SUCCESS;
154 }
155 
ConvertFormat(FormatConverterInfo & src,FormatConverterInfo & dst)156 ErrorCode FormatHelper::ConvertFormat(FormatConverterInfo &src, FormatConverterInfo &dst)
157 {
158     IEffectFormat srcFormat = src.bufferInfo.formatType_;
159     IEffectFormat dstFormat = dst.bufferInfo.formatType_;
160 
161     auto func = GetFormatConverterFunc(srcFormat, dstFormat);
162     CHECK_AND_RETURN_RET_LOG(func != nullptr, ErrorCode::ERR_NOT_SUPPORT_CONVERT_FORMAT,
163         "ConvertFormat: format not support convert! srcFormat=%{public}d, dstFormat=%{public}d", srcFormat, dstFormat);
164 
165     ErrorCode res = CheckConverterInfo(src, dst);
166     CHECK_AND_RETURN_RET_LOG(res == ErrorCode::SUCCESS, res, "ConvertFormat: invalid para! res=%{public}d", res);
167 
168     func(src, dst);
169     return ErrorCode::SUCCESS;
170 }
171 
ConvertRGBAToNV12(FormatConverterInfo & src,FormatConverterInfo & dst)172 void ConvertRGBAToNV12(FormatConverterInfo &src, FormatConverterInfo &dst)
173 {
174     EFFECT_LOGW("ConvertRGBAToNV12: ConvertRGBAToNV12 will loss alpha information!");
175     BufferInfo &srcBuffInfo = src.bufferInfo;
176     BufferInfo &dstBuffInfo = dst.bufferInfo;
177     uint32_t width = std::min(srcBuffInfo.width_, dstBuffInfo.width_);
178     uint32_t height = std::min(srcBuffInfo.height_, dstBuffInfo.height_);
179     uint32_t srcRowStride = srcBuffInfo.rowStride_;
180     uint32_t dstRowStride = dstBuffInfo.rowStride_;
181 
182     uint8_t *srcRGBA = static_cast<uint8_t *>(src.buffer);
183     uint8_t *dstNV12 = static_cast<uint8_t *>(dst.buffer);
184     uint8_t *dstNV12UV = dstNV12 + dstBuffInfo.height_ * dstRowStride;
185 
186 #pragma omp parallel for default(none) shared(height, width, srcRGBA, dstNV12, dstNV12UV, srcRowStride, dstRowStride)
187     for (uint32_t i = 0; i < height; i++) {
188         for (uint32_t j = 0; j < width; j++) {
189             uint32_t y_index = i * dstRowStride + j;
190             uint32_t nv_index = i / UV_SPLIT_FACTOR * dstRowStride + j - j % UV_SPLIT_FACTOR;
191             uint32_t srcIndex = i * srcRowStride + j * RGBA_BYTES_PER_PIXEL;
192             uint8_t r = srcRGBA[srcIndex + R];
193             uint8_t g = srcRGBA[srcIndex + G];
194             uint8_t b = srcRGBA[srcIndex + B];
195 
196             dstNV12[y_index] = FormatHelper::RGBToY(r, g, b);
197             dstNV12UV[nv_index] = FormatHelper::RGBToU(r, g, b);
198             dstNV12UV[nv_index + 1] = FormatHelper::RGBToV(r, g, b);
199         }
200     }
201 }
202 
ConvertRGBAToNV21(FormatConverterInfo & src,FormatConverterInfo & dst)203 void ConvertRGBAToNV21(FormatConverterInfo &src, FormatConverterInfo &dst)
204 {
205     EFFECT_LOGW("ConvertRGBAToNV21: ConvertRGBAToNV21 will loss alpha information!");
206     BufferInfo &srcBuffInfo = src.bufferInfo;
207     BufferInfo &dstBuffInfo = dst.bufferInfo;
208     uint32_t width = std::min(srcBuffInfo.width_, dstBuffInfo.width_);
209     uint32_t height = std::min(srcBuffInfo.height_, dstBuffInfo.height_);
210     uint32_t srcRowStride = srcBuffInfo.rowStride_;
211     uint32_t dstRowStride = dstBuffInfo.rowStride_;
212 
213     uint8_t *srcRGBA = static_cast<uint8_t *>(src.buffer);
214     uint8_t *dstNV21 = static_cast<uint8_t *>(dst.buffer);
215     uint8_t *dstNV21UV = dstNV21 + dstBuffInfo.height_ * dstRowStride;
216 
217 #pragma omp parallel for default(none) shared(height, width, srcRGBA, dstNV12, dstNV12UV, srcRowStride, dstRowStride)
218     for (uint32_t i = 0; i < height; i++) {
219         for (uint32_t j = 0; j < width; j++) {
220             uint32_t y_index = i * dstRowStride + j;
221             uint32_t nv_index = i / UV_SPLIT_FACTOR * dstRowStride + j - j % UV_SPLIT_FACTOR;
222             uint32_t srcIndex = i * srcRowStride + j * RGBA_BYTES_PER_PIXEL;
223             uint8_t r = srcRGBA[srcIndex + R];
224             uint8_t g = srcRGBA[srcIndex + G];
225             uint8_t b = srcRGBA[srcIndex + B];
226 
227             dstNV21[y_index] = FormatHelper::RGBToY(r, g, b);
228             dstNV21UV[nv_index] = FormatHelper::RGBToV(r, g, b);
229             dstNV21UV[nv_index + 1] = FormatHelper::RGBToU(r, g, b);
230         }
231     }
232 }
233 
ConvertNV12ToRGBA(FormatConverterInfo & src,FormatConverterInfo & dst)234 void ConvertNV12ToRGBA(FormatConverterInfo &src, FormatConverterInfo &dst)
235 {
236     BufferInfo &srcBuffInfo = src.bufferInfo;
237     BufferInfo &dstBuffInfo = dst.bufferInfo;
238     uint32_t width = std::min(srcBuffInfo.width_, dstBuffInfo.width_);
239     uint32_t height = std::min(srcBuffInfo.height_, dstBuffInfo.height_);
240     uint32_t srcRowStride = srcBuffInfo.rowStride_;
241     uint32_t dstRowStride = dstBuffInfo.rowStride_;
242 
243     uint8_t *srcNV12 = static_cast<uint8_t *>(src.buffer);
244     uint8_t *srcNV12UV = srcNV12 + srcBuffInfo.height_ * srcRowStride;
245     uint8_t *dstRGBA = static_cast<uint8_t *>(dst.buffer);
246 
247 #pragma omp parallel for default(none) shared(height, width, srcNV12, srcNV12UV, dstRGBA, srcRowStride, dstRowStride)
248     for (uint32_t i = 0; i < height; i++) {
249         for (uint32_t j = 0; j < width; j++) {
250             uint32_t y_index = i * srcRowStride + j;
251             uint32_t nv_index = i / UV_SPLIT_FACTOR * srcRowStride + j - j % UV_SPLIT_FACTOR;
252             uint32_t dstIndex = i * dstRowStride + j *RGBA_BYTES_PER_PIXEL;
253             uint8_t y = srcNV12[y_index];
254             uint8_t u = srcNV12UV[nv_index];
255             uint8_t v = srcNV12UV[nv_index + 1];
256 
257             dstRGBA[dstIndex + R] = FormatHelper::YuvToR(y, u, v);
258             dstRGBA[dstIndex + G] = FormatHelper::YuvToG(y, u, v);
259             dstRGBA[dstIndex + B] = FormatHelper::YuvToB(y, u, v);
260             dstRGBA[dstIndex + A] = UNSIGHED_CHAR_MAX;
261         }
262     }
263 }
264 
ConvertNV21ToRGBA(FormatConverterInfo & src,FormatConverterInfo & dst)265 void ConvertNV21ToRGBA(FormatConverterInfo &src, FormatConverterInfo &dst)
266 {
267     BufferInfo &srcBuffInfo = src.bufferInfo;
268     BufferInfo &dstBuffInfo = dst.bufferInfo;
269     uint32_t width = std::min(srcBuffInfo.width_, dstBuffInfo.width_);
270     uint32_t height = std::min(srcBuffInfo.height_, dstBuffInfo.height_);
271     uint32_t srcRowStride = srcBuffInfo.rowStride_;
272     uint32_t dstRowStride = dstBuffInfo.rowStride_;
273 
274     CHECK_AND_RETURN_LOG(src.buffer != nullptr && dst.buffer != nullptr,
275         "ConvertNV21ToRGBA: src buffer or dst buffer is null!");
276     uint8_t *srcNV21 = static_cast<uint8_t *>(src.buffer);
277     uint8_t *srcNV21UV = srcNV21 + srcBuffInfo.height_ * srcRowStride;
278     uint8_t *dstRGBA = static_cast<uint8_t *>(dst.buffer);
279 
280 #pragma omp parallel for default(none) shared(height, width, srcNV21, srcNV21UV, dstRGBA, srcRowStride, dstRowStride)
281     for (uint32_t i = 0; i < height; i++) {
282         for (uint32_t j = 0; j < width; j++) {
283             uint32_t y_index = i * srcRowStride + j;
284             uint32_t nv_index = i / UV_SPLIT_FACTOR * srcRowStride + j - j % UV_SPLIT_FACTOR;
285             uint32_t dstIndex = i * dstRowStride + j *RGBA_BYTES_PER_PIXEL;
286             uint8_t y = srcNV21[y_index];
287             uint8_t v = srcNV21UV[nv_index];
288             uint8_t u = srcNV21UV[nv_index + 1];
289 
290             dstRGBA[dstIndex + R] = FormatHelper::YuvToR(y, u, v);
291             dstRGBA[dstIndex + G] = FormatHelper::YuvToG(y, u, v);
292             dstRGBA[dstIndex + B] = FormatHelper::YuvToB(y, u, v);
293             dstRGBA[dstIndex + A] = UNSIGHED_CHAR_MAX;
294         }
295     }
296 }
297 } // namespace Effect
298 } // namespace Media
299 } // namespace OHOS