diff --git a/components/esp_driver_jpeg/include/driver/jpeg_decode.h b/components/esp_driver_jpeg/include/driver/jpeg_decode.h index 0d2d818ac3..4266c9290b 100644 --- a/components/esp_driver_jpeg/include/driver/jpeg_decode.h +++ b/components/esp_driver_jpeg/include/driver/jpeg_decode.h @@ -9,6 +9,7 @@ #include #include "esp_err.h" #include "jpeg_types.h" +#include "hal/jpeg_types.h" #ifdef __cplusplus extern "C" { @@ -19,7 +20,7 @@ extern "C" { */ typedef struct { jpeg_dec_output_format_t output_format; /*!< JPEG decoder output format */ - jpeg_dec_rgb_element_order_t 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_decode_cfg_t; @@ -37,6 +38,7 @@ typedef struct { typedef struct { uint32_t width; /*!< Number of pixels in the horizontal direction */ uint32_t height; /*!< Number of pixels in the vertical direction */ + jpeg_down_sampling_type_t sample_method; /*!< compressed JPEG picture sampling method */ } jpeg_decode_picture_info_t; /** diff --git a/components/esp_driver_jpeg/include/driver/jpeg_types.h b/components/esp_driver_jpeg/include/driver/jpeg_types.h index f9fa8dcd07..08ab102951 100644 --- a/components/esp_driver_jpeg/include/driver/jpeg_types.h +++ b/components/esp_driver_jpeg/include/driver/jpeg_types.h @@ -20,6 +20,9 @@ typedef enum { JPEG_DECODE_OUT_FORMAT_RGB888 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB888), /*!< output RGB888 format */ JPEG_DECODE_OUT_FORMAT_RGB565 = COLOR_TYPE_ID(COLOR_SPACE_RGB, COLOR_PIXEL_RGB565), /*!< output RGB565 format */ JPEG_DECODE_OUT_FORMAT_GRAY = COLOR_TYPE_ID(COLOR_SPACE_GRAY, COLOR_PIXEL_GRAY8), /*!< output the gray picture */ + JPEG_DECODE_OUT_FORMAT_YUV444 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV444), /*!< output yuv444 format */ + JPEG_DECODE_OUT_FORMAT_YUV422 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV422), /*!< output yuv422 format */ + JPEG_DECODE_OUT_FORMAT_YUV420 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV420), /*!< output yuv420 format */ } jpeg_dec_output_format_t; /** @@ -53,6 +56,7 @@ 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_ENCODE_IN_FORMAT_YUV422 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV422), /*!< input YUV422 format */ } jpeg_enc_input_format_t; /** diff --git a/components/esp_driver_jpeg/jpeg_decode.c b/components/esp_driver_jpeg/jpeg_decode.c index d06fa13e1f..422c2afd2b 100644 --- a/components/esp_driver_jpeg/jpeg_decode.c +++ b/components/esp_driver_jpeg/jpeg_decode.c @@ -144,6 +144,7 @@ esp_err_t jpeg_decoder_get_info(const uint8_t *in_buf, uint32_t inbuf_len, jpeg_ uint16_t width = 0; uint8_t thischar = 0; uint8_t lastchar = 0; + uint8_t hivi = 0; while (header_info->buffer_left) { lastchar = thischar; @@ -155,6 +156,10 @@ esp_err_t jpeg_decoder_get_info(const uint8_t *in_buf, uint32_t inbuf_len, jpeg_ jpeg_get_bytes(header_info, 1); height = jpeg_get_bytes(header_info, 2); width = jpeg_get_bytes(header_info, 2); + + jpeg_get_bytes(header_info, 1); + jpeg_get_bytes(header_info, 1); + hivi = jpeg_get_bytes(header_info, 1); break; } // This function only used for get width and height. So only read SOF marker is enough. @@ -167,6 +172,21 @@ esp_err_t jpeg_decoder_get_info(const uint8_t *in_buf, uint32_t inbuf_len, jpeg_ picture_info->height = height; picture_info->width = width; + switch (hivi) { + case 0x11: + picture_info->sample_method = JPEG_DOWN_SAMPLING_YUV444; + break; + case 0x21: + picture_info->sample_method = JPEG_DOWN_SAMPLING_YUV422; + break; + case 0x22: + picture_info->sample_method = JPEG_DOWN_SAMPLING_YUV420; + break; + default: + ESP_LOGE(TAG, "Sampling factor cannot be recognized"); + return ESP_ERR_INVALID_STATE; + } + free(header_info); return ESP_OK; } @@ -195,14 +215,13 @@ esp_err_t jpeg_decoder_process(jpeg_decoder_handle_t decoder_engine, const jpeg_ decoder_engine->output_format = decode_cfg->output_format; decoder_engine->rgb_order = decode_cfg->rgb_order; decoder_engine->conv_std = decode_cfg->conv_std; - decoder_engine->decoded_buf = decode_outbuf; ESP_GOTO_ON_ERROR(jpeg_parse_marker(decoder_engine, bit_stream, stream_size), err, TAG, "jpeg parse marker 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"); - *out_size = decoder_engine->header_info->process_h * decoder_engine->header_info->process_v * decoder_engine->pixel; + *out_size = decoder_engine->header_info->process_h * decoder_engine->header_info->process_v * decoder_engine->bit_per_pixel / 8; 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 height and width of output picture size will be adjusted to 16 bytes aligned automatically", outbuf_size, *out_size); dma2d_trans_config_t trans_desc = { @@ -222,8 +241,8 @@ esp_err_t jpeg_decoder_process(jpeg_decoder_handle_t decoder_engine, const jpeg_ // Blocking for JPEG decode transaction finishes. while (1) { jpeg_dma2d_dec_evt_t jpeg_dma2d_event; - BaseType_t ret = xQueueReceive(decoder_engine->evt_queue, &jpeg_dma2d_event, decoder_engine->timeout_tick); - ESP_GOTO_ON_FALSE(ret == pdTRUE, ESP_ERR_TIMEOUT, err, TAG, "jpeg-dma2d handle jpeg decode timeout, please check `timeout_ms` "); + BaseType_t ret_val = xQueueReceive(decoder_engine->evt_queue, &jpeg_dma2d_event, decoder_engine->timeout_tick); + ESP_GOTO_ON_FALSE(ret_val == pdTRUE, ESP_ERR_TIMEOUT, err, TAG, "jpeg-dma2d handle jpeg decode timeout, please check `timeout_ms` "); // Dealing with JPEG event if (jpeg_dma2d_event.jpgd_status != 0) { @@ -328,23 +347,49 @@ static esp_err_t jpeg_dec_config_dma_descriptor(jpeg_decoder_handle_t decoder_en jpeg_dec_format_hb_t best_hb_idx = 0; color_space_pixel_format_t picture_format; picture_format.color_type_id = decoder_engine->output_format; - decoder_engine->pixel = color_hal_pixel_format_get_bit_depth(picture_format) / 8; - switch (decoder_engine->output_format) { - case JPEG_DECODE_OUT_FORMAT_RGB888: - best_hb_idx = JPEG_DEC_RGB888_HB; + decoder_engine->bit_per_pixel = color_hal_pixel_format_get_bit_depth(picture_format); + if (decoder_engine->no_color_conversion == false) { + switch (decoder_engine->output_format) { + case JPEG_DECODE_OUT_FORMAT_RGB888: + best_hb_idx = JPEG_DEC_RGB888_HB; + break; + case JPEG_DECODE_OUT_FORMAT_RGB565: + best_hb_idx = JPEG_DEC_RGB565_HB; + break; + case JPEG_DECODE_OUT_FORMAT_GRAY: + best_hb_idx = JPEG_DEC_GRAY_HB; + break; + case JPEG_DECODE_OUT_FORMAT_YUV444: + best_hb_idx = JPEG_DEC_YUV444_HB; + break; + default: + ESP_LOGE(TAG, "wrong, we don't support decode to such format."); + return ESP_ERR_NOT_SUPPORTED; + } + } else { + best_hb_idx = JPEG_DEC_DIRECT_OUTPUT_HB; + } + + uint8_t sample_method_idx = 0; + switch (decoder_engine->sample_method) { + case JPEG_DOWN_SAMPLING_YUV444: + sample_method_idx = 0; break; - case JPEG_DECODE_OUT_FORMAT_RGB565: - best_hb_idx = JPEG_DEC_RGB565_HB; + case JPEG_DOWN_SAMPLING_YUV422: + sample_method_idx = 1; break; - case JPEG_DECODE_OUT_FORMAT_GRAY: - best_hb_idx = JPEG_DEC_GRAY_HB; + case JPEG_DOWN_SAMPLING_YUV420: + sample_method_idx = 2; + break; + case JPEG_DOWN_SAMPLING_GRAY: + sample_method_idx = 3; break; default: - ESP_LOGE(TAG, "wrong, we don't support decode to such format."); + ESP_LOGE(TAG, "wrong, we don't support such sampling mode."); return ESP_ERR_NOT_SUPPORTED; } - uint32_t dma_hb = dec_hb_tbl[decoder_engine->sample_method][best_hb_idx]; + uint32_t dma_hb = dec_hb_tbl[sample_method_idx][best_hb_idx]; uint32_t dma_vb = decoder_engine->header_info->mcuy; // Configure tx link descriptor @@ -375,7 +420,6 @@ static void jpeg_dec_config_dma_csc(jpeg_decoder_handle_t decoder_engine, dma2d_ dma2d_scramble_order_t post_scramble = DMA2D_SCRAMBLE_ORDER_BYTE2_1_0; dma2d_csc_rx_option_t rx_csc_option = DMA2D_CSC_RX_NONE; - // Config output Endians if (decoder_engine->rgb_order == JPEG_DEC_RGB_ELEMENT_ORDER_RGB) { if (decoder_engine->output_format == JPEG_DECODE_OUT_FORMAT_RGB565) { @@ -398,7 +442,13 @@ static void jpeg_dec_config_dma_csc(jpeg_decoder_handle_t decoder_engine, dma2d_ } else if (decoder_engine->conv_std == JPEG_YUV_RGB_CONV_STD_BT709) { rx_csc_option = DMA2D_CSC_RX_YUV420_TO_RGB888_709; } - } else if (decoder_engine->output_format == JPEG_DECODE_OUT_FORMAT_GRAY) { + } else if (decoder_engine->output_format == JPEG_DECODE_OUT_FORMAT_YUV444) { + if (decoder_engine->sample_method == JPEG_DOWN_SAMPLING_YUV422) { + rx_csc_option = DMA2D_CSC_RX_YUV422_TO_YUV444; + } else if (decoder_engine->sample_method == JPEG_DOWN_SAMPLING_YUV420) { + rx_csc_option = DMA2D_CSC_RX_YUV420_TO_YUV444; + } + } else { rx_csc_option = DMA2D_CSC_RX_NONE; } @@ -493,6 +543,27 @@ static bool jpeg_dec_transaction_on_picked(uint32_t channel_num, const dma2d_tra return false; } +static esp_err_t jpeg_color_space_support_check(jpeg_decoder_handle_t decoder_engine) +{ + if (decoder_engine->sample_method == JPEG_DOWN_SAMPLING_YUV444) { + if (decoder_engine->output_format == JPEG_DECODE_OUT_FORMAT_YUV422 || decoder_engine->output_format == JPEG_DECODE_OUT_FORMAT_YUV420) { + ESP_LOGE(TAG, "Detected YUV444 but want to convert to YUV422/YUV420, which is not supported"); + return ESP_ERR_INVALID_ARG; + } + } else if (decoder_engine->sample_method == JPEG_DOWN_SAMPLING_YUV422) { + if (decoder_engine->output_format == JPEG_DECODE_OUT_FORMAT_YUV420) { + ESP_LOGE(TAG, "Detected YUV422 but want to convert to YUV420, which is not supported"); + return ESP_ERR_INVALID_ARG; + } + } else if (decoder_engine->sample_method == JPEG_DOWN_SAMPLING_YUV420) { + if (decoder_engine->output_format == JPEG_DECODE_OUT_FORMAT_YUV422) { + ESP_LOGE(TAG, "Detected YUV420 but want to convert to YUV422, which is not supported"); + return ESP_ERR_INVALID_ARG; + } + } + return ESP_OK; +} + static esp_err_t jpeg_parse_header_info_to_hw(jpeg_decoder_handle_t decoder_engine) { ESP_RETURN_ON_FALSE(decoder_engine, ESP_ERR_INVALID_ARG, TAG, "jpeg decode handle is null"); @@ -534,6 +605,12 @@ static esp_err_t jpeg_parse_header_info_to_hw(jpeg_decoder_handle_t decoder_engi decoder_engine->sample_method = JPEG_DOWN_SAMPLING_GRAY; } + ESP_RETURN_ON_ERROR(jpeg_color_space_support_check(decoder_engine), TAG, "jpeg decoder not support the combination of output format and down sampling format"); + + if ((uint32_t)decoder_engine->sample_method == (uint32_t)decoder_engine->output_format) { + decoder_engine->no_color_conversion = true; + } + // Write DHT information dht_func[0][0](hal, header_info->huffbits[0][0], header_info->huffcode[0][0], header_info->tmp_huff); dht_func[0][1](hal, header_info->huffbits[0][1], header_info->huffcode[0][1], header_info->tmp_huff); diff --git a/components/esp_driver_jpeg/jpeg_encode.c b/components/esp_driver_jpeg/jpeg_encode.c index 9b5d260baf..d4df1137ec 100644 --- a/components/esp_driver_jpeg/jpeg_encode.c +++ b/components/esp_driver_jpeg/jpeg_encode.c @@ -142,6 +142,9 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_ ESP_RETURN_ON_FALSE(encode_inbuf, ESP_ERR_INVALID_ARG, TAG, "jpeg encode picture buffer is null"); ESP_RETURN_ON_FALSE(out_size, ESP_ERR_INVALID_ARG, TAG, "jpeg encode picture out_size 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 encode bit stream is not aligned, please use jpeg_alloc_encoder_mem to malloc your buffer"); + if (encode_cfg->src_type == JPEG_ENCODE_IN_FORMAT_YUV422) { + ESP_RETURN_ON_FALSE(encode_cfg->sub_sample == JPEG_DOWN_SAMPLING_YUV422, ESP_ERR_INVALID_ARG, TAG, "Sub sampling is not supported under this source type"); + } esp_err_t ret = ESP_OK; @@ -176,6 +179,10 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_ encoder_engine->color_space = JPEG_ENC_SRC_GRAY; best_hb_idx = JPEG_ENC_SRC_GRAY_HB; break; + case JPEG_ENCODE_IN_FORMAT_YUV422: + encoder_engine->color_space = JPEG_ENC_SRC_YUV422; + best_hb_idx = JPEG_ENC_SRC_YUV422_HB; + break; default: ESP_LOGE(TAG, "wrong, we don't support encode from such format."); ret = ESP_ERR_NOT_SUPPORTED; @@ -198,7 +205,26 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_ ESP_GOTO_ON_ERROR(s_jpeg_set_header_info(encoder_engine), err, TAG, "set header failed"); jpeg_hal_set_quantization_coefficient(hal, encoder_engine->header_info->m_quantization_tables[0], encoder_engine->header_info->m_quantization_tables[1]); - uint32_t dma_hb = enc_hb_tbl[best_hb_idx][encoder_engine->header_info->sub_sample]; + uint8_t sample_method_idx = 0; + switch (encoder_engine->header_info->sub_sample) { + case JPEG_DOWN_SAMPLING_YUV444: + sample_method_idx = 0; + break; + case JPEG_DOWN_SAMPLING_YUV422: + sample_method_idx = 1; + break; + case JPEG_DOWN_SAMPLING_YUV420: + sample_method_idx = 2; + break; + case JPEG_DOWN_SAMPLING_GRAY: + sample_method_idx = 3; + break; + default: + ESP_LOGE(TAG, "wrong, we don't support such sampling mode."); + return ESP_ERR_NOT_SUPPORTED; + } + + uint32_t dma_hb = enc_hb_tbl[best_hb_idx][sample_method_idx]; uint32_t dma_vb = encoder_engine->mcuy; ESP_GOTO_ON_FALSE((encoder_engine->header_info->header_len % cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA)) == 0, ESP_ERR_INVALID_STATE, err, TAG, "The header is not cache line aligned, please check"); @@ -237,8 +263,8 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_ if (s_rcv_event.dma_evt & JPEG_DMA2D_RX_EOF) { compressed_size = s_dma_desc_get_len(encoder_engine->rxlink); - compressed_size = JPEG_ALIGN_UP(compressed_size, cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA)); - ESP_GOTO_ON_ERROR(esp_cache_msync((void*)(bit_stream + encoder_engine->header_info->header_len), compressed_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), err, TAG, "sync memory to cache failed"); + uint32_t _compressed_size = JPEG_ALIGN_UP(compressed_size, cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA)); + ESP_GOTO_ON_ERROR(esp_cache_msync((void*)(bit_stream + encoder_engine->header_info->header_len), _compressed_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), err, TAG, "sync memory to cache failed"); break; } } diff --git a/components/esp_driver_jpeg/jpeg_param.c b/components/esp_driver_jpeg/jpeg_param.c index 59bf6bb547..eb09925dd5 100644 --- a/components/esp_driver_jpeg/jpeg_param.c +++ b/components/esp_driver_jpeg/jpeg_param.c @@ -39,7 +39,7 @@ const uint8_t zigzag_arr[64] = { * decompression. It is used to decode the Huffman-coded symbols in the compressed * data stream during the decoding process. */ -const uint32_t dec_hb_tbl[JPEG_DOWN_SAMPLING_MAX][JPEG_DEC_BEST_HB_MAX] = { +const uint32_t dec_hb_tbl[JPEG_DOWN_SAMPLING_NUM][JPEG_DEC_BEST_HB_MAX] = { {40, 40, 40, 32, 0}, {64, 32, 32, 64, 0}, {48, 32, 32, 48, 0}, @@ -53,7 +53,7 @@ const uint32_t dec_hb_tbl[JPEG_DOWN_SAMPLING_MAX][JPEG_DEC_BEST_HB_MAX] = { * compression. It is used to decode the Huffman-coded symbols in the compressed * data stream during the encoding process. */ -const uint32_t enc_hb_tbl[JPEG_ENC_BEST_HB_MAX][JPEG_DOWN_SAMPLING_MAX] = { +const uint32_t enc_hb_tbl[JPEG_ENC_BEST_HB_MAX][JPEG_DOWN_SAMPLING_NUM] = { {40, 32, 32, 0}, {0, 64, 0, 0}, {64, 64, 48, 0}, diff --git a/components/esp_driver_jpeg/jpeg_private.h b/components/esp_driver_jpeg/jpeg_private.h index 2154de0f38..01a489f930 100644 --- a/components/esp_driver_jpeg/jpeg_private.h +++ b/components/esp_driver_jpeg/jpeg_private.h @@ -56,9 +56,8 @@ struct jpeg_codec_t { }; typedef enum { - // TODO: Support DR and YUV444 on decoder. - //JPEG_DEC_DR_HB = 0, /*!< Direct output */ - //JPEG_DEC_YUV444_HB = 1, /*!< output YUV444 format */ + JPEG_DEC_DIRECT_OUTPUT_HB = 0, /*!< Direct output */ + JPEG_DEC_YUV444_HB = 1, /*!< output YUV444 format */ JPEG_DEC_RGB888_HB = 2, /*!< output RGB888 format */ JPEG_DEC_RGB565_HB = 3, /*!< output RGB565 format */ JPEG_DEC_GRAY_HB = 4, /*!< output the gray picture */ @@ -96,9 +95,10 @@ struct jpeg_decoder_t { 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_dec_output_format_t output_format; // picture output format. - jpeg_dec_rgb_element_order_t 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 - uint8_t pixel; // size per pixel + bool no_color_conversion; // No color conversion, directly output based on compressed format + uint8_t bit_per_pixel; // bit size per pixel QueueHandle_t evt_queue; // jpeg event from 2DDMA and JPEG engine uint8_t *decoded_buf; // pointer to the rx buffer. uint32_t total_size; // jpeg picture origin size (in bytes) @@ -127,8 +127,7 @@ typedef struct { typedef enum { JPEG_ENC_SRC_RGB888_HB = 0, // Input RGB888 format - // TODO: Support encoder source format for yuv422 - // JPEG_ENC_SRC_YUV422_HB = 1, // Input YUV422 format + JPEG_ENC_SRC_YUV422_HB = 1, // Input YUV422 format JPEG_ENC_SRC_RGB565_HB = 2, // Input RGB565 format JPEG_ENC_SRC_GRAY_HB = 3, // Input GRAY format JPEG_ENC_BEST_HB_MAX, diff --git a/components/esp_driver_jpeg/private/jpeg_param.h b/components/esp_driver_jpeg/private/jpeg_param.h index 4e1c2fc56c..abe66ff0e9 100644 --- a/components/esp_driver_jpeg/private/jpeg_param.h +++ b/components/esp_driver_jpeg/private/jpeg_param.h @@ -36,7 +36,7 @@ extern const uint8_t zigzag_arr[64]; * decompression. It is used to decode the Huffman-coded symbols in the compressed * data stream during the decoding process. */ -extern const uint32_t dec_hb_tbl[JPEG_DOWN_SAMPLING_MAX][JPEG_DEC_BEST_HB_MAX]; +extern const uint32_t dec_hb_tbl[JPEG_DOWN_SAMPLING_NUM][JPEG_DEC_BEST_HB_MAX]; /** * @brief DMA2D best hb value table for JPEG compression. @@ -45,7 +45,7 @@ extern const uint32_t dec_hb_tbl[JPEG_DOWN_SAMPLING_MAX][JPEG_DEC_BEST_HB_MAX]; * compression. It is used to decode the Huffman-coded symbols in the compressed * data stream during the encoding process. */ -extern const uint32_t enc_hb_tbl[JPEG_ENC_BEST_HB_MAX][JPEG_DOWN_SAMPLING_MAX]; +extern const uint32_t enc_hb_tbl[JPEG_ENC_BEST_HB_MAX][JPEG_DOWN_SAMPLING_NUM]; /** * @brief Setup the standard Huffman tables (JPEG standard sections K.3.3) diff --git a/components/hal/include/hal/jpeg_types.h b/components/hal/include/hal/jpeg_types.h index f81ff82df8..a8a833cdf9 100644 --- a/components/hal/include/hal/jpeg_types.h +++ b/components/hal/include/hal/jpeg_types.h @@ -23,6 +23,7 @@ extern "C" { #define DHT_TC_NUM (2) /// Table type #define DHT_TH_NUM (2) /// Huffman table destination identifier +#define JPEG_DOWN_SAMPLING_NUM (4) // The number of down sampling methods /** * @brief Enum for JPEG codec working mode. @@ -44,9 +45,9 @@ typedef struct { * @brief Enum for JPEG sampling mode. */ typedef enum { - JPEG_SAMPLE_MODE_YUV444 = COLOR_PIXEL_YUV444, ///< sample in YUV444 - JPEG_SAMPLE_MODE_YUV422 = COLOR_PIXEL_YUV422, ///< sample in YUV422 - JPEG_SAMPLE_MODE_YUV420 = COLOR_PIXEL_YUV420, ///< sample in YUV420 + JPEG_SAMPLE_MODE_YUV444 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV444), ///< sample in YUV444 + JPEG_SAMPLE_MODE_YUV422 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV422), ///< sample in YUV422 + JPEG_SAMPLE_MODE_YUV420 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV420), ///< sample in YUV420 } jpeg_sample_mode_t; /** @@ -64,11 +65,10 @@ typedef union { * @brief Enumeration for jpeg decoder sample methods. */ typedef enum { - JPEG_DOWN_SAMPLING_YUV444 = 0, /*!< Sample by YUV444 */ - JPEG_DOWN_SAMPLING_YUV422 = 1, /*!< Sample by YUV422 */ - JPEG_DOWN_SAMPLING_YUV420 = 2, /*!< Sample by YUV420 */ - JPEG_DOWN_SAMPLING_GRAY = 3, /*!< Sample the gray picture */ - JPEG_DOWN_SAMPLING_MAX, /*!< Max value of sample enumeration */ + JPEG_DOWN_SAMPLING_YUV444 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV444), /*!< Sample by YUV444 */ + JPEG_DOWN_SAMPLING_YUV422 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV422), /*!< Sample by YUV422 */ + JPEG_DOWN_SAMPLING_YUV420 = COLOR_TYPE_ID(COLOR_SPACE_YUV, COLOR_PIXEL_YUV420), /*!< Sample by YUV420 */ + JPEG_DOWN_SAMPLING_GRAY = COLOR_TYPE_ID(COLOR_SPACE_GRAY, COLOR_PIXEL_GRAY8), /*!< Sample the gray picture */ } jpeg_down_sampling_type_t; /** diff --git a/docs/_static/diagrams/jpeg/rgb565.png b/docs/_static/diagrams/jpeg/rgb565.png new file mode 100644 index 0000000000..a76fdcdaa9 Binary files /dev/null and b/docs/_static/diagrams/jpeg/rgb565.png differ diff --git a/docs/_static/diagrams/jpeg/rgb565_bigendian.png b/docs/_static/diagrams/jpeg/rgb565_bigendian.png new file mode 100644 index 0000000000..0d55a55a4f Binary files /dev/null and b/docs/_static/diagrams/jpeg/rgb565_bigendian.png differ diff --git a/docs/_static/diagrams/jpeg/rgb888.png b/docs/_static/diagrams/jpeg/rgb888.png new file mode 100644 index 0000000000..62f372df5b Binary files /dev/null and b/docs/_static/diagrams/jpeg/rgb888.png differ diff --git a/docs/_static/diagrams/jpeg/rgb888_bigendian.png b/docs/_static/diagrams/jpeg/rgb888_bigendian.png new file mode 100644 index 0000000000..490c95ba88 Binary files /dev/null and b/docs/_static/diagrams/jpeg/rgb888_bigendian.png differ diff --git a/docs/_static/diagrams/jpeg/yuv420.png b/docs/_static/diagrams/jpeg/yuv420.png new file mode 100644 index 0000000000..1dea4a94cf Binary files /dev/null and b/docs/_static/diagrams/jpeg/yuv420.png differ diff --git a/docs/_static/diagrams/jpeg/yuv422.png b/docs/_static/diagrams/jpeg/yuv422.png new file mode 100644 index 0000000000..a30190ca90 Binary files /dev/null and b/docs/_static/diagrams/jpeg/yuv422.png differ diff --git a/docs/_static/diagrams/jpeg/yuv444.png b/docs/_static/diagrams/jpeg/yuv444.png new file mode 100644 index 0000000000..e45d274cba Binary files /dev/null and b/docs/_static/diagrams/jpeg/yuv444.png differ diff --git a/docs/en/api-reference/peripherals/jpeg.rst b/docs/en/api-reference/peripherals/jpeg.rst index ad24411a53..23426412b5 100644 --- a/docs/en/api-reference/peripherals/jpeg.rst +++ b/docs/en/api-reference/peripherals/jpeg.rst @@ -18,6 +18,7 @@ This document covers the following sections: - `JPEG Decoder Engine <#jpeg-decoder-engine>`__ - covers behavior of JPEG decoder engine. Introduce how to use decoder engine functions to decode an image (from jpg format to raw format). - `JPEG Encoder Engine <#jpeg-encoder-engine>`__ - covers behavior of JPEG encoder engine. Introduce how to use encoder engine functions to encode an image (from raw format to jpg format). - `Performance Overview <#performance-overview>`__ - covers encoder and decoder performance. +- `Pixel Storage Layout for Different Color Formats <#pixel-storage-layout-for-different-color-formats>`__ - covers color space order overview required in this JPEG decoder and encoder. - `Thread Safety <#thread-safety>`__ - lists which APIs are guaranteed to be thread safe by the driver. - `Power Management <#power-management>`__ - describes how jpeg driver would be affected by power consumption. - `Kconfig Options <#kconfig-options>`__ - lists the supported Kconfig options that can bring different effects to the driver. @@ -104,18 +105,28 @@ The format conversions supported by this driver are listed in the table below: | Format of the already compressed image | Format after decompressing | +========================================+===================================+ | | RGB565 | -| YUV444 +-----------------------------------+ +| YUV444 +-----------------------------------+ | | RGB888 | +| +-----------------------------------+ +| | YUV444 | +----------------------------------------+-----------------------------------+ | | RGB565 | -| YUV422 +-----------------------------------+ +| +-----------------------------------+ | | RGB888 | +| YUV422 +-----------------------------------+ +| | YUV444 | +| +-----------------------------------+ +| | YUV422 | +----------------------------------------+-----------------------------------+ | | RGB565 | -| YUV420 +-----------------------------------+ +| +-----------------------------------+ | | RGB888 | +| YUV420 +-----------------------------------+ +| | YUV444 | +| +-----------------------------------+ +| | YUV420 | +----------------------------------------+-----------------------------------+ -| GRAY | GRAY | +| GRAY | GRAY | +----------------------------------------+-----------------------------------+ Overall, You can take following code as reference, the code is going to decode a 1080*1920 picture. @@ -167,11 +178,13 @@ The format conversions supported by this driver are listed in the table below: +==========================+======================================+ | | YUV444 | | +--------------------------------------+ -| RGB565/RGB888 | YUV422 | +| RGB565/RGB888 | YUV422 | | +--------------------------------------+ | | YUV420 | +--------------------------+--------------------------------------+ -| GRAY | GRAY | +| GRAY | GRAY | ++--------------------------+--------------------------------------+ +| YUV422 | YUV422 | +--------------------------+--------------------------------------+ @@ -236,6 +249,12 @@ JPEG decoder performance +--------+-------+--------------------------------------------+----------------------------------------+------------------+ | 720 | 1280 | GRAY | GRAY | 161 | +--------+-------+--------------------------------------------+----------------------------------------+------------------+ +| 480 | 800 | YUV444 | YUV444 | 129 | ++--------+-------+--------------------------------------------+----------------------------------------+------------------+ +| 480 | 800 | YUV422 | YUV444/YUV422 | 190 | ++--------+-------+--------------------------------------------+----------------------------------------+------------------+ +| 480 | 800 | YUV420 | YUV444/YUV420 | 253 | ++--------+-------+--------------------------------------------+----------------------------------------+------------------+ JPEG encoder performance ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -269,8 +288,86 @@ JPEG encoder performance +--------+-------+-----------------------------------------+-------------------------------------------+------------------+ | 720 | 1280 | GRAY | GRAY | 163 | +--------+-------+-----------------------------------------+-------------------------------------------+------------------+ +| 480 | 800 | YUV422 | YUV422 | 146 | ++--------+-------+-----------------------------------------+-------------------------------------------+------------------+ +Pixel Storage Layout for Different Color Formats +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The encoder and decoder described in this guide use the same uncompressed raw image formats (RGB, YUV). Therefore, the encoder and decoder are not discussed separately in this section. The pixel layout of the following formats applies to the input direction of the encoder and the output direction of the decoder (if supported). The specific pixel layout is shown in the following figure: + +RGB888 +~~~~~~ + +In the following picture, each small block means one bit. + +.. figure:: ../../../_static/diagrams/jpeg/rgb888.png + :align: center + :alt: RGB888 pixel order + + RGB888 pixel order + +For RGB888, the order can be changed via :cpp:member:`jpeg_decode_cfg_t::rgb_order` sets the pixel to `RGB` order. + +.. figure:: ../../../_static/diagrams/jpeg/rgb888_bigendian.png + :align: center + :alt: RGB888 pixel big endian order + + RGB888 pixel big endian order + +RGB565 +~~~~~~ + +In the following picture, each small block means one bit. + +.. figure:: ../../../_static/diagrams/jpeg/rgb565.png + :align: center + :alt: RGB565 pixel order + + RGB565 pixel order + +For RGB565, the order can be changed via :cpp:member:`jpeg_decode_cfg_t::rgb_order` sets the pixel to `RGB` order. + +.. figure:: ../../../_static/diagrams/jpeg/rgb565_bigendian.png + :align: center + :alt: RGB565 pixel big endian order + + RGB565 pixel big endian order + +YUV444 +~~~~~~ + +In the following picture, each small block means one byte. + +.. figure:: ../../../_static/diagrams/jpeg/yuv444.png + :align: center + :alt: YUV444 pixel order + + YUV444 pixel order + +YUV422 +~~~~~~ + +In the following picture, each small block means one byte. + +.. figure:: ../../../_static/diagrams/jpeg/yuv422.png + :align: center + :alt: YUV422 pixel order + + YUV422 pixel order + +YUV420 +~~~~~~ + +In the following picture, each small block means one byte. + +.. figure:: ../../../_static/diagrams/jpeg/yuv420.png + :align: center + :alt: YUV420 pixel order + + YUV420 pixel order + Thread Safety ^^^^^^^^^^^^^ diff --git a/examples/peripherals/jpeg/jpeg_decode/README.md b/examples/peripherals/jpeg/jpeg_decode/README.md index 7947801298..ff99171c3e 100644 --- a/examples/peripherals/jpeg/jpeg_decode/README.md +++ b/examples/peripherals/jpeg/jpeg_decode/README.md @@ -51,7 +51,7 @@ I (13336) jpeg.example: Card unmounted I (13336) main_task: Returned from app_main() ``` -Moreover, we provided a helper script called `open_rgb.py`, which can help you easily see the outputs on your computer. For requirements component you need, you can call `pip install -r requirements.txt` under `examples/peripheral/jpeg/jpeg_decode` folder. +Also, the helper script [open_raw_picture.py](./open_raw_picture.py) simplifies the visualization of the output on your computer. For this to work, go to `examples/peripheral/jpeg/jpeg_decode` and install the requirements by running `pip install -r requirements.txt`. ## Troubleshooting diff --git a/examples/peripherals/jpeg/jpeg_decode/main/Kconfig.projbuild b/examples/peripherals/jpeg/jpeg_decode/main/Kconfig.projbuild index a33f65db3b..f6154c38ed 100644 --- a/examples/peripherals/jpeg/jpeg_decode/main/Kconfig.projbuild +++ b/examples/peripherals/jpeg/jpeg_decode/main/Kconfig.projbuild @@ -6,4 +6,13 @@ menu "JPEG Decode Example menu" help If this config item is set, format_if_mount_failed will be set to true and the card will be formatted if the mount has failed. + + config EXAMPLE_SDMMC_IO_POWER_INTERNAL_LDO + depends on SOC_SDMMC_IO_POWER_EXTERNAL + bool "SDMMC IO power supply comes from internal LDO (READ HELP!)" + default y + help + Please read the schematic first and check if the SDMMC VDD is connected to any internal LDO output. + If the SDMMC is powered by an external supplier, unselect me + endmenu diff --git a/examples/peripherals/jpeg/jpeg_decode/main/jpeg_decode_main.c b/examples/peripherals/jpeg/jpeg_decode/main/jpeg_decode_main.c index 6d467f337e..e5f0243bf8 100644 --- a/examples/peripherals/jpeg/jpeg_decode/main/jpeg_decode_main.c +++ b/examples/peripherals/jpeg/jpeg_decode/main/jpeg_decode_main.c @@ -11,6 +11,7 @@ #include "driver/sdmmc_host.h" #include "esp_attr.h" #include "driver/jpeg_decode.h" +#include "sd_pwr_ctrl_by_on_chip_ldo.h" static const char *TAG = "jpeg.example"; static sdmmc_card_t *s_card; @@ -38,6 +39,21 @@ static esp_err_t sdcard_init(void) sdmmc_host_t host = SDMMC_HOST_DEFAULT(); host.max_freq_khz = SDMMC_FREQ_HIGHSPEED; + +#if CONFIG_EXAMPLE_SDMMC_IO_POWER_INTERNAL_LDO + sd_pwr_ctrl_ldo_config_t ldo_config = { + .ldo_chan_id = 4, // `LDO_VO4` is used as the SDMMC IO power + }; + sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL; + + ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to new an on-chip ldo power control driver"); + return ret; + } + host.pwr_ctrl_handle = pwr_ctrl_handle; +#endif + // This initializes the slot without card detect (CD) and write protect (WP) signals. // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals. sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); @@ -65,6 +81,13 @@ static void sdcard_deinit(void) { const char mount_point[] = MOUNT_POINT; esp_vfs_fat_sdcard_unmount(mount_point, s_card); +#if SOC_SDMMC_IO_POWER_EXTERNAL + esp_err_t ret = sd_pwr_ctrl_del_on_chip_ldo(s_card->host.pwr_ctrl_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to delete on-chip ldo power control driver"); + return; + } +#endif } void app_main(void) diff --git a/examples/peripherals/jpeg/jpeg_decode/open_raw_picture.py b/examples/peripherals/jpeg/jpeg_decode/open_raw_picture.py new file mode 100644 index 0000000000..afb243db1d --- /dev/null +++ b/examples/peripherals/jpeg/jpeg_decode/open_raw_picture.py @@ -0,0 +1,189 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import argparse + +import cv2 as cv +import numpy as np +from numpy.typing import NDArray + + +def open_picture(path): # type: (str) -> list[int] + with open(path, 'rb') as f: + data = f.read() + f.close() + new_data = [int(x) for x in data] + return new_data + + +def picture_show_rgb888(data, h, w): # type: (list[int], int, int) -> None + data = np.array(data).reshape(h, w, 3).astype(np.uint8) + cv.imshow('data', data) + cv.waitKey() + + +def picture_show_rgb565(data, h, w): # type: (list[int], int, int) -> None + + new_data = [0] * ((len(data) // 2) * 3) + for i in range(len(data)): + if i % 2 != 0: + new_data[3 * (i - 1) // 2 + 2] = (data[i] & 0xf8) + new_data[3 * (i - 1) // 2 + 1] |= (data[i] & 0x7) << 5 + else: + new_data[3 * i // 2] = (data[i] & 0x1f) << 3 + new_data[3 * i // 2 + 1] |= (data[i] & 0xe0) >> 3 + + new_data = np.array(new_data).reshape(h, w, 3).astype(np.uint8) + cv.imshow('data', new_data) + cv.waitKey() + + +def picture_show_gray(data, h, w): # type: (list[int], int, int) -> None + new_data = np.array(data).reshape(h, w, 1).astype(np.uint8) + cv.imshow('data', new_data) + cv.waitKey() + + +def convert_YUV_to_RGB(Y, U, V): # type: (NDArray, NDArray, NDArray) -> tuple[NDArray, NDArray, NDArray] + B = np.clip(Y + 1.7790 * (U - 128), 0, 255).astype(np.uint8) + G = np.clip(Y - 0.3455 * (U - 128) - 0.7169 * (V - 128), 0, 255).astype(np.uint8) + R = np.clip(Y + 1.4075 * (V - 128), 0, 255).astype(np.uint8) + + return B, G, R + + +def picture_show_yuv420(data, h, w): # type: (list[int], int, int) -> None + new_u = [0] * (h * w) + new_v = [0] * (h * w) + new_y = [0] * (h * w) + + for i in range(int(h * w * 1.5)): + is_even_row = ((i // (w * 1.5)) % 2 == 0) + if is_even_row: + if (i % 3 == 0): + new_u[(i // 3) * 2] = data[i] + new_u[(i // 3) * 2 + 1] = data[i] + else: + if (i % 3 == 0): + new_u[(i // 3) * 2] = new_u[int((i - (w * 1.5)) // 3) * 2] + new_u[(i // 3) * 2 + 1] = new_u[int((i - (w * 1.5)) // 3) * 2 + 1] + + for i in range(int(h * w * 1.5)): + if (i // (w * 1.5)) % 2 != 0 and (i % 3 == 0): + idx = (i // 3) * 2 + new_v[idx] = data[i] + new_v[idx + 1] = data[i] + + for i in range(int(h * w * 1.5)): + if (i // (w * 1.5)) % 2 == 0 and (i % 3 == 0): + idx = (i // 3) * 2 + new_v[idx] = new_v[int((i + (w * 1.5)) // 3) * 2] + new_v[idx + 1] = new_v[int((i + (w * 1.5)) // 3) * 2 + 1] + + new_y = [data[i] for i in range(int(h * w * 1.5)) if i % 3 != 0] + + Y = np.array(new_y) + U = np.array(new_u) + V = np.array(new_v) + + B, G, R = convert_YUV_to_RGB(Y, U, V) + # Merge channels + new_data = np.stack((B, G, R), axis=-1) + new_data = np.array(new_data).reshape(h, w, 3).astype(np.uint8) + + # Display the image + cv.imshow('data', new_data) + cv.waitKey() + + +def picture_show_yuv422(data, h, w): # type: (list[int], int, int) -> None + # Reshape the input data to a 2D array + data_array = np.array(data).reshape(h, w * 2) + + # Separate Y, U, and V channels + Y = data_array[:, 1::2] + U = data_array[:, 0::4].repeat(2, axis=1) + V = data_array[:, 2::4].repeat(2, axis=1) + + # Convert YUV to RGB + B, G, R = convert_YUV_to_RGB(Y, U, V) + + # Merge channels + new_data = np.stack((B, G, R), axis=-1) + + # Display the image + cv.imshow('data', new_data) + cv.waitKey() + + +def picture_show_yuv444(data, h, w): # type: (list[int], int, int) -> None + # Reshape the input data to a 2D array + data_array = np.array(data).reshape(h, w * 3) + + # Separate Y, U, and V channels + Y = data_array[:, 2::3] + U = data_array[:, 1::3] + V = data_array[:, 0::3] + + # Convert YUV to RGB + B, G, R = convert_YUV_to_RGB(Y, U, V) + + # Merge channels + new_data = np.stack((B, G, R), axis=-1) + + # Display the image + cv.imshow('data', new_data) + cv.waitKey() + + +def main(): # type: () -> None + parser = argparse.ArgumentParser(description='which mode need to show') + + parser.add_argument( + '--pic_path', + type=str, + help='What is the path of your picture', + required=True) + + parser.add_argument( + '--pic_type', + type=str, + help='What type you want to show', + required=True, + choices=['rgb565', 'rgb888', 'gray', 'yuv422', 'yuv420', 'yuv444']) + + parser.add_argument( + '--height', + type=int, + help='the picture height', + default=480) + + parser.add_argument( + '--width', + type=int, + help='the picture width', + default=640) + + args = parser.parse_args() + + height = args.height + width = args.width + + data = open_picture(args.pic_path) + if (args.pic_type == 'rgb565'): + picture_show_rgb565(data, height, width) + elif (args.pic_type == 'rgb888'): + picture_show_rgb888(data, height, width) + elif (args.pic_type == 'gray'): + picture_show_gray(data, height, width) + elif (args.pic_type == 'yuv420'): + picture_show_yuv420(data, height, width) + elif (args.pic_type == 'yuv422'): + picture_show_yuv422(data, height, width) + elif (args.pic_type == 'yuv444'): + picture_show_yuv444(data, height, width) + else: + print('This type is not supported in this script!') + + +if __name__ == '__main__': + main() diff --git a/examples/peripherals/jpeg/jpeg_decode/open_rgb.py b/examples/peripherals/jpeg/jpeg_decode/open_rgb.py deleted file mode 100644 index c78809627f..0000000000 --- a/examples/peripherals/jpeg/jpeg_decode/open_rgb.py +++ /dev/null @@ -1,91 +0,0 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: Unlicense OR CC0-1.0 -import argparse - -import cv2 as cv -import numpy as np - - -def open_picture(path): # type: (str) -> list[int] - with open(path, 'rb') as f: - data = f.read() - f.close() - new_data = [int(x) for x in data] - return new_data - - -def picture_show_rgb888(data, h, w): # type: (list[int], int, int) -> None - data = np.array(data).reshape(h, w, 3).astype(np.uint8) - cv.imshow('data', data) - cv.waitKey() - - -def picture_show_rgb565(data, h, w): # type: (list[int], int, int) -> None - - new_data = [0] * ((len(data) // 2) * 3) - for i in range(len(data)): - if i % 2 != 0: - new_data[3 * (i - 1) // 2 + 2] = (data[i] & 0xf8) - new_data[3 * (i - 1) // 2 + 1] |= (data[i] & 0x7) << 5 - else: - new_data[3 * i // 2] = (data[i] & 0x1f) << 3 - new_data[3 * i // 2 + 1] |= (data[i] & 0xe0) >> 3 - - new_data = np.array(new_data).reshape(h, w, 3).astype(np.uint8) - cv.imshow('data', new_data) - cv.waitKey() - - -def picture_show_gray(data, h, w): # type: (list[int], int, int) -> None - new_data = np.array(data).reshape(h, w, 1).astype(np.uint8) - cv.imshow('data', new_data) - cv.waitKey() - - -def main(): # type: () -> None - parser = argparse.ArgumentParser(description='which mode need to show') - - parser.add_argument( - '--pic_path', - type=str, - help='What is the path of your picture', - required=True) - - parser.add_argument( - '--pic_type', - type=str, - help='What type you want to show', - required=True, - choices=['rgb565', 'rgb888', 'gray']) - - parser.add_argument( - '--hight', - type=int, - help='the picture hight', - default=480) - - parser.add_argument( - '--width', - type=int, - help='the picture width', - default=640) - - args = parser.parse_args() - - hight = args.hight - width = args.width - - data = open_picture(args.pic_path) - - if (args.pic_type == 'rgb565'): - picture_show_rgb565(data, hight, width) - elif (args.pic_type == 'rgb888'): - picture_show_rgb888(data, hight, width) - elif (args.pic_type == 'gray'): - picture_show_gray(data, hight, width) - else: - print('This type is not supported in this script!') - - -if __name__ == '__main__': - main() diff --git a/examples/peripherals/jpeg/jpeg_encode/main/Kconfig.projbuild b/examples/peripherals/jpeg/jpeg_encode/main/Kconfig.projbuild index af809cf149..7677cd73bd 100644 --- a/examples/peripherals/jpeg/jpeg_encode/main/Kconfig.projbuild +++ b/examples/peripherals/jpeg/jpeg_encode/main/Kconfig.projbuild @@ -6,4 +6,13 @@ menu "JPEG Encode Example menu" help If this config item is set, format_if_mount_failed will be set to true and the card will be formatted if the mount has failed. + + config EXAMPLE_SDMMC_IO_POWER_INTERNAL_LDO + depends on SOC_SDMMC_IO_POWER_EXTERNAL + bool "SDMMC IO power supply comes from internal LDO (READ HELP!)" + default y + help + Please read the schematic first and check if the SDMMC VDD is connected to any internal LDO output. + If the SDMMC is powered by an external supplier, unselect me + endmenu diff --git a/examples/peripherals/jpeg/jpeg_encode/main/jpeg_encode_main.c b/examples/peripherals/jpeg/jpeg_encode/main/jpeg_encode_main.c index 8ee0a49a86..cc38e62b8b 100644 --- a/examples/peripherals/jpeg/jpeg_encode/main/jpeg_encode_main.c +++ b/examples/peripherals/jpeg/jpeg_encode/main/jpeg_encode_main.c @@ -10,6 +10,7 @@ #include "sdmmc_cmd.h" #include "driver/sdmmc_host.h" #include "driver/jpeg_encode.h" +#include "sd_pwr_ctrl_by_on_chip_ldo.h" static const char *TAG = "jpeg.example"; static sdmmc_card_t *s_card; @@ -35,6 +36,21 @@ static esp_err_t sdcard_init(void) sdmmc_host_t host = SDMMC_HOST_DEFAULT(); host.max_freq_khz = SDMMC_FREQ_HIGHSPEED; + +#if CONFIG_EXAMPLE_SDMMC_IO_POWER_INTERNAL_LDO + sd_pwr_ctrl_ldo_config_t ldo_config = { + .ldo_chan_id = 4, // `LDO_VO4` is used as the SDMMC IO power + }; + sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL; + + ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to new an on-chip ldo power control driver"); + return ret; + } + host.pwr_ctrl_handle = pwr_ctrl_handle; +#endif + // This initializes the slot without card detect (CD) and write protect (WP) signals. // Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals. sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); @@ -62,6 +78,13 @@ static void sdcard_deinit(void) { const char mount_point[] = MOUNT_POINT; esp_vfs_fat_sdcard_unmount(mount_point, s_card); +#if SOC_SDMMC_IO_POWER_EXTERNAL + esp_err_t ret = sd_pwr_ctrl_del_on_chip_ldo(s_card->host.pwr_ctrl_handle); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to delete on-chip ldo power control driver"); + return; + } +#endif } void app_main(void)