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 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 <getopt.h>
17 #include <iostream>
18 #include <map>
19 #include "command_parser.h"
20
21 namespace OHOS::VDI::HEIF {
22 using namespace std;
23
24 enum ShortOption {
25 OPT_UNKONWN = 0,
26 OPT_HELP,
27 OPT_PRIMARY_IMG,
28 OPT_AUXILIARY_IMG,
29 OPT_THUMBNAIL_IMG,
30 OPT_GAIN_MAP,
31 OPT_EXIF_DATA,
32 OPT_USER_DATA,
33 OPT_ICC_PROFILE,
34 OPT_IT35,
35 OPT_MIRROR,
36 OPT_ROTATE,
37 OPT_OUTPUT = 'o',
38 OPT_INPUT_PATH = 'i',
39 OPT_SAMPLE_SIZE,
40 OPT_PIXEL_FMT,
41 OPT_IS_ENCODER,
42 OPT_IS_LIMITED_RANGE,
43 OPT_COLORSPACE
44 };
45
46 static struct option g_longOptions[] = {
47 {"help", no_argument, nullptr, static_cast<int>(ShortOption::OPT_HELP)},
48 {"primaryImg", required_argument, nullptr, static_cast<int>(ShortOption::OPT_PRIMARY_IMG)},
49 {"auxiliaryImg", required_argument, nullptr, static_cast<int>(ShortOption::OPT_AUXILIARY_IMG)},
50 {"thumbnailImg", required_argument, nullptr, static_cast<int>(ShortOption::OPT_THUMBNAIL_IMG)},
51 {"gainMap", required_argument, nullptr, static_cast<int>(ShortOption::OPT_GAIN_MAP)},
52 {"exifData", required_argument, nullptr, static_cast<int>(ShortOption::OPT_EXIF_DATA)},
53 {"userData", required_argument, nullptr, static_cast<int>(ShortOption::OPT_USER_DATA)},
54 {"iccProfile", required_argument, nullptr, static_cast<int>(ShortOption::OPT_ICC_PROFILE)},
55 {"it35", required_argument, nullptr, static_cast<int>(ShortOption::OPT_IT35)},
56 {"mirror", required_argument, nullptr, static_cast<int>(ShortOption::OPT_MIRROR)},
57 {"rotate", required_argument, nullptr, static_cast<int>(ShortOption::OPT_ROTATE)},
58 {"out", required_argument, nullptr, static_cast<int>(ShortOption::OPT_OUTPUT)},
59 {"inputPath", required_argument, nullptr, static_cast<int>(ShortOption::OPT_INPUT_PATH)},
60 {"sampleSize", required_argument, nullptr, static_cast<int>(ShortOption::OPT_SAMPLE_SIZE)},
61 {"pixelFmt", required_argument, nullptr, static_cast<int>(ShortOption::OPT_PIXEL_FMT)},
62 {"isEncoder", required_argument, nullptr, static_cast<int>(ShortOption::OPT_IS_ENCODER)},
63 {"isLimitedRange", required_argument, nullptr, static_cast<int>(ShortOption::OPT_IS_LIMITED_RANGE)},
64 {"colorSpace", required_argument, nullptr, static_cast<int>(ShortOption::OPT_COLORSPACE)},
65 {nullptr, no_argument, nullptr, static_cast<int>(ShortOption::OPT_UNKONWN)},
66 };
67
ShowUsage()68 void ShowUsage()
69 {
70 std::string rotateValueOpt = "0: ANTI_CLOCKWISE_90, 1: ANTI_CLOCKWISE_180, 2: ANTI_CLOCKWISE_270";
71 std::string pixelFmtValueOpt = "0:NV12(default), 1:NV21, 2:NV12_10BIT, 3:NV21_10BIT, " \
72 "4:RGBA8888, 5:BGRA8888, 6:RGB565, 7:RGBA1010102";
73 std::string colorSpaceOpt = "0: BT_601_P(default), 1: BT_601_N, 2: P3, 3: BT_709, 4: BT_2020";
74 std::cout << " --help help info." << std::endl;
75 std::cout << " --isEncoder codec type. 0: decoder, 1: encoder" << std::endl;
76 std::cout << "Heif Hardware encode Demo Options:" << std::endl;
77 std::cout << " --primaryImg full path for primary image file." << std::endl;
78 std::cout << " --auxiliaryImg (optional) full path for auxiliary image file." << std::endl;
79 std::cout << " --thumbnailImg (optional) full path for thumbnail image file." << std::endl;
80 std::cout << " --gainMap (optional) full path for gainMap file." << std::endl;
81 std::cout << " --exifData (optional) full path for exifData file." << std::endl;
82 std::cout << " --userData (optional) full path for userData file." << std::endl;
83 std::cout << " --iccProfile (optional) full path for iccProfile file." << std::endl;
84 std::cout << " --it35 (optional) full path for it35 file." << std::endl;
85 std::cout << " --mirror (optional) image mirror info. 0: HORIZONTAL, 1: VERTICAL" << std::endl;
86 std::cout << " --rotate (optional) image rotate info. " << rotateValueOpt << std::endl;
87 std::cout << " -o, --out full path for output file." << std::endl;
88 std::cout << "Heif Hardware decode Demo Options:" << std::endl;
89 std::cout << " -i, --inputPath full path for input." << std::endl;
90 std::cout << " --sampleSize (optional) output sample size. options: 2/4/8/16" << std::endl;
91 std::cout << " --pixelFmt (optional) output pixel format. " << pixelFmtValueOpt << std::endl;
92 std::cout << " --isLimitedRange (optional) range flag. 0: full range, 1: limited range" << std::endl;
93 std::cout << " --colorSpace (optional) color space type. " << colorSpaceOpt << std::endl;
94 }
95
AnalyzeParamForEncoder(ShortOption c,CommandOpt & opt)96 static void AnalyzeParamForEncoder(ShortOption c, CommandOpt& opt)
97 {
98 switch (c) {
99 case ShortOption::OPT_PRIMARY_IMG:
100 opt.primaryImgPath = string(optarg);
101 break;
102 case ShortOption::OPT_AUXILIARY_IMG:
103 opt.auxiliaryImgPath = string(optarg);
104 break;
105 case ShortOption::OPT_THUMBNAIL_IMG:
106 opt.thumbnailImgPath = string(optarg);
107 break;
108 case ShortOption::OPT_GAIN_MAP:
109 opt.gainMapPath = string(optarg);
110 break;
111 case ShortOption::OPT_EXIF_DATA:
112 opt.exifDataPath = string(optarg);
113 break;
114 case ShortOption::OPT_USER_DATA:
115 opt.userDataPath = string(optarg);
116 break;
117 case ShortOption::OPT_ICC_PROFILE:
118 opt.iccProfilePath = string(optarg);
119 break;
120 case ShortOption::OPT_IT35:
121 opt.it35Path = string(optarg);
122 break;
123 case ShortOption::OPT_MIRROR:
124 opt.mirrorInfo = static_cast<ImageMirror>(stol(optarg));
125 break;
126 case ShortOption::OPT_ROTATE:
127 opt.rotateInfo = static_cast<ImageRotation>(stol(optarg));
128 break;
129 case ShortOption::OPT_OUTPUT:
130 opt.outputPath = string(optarg);
131 break;
132 default:
133 break;
134 }
135 }
136
AnalyzeParamForDecoder(ShortOption c,CommandOpt & opt)137 static void AnalyzeParamForDecoder(ShortOption c, CommandOpt& opt)
138 {
139 switch (c) {
140 case ShortOption::OPT_INPUT_PATH:
141 opt.inputPath = string(optarg);
142 break;
143 case ShortOption::OPT_SAMPLE_SIZE:
144 opt.sampleSize = static_cast<SampleSize>(stol(optarg));
145 break;
146 case ShortOption::OPT_PIXEL_FMT:
147 opt.pixelFmt = static_cast<UserPixelFormat>(stol(optarg));
148 break;
149 case ShortOption::OPT_IS_LIMITED_RANGE:
150 opt.isLimitedRange = (stol(optarg) != 0);
151 break;
152 case ShortOption::OPT_COLORSPACE:
153 opt.colorSpace = static_cast<ColorSpace>(stol(optarg));
154 break;
155 default:
156 break;
157 }
158 }
159
Parse(int argc,char * argv[])160 CommandOpt Parse(int argc, char *argv[])
161 {
162 CommandOpt opt;
163 int c;
164 while ((c = getopt_long(argc, argv, "o:i:", g_longOptions, nullptr)) != -1) {
165 switch (static_cast<ShortOption>(c)) {
166 case ShortOption::OPT_HELP:
167 ShowUsage();
168 opt.isGetHelpInfoOnly = true;
169 break;
170 case ShortOption::OPT_IS_ENCODER:
171 opt.isEncoder = (stol(optarg) != 0);
172 break;
173 default:
174 break;
175 }
176 if (!opt.isGetHelpInfoOnly) {
177 AnalyzeParamForEncoder(static_cast<ShortOption>(c), opt);
178 AnalyzeParamForDecoder(static_cast<ShortOption>(c), opt);
179 }
180 }
181 return opt;
182 }
183
GetMirrorPrintInfo(const ImageMirror & info)184 static string GetMirrorPrintInfo(const ImageMirror& info)
185 {
186 if (info == ImageMirror::NONE) {
187 return "ImageMirror::NONE";
188 }
189 if (info == ImageMirror::HORIZONTAL) {
190 return "ImageMirror::HORIZONTAL";
191 }
192 if (info == ImageMirror::VERTICAL) {
193 return "ImageMirror::VERTICAL";
194 }
195 return "unknown mirror info";
196 }
197
GetRotatePrintInfo(const ImageRotation & info)198 static string GetRotatePrintInfo(const ImageRotation& info)
199 {
200 if (info == ImageRotation::NONE) {
201 return "ImageRotation::NONE";
202 }
203 if (info == ImageRotation::ANTI_CLOCKWISE_90) {
204 return "ImageRotation::ANTI_CLOCKWISE_90";
205 }
206 if (info == ImageRotation::ANTI_CLOCKWISE_180) {
207 return "ImageRotation::ANTI_CLOCKWISE_180";
208 }
209 if (info == ImageRotation::ANTI_CLOCKWISE_270) {
210 return "ImageRotation::ANTI_CLOCKWISE_270";
211 }
212 return "unknown rotate info";
213 }
214
PrintEncoderParam() const215 void CommandOpt::PrintEncoderParam() const
216 {
217 std::cout << "=========================== OPT INFO ===========================" << endl;
218 std::cout << " primaryImgPath : " << primaryImgPath << endl;
219 std::cout << " auxiliaryImgPath : " << auxiliaryImgPath << endl;
220 std::cout << " thumbnailImgPath : " << thumbnailImgPath << endl;
221 std::cout << " gainMapPath : " << gainMapPath << endl;
222 std::cout << " exifDataPath : " << exifDataPath << endl;
223 std::cout << " userDataPath : " << userDataPath << endl;
224 std::cout << " iccProfilePath : " << iccProfilePath << endl;
225 std::cout << " it35Path : " << it35Path << endl;
226 std::cout << " mirrorInfo : " << GetMirrorPrintInfo(mirrorInfo) << endl;
227 std::cout << " rotateInfo : " << GetRotatePrintInfo(rotateInfo) << endl;
228 std::cout << " outputPath : " << outputPath << endl;
229 std::cout << "=================================================================" << endl;
230 }
231
GetSampleSizePrintInfo(const SampleSize & info)232 static string GetSampleSizePrintInfo(const SampleSize& info)
233 {
234 static const map<SampleSize, string> sampleSizeMap = {
235 { SampleSize::SAMPLE_SIZE_1, "1" },
236 { SampleSize::SAMPLE_SIZE_2, "2" },
237 { SampleSize::SAMPLE_SIZE_4, "4" },
238 { SampleSize::SAMPLE_SIZE_8, "8" },
239 { SampleSize::SAMPLE_SIZE_16, "16" },
240 };
241 auto iter = sampleSizeMap.find(info);
242 if (iter != sampleSizeMap.end()) {
243 return iter->second;
244 }
245 return "unknown sample size";
246 }
247
GetPixelFmtPrintInfo(const UserPixelFormat & info)248 static string GetPixelFmtPrintInfo(const UserPixelFormat& info)
249 {
250 static const map<UserPixelFormat, string> pixelFmtMap = {
251 { UserPixelFormat::NONE, "UserPixelFormat::NONE" },
252 { UserPixelFormat::NV12, "UserPixelFormat::NV12" },
253 { UserPixelFormat::NV21, "UserPixelFormat::NV21" },
254 { UserPixelFormat::NV12_10BIT, "UserPixelFormat::NV12_10BIT" },
255 { UserPixelFormat::NV21_10BIT, "UserPixelFormat::NV21_10BIT" },
256 { UserPixelFormat::RGBA8888, "UserPixelFormat::RGBA8888" },
257 { UserPixelFormat::BGRA8888, "UserPixelFormat::BRGA8888" },
258 { UserPixelFormat::RGB565, "UserPixelFormat::RGB565" },
259 { UserPixelFormat::RGBA1010102, "UserPixelFormat::RGBA1010102" },
260 };
261 auto iter = pixelFmtMap.find(info);
262 if (iter != pixelFmtMap.end()) {
263 return iter->second;
264 }
265 return "unknown pixel format";
266 }
267
GetColorSpacePrintInfo(const ColorSpace & info)268 static string GetColorSpacePrintInfo(const ColorSpace& info)
269 {
270 static const map<ColorSpace, string> colorSpaceMap = {
271 { ColorSpace::BT_601_P, "ColorSpace::BT_601_P" },
272 { ColorSpace::BT_601_N, "ColorSpace::BT_601_N" },
273 { ColorSpace::P3, "ColorSpace::P3" },
274 { ColorSpace::BT_709, "ColorSpace::BT_709" },
275 { ColorSpace::BT_2020, "ColorSpace::BT_2020" },
276 };
277 auto iter = colorSpaceMap.find(info);
278 if (iter != colorSpaceMap.end()) {
279 return iter->second;
280 }
281 return "unknown color space, use ColorSpace::BT_601_P as default";
282 }
283
PrintDecoderParam() const284 void CommandOpt::PrintDecoderParam() const
285 {
286 std::cout << "=========================== OPT INFO ===========================" << endl;
287 std::cout << " inputPath : " << inputPath << endl;
288 std::cout << " sampleSize : " << GetSampleSizePrintInfo(sampleSize) << endl;
289 std::cout << " pixelFmt : " << GetPixelFmtPrintInfo(pixelFmt) << endl;
290 std::cout << " colorSpace : " << GetColorSpacePrintInfo(colorSpace) << endl;
291 std::cout << " range : " << (isLimitedRange ? "limited range" : "full range") << endl;
292 std::cout << "=================================================================" << endl;
293 }
294
Print() const295 void CommandOpt::Print() const
296 {
297 if (isEncoder) {
298 PrintEncoderParam();
299 } else {
300 PrintDecoderParam();
301 }
302 }
303 }
304