Merge branch 'cleanup/jpeg_encoder' into 'master'

change(jpeg): Clean up some mess code in jpeg encoder

See merge request espressif/esp-idf!30075
This commit is contained in:
C.S.M 2024-04-09 13:30:55 +08:00
commit e867b129f0
10 changed files with 26 additions and 33 deletions

View File

@ -19,11 +19,11 @@ extern "C" {
* @brief JPEG encoder configure structure
*/
typedef struct {
uint32_t height; /*!< Number of pixels in the horizontal direction */
uint32_t height; /*!< Number of pixels in the horizontal direction */
uint32_t width; /*!< Number of pixels in the vertical direction */
jpeg_enc_input_format_t src_type; /*!< Source type of raw image to be encoded, see `jpeg_enc_src_type_t` */
jpeg_down_sampling_type_t sub_sample; /*!< JPEG subsampling method */
uint32_t image_quality; /*!< JPEG compressing quality, value from 1-100 */
uint32_t image_quality; /*!< JPEG compressing quality, value from 1-100, higher value means higher quality */
} jpeg_encode_cfg_t;
/**
@ -31,14 +31,14 @@ typedef struct {
*/
typedef struct {
int intr_priority; /*!< JPEG interrupt priority, if set to 0, driver will select the default priority (1,2,3). */
int timeout_ms; /*!< JPEG timeout threshold for handling a picture, should larger than valid decode time in ms. For example, for 30fps decode, this value must larger than 34. -1 means wait forever */
int timeout_ms; /*!< JPEG timeout threshold for handling a picture, should larger than valid encode time in ms. For example, for 30fps encode, this value must larger than 34. -1 means wait forever */
} jpeg_encode_engine_cfg_t;
/**
* @brief JPEG encoder memory allocation config
*/
typedef struct {
jpeg_enc_buffer_alloc_direction_t buffer_direction; /*!< Buffer direction for jpeg decoder memory allocation */
jpeg_enc_buffer_alloc_direction_t buffer_direction; /*!< Buffer direction for jpeg encoder memory allocation */
} jpeg_encode_memory_alloc_cfg_t;
/**

View File

@ -68,11 +68,6 @@ typedef enum {
*/
typedef struct jpeg_decoder_t *jpeg_decoder_handle_t;
/**
* @brief Type of jpeg codec handle
*/
typedef struct jpeg_codec_t *jpeg_codec_handle_t;
/**
* @brief Type of jpeg encoder handle
*/

View File

@ -6,6 +6,7 @@
#include <stdio.h>
#include <string.h>
#include "sys/param.h"
#include "esp_log.h"
#include "jpeg_private.h"
#include "private/jpeg_param.h"
@ -13,9 +14,6 @@
#include "hal/jpeg_defs.h"
#include "esp_private/esp_cache_private.h"
#define JPEG_MAX(a, b) (((a) > (b)) ? (a) : (b))
#define JPEG_MIN(a, b) (((a) < (b)) ? (a) : (b))
static void emit_byte(jpeg_enc_header_info_t *header_info, uint8_t i)
{
header_info->header_buf[header_info->header_len] = i;
@ -66,7 +64,7 @@ static void compute_quant_table(uint32_t *quant_table, const uint32_t *basic_tab
for (int i = 0; i < 64; i++) {
int temp = *basic_table++;
temp = (temp * scaling_factor + 50L) / 100L;
*quant_table++ = JPEG_MIN(JPEG_MAX(temp, 1), 255);
*quant_table++ = MIN(MAX(temp, 1), 255);
}
}
@ -232,7 +230,10 @@ esp_err_t emit_com_marker(jpeg_enc_header_info_t *header_info)
size_t cache_align = 0;
esp_cache_get_alignment(ESP_CACHE_MALLOC_FLAG_PSRAM, &cache_align);
// compensate_size = aligned_size - SOS marker size(2 * header_info->num_components + 2 + 1 + 3 + 2) - COM marker size(4).
uint32_t compensate_size = ((header_info->header_len / cache_align + 1) * cache_align) - header_info->header_len - (2 * header_info->num_components + 2 + 1 + 3 + 2) - 4;
int compensate_size = ((header_info->header_len / cache_align + 1) * cache_align) - header_info->header_len - (2 * header_info->num_components + 2 + 1 + 3 + 2) - 4;
if (compensate_size < 0) {
compensate_size += cache_align;
}
emit_marker(header_info, JPEG_M_COM & 0xff);
emit_word(header_info, compensate_size);
for (int i = 0; i < compensate_size; i++) {

View File

@ -441,7 +441,7 @@ static void s_jpeg_enc_config_picture_color_space(jpeg_encoder_handle_t encoder_
{
jpeg_hal_context_t *hal = &encoder_engine->codec_base->hal;
color_space_pixel_format_t picture_format;
jpeg_ll_config_picture_color_space(hal->dev, encoder_engine->color_space);
jpeg_ll_config_picture_pixel_format(hal->dev, encoder_engine->color_space);
picture_format.color_type_id = encoder_engine->picture_format;
encoder_engine->bytes_per_pixel = color_hal_pixel_format_get_bit_depth(picture_format);
if (encoder_engine->color_space == JPEG_ENC_SRC_GRAY) {

View File

@ -1,2 +1,4 @@
| Supported Targets | ESP32-P4 |
| ----------------- | -------- |
jpeg_decoder can be used to generate '*.rgb' file which to be used for this test.

View File

@ -68,12 +68,12 @@ TEST_CASE("JPEG encode performance test for 480*640 RGB->YUV picture", "[jpeg]")
uint32_t jpg_size_480p = 0;
size_t bit_stream_length = (size_t)image_esp480_rgb_end - (size_t)image_esp480_rgb_start;
size_t rgb_file_size = (size_t)image_esp480_rgb_end - (size_t)image_esp480_rgb_start;
size_t tx_buffer_size = 0;
uint8_t *raw_buf_480p = (uint8_t*)jpeg_alloc_encoder_mem(bit_stream_length, &tx_mem_cfg, &tx_buffer_size);
uint8_t *raw_buf_480p = (uint8_t*)jpeg_alloc_encoder_mem(rgb_file_size, &tx_mem_cfg, &tx_buffer_size);
// Copy bit stream to psram
memcpy(raw_buf_480p, image_esp480_rgb_start, bit_stream_length);
memcpy(raw_buf_480p, image_esp480_rgb_start, rgb_file_size);
TEST_ESP_OK(jpeg_new_encoder_engine(&encode_eng_cfg, &jpeg_handle));
ccomp_timer_start();
@ -81,7 +81,7 @@ TEST_CASE("JPEG encode performance test for 480*640 RGB->YUV picture", "[jpeg]")
// Decode picture for 50 times, and get the average
uint8_t cnt = 50;
for (int i = 0; i < cnt; i++) {
TEST_ESP_OK(jpeg_encoder_process(jpeg_handle, &enc_config, raw_buf_480p, bit_stream_length, jpg_buf_480p, rx_buffer_size, &jpg_size_480p));
TEST_ESP_OK(jpeg_encoder_process(jpeg_handle, &enc_config, raw_buf_480p, rgb_file_size, jpg_buf_480p, rx_buffer_size, &jpg_size_480p));
}
int64_t encode_time = ccomp_timer_stop();

View File

@ -632,10 +632,10 @@ static inline uint32_t jpeg_ll_get_intr_status(jpeg_dev_t *hw)
return hw->int_st.val;
}
static inline void jpeg_ll_config_picture_color_space(jpeg_dev_t *hw, jpeg_enc_src_type_t color_space)
static inline void jpeg_ll_config_picture_pixel_format(jpeg_dev_t *hw, jpeg_enc_src_type_t pixel_format)
{
uint8_t cs = 0;
switch (color_space) {
switch (pixel_format) {
case JPEG_ENC_SRC_RGB888:
cs = 0;
break;

View File

@ -10,6 +10,7 @@ Peripherals API
:SOC_ADC_DMA_SUPPORTED: adc_continuous
:SOC_ADC_SUPPORTED: adc_calibration
:SOC_ANA_CMPR_SUPPORTED: ana_cmpr
:SOC_MIPI_CSI_SUPPORTED: camera_driver
:SOC_CLK_TREE_SUPPORTED: clk_tree
:SOC_DAC_SUPPORTED: dac
:SOC_ECDSA_SUPPORTED: ecdsa
@ -22,11 +23,10 @@ Peripherals API
i2c
:SOC_I2S_SUPPORTED: i2s
:SOC_ISP_SUPPORTED: isp
:SOC_JPEG_CODEC_SUPPORTED: jpeg
lcd/index
:SOC_GP_LDO_SUPPORTED: ldo_regulator
ledc
:SOC_JPEG_CODEC_SUPPORTED: jpeg
:SOC_MIPI_CSI_SUPPORTED: camera_driver
:SOC_MCPWM_SUPPORTED: mcpwm
:SOC_PARLIO_SUPPORTED: parlio
:SOC_PCNT_SUPPORTED: pcnt

View File

@ -17,6 +17,7 @@ This example makes use of the hardware-based JPEG encoder. If you have multiple
* A USB cable for power supply and serial communication
* Computer with ESP-IDF installed and configured
* The raw picture is the only source that you need to prepare (We have an [esp1080p.rgb](https://github.com/espressif/esp-idf/tree/master/examples/peripherals/jpeg/jpeg_encode/resources/esp1080.rgb) in resources folder, you can also get it from [jpeg_decode](https://github.com/espressif/esp-idf/tree/master/examples/peripherals/jpeg/jpeg_decode) example).
* ffmpeg can also be used to produce rgb picture. For example `ffmpeg -i input.jpg -pix_fmt rgb24 output.rgb`
### Build and Flash

View File

@ -90,26 +90,20 @@ void app_main(void)
.buffer_direction = JPEG_DEC_ALLOC_INPUT_BUFFER,
};
jpeg_new_encoder_engine(&encode_eng_cfg, &jpeg_handle);
ESP_ERROR_CHECK(jpeg_new_encoder_engine(&encode_eng_cfg, &jpeg_handle));
// Read 1080p raw picture
fseek(file_raw_1080p, 0, SEEK_END);
raw_size_1080p = ftell(file_raw_1080p);
fseek(file_raw_1080p, 0, SEEK_SET);
size_t tx_buffer_size = 0;
uint8_t *raw_buf_1080p = (uint8_t*)jpeg_alloc_encoder_mem(raw_size_1080p, &tx_mem_cfg, &tx_buffer_size);
if (raw_buf_1080p == NULL) {
ESP_LOGE(TAG, "alloc 1080p tx buffer error");
return;
}
assert(raw_buf_1080p != NULL);
fread(raw_buf_1080p, 1, raw_size_1080p, file_raw_1080p);
fclose(file_raw_1080p);
size_t rx_buffer_size = 0;
uint8_t *jpg_buf_1080p = (uint8_t*)jpeg_alloc_encoder_mem(raw_size_1080p / 10, &rx_mem_cfg, &rx_buffer_size); // Assume that compression ratio of 10 to 1
if (jpg_buf_1080p == NULL) {
ESP_LOGE(TAG, "alloc jpg_buf_1080p error");
return;
}
assert(jpg_buf_1080p != NULL);
jpeg_encode_cfg_t enc_config = {
.src_type = JPEG_ENCODE_IN_FORMAT_RGB888,
@ -119,7 +113,7 @@ void app_main(void)
.height = 1080,
};
jpeg_encoder_process(jpeg_handle, &enc_config, raw_buf_1080p, raw_size_1080p, jpg_buf_1080p, rx_buffer_size, &jpg_size_1080p);
ESP_ERROR_CHECK(jpeg_encoder_process(jpeg_handle, &enc_config, raw_buf_1080p, raw_size_1080p, jpg_buf_1080p, rx_buffer_size, &jpg_size_1080p));
FILE *file_jpg_1080p = fopen(s_outfile_1080p, "wb");
ESP_LOGI(TAG, "outfile:%s", s_outfile_1080p);