Files
fml13v01-buildroot/package/starfive/v4l2_test/common.c
T

323 lines
8.6 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2021 StarFive Technology Co., Ltd.
*/
#include "common.h"
#include <stddef.h>
#include <jpeglib.h>
#include <libdrm/drm_fourcc.h>
#include "convert.h"
#include "stf_log.h"
/**
Print error message and terminate programm with EXIT_FAILURE return code.
\param s error message to print
*/
void errno_exit(const char* s)
{
LOG(STF_LEVEL_ERR, "%s error %d, %s\n", s, errno, strerror(errno));
exit(EXIT_FAILURE);
}
void errno_print(const char *s)
{
LOG(STF_LEVEL_ERR, "%s error %d, %s\n", s, errno, strerror(errno));
}
void dump_fourcc(uint32_t fourcc)
{
LOG(STF_LEVEL_LOG, " %c%c%c%c \n",
fourcc,
fourcc >> 8,
fourcc >> 16,
fourcc >> 24);
}
int is_raw_v4l2fmt(uint32_t format)
{
int ret;
switch (format) {
case V4L2_PIX_FMT_SRGGB12:
case V4L2_PIX_FMT_SGRBG12:
case V4L2_PIX_FMT_SGBRG12:
case V4L2_PIX_FMT_SBGGR12:
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
// convert v4l2 format to fb format
int v4l2fmt_to_fbfmt(uint32_t format)
{
int pixformat = COLOR_RGB565;
switch (format) {
case V4L2_PIX_FMT_RGB565:
pixformat = COLOR_RGB565;
break;
case V4L2_PIX_FMT_RGB24:
pixformat = COLOR_RGB888_ARGB;
break;
case V4L2_PIX_FMT_YUV420:
pixformat = COLOR_YUV420P;
break;
case V4L2_PIX_FMT_YUYV:
pixformat = COLOR_YUV422_YUYV;
break;
case V4L2_PIX_FMT_NV21:
pixformat = COLOR_YUV420_NV21;
break;
case V4L2_PIX_FMT_NV12:
pixformat = COLOR_YUV420_NV12;
break;
case V4L2_PIX_FMT_YVYU:
pixformat = COLOR_YUV422_YVYU;
break;
default:
pixformat = COLOR_RGB565;
break;
}
return pixformat;
}
// convert v4l2 format to drm format
uint32_t v4l2fmt_to_drmfmt(uint32_t v4l2_fmt)
{
uint32_t drm_fmt;
// dump_fourcc(v4l2_fmt);
switch (v4l2_fmt) {
case V4L2_PIX_FMT_RGB565:
drm_fmt = DRM_FORMAT_RGB565;
break;
case V4L2_PIX_FMT_RGB24:
drm_fmt = DRM_FORMAT_ARGB8888;
break;
case V4L2_PIX_FMT_YUV420:
drm_fmt = DRM_FORMAT_YUV420;
break;
case V4L2_PIX_FMT_YUYV:
drm_fmt = DRM_FORMAT_YUYV;
break;
case V4L2_PIX_FMT_YVYU:
drm_fmt = DRM_FORMAT_YVYU;
break;
case V4L2_PIX_FMT_NV21:
drm_fmt = DRM_FORMAT_NV21;
break;
case V4L2_PIX_FMT_NV12:
drm_fmt = DRM_FORMAT_NV12;
break;
default:
drm_fmt = DRM_FORMAT_NV21;
LOG(STF_LEVEL_WARN, "drm not support the V4L2_format\n");
break;
}
return drm_fmt;
}
void test_performance()
{
int count = 1920 * 1080 * 2;
float r, g, b;
float y = 10, u = 20, v = 30;
int int_r, int_g, int_b;
int int_y = 10, int_u = 20, int_v = 30;
struct timeval tv1, tv2, tv3;
long long elapse = 0;
int i;
gettimeofday(&tv1, NULL);
while (count--) {
b = 1.164 * (y - 16) + 2.018 * (u - 128);
g = 1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u - 128);
r = 1.164 * (y - 16) + 1.596 * (v - 128);
y ++;
u ++;
v ++;
}
gettimeofday(&tv2, NULL);
elapse = (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000;
LOG(STF_LEVEL_INFO, "elapse: %lldms, out: r=%f, g=%f, b=%f\n",
elapse ,r, g, b);
count = 1920 * 1080 * 2;
gettimeofday(&tv1, NULL);
while (count--) {
int_b = 1164 * (y - 16) + 2018 * (u - 128);
int_g = 1164 * (y - 16) - 813 * (v - 128) - 391 * (u - 128);
int_r = 1164 * (y - 16) + 1596 * (v - 128);
int_y ++;
int_u ++;
int_v ++;
}
gettimeofday(&tv2, NULL);
elapse = (tv2.tv_sec - tv1.tv_sec) + (tv2.tv_usec - tv1.tv_usec);
LOG(STF_LEVEL_INFO, "elapse: %lldus, out: r=%d, g=%d, b=%d\n",
elapse , int_r, int_g, int_b);
count = 1920 * 1080 * 2;
unsigned char* arraybuf = NULL;
arraybuf = (unsigned char*)malloc(count);
if (!arraybuf) {
LOG(STF_LEVEL_ERR, "arraybuf malloc error\n");
return;
}
unsigned char* arraybuf2 = NULL;
arraybuf2 = (unsigned char*)malloc(count);
if (!arraybuf2) {
LOG(STF_LEVEL_ERR, "arraybuf2 malloc error\n");
return;
}
gettimeofday(&tv1, NULL);
for (i = 0; i < count; i++) {
arraybuf[i] = i + 1;
}
gettimeofday(&tv2, NULL);
memcpy(arraybuf2, arraybuf, count);
gettimeofday(&tv3, NULL);
elapse = (tv2.tv_sec - tv1.tv_sec) * 1000 + (tv2.tv_usec - tv1.tv_usec) / 1000;
LOG(STF_LEVEL_INFO, "for() elapse: %lldms\n", elapse);
elapse = (tv3.tv_sec - tv2.tv_sec) * 1000000 + (tv3.tv_usec - tv2.tv_usec);
LOG(STF_LEVEL_INFO, "memcpy() run elapse: %lldus\n", elapse);
convert_nv21_to_rgb((const uint8_t*)arraybuf, arraybuf2, 1920, 1080, 1);
free(arraybuf);
free(arraybuf2);
}
int write_file(char * filename, const uint8_t *image_buffer, int size)
{
/* More stuff */
FILE * outfile; /* target file */
if ((outfile = fopen(filename, "w+")) == NULL) {
LOG(STF_LEVEL_ERR, "can't open %s\n", filename);
return -1;
}
fwrite(image_buffer, size, 1, outfile);
fclose(outfile);
return 0 ;
}
int write_JPEG_file(char * filename, uint8_t *image_buffer,
int image_width, int image_height, int quality)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
/* More stuff */
FILE * outfile; /* target file */
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
/* Step 1: allocate and initialize JPEG compression object */
cinfo.err = jpeg_std_error(&jerr);
/* Now we can initialize the JPEG compression object. */
jpeg_create_compress(&cinfo);
/* Step 2: specify data destination (eg, a file) */
/* Note: steps 2 and 3 can be done in either order. */
if ((outfile = fopen(filename, "w+")) == NULL) {
LOG(STF_LEVEL_ERR, "can't open %s\n", filename);
return -1;
}
jpeg_stdio_dest(&cinfo, outfile);
/* Step 3: set parameters for compression */
cinfo.image_width = image_width; /* image width and height, in pixels */
cinfo.image_height = image_height;
cinfo.input_components = 3; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
/* Step 4: Start compressor */
jpeg_start_compress(&cinfo, TRUE);
/* Step 5: while (scan lines remain to be written) */
row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
/* Step 6: Finish compression */
jpeg_finish_compress(&cinfo);
/* After finish_compress, we can close the output file. */
fclose(outfile);
/* Step 7: release JPEG compression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_compress(&cinfo);
/* And we're done! */
return 0;
}
void jpegWrite(uint8_t* img, char* jpegFilename,
uint32_t width, uint32_t height, int jpegQuality)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPROW row_pointer[1];
FILE *outfile = fopen( jpegFilename, "wb" );
// try to open file for saving
if (!outfile) {
errno_exit("jpeg");
}
// create jpeg data
cinfo.err = jpeg_std_error( &jerr );
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, outfile);
// set image parameters
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_YCbCr;
// set jpeg compression parameters to default
jpeg_set_defaults(&cinfo);
// and then adjust quality setting
jpeg_set_quality(&cinfo, jpegQuality, TRUE);
// start compress
jpeg_start_compress(&cinfo, TRUE);
// feed data
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = &img[cinfo.next_scanline * cinfo.image_width * cinfo.input_components];
jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
// finish compression
jpeg_finish_compress(&cinfo);
// destroy jpeg data
jpeg_destroy_compress(&cinfo);
// close output file
fclose(outfile);
}