1 /*
2 * Copyright (C) 2014 Intel Corporation. All rights reserved.
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 <expat.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <utils/Log.h>
21 #include "isv_profile.h"
22
23 #undef LOG_TAG
24 #define LOG_TAG "ISVProfile"
25
26 #define QCIF_AREA (176 * 144)
27
28 #define DEFAULT_XML_FILE "/etc/video_isv_profile.xml"
29
30 using namespace android;
31 static const char StatusOn[][5] = {"1frc", "1vpp"};
32
ISVProfile(const uint32_t width,const uint32_t height)33 ISVProfile::ISVProfile(const uint32_t width, const uint32_t height)
34 {
35 int i;
36
37 mWidth = width;
38 mHeight = height;
39
40 mCurrentFilter = 0;
41 mCurrentFrcTab = 0;
42 mDefaultVPPStatus = 0;
43 mDefaultFRCStatus = 0;
44
45 mStatus = 0;
46
47 memset(mConfigs, 0, sizeof(ISVConfig) * ProcFilterCount);
48
49 for (i = 0; i < MAX_TAB_SIZE; i++) {
50 mFrcRates[i].input_fps = 0;
51 mFrcRates[i].rate = FRC_RATE_1X;
52 }
53
54 /* get the vpp global setting */
55 //getGlobalStatus();
56
57 /* load the config data from XML file */
58 getDataFromXmlFile();
59
60 /* update the filter status according to the configs */
61 updateFilterStatus();
62
63 /* dump data for debug */
64 dumpConfigData();
65 }
66
~ISVProfile()67 ISVProfile::~ISVProfile()
68 {
69 }
70
getFRCRate(uint32_t inputFps)71 FRC_RATE ISVProfile::getFRCRate(uint32_t inputFps)
72 {
73 FRC_RATE rate = FRC_RATE_1X;
74 int i;
75
76 for (i = 0; i < MAX_TAB_SIZE; i++) {
77 if (mFrcRates[i].input_fps == inputFps) {
78 rate = mFrcRates[i].rate;
79 break;
80 }
81 }
82 return rate;
83 }
84
getFilterStatus()85 uint32_t ISVProfile::getFilterStatus()
86 {
87 return mStatus;
88 }
89
isVPPOn()90 bool ISVProfile::isVPPOn()
91 {
92 int32_t status = getGlobalStatus();
93 return (status != -1) ? (((status & VPP_COMMON_ON) != 0) ? true : false) : false;
94 }
95
isFRCOn()96 bool ISVProfile::isFRCOn()
97 {
98 int32_t status = getGlobalStatus();
99 return (status != -1) ? (((status & VPP_FRC_ON) != 0) ? true : false) : false;
100 }
101
updateFilterStatus()102 void ISVProfile::updateFilterStatus() {
103 int i;
104 uint32_t area = mWidth * mHeight;
105
106 for (i = 1; i < ProcFilterCount; i++) {
107 /* check config */
108 if (mConfigs[i].enabled == false)
109 continue;
110
111 if (area > mConfigs[i].minResolution && area <= mConfigs[i].maxResolution)
112 mStatus |= 1 << i;
113 /* we should cover QCIF */
114 else if (area == mConfigs[i].minResolution && area == QCIF_AREA)
115 mStatus |= 1 << i;
116 }
117 }
118
getFilterID(const char * name)119 int ISVProfile::getFilterID(const char * name)
120 {
121 int index = 0;
122
123 if (strcmp(name, "ProcFilterNoiseReduction") == 0)
124 index = ProcFilterNoiseReduction;
125 else if (strcmp(name, "ProcFilterDeinterlacing") == 0)
126 index = ProcFilterDeinterlacing;
127 else if (strcmp(name, "ProcFilterSharpening") == 0)
128 index = ProcFilterSharpening;
129 else if (strcmp(name, "ProcFilterColorBalance") == 0)
130 index = ProcFilterColorBalance;
131 else if (strcmp(name, "ProcFilterDeblocking") == 0)
132 index = ProcFilterDeblocking;
133 else if (strcmp(name, "ProcFilterFrameRateConversion") == 0)
134 index = ProcFilterFrameRateConversion;
135 else if (strcmp(name, "ProcFilterSkinToneEnhancement") == 0)
136 index = ProcFilterSkinToneEnhancement;
137 else if (strcmp(name, "ProcFilterTotalColorCorrection") == 0)
138 index = ProcFilterTotalColorCorrection;
139 else if (strcmp(name, "ProcFilterNonLinearAnamorphicScaling") == 0)
140 index = ProcFilterNonLinearAnamorphicScaling;
141 else if (strcmp(name, "ProcFilterImageStabilization") == 0)
142 index = ProcFilterImageStabilization;
143 else
144 index = 0;
145
146 mCurrentFilter = index;
147
148 return index;
149 }
150
getResolution(const char * name)151 uint32_t ISVProfile::getResolution(const char * name)
152 {
153 uint32_t width = 0, height = 0;
154 char *p = NULL, *str = NULL;
155 int32_t lenth = strlen(name);
156
157 str = (char*)malloc(lenth+1);
158 if (NULL == str) {
159 ALOGE("%s: failed to malloc buffer", __func__);
160 return 0;
161 }
162 strncpy(str, name, lenth);
163 str[lenth] = '\0';
164
165 p = strtok(str, "x");
166 if (p)
167 width = atoi(p);
168 p = strtok(NULL, "x");
169 if (p)
170 height = atoi(p);
171
172 if (str) {
173 free(str);
174 str = NULL;
175 }
176 return width * height;
177 }
178
getConfigData(const char * name,const char ** atts)179 void ISVProfile::getConfigData(const char *name, const char **atts)
180 {
181 int attIndex = 0;
182
183 if (strcmp(name, "VideoPostProcessSettings") == 0) {
184 return;
185 } else if (strcmp(name, "Filter") == 0) {
186 if (strcmp(atts[attIndex], "name") == 0) {
187 if (getFilterID(atts[attIndex + 1]) == 0) {
188 ALOGE("Couldn't parase the filter %s\n", atts[attIndex+1]);
189 }
190 } else {
191 ALOGE("couldn't handle \"%s\" element for Filter\n", name);
192 }
193 } else if (strcmp(name, "enabled") == 0) {
194 if (mCurrentFilter) {
195 if (!strcmp(atts[attIndex], "value") && !strcmp(atts[attIndex + 1], "true"))
196 mConfigs[mCurrentFilter].enabled = true;
197 } else {
198 ALOGE("Skip this element(%s) becaue this filter couldn't be supported\n", name);
199 }
200 } else if (strcmp(name, "minResolution") == 0) {
201 if (mCurrentFilter && !strcmp(atts[attIndex], "value")) {
202 if (!strcmp(atts[attIndex + 1], "0"))
203 mConfigs[mCurrentFilter].minResolution = 0;
204 else if (!strcmp(atts[attIndex + 1], "FFFFFFFF"))
205 mConfigs[mCurrentFilter].minResolution = 0xFFFFFFFF;
206 else
207 mConfigs[mCurrentFilter].minResolution = getResolution(atts[attIndex + 1]);
208 } else {
209 ALOGE("Skip this element(%s) becaue this filter couldn't be supported\n", name);
210 }
211 } else if (strcmp(name, "maxResolution") == 0) {
212 if (mCurrentFilter && !strcmp(atts[attIndex], "value")) {
213 if (!strcmp(atts[attIndex + 1], "0"))
214 mConfigs[mCurrentFilter].maxResolution = 0;
215 else if (!strcmp(atts[attIndex + 1], "FFFFFFFF"))
216 mConfigs[mCurrentFilter].maxResolution = 0xFFFFFFFF;
217 else
218 mConfigs[mCurrentFilter].maxResolution = getResolution(atts[attIndex + 1]);
219 } else {
220 ALOGE("Skip this element(%s) becaue this filter couldn't be supported\n", name);
221 }
222 } else if (strcmp(name, "FRCRate") == 0) {
223 if (mCurrentFilter == ProcFilterFrameRateConversion) {
224 if (!strcmp(atts[attIndex], "input") && !strcmp(atts[attIndex + 2], "rate")) {
225 mFrcRates[mCurrentFrcTab].input_fps = atoi(atts[attIndex + 1]);
226 if (!strcmp(atts[attIndex + 3], "2"))
227 mFrcRates[mCurrentFrcTab].rate = FRC_RATE_2X;
228 else if (!strcmp(atts[attIndex + 3], "2.5"))
229 mFrcRates[mCurrentFrcTab].rate = FRC_RATE_2_5X;
230 else if (!strcmp(atts[attIndex + 3], "4"))
231 mFrcRates[mCurrentFrcTab].rate = FRC_RATE_4X;
232 else
233 mFrcRates[mCurrentFrcTab].rate = FRC_RATE_1X;
234
235 /* update the pointer */
236 if (mCurrentFrcTab < MAX_TAB_SIZE)
237 mCurrentFrcTab++;
238 }
239 } else {
240 ALOGE("\"FRCRate\" element is only for ProcFilterFrameRateConversion\n");
241 }
242 } else if (strcmp(name, "parameter") == 0) {
243 /* <parameter /> */
244 handleFilterParameter(name, atts);
245 } else if (strcmp(name, "Parameter") == 0) {
246 /* <Parameter /> */
247 handleCommonParameter(name, atts);
248 } else
249 ALOGE("Couldn't handle this element %s!\n", name);
250 }
251
handleFilterParameter(const char * name,const char ** atts)252 void ISVProfile::handleFilterParameter(const char *name, const char **atts)
253 {
254 int attIndex = 0;
255
256 if (!mCurrentFilter) {
257 ALOGE("\"%s\" must be in Filter element\n", name);
258 return;
259 }
260
261 if (strcmp(atts[attIndex], "name") || strcmp(atts[attIndex + 2], "value")) {
262 ALOGE("\"%s\" or \"%s\" couldn't match the %s format\n", atts[attIndex], atts[attIndex + 2], name);
263 return;
264 }
265
266 }
267
handleCommonParameter(const char * name,const char ** atts)268 void ISVProfile::handleCommonParameter(const char *name, const char **atts)
269 {
270 int attIndex = 0;
271
272 if (strcmp(atts[attIndex], "name") || strcmp(atts[attIndex + 2], "value")) {
273 ALOGE("\"%s\" or \"%s\" couldn't match the %s format\n", atts[attIndex], atts[attIndex + 2], name);
274 return;
275 }
276
277 /* The default status of VPP */
278 if (strcmp(atts[attIndex + 1], "DefaultVPPStatus") == 0)
279 mDefaultVPPStatus = atoi(atts[attIndex + 3]);
280 /* The default status of FRC */
281 else if (strcmp(atts[attIndex + 1], "DefaultFRCStatus") == 0)
282 mDefaultFRCStatus = atoi(atts[attIndex + 3]);
283 }
284
startElement(void * userData,const char * name,const char ** atts)285 void ISVProfile::startElement(void *userData, const char *name, const char **atts)
286 {
287 ISVProfile *profile = (ISVProfile *)userData;
288
289 profile->getConfigData(name, atts);
290 }
291
endElement(void * userData,const char * name)292 void ISVProfile::endElement(void *userData, const char *name)
293 {
294 ISVProfile *profile = (ISVProfile *)userData;
295
296 if (!strcmp(name, "Filter"))
297 profile->mCurrentFilter = 0;
298 }
299
getDataFromXmlFile()300 void ISVProfile::getDataFromXmlFile()
301 {
302 int done;
303 void *pBuf = NULL;
304 FILE *fp = NULL;
305
306 fp = ::fopen(DEFAULT_XML_FILE, "r");
307 if (NULL == fp) {
308 ALOGE("@%s, line:%d, couldn't open profile %s", __func__, __LINE__, DEFAULT_XML_FILE);
309 return;
310 }
311
312 XML_Parser parser = ::XML_ParserCreate(NULL);
313 if (NULL == parser) {
314 ALOGE("@%s, line:%d, parser is NULL", __func__, __LINE__);
315 goto exit;
316 }
317 ::XML_SetUserData(parser, this);
318 ::XML_SetElementHandler(parser, startElement, endElement);
319
320 pBuf = malloc(mBufSize);
321 if (NULL == pBuf) {
322 ALOGE("@%s, line:%d, failed to malloc buffer", __func__, __LINE__);
323 goto exit;
324 }
325
326 do {
327 int len = (int)::fread(pBuf, 1, mBufSize, fp);
328 if (!len) {
329 if (ferror(fp)) {
330 clearerr(fp);
331 goto exit;
332 }
333 }
334 done = len < mBufSize;
335 if (XML_Parse(parser, (const char *)pBuf, len, done) == XML_STATUS_ERROR) {
336 ALOGE("@%s, line:%d, XML_Parse error", __func__, __LINE__);
337 goto exit;
338 }
339 } while (!done);
340
341 exit:
342 if (parser)
343 ::XML_ParserFree(parser);
344 if (pBuf)
345 free(pBuf);
346 if (fp)
347 ::fclose(fp);
348 }
349
getGlobalStatus()350 int32_t ISVProfile::getGlobalStatus()
351 {
352 char path[80];
353 int userId = 0;
354 int32_t status = 0;
355 FILE *setting_handle, *config_handle;
356
357 snprintf(path, 80, "/data/user/%d/com.intel.vpp/shared_prefs/vpp_settings.xml", userId);
358 ALOGV("%s: %s",__func__, path);
359 setting_handle = fopen(path, "r");
360 if(setting_handle == NULL) {
361 ALOGE("%s: failed to open file %s\n", __func__, path);
362
363 /* Read the Filter config file to get default value */
364 config_handle = fopen(DEFAULT_XML_FILE, "r");
365 if (config_handle == NULL) {
366 ALOGE("%s: failed to open file %s\n", __func__, DEFAULT_XML_FILE);
367 return -1;
368 }
369
370 char xml_buf[MAX_BUF_SIZE + 1] = {0};
371 memset(xml_buf, 0, MAX_BUF_SIZE);
372 if (fread(xml_buf, 1, MAX_BUF_SIZE, config_handle) <= 0) {
373 ALOGE("%s: failed to read config xml file!\n", __func__);
374 fclose(config_handle);
375 return -1;
376 }
377 xml_buf[MAX_BUF_SIZE] = '\0';
378
379 if (strstr(xml_buf, "name=\"DefaultVPPStatus\" value=\"1\"") != NULL)
380 status |= VPP_COMMON_ON;
381 if (strstr(xml_buf, "name=\"DefaultFRCStatus\" value=\"1\"") != NULL)
382 status |= VPP_FRC_ON;
383
384 ALOGV("%s: using the default status: VPP=%d, FRC=%d\n", __func__,
385 ((status & VPP_COMMON_ON) == 0) ? 0 : 1,
386 ((status & VPP_FRC_ON) == 0) ? 0: 1);
387
388 fclose(config_handle);
389 return status;
390 }
391
392 const int MAXLEN = 1024;
393 char buf[MAXLEN] = {0};
394 memset(buf, 0 ,MAXLEN);
395 if(fread(buf, 1, MAXLEN, setting_handle) <= 0) {
396 ALOGE("%s: failed to read vpp config file %d", __func__, userId);
397 fclose(setting_handle);
398 return -1;
399 }
400 buf[MAXLEN - 1] = '\0';
401
402 if(strstr(buf, StatusOn[0]) != NULL)
403 status |= VPP_FRC_ON;
404
405 if(strstr(buf, StatusOn[1]) != NULL)
406 status |= VPP_COMMON_ON;
407
408 fclose(setting_handle);
409 return status;
410 }
411
dumpConfigData()412 void ISVProfile::dumpConfigData()
413 {
414 uint32_t i, j;
415 char filterNames[][50] = {
416 "ProcFilterNone",
417 "ProcFilterNoiseReduction",
418 "ProcFilterDeinterlacing",
419 "ProcFilterSharpening",
420 "ProcFilterColorBalance",
421 "ProcFilterDeblocking",
422 "ProcFilterFrameRateConversion",
423 "ProcFilterSkinToneEnhancement",
424 "ProcFilterTotalColorCorrection",
425 "ProcFilterNonLinearAnamorphicScaling",
426 "ProcFilterImageStabilization"
427 };
428 char rateNames[][20] = {
429 "FRC_RATE_0X",
430 "FRC_RATE_1X",
431 "FRC_RATE_2X",
432 "FRC_RATE_2_5X",
433 "FRC_RATE_4X",
434 };
435
436 ALOGV("========== VPP filter configs:==========\n");
437 for (i = 1; i < ProcFilterCount; i++) {
438 ALOGV("name=%s, enabled=%s, minResolution=%d, maxResolution=%d, isOn=%s\n",
439 filterNames[i],
440 (mConfigs[i].enabled == true) ? "true" : "false",
441 mConfigs[i].minResolution,
442 mConfigs[i].maxResolution,
443 ((mStatus & (1 << i)) == 0) ? "false" : "true");
444 if (mConfigs[i].paraSize) {
445 ALOGV("\t\t parameters: ");
446 for(j = 0; j < mConfigs[i].paraSize; j++)
447 ALOGE("%s=%f,", mConfigs[i].paraTables[j].name, mConfigs[i].paraTables[j].value);
448 ALOGV("\n");
449 }
450 }
451
452 ALOGV("========== FRC rate configs:===========\n");
453 for (i = 0; i < MAX_TAB_SIZE; i++) {
454 if (mFrcRates[i].input_fps == 0)
455 break;
456 ALOGV("input_fps=%d, rate=%s\n", mFrcRates[i].input_fps, rateNames[mFrcRates[i].rate]);
457 }
458
459 ALOGI("========== common parameter configs:===========\n");
460 ALOGI("mDefaultVPPStatus=%d\n", mDefaultVPPStatus);
461 ALOGI("mDefaultFRCStatus=%d\n", mDefaultFRCStatus);
462
463 }
464