/* * 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 #include #include #include #include #include #include #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(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"); } }