mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
fix(jpeg_decoder): Improve apis for better align strategy and provide buffer size parameter
This commit is contained in:
parent
9ffebf3cf2
commit
ba6a0d59b0
@ -19,7 +19,7 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
jpeg_dec_output_format_t output_format; /*!< JPEG decoder output format */
|
jpeg_dec_output_format_t output_format; /*!< JPEG decoder output format */
|
||||||
jpeg_dec_rgb_element_order rgb_order; /*!< JPEG decoder output order */
|
jpeg_dec_rgb_element_order_t rgb_order; /*!< JPEG decoder output order */
|
||||||
jpeg_yuv_rgb_conv_std_t conv_std; /*!< JPEG decoder yuv->rgb standard */
|
jpeg_yuv_rgb_conv_std_t conv_std; /*!< JPEG decoder yuv->rgb standard */
|
||||||
} jpeg_decode_cfg_t;
|
} jpeg_decode_cfg_t;
|
||||||
|
|
||||||
@ -39,6 +39,13 @@ typedef struct {
|
|||||||
uint32_t height; /*!< Number of pixels in the vertical direction */
|
uint32_t height; /*!< Number of pixels in the vertical direction */
|
||||||
} jpeg_decode_picture_info_t;
|
} jpeg_decode_picture_info_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief JPEG decoder memory allocation config
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
jpeg_dec_buffer_alloc_direction_t buffer_direction; /*!< Buffer direction for jpeg decoder memory allocation */
|
||||||
|
} jpeg_decode_memory_alloc_cfg_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Acquire a JPEG decode engine with the specified configuration.
|
* @brief Acquire a JPEG decode engine with the specified configuration.
|
||||||
*
|
*
|
||||||
@ -82,19 +89,21 @@ esp_err_t jpeg_decoder_get_info(const uint8_t *bit_stream, uint32_t stream_size,
|
|||||||
* decoded image data is written to the `decode_outbuf` buffer, and the length of the output image data is
|
* decoded image data is written to the `decode_outbuf` buffer, and the length of the output image data is
|
||||||
* returned through the `out_size` pointer.
|
* returned through the `out_size` pointer.
|
||||||
*
|
*
|
||||||
* @note Please make sure that the content of `bit_stream` pointer cannot be modified until this function returns.
|
* @note 1.Please make sure that the content of `bit_stream` pointer cannot be modified until this function returns.
|
||||||
|
* 2.Please note that the output size of image is always the multiple of 16 depends on protocol of JPEG.
|
||||||
*
|
*
|
||||||
* @param[in] decoder_engine Handle of the JPEG decoder instance to use for processing.
|
* @param[in] decoder_engine Handle of the JPEG decoder instance to use for processing.
|
||||||
* @param[in] decode_cfg Config structure of decoder.
|
* @param[in] decode_cfg Config structure of decoder.
|
||||||
* @param[in] bit_stream Pointer to the buffer containing the input JPEG image data.
|
* @param[in] bit_stream Pointer to the buffer containing the input JPEG image data.
|
||||||
* @param[in] stream_size Size of the input JPEG image data in bytes.
|
* @param[in] stream_size Size of the input JPEG image data in bytes.
|
||||||
* @param[out] decode_outbuf Pointer to the buffer that will receive the decoded image data.
|
* @param[in] decode_outbuf Pointer to the buffer that will receive the decoded image data.
|
||||||
|
* @param[in] outbuf_size The size of `decode_outbuf`
|
||||||
* @param[out] out_size Pointer to a variable that will receive the length of the output image data.
|
* @param[out] out_size Pointer to a variable that will receive the length of the output image data.
|
||||||
* @return
|
* @return
|
||||||
* - ESP_OK: JPEG decoder process successfully.
|
* - ESP_OK: JPEG decoder process successfully.
|
||||||
* - ESP_ERR_INVALID_ARG: JPEG decoder process failed because of invalid argument.
|
* - ESP_ERR_INVALID_ARG: JPEG decoder process failed because of invalid argument.
|
||||||
*/
|
*/
|
||||||
esp_err_t jpeg_decoder_process(jpeg_decoder_handle_t decoder_engine, const jpeg_decode_cfg_t *decode_cfg, const uint8_t *bit_stream, uint32_t stream_size, uint8_t *decode_outbuf, uint32_t *out_size);
|
esp_err_t jpeg_decoder_process(jpeg_decoder_handle_t decoder_engine, const jpeg_decode_cfg_t *decode_cfg, const uint8_t *bit_stream, uint32_t stream_size, uint8_t *decode_outbuf, uint32_t outbuf_size, uint32_t *out_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Release resources used by a JPEG decoder instance.
|
* @brief Release resources used by a JPEG decoder instance.
|
||||||
@ -112,10 +121,12 @@ esp_err_t jpeg_del_decoder_engine(jpeg_decoder_handle_t decoder_engine);
|
|||||||
/**
|
/**
|
||||||
* @brief A helper function to allocate memory space for JPEG decoder.
|
* @brief A helper function to allocate memory space for JPEG decoder.
|
||||||
*
|
*
|
||||||
* @param size The size of memory to allocate.
|
* @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.
|
* @return Pointer to the allocated memory space, or NULL if allocation fails.
|
||||||
*/
|
*/
|
||||||
void * jpeg_alloc_decoder_mem(size_t size);
|
void *jpeg_alloc_decoder_mem(size_t size, jpeg_decode_memory_alloc_cfg_t *mem_cfg, size_t *allocated_size);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,15 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
JPEG_DEC_RGB_ELEMENT_ORDER_BGR = COLOR_RGB_ELEMENT_ORDER_BGR, /*!< Output the color component in small endian */
|
JPEG_DEC_RGB_ELEMENT_ORDER_BGR = COLOR_RGB_ELEMENT_ORDER_BGR, /*!< Output the color component in small endian */
|
||||||
JPEG_DEC_RGB_ELEMENT_ORDER_RGB = COLOR_RGB_ELEMENT_ORDER_RGB, /*!< Output the color component in big endian */
|
JPEG_DEC_RGB_ELEMENT_ORDER_RGB = COLOR_RGB_ELEMENT_ORDER_RGB, /*!< Output the color component in big endian */
|
||||||
} jpeg_dec_rgb_element_order;
|
} jpeg_dec_rgb_element_order_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enumeration for jpeg decoder alloc buffer direction.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
JPEG_DEC_ALLOC_INPUT_BUFFER = 0, /*!< Alloc the picture input buffer, (compressed format in decoder) */
|
||||||
|
JPEG_DEC_ALLOC_OUTPUT_BUFFER = 1, /*!< Alloc the picture output buffer, (decompressed format in decoder) */
|
||||||
|
} jpeg_dec_buffer_alloc_direction_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Type of jpeg decoder handle
|
* @brief Type of jpeg decoder handle
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "soc/dma2d_channel.h"
|
#include "soc/dma2d_channel.h"
|
||||||
#include "soc/interrupts.h"
|
#include "soc/interrupts.h"
|
||||||
#include "esp_dma_utils.h"
|
#include "esp_dma_utils.h"
|
||||||
|
#include "esp_private/esp_cache_private.h"
|
||||||
#if CONFIG_JPEG_ENABLE_DEBUG_LOG
|
#if CONFIG_JPEG_ENABLE_DEBUG_LOG
|
||||||
// The local log level must be defined before including esp_log.h
|
// The local log level must be defined before including esp_log.h
|
||||||
// Set the maximum log level for this source file
|
// Set the maximum log level for this source file
|
||||||
@ -172,13 +173,12 @@ esp_err_t jpeg_decoder_get_info(const uint8_t *in_buf, uint32_t inbuf_len, jpeg_
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t jpeg_decoder_process(jpeg_decoder_handle_t decoder_engine, const jpeg_decode_cfg_t *decode_cfg, const uint8_t *bit_stream, uint32_t stream_size, uint8_t *decode_outbuf, uint32_t *out_size)
|
esp_err_t jpeg_decoder_process(jpeg_decoder_handle_t decoder_engine, const jpeg_decode_cfg_t *decode_cfg, const uint8_t *bit_stream, uint32_t stream_size, uint8_t *decode_outbuf, uint32_t outbuf_size, uint32_t *out_size)
|
||||||
{
|
{
|
||||||
ESP_RETURN_ON_FALSE(decoder_engine, ESP_ERR_INVALID_ARG, TAG, "jpeg decode handle is null");
|
ESP_RETURN_ON_FALSE(decoder_engine, ESP_ERR_INVALID_ARG, TAG, "jpeg decode handle is null");
|
||||||
ESP_RETURN_ON_FALSE(decode_cfg, ESP_ERR_INVALID_ARG, TAG, "jpeg decode config is null");
|
ESP_RETURN_ON_FALSE(decode_cfg, ESP_ERR_INVALID_ARG, TAG, "jpeg decode config is null");
|
||||||
ESP_RETURN_ON_FALSE(decode_outbuf, ESP_ERR_INVALID_ARG, TAG, "jpeg decode picture buffer is null");
|
ESP_RETURN_ON_FALSE(decode_outbuf, ESP_ERR_INVALID_ARG, TAG, "jpeg decode picture buffer is null");
|
||||||
ESP_RETURN_ON_FALSE(((uintptr_t)bit_stream % cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA)) == 0, ESP_ERR_INVALID_ARG, TAG, "jpeg decode bit stream is not aligned, please use jpeg_alloc_decoder_mem to malloc your buffer");
|
ESP_RETURN_ON_FALSE(esp_dma_is_buffer_aligned(decode_outbuf, outbuf_size, ESP_DMA_BUF_LOCATION_PSRAM), ESP_ERR_INVALID_ARG, TAG, "jpeg decode decode_outbuf or out_buffer size is not aligned, please use jpeg_alloc_decoder_mem to malloc your buffer");
|
||||||
ESP_RETURN_ON_FALSE(((uintptr_t)decode_outbuf % cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA)) == 0, ESP_ERR_INVALID_ARG, TAG, "jpeg decode decode_outbuf is not aligned, please use jpeg_alloc_decoder_mem to malloc your buffer");
|
|
||||||
|
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
|
|
||||||
@ -200,6 +200,9 @@ esp_err_t jpeg_decoder_process(jpeg_decoder_handle_t decoder_engine, const jpeg_
|
|||||||
ESP_GOTO_ON_ERROR(jpeg_parse_header_info_to_hw(decoder_engine), err, TAG, "write header info to hw failed");
|
ESP_GOTO_ON_ERROR(jpeg_parse_header_info_to_hw(decoder_engine), err, TAG, "write header info to hw failed");
|
||||||
ESP_GOTO_ON_ERROR(jpeg_dec_config_dma_descriptor(decoder_engine), err, TAG, "config dma descriptor failed");
|
ESP_GOTO_ON_ERROR(jpeg_dec_config_dma_descriptor(decoder_engine), err, TAG, "config dma descriptor failed");
|
||||||
|
|
||||||
|
*out_size = decoder_engine->header_info->process_h * decoder_engine->header_info->process_v * decoder_engine->pixel;
|
||||||
|
ESP_GOTO_ON_FALSE((*out_size <= outbuf_size), ESP_ERR_INVALID_ARG, err, TAG, "Given buffer size % " PRId32 " is smaller than actual jpeg decode output size % " PRId32 "the hight and width of output picture size will be adjusted to 16 bytes aligned automatically", outbuf_size, *out_size);
|
||||||
|
|
||||||
dma2d_trans_config_t trans_desc = {
|
dma2d_trans_config_t trans_desc = {
|
||||||
.tx_channel_num = 1,
|
.tx_channel_num = 1,
|
||||||
.rx_channel_num = 1,
|
.rx_channel_num = 1,
|
||||||
@ -212,10 +215,6 @@ esp_err_t jpeg_decoder_process(jpeg_decoder_handle_t decoder_engine, const jpeg_
|
|||||||
ret = esp_cache_msync((void*)decoder_engine->header_info->buffer_offset, decoder_engine->header_info->buffer_left, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
ret = esp_cache_msync((void*)decoder_engine->header_info->buffer_offset, decoder_engine->header_info->buffer_left, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
||||||
assert(ret == ESP_OK);
|
assert(ret == ESP_OK);
|
||||||
|
|
||||||
// Before 2DDMA starts. invalid memory space of decoded buffer
|
|
||||||
ret = esp_cache_msync((void*)decoder_engine->decoded_buf, decoder_engine->header_info->process_h * decoder_engine->header_info->process_v * decoder_engine->pixel, ESP_CACHE_MSYNC_FLAG_DIR_M2C | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
|
||||||
assert(ret == ESP_OK);
|
|
||||||
|
|
||||||
ESP_GOTO_ON_ERROR(dma2d_enqueue(decoder_engine->dma2d_group_handle, &trans_desc, decoder_engine->trans_desc), err, TAG, "enqueue dma2d failed");
|
ESP_GOTO_ON_ERROR(dma2d_enqueue(decoder_engine->dma2d_group_handle, &trans_desc, decoder_engine->trans_desc), err, TAG, "enqueue dma2d failed");
|
||||||
bool need_yield;
|
bool need_yield;
|
||||||
// Blocking for JPEG decode transaction finishes.
|
// Blocking for JPEG decode transaction finishes.
|
||||||
@ -234,12 +233,12 @@ esp_err_t jpeg_decoder_process(jpeg_decoder_handle_t decoder_engine, const jpeg_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (jpeg_dma2d_event.dma_evt & JPEG_DMA2D_RX_EOF) {
|
if (jpeg_dma2d_event.dma_evt & JPEG_DMA2D_RX_EOF) {
|
||||||
|
ret = esp_cache_msync((void*)decoder_engine->decoded_buf, outbuf_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
|
||||||
|
assert(ret == ESP_OK);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_size = decoder_engine->header_info->process_h * decoder_engine->header_info->process_v * decoder_engine->pixel;
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
xSemaphoreGive(decoder_engine->codec_base->codec_mutex);
|
xSemaphoreGive(decoder_engine->codec_base->codec_mutex);
|
||||||
if (decoder_engine->codec_base->pm_lock) {
|
if (decoder_engine->codec_base->pm_lock) {
|
||||||
@ -280,9 +279,23 @@ esp_err_t jpeg_del_decoder_engine(jpeg_decoder_handle_t decoder_engine)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * jpeg_alloc_decoder_mem(size_t size)
|
void *jpeg_alloc_decoder_mem(size_t size, jpeg_decode_memory_alloc_cfg_t *mem_cfg, size_t *allocated_size)
|
||||||
{
|
{
|
||||||
return heap_caps_aligned_calloc(cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA), 1, size, JPEG_MEM_ALLOC_CAPS);
|
/*
|
||||||
|
Principle of buffer align.
|
||||||
|
For output buffer(for decoder is 2DDMA write to PSRAM), both address and size should be aligned according to cache invalidate.
|
||||||
|
FOr input buffer(for decoder is PSRAM write to 2DDMA), no restriction for any align (both cache writeback and requirement from 2DDMA).
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
*allocated_size = size;
|
||||||
|
return heap_caps_aligned_calloc(cache_align, 1, size, MALLOC_CAP_SPIRAM);
|
||||||
|
} else {
|
||||||
|
*allocated_size = size;
|
||||||
|
return heap_caps_calloc(1, size, MALLOC_CAP_SPIRAM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
|
@ -93,7 +93,7 @@ struct jpeg_decoder_t {
|
|||||||
jpeg_dec_header_info_t *header_info; // Pointer to current picture information
|
jpeg_dec_header_info_t *header_info; // Pointer to current picture information
|
||||||
jpeg_down_sampling_type_t sample_method; // method of sampling the JPEG picture.
|
jpeg_down_sampling_type_t sample_method; // method of sampling the JPEG picture.
|
||||||
jpeg_dec_output_format_t output_format; // picture output format.
|
jpeg_dec_output_format_t output_format; // picture output format.
|
||||||
jpeg_dec_rgb_element_order rgb_order; // RGB pixel order
|
jpeg_dec_rgb_element_order_t rgb_order; // RGB pixel order
|
||||||
jpeg_yuv_rgb_conv_std_t conv_std; // YUV RGB conversion standard
|
jpeg_yuv_rgb_conv_std_t conv_std; // YUV RGB conversion standard
|
||||||
uint8_t pixel; // size per pixel
|
uint8_t pixel; // size per pixel
|
||||||
QueueHandle_t evt_queue; // jpeg event from 2DDMA and JPEG engine
|
QueueHandle_t evt_queue; // jpeg event from 2DDMA and JPEG engine
|
||||||
|
@ -52,12 +52,22 @@ TEST_CASE("JPEG decode performance test for 1080*1920 YUV->RGB picture", "[jpeg]
|
|||||||
.output_format = JPEG_DECODE_OUT_FORMAT_RGB565,
|
.output_format = JPEG_DECODE_OUT_FORMAT_RGB565,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t *rx_buf_1080p = (uint8_t*)jpeg_alloc_decoder_mem(1080 * 1920 * 3);
|
jpeg_decode_memory_alloc_cfg_t rx_mem_cfg = {
|
||||||
|
.buffer_direction = JPEG_DEC_ALLOC_OUTPUT_BUFFER,
|
||||||
|
};
|
||||||
|
|
||||||
|
jpeg_decode_memory_alloc_cfg_t tx_mem_cfg = {
|
||||||
|
.buffer_direction = JPEG_DEC_ALLOC_INPUT_BUFFER,
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t rx_buffer_size;
|
||||||
|
uint8_t *rx_buf_1080p = (uint8_t*)jpeg_alloc_decoder_mem(1080 * 1920 * 3, &rx_mem_cfg, &rx_buffer_size);
|
||||||
uint32_t out_size_1080p = 0;
|
uint32_t out_size_1080p = 0;
|
||||||
|
|
||||||
size_t bit_stream_length = (size_t)image_esp1080_jpg_end - (size_t)image_esp1080_jpg_start;
|
size_t bit_stream_length = (size_t)image_esp1080_jpg_end - (size_t)image_esp1080_jpg_start;
|
||||||
|
|
||||||
uint8_t *tx_buf_1080p = (uint8_t*)jpeg_alloc_decoder_mem(bit_stream_length);
|
size_t tx_buffer_size;
|
||||||
|
uint8_t *tx_buf_1080p = (uint8_t*)jpeg_alloc_decoder_mem(bit_stream_length, &tx_mem_cfg, &tx_buffer_size);
|
||||||
// Copy bit stream to psram
|
// Copy bit stream to psram
|
||||||
memcpy(tx_buf_1080p, image_esp1080_jpg_start, bit_stream_length);
|
memcpy(tx_buf_1080p, image_esp1080_jpg_start, bit_stream_length);
|
||||||
TEST_ESP_OK(jpeg_new_decoder_engine(&decode_eng_cfg, &jpgd_handle));
|
TEST_ESP_OK(jpeg_new_decoder_engine(&decode_eng_cfg, &jpgd_handle));
|
||||||
@ -67,7 +77,7 @@ TEST_CASE("JPEG decode performance test for 1080*1920 YUV->RGB picture", "[jpeg]
|
|||||||
// Decode picture for 50 times, and get the average
|
// Decode picture for 50 times, and get the average
|
||||||
uint8_t cnt = 50;
|
uint8_t cnt = 50;
|
||||||
for (int i = 0; i < cnt; i++) {
|
for (int i = 0; i < cnt; i++) {
|
||||||
TEST_ESP_OK(jpeg_decoder_process(jpgd_handle, &decode_cfg, tx_buf_1080p, bit_stream_length, rx_buf_1080p, &out_size_1080p));
|
TEST_ESP_OK(jpeg_decoder_process(jpgd_handle, &decode_cfg, tx_buf_1080p, bit_stream_length, rx_buf_1080p, rx_buffer_size, &out_size_1080p));
|
||||||
}
|
}
|
||||||
int64_t decode_time = ccomp_timer_stop();
|
int64_t decode_time = ccomp_timer_stop();
|
||||||
|
|
||||||
|
@ -67,8 +67,19 @@ Overall, You can take following code as reference, the code is going to decode a
|
|||||||
.rgb_order = JPEG_DEC_RGB_ELEMENT_ORDER_BGR,
|
.rgb_order = JPEG_DEC_RGB_ELEMENT_ORDER_BGR,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t *bit_stream = (uint8_t*)heap_caps_aligned_calloc(JPEG_BUFFER_MALLOC_ALIGN_VALUE, 1, bit_stream_size, MALLOC_CAP_SPIRAM);
|
size_t tx_buffer_size;
|
||||||
uint8_t *out_buf = (uint8_t*)heap_caps_aligned_calloc(JPEG_BUFFER_MALLOC_ALIGN_VALUE, 1, 1920 * 1080 * 3, MALLOC_CAP_SPIRAM); // Sufficient space for output images.
|
size_t rx_buffer_size;
|
||||||
|
|
||||||
|
jpeg_decode_memory_alloc_cfg_t rx_mem_cfg = {
|
||||||
|
.buffer_direction = JPEG_DEC_ALLOC_OUTPUT_BUFFER,
|
||||||
|
};
|
||||||
|
|
||||||
|
jpeg_decode_memory_alloc_cfg_t tx_mem_cfg = {
|
||||||
|
.buffer_direction = JPEG_DEC_ALLOC_INPUT_BUFFER,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t *bit_stream = (uint8_t*)jpeg_alloc_decoder_mem(jpeg_size, &tx_mem_cfg, &tx_buffer_size);
|
||||||
|
uint8_t *out_buf = (uint8_t*)jpeg_alloc_decoder_mem(1920 * 1088 * 3, &rx_mem_cfg, &rx_buffer_size);
|
||||||
|
|
||||||
jpeg_decode_picture_info_t header_info;
|
jpeg_decode_picture_info_t header_info;
|
||||||
ESP_ERROR_CHECK(jpeg_decoder_get_info(bit_stream, bit_stream_size, &header_info));
|
ESP_ERROR_CHECK(jpeg_decoder_get_info(bit_stream, bit_stream_size, &header_info));
|
||||||
@ -77,8 +88,9 @@ Overall, You can take following code as reference, the code is going to decode a
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Firstly, in above code, you should make sure the `bit_stream` and `out_buf` should be :c:macro:`JPEG_BUFFER_MALLOC_ALIGN_VALUE` byte aligned.
|
Firstly, in above code, you should make sure the `bit_stream` and `out_buf` should be aligned by certain rules. We provide a helper function :cpp:func:`jpeg_alloc_decoder_mem` to help you malloc a buffer which is aligned in both size and address.
|
||||||
Secondly, the content of `bit_stream` buffer should not be changed until :cpp:func:`jpeg_decoder_process` returns.
|
Secondly, the content of `bit_stream` buffer should not be changed until :cpp:func:`jpeg_decoder_process` returns.
|
||||||
|
Thirdly, the width and hight of output picture would be 16 bytes aligned if original picture is formatted by YUV420 or YUV422. For example, if the input picture is 1080*1920, the output picture will be 1088*1920. That is the restriction of jpeg protocol. Please provide sufficient output buffer memory.
|
||||||
|
|
||||||
Thread Safety
|
Thread Safety
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
@ -88,6 +88,14 @@ void app_main(void)
|
|||||||
.output_format = JPEG_DECODE_OUT_FORMAT_GRAY,
|
.output_format = JPEG_DECODE_OUT_FORMAT_GRAY,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
jpeg_decode_memory_alloc_cfg_t rx_mem_cfg = {
|
||||||
|
.buffer_direction = JPEG_DEC_ALLOC_OUTPUT_BUFFER,
|
||||||
|
};
|
||||||
|
|
||||||
|
jpeg_decode_memory_alloc_cfg_t tx_mem_cfg = {
|
||||||
|
.buffer_direction = JPEG_DEC_ALLOC_INPUT_BUFFER,
|
||||||
|
};
|
||||||
|
|
||||||
FILE *file_jpg_1080p = fopen(jpg_file_1080, "rb");
|
FILE *file_jpg_1080p = fopen(jpg_file_1080, "rb");
|
||||||
ESP_LOGI(TAG, "jpg_file_1080:%s", jpg_file_1080);
|
ESP_LOGI(TAG, "jpg_file_1080:%s", jpg_file_1080);
|
||||||
if (file_jpg_1080p == NULL) {
|
if (file_jpg_1080p == NULL) {
|
||||||
@ -98,7 +106,8 @@ void app_main(void)
|
|||||||
fseek(file_jpg_1080p, 0, SEEK_END);
|
fseek(file_jpg_1080p, 0, SEEK_END);
|
||||||
int jpeg_size_1080p = ftell(file_jpg_1080p);
|
int jpeg_size_1080p = ftell(file_jpg_1080p);
|
||||||
fseek(file_jpg_1080p, 0, SEEK_SET);
|
fseek(file_jpg_1080p, 0, SEEK_SET);
|
||||||
uint8_t *tx_buf_1080p = (uint8_t*)jpeg_alloc_decoder_mem(jpeg_size_1080p);
|
size_t tx_buffer_size_1080p = 0;
|
||||||
|
uint8_t *tx_buf_1080p = (uint8_t*)jpeg_alloc_decoder_mem(jpeg_size_1080p, &tx_mem_cfg, &tx_buffer_size_1080p);
|
||||||
if (tx_buf_1080p == NULL) {
|
if (tx_buf_1080p == NULL) {
|
||||||
ESP_LOGE(TAG, "alloc 1080p tx buffer error");
|
ESP_LOGE(TAG, "alloc 1080p tx buffer error");
|
||||||
return;
|
return;
|
||||||
@ -115,7 +124,8 @@ void app_main(void)
|
|||||||
fseek(file_jpg_720p, 0, SEEK_END);
|
fseek(file_jpg_720p, 0, SEEK_END);
|
||||||
int jpeg_size_720p = ftell(file_jpg_720p);
|
int jpeg_size_720p = ftell(file_jpg_720p);
|
||||||
fseek(file_jpg_720p, 0, SEEK_SET);
|
fseek(file_jpg_720p, 0, SEEK_SET);
|
||||||
uint8_t *tx_buf_720p = (uint8_t*)jpeg_alloc_decoder_mem(jpeg_size_720p);
|
size_t tx_buffer_size_720p = 0;
|
||||||
|
uint8_t *tx_buf_720p = (uint8_t*)jpeg_alloc_decoder_mem(jpeg_size_720p, &tx_mem_cfg, &tx_buffer_size_720p);
|
||||||
if (tx_buf_720p == NULL) {
|
if (tx_buf_720p == NULL) {
|
||||||
ESP_LOGE(TAG, "alloc 720p tx buffer error");
|
ESP_LOGE(TAG, "alloc 720p tx buffer error");
|
||||||
return;
|
return;
|
||||||
@ -123,8 +133,10 @@ void app_main(void)
|
|||||||
fread(tx_buf_720p, 1, jpeg_size_720p, file_jpg_720p);
|
fread(tx_buf_720p, 1, jpeg_size_720p, file_jpg_720p);
|
||||||
fclose(file_jpg_720p);
|
fclose(file_jpg_720p);
|
||||||
|
|
||||||
uint8_t *rx_buf_1080p = (uint8_t*)jpeg_alloc_decoder_mem(1920 * 1080 * 3);
|
size_t rx_buffer_size_1080p = 0;
|
||||||
uint8_t *rx_buf_720p = (uint8_t*)jpeg_alloc_decoder_mem(720 * 1280);
|
size_t rx_buffer_size_720p = 0;
|
||||||
|
uint8_t *rx_buf_1080p = (uint8_t*)jpeg_alloc_decoder_mem(1920 * 1088 * 3, &rx_mem_cfg, &rx_buffer_size_1080p);
|
||||||
|
uint8_t *rx_buf_720p = (uint8_t*)jpeg_alloc_decoder_mem(720 * 1280, &rx_mem_cfg, &rx_buffer_size_720p);
|
||||||
if (rx_buf_1080p == NULL) {
|
if (rx_buf_1080p == NULL) {
|
||||||
ESP_LOGE(TAG, "alloc 1080p rx buffer error");
|
ESP_LOGE(TAG, "alloc 1080p rx buffer error");
|
||||||
return;
|
return;
|
||||||
@ -141,8 +153,8 @@ void app_main(void)
|
|||||||
|
|
||||||
uint32_t out_size_1080p = 0;
|
uint32_t out_size_1080p = 0;
|
||||||
uint32_t out_size_720p = 0;
|
uint32_t out_size_720p = 0;
|
||||||
ESP_ERROR_CHECK(jpeg_decoder_process(jpgd_handle, &decode_cfg_rgb, tx_buf_1080p, jpeg_size_1080p, rx_buf_1080p, &out_size_1080p));
|
ESP_ERROR_CHECK(jpeg_decoder_process(jpgd_handle, &decode_cfg_rgb, tx_buf_1080p, jpeg_size_1080p, rx_buf_1080p, rx_buffer_size_1080p, &out_size_1080p));
|
||||||
ESP_ERROR_CHECK(jpeg_decoder_process(jpgd_handle, &decode_cfg_gray, tx_buf_720p, jpeg_size_720p, rx_buf_720p, &out_size_720p));
|
ESP_ERROR_CHECK(jpeg_decoder_process(jpgd_handle, &decode_cfg_gray, tx_buf_720p, jpeg_size_720p, rx_buf_720p, rx_buffer_size_720p, &out_size_720p));
|
||||||
|
|
||||||
// Write two pictures.
|
// Write two pictures.
|
||||||
FILE *file_rgb_1080p = fopen(raw_file_1080, "wb");
|
FILE *file_rgb_1080p = fopen(raw_file_1080, "wb");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user