Skip to content

Commit

Permalink
Merge branch 'feature/jpeg_encoder' into 'master'
Browse files Browse the repository at this point in the history
feat(jpge): Add basic support for jpeg encoder 🖼️

See merge request espressif/esp-idf!29411
  • Loading branch information
mythbuster5 committed Apr 1, 2024
2 parents b18a039 + 69835eb commit 4921c63
Show file tree
Hide file tree
Showing 37 changed files with 1,885 additions and 18 deletions.
2 changes: 1 addition & 1 deletion .codespellrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[codespell]
skip = build,*.yuv,components/fatfs/src/*,alice.txt
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb
ignore-words-list = ser,dout,rsource,fram,inout
write-changes = true
3 changes: 2 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ repos:
.*_pb2.py|
.*.pb-c.h|
.*.pb-c.c|
.*.yuv
.*.yuv|
.*.rgb
)$
- id: end-of-file-fixer
exclude: *whitespace_excludes
Expand Down
6 changes: 6 additions & 0 deletions components/esp_driver_jpeg/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ if(CONFIG_SOC_JPEG_CODEC_SUPPORTED)
"jpeg_decode.c"
)
endif()
if(CONFIG_SOC_JPEG_ENCODE_SUPPORTED)
list(APPEND srcs
"jpeg_emit_marker.c"
"jpeg_encode.c"
)
endif()
endif()

idf_component_register(SRCS ${srcs}
Expand Down
2 changes: 1 addition & 1 deletion components/esp_driver_jpeg/include/driver/jpeg_decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ esp_err_t jpeg_del_decoder_engine(jpeg_decoder_handle_t decoder_engine);
* @param[out] allocated_size Actual allocated buffer size.
* @return Pointer to the allocated memory space, or NULL if allocation fails.
*/
void *jpeg_alloc_decoder_mem(size_t size, jpeg_decode_memory_alloc_cfg_t *mem_cfg, size_t *allocated_size);
void *jpeg_alloc_decoder_mem(size_t size, const jpeg_decode_memory_alloc_cfg_t *mem_cfg, size_t *allocated_size);

#ifdef __cplusplus
}
Expand Down
103 changes: 103 additions & 0 deletions components/esp_driver_jpeg/include/driver/jpeg_encode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <stdint.h>
#include "esp_err.h"
#include "jpeg_types.h"
#include "hal/jpeg_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief JPEG encoder configure structure
*/
typedef struct {
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 */
} jpeg_encode_cfg_t;

/**
* @brief Configuration parameters for the JPEG encode engine.
*/
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 */
} 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_encode_memory_alloc_cfg_t;

/**
* @brief Allocate JPEG encoder
*
* @param[in] enc_eng_cfg config for jpeg encoder
* @param[out] ret_encoder handle for jpeg encoder
* @return
* - ESP_OK: JPEG encoder initialized successfully.
* - ESP_ERR_INVALID_ARG: JPEG encoder initialization failed because of invalid argument.
* - ESP_ERR_NO_MEM: Create JPEG encoder failed because of out of memory.
*/
esp_err_t jpeg_new_encoder_engine(const jpeg_encode_engine_cfg_t *enc_eng_cfg, jpeg_encoder_handle_t *ret_encoder);

/**
* @brief Process encoding of JPEG data using the specified encoder engine.
*
* This function processes the encoding of JPEG data using the provided encoder engine
* and configuration. It takes an input buffer containing the raw image data, performs
* encoding based on the configuration settings, and outputs the compressed bitstream.
*
* @param[in] encoder_engine Handle to the JPEG encoder engine to be used for encoding.
* @param[in] encode_cfg Pointer to the configuration structure for the JPEG encoding process.
* @param[in] encode_inbuf Pointer to the input buffer containing the raw image data.
* @param[in] inbuf_size Size of the input buffer in bytes.
* @param[in] encode_outbuf Pointer to the output buffer where the compressed bitstream will be stored.
* @param[in] outbuf_size The size of output buffer.
* @param[out] out_size Pointer to a variable where the size of the output bitstream will be stored.
*
* @return
* - ESP_OK: JPEG encoder process successfully.
* - ESP_ERR_INVALID_ARG: JPEG encoder process failed because of invalid argument.
* - ESP_ERR_TIMEOUT: JPEG encoder process timeout.
*/
esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_encode_cfg_t *encode_cfg, const uint8_t *encode_inbuf, uint32_t inbuf_size, uint8_t *encode_outbuf, uint32_t outbuf_size, uint32_t *out_size);

/**
* @brief Release resources used by a JPEG encoder instance.
*
* This function releases the resources used by the specified JPEG encoder instance. The encoder instance is
* specified by the `encoder_engine` parameter.
*
* @param[in] encoder_engine Handle of the JPEG encoder instance to release resources for.
* @return
* - ESP_OK: Delete JPEG encoder successfully.
* - ESP_ERR_INVALID_ARG: Delete JPEG encoder failed because of invalid argument.
*/
esp_err_t jpeg_del_encoder_engine(jpeg_encoder_handle_t encoder_engine);

/**
* @brief A helper function to allocate memory space for JPEG encoder.
*
* @param[in] size The size of memory to allocate.
* @param[in] mem_cfg Memory configuration for memory allocation
* @param[out] allocated_size Actual allocated buffer size.
* @return Pointer to the allocated memory space, or NULL if allocation fails.
*/
void *jpeg_alloc_encoder_mem(size_t size, const jpeg_encode_memory_alloc_cfg_t *mem_cfg, size_t *allocated_size);

#ifdef __cplusplus
}
#endif
27 changes: 27 additions & 0 deletions components/esp_driver_jpeg/include/driver/jpeg_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,38 @@ typedef enum {
JPEG_DEC_ALLOC_OUTPUT_BUFFER = 1, /*!< Alloc the picture output buffer, (decompressed format in decoder) */
} jpeg_dec_buffer_alloc_direction_t;

/**
* @brief Enumeration for jpeg input format.
*/
typedef enum {
JPEG_ENCODE_IN_FORMAT_RGB888 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB888), /*!< input RGB888 format */
JPEG_ENCODE_IN_FORMAT_RGB565 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB565), /*!< input RGB565 format */
JPEG_ENCODE_IN_FORMAT_GRAY = COLOR_TYPE_ID(COLOR_SPACE_GRAY, COLOR_PIXEL_GRAY8), /*!< input GRAY format */
} jpeg_enc_input_format_t;

/**
* @brief Enumeration for jpeg encoder alloc buffer direction.
*/
typedef enum {
JPEG_ENC_ALLOC_INPUT_BUFFER = 0, /*!< Alloc the picture input buffer, (decompressed format in encoder) */
JPEG_ENC_ALLOC_OUTPUT_BUFFER = 1, /*!< Alloc the picture output buffer, (compressed format in encoder) */
} jpeg_enc_buffer_alloc_direction_t;

/**
* @brief Type of jpeg decoder handle
*/
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
*/
typedef struct jpeg_encoder_t *jpeg_encoder_handle_t;

#ifdef __cplusplus
}
#endif
8 changes: 3 additions & 5 deletions components/esp_driver_jpeg/jpeg_decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@

static const char *TAG = "jpeg.decoder";

#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))

static void s_decoder_error_log_print(uint32_t status);
static esp_err_t jpeg_dec_config_dma_descriptor(jpeg_decoder_handle_t decoder_engine);
static esp_err_t jpeg_parse_marker(jpeg_decoder_handle_t decoder_engine, const uint8_t *in_buf, uint32_t inbuf_len);
Expand Down Expand Up @@ -77,7 +75,7 @@ esp_err_t jpeg_new_decoder_engine(const jpeg_decode_engine_cfg_t *dec_eng_cfg, j

uint32_t cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA);
uint32_t alignment = cache_line_size;
size_t dma_desc_mem_size = ALIGN_UP(sizeof(dma2d_descriptor_t), cache_line_size);
size_t dma_desc_mem_size = JPEG_ALIGN_UP(sizeof(dma2d_descriptor_t), cache_line_size);

decoder_engine->rxlink = (dma2d_descriptor_t*)heap_caps_aligned_calloc(alignment, 1, dma_desc_mem_size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | JPEG_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(decoder_engine->rxlink, ESP_ERR_NO_MEM, err, TAG, "no memory for jpeg decode rxlink");
Expand Down Expand Up @@ -279,7 +277,7 @@ esp_err_t jpeg_del_decoder_engine(jpeg_decoder_handle_t decoder_engine)
return ESP_OK;
}

void *jpeg_alloc_decoder_mem(size_t size, jpeg_decode_memory_alloc_cfg_t *mem_cfg, size_t *allocated_size)
void *jpeg_alloc_decoder_mem(size_t size, const jpeg_decode_memory_alloc_cfg_t *mem_cfg, size_t *allocated_size)
{
/*
Principle of buffer align.
Expand All @@ -289,7 +287,7 @@ void *jpeg_alloc_decoder_mem(size_t size, jpeg_decode_memory_alloc_cfg_t *mem_cf
size_t cache_align = 0;
esp_cache_get_alignment(ESP_CACHE_MALLOC_FLAG_PSRAM, &cache_align);
if (mem_cfg->buffer_direction == JPEG_DEC_ALLOC_OUTPUT_BUFFER) {
size = ALIGN_UP(size, cache_align);
size = JPEG_ALIGN_UP(size, cache_align);
*allocated_size = size;
return heap_caps_aligned_calloc(cache_align, 1, size, MALLOC_CAP_SPIRAM);
} else {
Expand Down
Loading

0 comments on commit 4921c63

Please sign in to comment.