android13/hardware/rockchip/libhwjpeg/src/Utils.cpp

433 lines
12 KiB
C++

/*
* Copyright 2021 Rockchip Electronics Co. LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* author: kevin.chen@rock-chips.com
*/
//#define LOG_NDEBUG 0
#define LOG_TAG "Utils"
#include <utils/Log.h>
#include <sys/system_properties.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "mpp_mem.h"
#include "Utils.h"
#include "RockchipRga.h"
#include "im2d.h"
using namespace android;
rga_buffer_handle_t importRgaBuffer(int32_t width, int32_t height,
int32_t format, int32_t fd) {
im_handle_param_t imParam;
memset(&imParam, 0, sizeof(im_handle_param_t));
imParam.width = width;
imParam.height = height;
imParam.format = format;
return importbuffer_fd(fd, &imParam);
}
void freeRgaBuffer(rga_buffer_handle_t handle) {
releasebuffer_handle(handle);
}
void CommonUtil::dumpMppFrameToFile(MppFrame frame, FILE *file)
{
int width = 0;
int height = 0;
int h_stride = 0;
int v_stride = 0;
MppFrameFormat fmt = MPP_FMT_YUV420SP;
MppBuffer buffer = NULL;
uint8_t *base = NULL;
if (NULL == file || NULL == frame)
return;
width = mpp_frame_get_width(frame);
height = mpp_frame_get_height(frame);
h_stride = mpp_frame_get_hor_stride(frame);
v_stride = mpp_frame_get_ver_stride(frame);
fmt = mpp_frame_get_fmt(frame);
buffer = mpp_frame_get_buffer(frame);
if (NULL == buffer)
return;
base = (uint8_t *)mpp_buffer_get_ptr(buffer);
switch (fmt) {
case MPP_FMT_YUV422SP : {
/* YUV422SP -> YUV422P for better display */
int i, j;
uint8_t *base_y = base;
uint8_t *base_c = base + h_stride * v_stride;
uint8_t *tmp = mpp_malloc(uint8_t, h_stride * height * 2);
uint8_t *tmp_u = tmp;
uint8_t *tmp_v = tmp + width * height / 2;
for (i = 0; i < height; i++, base_y += h_stride)
fwrite(base_y, 1, width, file);
for (i = 0; i < height; i++, base_c += h_stride) {
for (j = 0; j < width / 2; j++) {
tmp_u[j] = base_c[2 * j + 0];
tmp_v[j] = base_c[2 * j + 1];
}
tmp_u += width / 2;
tmp_v += width / 2;
}
fwrite(tmp, 1, width * height, file);
mpp_free(tmp);
} break;
case MPP_FMT_YUV420SP : {
int i;
uint8_t *base_y = base;
uint8_t *base_c = base + h_stride * v_stride;
for (i = 0; i < height; i++, base_y += h_stride) {
fwrite(base_y, 1, width, file);
}
for (i = 0; i < height / 2; i++, base_c += h_stride) {
fwrite(base_c, 1, width, file);
}
} break;
case MPP_FMT_YUV420P : {
int i;
uint8_t *base_y = base;
uint8_t *base_c = base + h_stride * v_stride;
for (i = 0; i < height; i++, base_y += h_stride) {
fwrite(base_y, 1, width, file);
}
for (i = 0; i < height / 2; i++, base_c += h_stride / 2) {
fwrite(base_c, 1, width / 2, file);
}
for (i = 0; i < height / 2; i++, base_c += h_stride / 2) {
fwrite(base_c, 1, width / 2, file);
}
} break;
case MPP_FMT_YUV444SP : {
/* YUV444SP -> YUV444P for better display */
int i, j;
uint8_t *base_y = base;
uint8_t *base_c = base + h_stride * v_stride;
uint8_t *tmp = mpp_malloc(uint8_t, h_stride * height * 2);
uint8_t *tmp_u = tmp;
uint8_t *tmp_v = tmp + width * height;
for (i = 0; i < height; i++, base_y += h_stride)
fwrite(base_y, 1, width, file);
for (i = 0; i < height; i++, base_c += h_stride * 2) {
for (j = 0; j < width; j++) {
tmp_u[j] = base_c[2 * j + 0];
tmp_v[j] = base_c[2 * j + 1];
}
tmp_u += width;
tmp_v += width;
}
fwrite(tmp, 1, width * height * 2, file);
mpp_free(tmp);
} break;
default : {
ALOGE("not supported format %d", fmt);
} break;
}
}
void CommonUtil::dumpMppPacketToFile(MppPacket packet, FILE *file)
{
uint8_t *data;
int len;
if (NULL == file || NULL == packet)
return;
data = (uint8_t*)mpp_packet_get_pos(packet);
len = mpp_packet_get_length(packet);
fwrite(data, 1, len, file);
fflush(file);
}
void CommonUtil::dumpDataToFile(char *data, size_t size, FILE *file)
{
if (NULL == file || NULL == data)
return;
fwrite(data, 1, size, file);
fflush(file);
}
void CommonUtil::dumpDataToFile(char *data, size_t size, const char *fileName)
{
FILE *file = NULL;
file = fopen(fileName, "w+b");
if (NULL == file) {
ALOGE("failed to open file %s - %s", fileName, strerror(errno));
return;
}
fwrite(data, 1, size, file);
fflush(file);
fclose(file);
}
void CommonUtil::dumpDmaFdToFile(int fd, size_t size, FILE *file)
{
void *ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (ptr != NULL) {
fwrite(ptr, 1, size, file);
fflush(file);
} else {
ALOGE("failed to map fd value %d", fd);
}
}
MPP_RET CommonUtil::storeFileData(const char *file_name, char **data, size_t *length)
{
FILE *file = NULL;
size_t fileLen = 0;
file = fopen(file_name, "rb");
if (NULL == file) {
ALOGE("failed to open file %s - %s", file_name, strerror(errno));
return MPP_NOK;
}
fseek(file, 0L, SEEK_END);
fileLen = ftell(file);
rewind(file);
*data = (char *)malloc(fileLen);
if (NULL == *data) {
ALOGE("failed to malloc buffer - file %s", file_name);
fclose(file);
return MPP_NOK;
}
fread(*data, 1, fileLen, file);
*length = fileLen;
fclose(file);
return MPP_OK;
}
MPP_RET CommonUtil::cropImage(int src, int dst,
int src_width, int src_height,
int src_wstride, int src_hstride,
int dst_width, int dst_height)
{
int ret = 0;
int srcFormat, dstFormat;
rga_info_t rgasrc, rgadst;
rga_buffer_handle_t srcHdl;
rga_buffer_handle_t dstHdl;
RockchipRga& rkRga(RockchipRga::get());
srcFormat = dstFormat = HAL_PIXEL_FORMAT_YCrCb_NV12;
memset(&rgasrc, 0, sizeof(rga_info_t));
memset(&rgadst, 0, sizeof(rga_info_t));
srcHdl = importRgaBuffer(src_width, src_height, srcFormat, src);
dstHdl = importRgaBuffer(dst_width, dst_height, dstFormat, dst);
if (!srcHdl || !dstHdl) {
ALOGE("failed to import rga buffer");
return MPP_NOK;
}
rgasrc.handle = srcHdl;
rgadst.handle = dstHdl;
rga_set_rect(&rgasrc.rect, 0, 0, src_width, src_height,
src_wstride, src_hstride, srcFormat);
rga_set_rect(&rgadst.rect, 0, 0, dst_width, dst_height,
dst_width, dst_height, dstFormat);
ret = rkRga.RkRgaBlit(&rgasrc, &rgadst, NULL);
if (ret) {
ALOGE("failed to rga blit ret %d", ret);
return MPP_NOK;
}
freeRgaBuffer(srcHdl);
freeRgaBuffer(dstHdl);
return MPP_OK;
}
MPP_RET CommonUtil::readImage(char *src, char *dst,
int width, int height,
int wstride, int hstride,
MppFrameFormat fmt)
{
MPP_RET ret = MPP_OK;
int row = 0;
char *buf_y = dst;
char *buf_u = buf_y + wstride * hstride;
char *buf_v = buf_u + wstride * hstride / 4;
switch (fmt) {
case MPP_FMT_YUV420SP : {
for (row = 0; row < height; row++) {
memcpy(buf_y + row * wstride, src, width);
src += width;
}
for (row = 0; row < height / 2; row++) {
memcpy(buf_u + row * wstride, src, width);
src += width;
}
} break;
case MPP_FMT_YUV420P : {
for (row = 0; row < height; row++) {
memcpy(buf_y + row * wstride, src, width);
src += width;
}
for (row = 0; row < height / 2; row++) {
memcpy(buf_u + row * wstride / 2, src, width / 2);
src += width / 2;
}
for (row = 0; row < height / 2; row++) {
memcpy(buf_v + row * wstride / 2, src, width / 2);
src += width / 2;
}
} break;
case MPP_FMT_RGBA8888 :
case MPP_FMT_ABGR8888 :
case MPP_FMT_ARGB8888 : {
for (row = 0; row < height; row++) {
memcpy(buf_y + row * wstride * 4, src, width * 4);
src += width * 4;
}
} break;
case MPP_FMT_YUV422_YUYV :
case MPP_FMT_YUV422_UYVY : {
for (row = 0; row < height; row++) {
memcpy(buf_y + row * wstride * 2, src, width * 2);
src += width * 2;
}
} break;
case MPP_FMT_RGB888 :
case MPP_FMT_BGR888 : {
for (row = 0; row < height; row++) {
memcpy(buf_y + row * wstride * 3, src, width * 3);
src += width * 3;
}
} break;
default : {
ALOGE("read image do not support fmt %d", fmt);
ret = MPP_ERR_VALUE;
} break;
}
return ret;
}
int CommonUtil::envGetU32(const char *name, uint32_t *value, uint32_t default_value)
{
char prop[PROP_VALUE_MAX + 1];
int len = __system_property_get(name, prop);
if (len > 0) {
char *endptr;
int base = (prop[0] == '0' && prop[1] == 'x') ? (16) : (10);
errno = 0;
*value = strtoul(prop, &endptr, base);
if (errno || (prop == endptr)) {
errno = 0;
*value = default_value;
}
} else {
*value = default_value;
}
return 0;
}
int CommonUtil::envGetStr(const char *name, const char **value, const char *default_value)
{
static unsigned char env_str[2][PROP_VALUE_MAX + 1];
static int32_t env_idx = 0;
char *prop = reinterpret_cast<char *>(env_str[env_idx]);
int len = __system_property_get(name, prop);
if (len > 0) {
*value = prop;
env_idx = !env_idx;
} else {
*value = default_value;
}
return 0;
}
int CommonUtil::envSetU32(const char *name, uint32_t value)
{
char buf[PROP_VALUE_MAX + 1 + 2];
snprintf(buf, sizeof(buf), "0x%x", value);
int len = __system_property_set(name, buf);
return (len) ? (0) : (-1);
}
int CommonUtil::envSetStr(const char *name, char *value)
{
int len = __system_property_set(name, value);
return (len) ? (0) : (-1);
}
bool CommonUtil::isValidDmaFd(int fd)
{
/* detect input file handle */
int fs_flag = fcntl(fd, F_GETFL, NULL);
int fd_flag = fcntl(fd, F_GETFD, NULL);
if (fs_flag == -1 || fd_flag == -1) {
return false;;
}
return true;
}
void CommonUtil::setPerformanceMode(int on)
{
int fd = -1;
fd = open("/sys/class/devfreq/dmc/system_status", O_WRONLY);
if (fd == -1) {
ALOGD("failed to open /sys/class/devfreq/dmc/system_status");
}
if (fd != -1) {
ALOGD("%s performance mode", (on == 1) ? "config" : "clear");
write(fd, (on == 1) ? "p" : "n", 1);
close(fd);
} else {
ALOGD("failed to open /sys/class/devfreq/dmc/system_status");
}
}