package: Move v4l2test to starfive package
1.Create starfive package, and move v4l2test into it. 2.Sync the latest v4l2test package from JH7100. Signed-off-by: mason.huo <mason.huo@starfivetech.com> (cherry-pick commit 87583e4004ba7ceefa317d939ea8004f38eb9570 from jh7110-mm-devel branch)
This commit is contained in:
committed by
changhuang.liang
parent
313e975390
commit
cf9c62a4f1
@@ -0,0 +1,303 @@
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user