/*
|
* Copyright (C) 2020 Rockchip Electronics Co., Ltd.
|
* author: Zhihua Wang, hogan.wang@rock-chips.com
|
*
|
* This software is available to you under a choice of one of two
|
* licenses. You may choose to be licensed under the terms of the GNU
|
* General Public License (GPL), available from the file
|
* COPYING in the main directory of this source tree, or the
|
* OpenIB.org BSD license below:
|
*
|
* Redistribution and use in source and binary forms, with or
|
* without modification, are permitted provided that the following
|
* conditions are met:
|
*
|
* - Redistributions of source code must retain the above
|
* copyright notice, this list of conditions and the following
|
* disclaimer.
|
*
|
* - Redistributions in binary form must reproduce the above
|
* copyright notice, this list of conditions and the following
|
* disclaimer in the documentation and/or other materials
|
* provided with the distribution.
|
*
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* SOFTWARE.
|
*/
|
#include "image_read.h"
|
#include "vpu_decode.h"
|
#include "rga_control.h"
|
|
static int mjpeg_get_resolutin(FILE *fp, int *width, int *height)
|
{
|
int ret = -1;
|
char mark[2];
|
char size[2];
|
char data[14];
|
|
rewind(fp);
|
while (!feof(fp)) {
|
fread(mark, 1, sizeof(mark), fp);
|
if (mark[0] == 0xFF && mark[1] == 0xD8)
|
continue;
|
if (mark[0] != 0xFF)
|
break;
|
if (mark[1] == 0xC0) {
|
fseek(fp, 3, SEEK_CUR);
|
fread(data, 1, sizeof(data), fp);
|
*height = data[0] * 256 + data[1];
|
*width = data[2] * 256 + data[3];
|
/* rga support RK_FORMAT_YCbCr_420_SP and RK_FORMAT_YCbCr_422_SP */
|
if (data[4] == 3 && (data[6] == 0x22 || data[6] == 0x21) && data[9] == 0x11 && data[12] == 0x11)
|
ret = 0;
|
break;
|
} else {
|
fread(size, 1, sizeof(size), fp);
|
fseek(fp, size[0] * 256 + size[1] - 2, SEEK_CUR);
|
continue;
|
}
|
}
|
|
return ret;
|
}
|
|
static int _decode(int width, int height, void *data, size_t size, int out_fd, void* out_data, int *fmt, int *hor_stride, int *ver_stride)
|
{
|
int ret = -1;
|
struct vpu_decode dec;
|
memset(&dec, 0, sizeof(dec));
|
if (!vpu_decode_jpeg_init(&dec, width, height))
|
ret = vpu_decode_jpeg_doing(&dec, data, size, out_fd, out_data);
|
*fmt = (MPP_FMT_YUV422SP != dec.fmt ? RK_FORMAT_YCbCr_420_SP : RK_FORMAT_YCbCr_422_SP);
|
*hor_stride = dec.hor_stride;
|
*ver_stride = dec.ver_stride;
|
vpu_decode_jpeg_done(&dec);
|
return ret;
|
}
|
|
static int image_read_begin(const char *path, bo_t *buf_bo, int *buf_fd, int *w, int *h, int *fmt, int *hor_stride, int *ver_stride)
|
{
|
int ret = 0;
|
int width, height;
|
FILE *fp;
|
size_t size;
|
void *data;
|
|
memset(buf_bo, 0, sizeof(bo_t));
|
*buf_fd = -1;
|
|
fp = fopen(path, "rb");
|
if (!fp)
|
return -1;
|
|
if (mjpeg_get_resolutin(fp, &width, &height) || width % 2 || height % 2) {
|
ret = -1;
|
goto err_close;
|
}
|
|
fseek(fp, 0, SEEK_END);
|
size = ftell(fp);
|
|
data = malloc(size);
|
if (!data) {
|
ret = -1;
|
goto err_close;
|
}
|
|
rewind(fp);
|
fread(data, 1, size, fp);
|
|
*w = width;
|
*h = height;
|
if (rga_control_buffer_init(buf_bo, buf_fd, MPP_ALIGN(width, 16), MPP_ALIGN(height, 16), 24)) {
|
printf("%s: alloc buffer failed!\n", __func__);
|
ret = -1;
|
goto err_free;
|
}
|
|
ret = _decode(width, height, data, size, *buf_fd, buf_bo->ptr, fmt, hor_stride, ver_stride);
|
|
err_free:
|
if (data)
|
free(data);
|
|
err_close:
|
if (fp)
|
fclose(fp);
|
return ret;
|
}
|
|
static int image_read_end(bo_t *buf_bo, int buf_fd)
|
{
|
rga_control_buffer_deinit(buf_bo, buf_fd);
|
return 0;
|
}
|
|
int image_read(const char *path, rockface_image_t *img, bo_t *rgb_bo, int *rgb_fd)
|
{
|
int ret = -1;
|
bo_t dec_bo;
|
int dec_fd = -1;
|
int width = 0, height = 0;
|
int fmt;
|
int hor_stride, ver_stride;
|
|
if (image_read_begin(path, &dec_bo, &dec_fd, &width, &height, &fmt, &hor_stride, &ver_stride)) {
|
ret = -2;
|
goto exit0;
|
}
|
|
if (rga_control_buffer_init(rgb_bo, rgb_fd, hor_stride, ver_stride, 24)) {
|
printf("%s: alloc buffer failed!\n", __func__);
|
goto exit0;
|
}
|
|
rga_info_t src, dst;
|
memset(&src, 0, sizeof(rga_info_t));
|
src.fd = -1;
|
src.virAddr = dec_bo.ptr;
|
src.mmuFlag = 1;
|
rga_set_rect(&src.rect, 0, 0, width, height, hor_stride, ver_stride, fmt);
|
memset(&dst, 0, sizeof(rga_info_t));
|
dst.fd = -1;
|
dst.virAddr = rgb_bo->ptr;
|
dst.mmuFlag = 1;
|
rga_set_rect(&dst.rect, 0, 0, hor_stride, ver_stride, hor_stride, ver_stride, RK_FORMAT_RGB_888);
|
if (c_RkRgaBlit(&src, &dst, NULL)) {
|
printf("%s: rga fail\n", __func__);
|
goto exit0;
|
}
|
|
memset(img, 0, sizeof(rockface_image_t));
|
img->width = hor_stride;
|
img->height = ver_stride;
|
img->pixel_format = ROCKFACE_PIXEL_FORMAT_RGB888;
|
img->data = (uint8_t *)rgb_bo->ptr;
|
ret = 0;
|
|
exit0:
|
if (width > 0 && height > 0)
|
image_read_end(&dec_bo, dec_fd);
|
return ret;
|
}
|
|
int image_read_deinit(bo_t *rgb_bo, int *rgb_fd)
|
{
|
rga_control_buffer_deinit(rgb_bo, *rgb_fd);
|
}
|