This commit is contained in:
huxi
2025-12-03 11:12:34 +08:00
parent c23ae4f24c
commit bc195654bf
8163 changed files with 3799544 additions and 92 deletions
@@ -0,0 +1,265 @@
#include "system/includes.h"
#include "app_config.h"
// 如果定义了 USE_PSRAM,就把 malloc/free 映射到 malloc_psram/free_psram
#if TCFG_PSRAM_DEV_ENABLE
#define malloc(size) malloc_psram(size)
#define free(ptr) free_psram(ptr)
#else
#define malloc(size) malloc(size)
#define free(ptr) free(ptr)
#endif
extern int jpgenc_get_heapsize(int width, int height);
extern void *jpgenc_init(unsigned char *heap, int width, int height, int stride, int quality);
extern void jpgenc_free(void *ctxt);
extern void jpgenc_set_quality(void *ctxt, int quality);
extern void jpgenc_get_header(void *ctxt, unsigned char **output, int *out_size);
extern void jpgenc_encode_yuyv(void *ctxt, unsigned char *data, unsigned char *output, int *out_size, int vlen, int voff);
struct software_jpegenc_hdl {
void *jfif;
u8 *heap;
u8 *jpeg_header;
int jpeg_header_size;
};
/* ------------------------------------------------------------------------------------*/
/**
* @brief software_jpegenc_init jpeg软件分行编码初始化
*
* @param img_width 图像宽
* @param img_height 图像高
* @param img_stride
* @param q_val 编码Q值,范围(1-100)
* @return enc_hdl_ptr:成功 NULL:失败
*/
/* ------------------------------------------------------------------------------------*/
void *software_jpegenc_init(int img_width, int img_height, int img_stride, int q_val)
{
struct software_jpegenc_hdl *hdl = malloc(sizeof(struct software_jpegenc_hdl));
if (!hdl) {
printf("jpgenc hdl malloc fail \n");
return NULL;
}
memset(hdl, 0x00, sizeof(struct software_jpegenc_hdl));
//获取jpg头信息大小
int heapsize = jpgenc_get_heapsize(img_width, img_height);
/* printf("jpgenc heapsize:%d \n",heapsize); */
// 申请jpg头部控件
u8 *heap = malloc(heapsize);
if (!heap) {
printf("jpgenc heap malloc fail \n");
free(hdl);
return NULL;
}
//JPG图像编码初始化
u8 *header;
int header_size;
void *jfif = jpgenc_init(heap, img_width, img_height, img_stride, q_val);
jpgenc_get_header(jfif, &header, &header_size);
/* printf("jpgenc header_size:%d \n",header_size); */
hdl->jfif = jfif;
hdl->heap = heap;
hdl->jpeg_header = header;
hdl->jpeg_header_size = header_size;
return (void *)hdl;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief software_jpegenc_line jpeg软件分行编码
*
* @param jpgenc_hdl 编码句柄,software_jpegenc_init获取
* @param out_buf 编码位流保存buf
* @param out_buf_size 编码位流保存buf大小
* @param in_data 待编码的YUYV数据buf
* @param vlen 编码行数
* @param voff 编码行数偏移
* @param jpgenc_out_size 此次编码输出位流的大小
*
* @return 0:成功 -1:失败
*/
/* ------------------------------------------------------------------------------------*/
int software_jpegenc_line(void *jpgenc_hdl, u8 *out_buf, int out_buf_size, u8 *in_data, int vlen, int voff, int *jpgenc_out_size)
{
if (!jpgenc_hdl || !out_buf || !in_data) {
printf("jpgenc ptr err \n");
return -1;
}
struct software_jpegenc_hdl *hdl = (struct software_jpegenc_hdl *)jpgenc_hdl;
int total_size = 0;
u8 *buf_ptr = out_buf;
int buf_size = out_buf_size;
if (voff == 0) {
if (buf_size < hdl->jpeg_header_size) {
printf("jpgenc header buf_size err buf_size:%d need size:%d \n",
buf_size, hdl->jpeg_header_size);
return -1;
}
memcpy(out_buf, hdl->jpeg_header, hdl->jpeg_header_size);
buf_ptr += hdl->jpeg_header_size;
buf_size -= hdl->jpeg_header_size;
total_size += hdl->jpeg_header_size;
}
int out_size = buf_size;
jpgenc_encode_yuyv(hdl->jfif, in_data, buf_ptr, &out_size, vlen, voff);
if (out_size == buf_size) {
printf("jpgenc encode buf_size err \n");
return -1;
}
total_size += out_size;
*jpgenc_out_size = total_size;
return 0;
}
/* ------------------------------------------------------------------------------------*/
/**
* @brief software_jpegenc_exit jpeg软件编码退出流程,释放内存
*
* @param jpgenc_hdl init时申请的句柄
*
*/
/* ------------------------------------------------------------------------------------*/
void software_jpegenc_exit(void *jpgenc_hdl)
{
if (!jpgenc_hdl) {
return;
}
struct software_jpegenc_hdl *hdl = (struct software_jpegenc_hdl *)jpgenc_hdl;
if (hdl->heap) {
free(hdl->heap);
}
if (hdl->jfif) {
jpgenc_free(hdl->jfif);
}
free(hdl);
}
//测试代码
//os_task_create(software_jpegenc_demo_task,NULL,10,2048,1024,"jpegenc_demo_task");
void software_jpegenc_demo_task(void *priv)
{
mem_stats();
//1.128x128 YUYV
int img_width = 240; //图片宽
int img_height = 320; //图片高
int vlen = 32; //每次编码的行数
void *fp = NULL, *w_fp = NULL;
int jpeg_buf_size, yuv_buf_size, cur_enc_line, out_buf_size, jpgenc_out_total_size;
u8 *jpeg_buf = NULL, *yuv_buf = NULL, *out_buf = NULL;
void *enc_hdl = NULL;
uint32_t enc_time;
fp = (void *)fopen("storage/sd0/C/output1.yuy", "r");
if (!fp) {
printf("fopen err \n");
goto exit;
}
printf("yuv file len:%d \n", flen(fp));
//确保内存足够装下, 测试图片240*320 Q值50,编码出来8K内存
jpeg_buf_size = 20 * 1024;
jpeg_buf = malloc(jpeg_buf_size);
if (!jpeg_buf) {
printf("malloc jpg buf err \n");
mem_stats();
goto exit;
}
yuv_buf_size = img_width * vlen * 2;
yuv_buf = malloc(yuv_buf_size);
if (!yuv_buf) {
printf("malloc yuv buf err \n");
mem_stats();
goto exit;
}
enc_hdl = software_jpegenc_init(img_width, img_height, img_width, 50);
if (!enc_hdl) {
printf("software jpegenc init err \n");
goto exit;
}
cur_enc_line = 0;
out_buf = jpeg_buf;
out_buf_size = jpeg_buf_size;
jpgenc_out_total_size = 0;
enc_time = 0;
while (cur_enc_line < img_height) {
int jpgenc_out_size = 0;
if (fread(yuv_buf, 1, yuv_buf_size, fp) != yuv_buf_size) {
printf("yuv fread err \n");
goto exit;
}
uint32_t timer_get_ms(void);
uint32_t enc_start_time = timer_get_ms();
if (software_jpegenc_line(enc_hdl, out_buf, out_buf_size, yuv_buf, vlen, cur_enc_line, &jpgenc_out_size)) {
printf("software jpgenc line err \n");
goto exit;
}
enc_time += timer_get_ms() - enc_start_time;
out_buf += jpgenc_out_size;
out_buf_size -= jpgenc_out_size;
jpgenc_out_total_size += jpgenc_out_size;
cur_enc_line += vlen;
}
printf("jpgenc finish use time: %dms jpg size:%d \n", enc_time, jpgenc_out_total_size);
w_fp = fopen("storage/sd0/C/output1.jpg", "w+");
if (!w_fp) {
printf("jpeg fopen err \n");
goto exit;
}
if (fwrite(jpeg_buf, 1, jpgenc_out_total_size, w_fp) != jpgenc_out_total_size) {
printf("jpeg fwrite err \n");
goto exit;
}
exit:
printf("software_jpegenc_demo_task exit \n");
if (w_fp) {
fclose(w_fp);
w_fp = NULL;
}
if (fp) {
fclose(fp);
fp = NULL;
}
if (enc_hdl) {
software_jpegenc_exit(enc_hdl);
enc_hdl = NULL;
}
if (yuv_buf) {
free(yuv_buf);
yuv_buf = NULL;
}
if (jpeg_buf) {
free(jpeg_buf);
jpeg_buf = NULL;
}
mem_stats();
os_time_dly(-1);
}
@@ -0,0 +1,46 @@
#ifndef SOFTWARE_JPEGENC_H
#define SOFTWARE_JPEGENC_H
/* ------------------------------------------------------------------------------------*/
/**
* @brief software_jpegenc_init jpeg软件分行编码初始化
*
* @param img_width 图像宽
* @param img_height 图像高
* @param img_stride
* @param q_val 编码Q值,范围(1-100)
* @return enc_hdl_ptr:成功 NULL:失败
*/
/* ------------------------------------------------------------------------------------*/
void *software_jpegenc_init(int img_width, int img_height, int img_stride, int q_val);
/* ------------------------------------------------------------------------------------*/
/**
* @brief software_jpegenc_line jpeg软件分行编码
*
* @param jpgenc_hdl 编码句柄,software_jpegenc_init获取
* @param out_buf 编码位流保存buf
* @param out_buf_size 编码位流保存buf大小
* @param in_data 待编码的YUYV数据buf
* @param vlen 编码行数
* @param voff 编码行数偏移
* @param jpgenc_out_size 此次编码输出位流的大小
*
* @return 0:成功 -1:失败
*/
/* ------------------------------------------------------------------------------------*/
int software_jpegenc_line(void *jpgenc_hdl, u8 *out_buf, int out_buf_size, u8 *in_data, int vlen, int voff, int *jpgenc_out_size);
/* ------------------------------------------------------------------------------------*/
/**
* @brief software_jpegenc_exit jpeg软件编码退出流程,释放内存
*
* @param jpgenc_hdl init时申请的句柄
*
*/
/* ------------------------------------------------------------------------------------*/
void software_jpegenc_exit(void *jpgenc_hdl);
#endif /* SOFTWARE_JPEGENC_H */