|
|
|
@@ -40,6 +40,7 @@ static void s_cfg_desc(jpeg_encoder_handle_t encoder_engine, dma2d_descriptor_t
|
|
|
|
|
static void s_jpeg_enc_config_picture_color_space(jpeg_encoder_handle_t encoder_engine);
|
|
|
|
|
static void s_jpeg_enc_select_sample_mode(jpeg_encoder_handle_t encoder_engine);
|
|
|
|
|
static void s_encoder_error_log_print(uint32_t status);
|
|
|
|
|
static esp_err_t jpeg_enc_validate_sub_sample(jpeg_enc_src_type_t color_space, jpeg_down_sampling_type_t sub_sample);
|
|
|
|
|
|
|
|
|
|
static void jpeg_encoder_isr_handle_default(void *arg)
|
|
|
|
|
{
|
|
|
|
@@ -73,6 +74,31 @@ static esp_err_t s_jpeg_set_header_info(jpeg_encoder_handle_t encoder_engine)
|
|
|
|
|
return ESP_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static esp_err_t jpeg_enc_validate_sub_sample(jpeg_enc_src_type_t color_space, jpeg_down_sampling_type_t sub_sample)
|
|
|
|
|
{
|
|
|
|
|
if (color_space == JPEG_ENC_SRC_GRAY) {
|
|
|
|
|
if (sub_sample != JPEG_DOWN_SAMPLING_GRAY) {
|
|
|
|
|
ESP_LOGE(TAG, "Detected GRAY but want to convert to other format, which is not supported");
|
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
|
}
|
|
|
|
|
} else if (sub_sample == JPEG_DOWN_SAMPLING_GRAY) {
|
|
|
|
|
ESP_LOGE(TAG, "Detected not GRAY but want to convert to GRAY, which is not supported");
|
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (color_space == JPEG_ENC_SRC_YUV422) {
|
|
|
|
|
if (sub_sample == JPEG_DOWN_SAMPLING_YUV444) {
|
|
|
|
|
ESP_LOGE(TAG, "Detected YUV422 but want to convert to YUV444, which is not supported");
|
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
|
}
|
|
|
|
|
} else if (color_space == JPEG_ENC_SRC_YUV420 && sub_sample != JPEG_DOWN_SAMPLING_YUV420) {
|
|
|
|
|
ESP_LOGE(TAG, "Detected YUV420 but want to convert to YUV422/YUV444, which is not supported");
|
|
|
|
|
return ESP_ERR_INVALID_ARG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ESP_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
esp_err_t jpeg_new_encoder_engine(const jpeg_encode_engine_cfg_t *enc_eng_cfg, jpeg_encoder_handle_t *ret_encoder)
|
|
|
|
|
{
|
|
|
|
|
#if CONFIG_JPEG_ENABLE_DEBUG_LOG
|
|
|
|
@@ -89,9 +115,9 @@ esp_err_t jpeg_new_encoder_engine(const jpeg_encode_engine_cfg_t *enc_eng_cfg, j
|
|
|
|
|
uint32_t alignment = cache_line_size;
|
|
|
|
|
size_t dma_desc_mem_size = JPEG_ALIGN_UP(sizeof(dma2d_descriptor_t), cache_line_size);
|
|
|
|
|
|
|
|
|
|
encoder_engine->rxlink = (dma2d_descriptor_t*)heap_caps_aligned_calloc(alignment, 1, sizeof(dma2d_descriptor_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | JPEG_MEM_ALLOC_CAPS);
|
|
|
|
|
encoder_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(encoder_engine->rxlink, ESP_ERR_NO_MEM, err, TAG, "no memory for jpeg encoder rxlink");
|
|
|
|
|
encoder_engine->txlink = (dma2d_descriptor_t*)heap_caps_aligned_calloc(alignment, 1, sizeof(dma2d_descriptor_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | JPEG_MEM_ALLOC_CAPS);
|
|
|
|
|
encoder_engine->txlink = (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(encoder_engine->txlink, ESP_ERR_NO_MEM, err, TAG, "no memory for jpeg encoder txlink");
|
|
|
|
|
encoder_engine->dma_desc_size = dma_desc_mem_size;
|
|
|
|
|
|
|
|
|
@@ -140,11 +166,9 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_
|
|
|
|
|
ESP_RETURN_ON_FALSE(encoder_engine, ESP_ERR_INVALID_ARG, TAG, "jpeg encode handle is null");
|
|
|
|
|
ESP_RETURN_ON_FALSE(encode_cfg, ESP_ERR_INVALID_ARG, TAG, "jpeg encode config is null");
|
|
|
|
|
ESP_RETURN_ON_FALSE(encode_inbuf, ESP_ERR_INVALID_ARG, TAG, "jpeg encode picture buffer is null");
|
|
|
|
|
ESP_RETURN_ON_FALSE(bit_stream, ESP_ERR_INVALID_ARG, TAG, "jpeg encode output 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;
|
|
|
|
|
|
|
|
|
@@ -156,6 +180,7 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_
|
|
|
|
|
jpeg_hal_context_t *hal = &encoder_engine->codec_base->hal;
|
|
|
|
|
uint8_t *raw_buffer = (uint8_t*)encode_inbuf;
|
|
|
|
|
uint32_t compressed_size;
|
|
|
|
|
uint32_t payload_buf_size;
|
|
|
|
|
xSemaphoreTake(encoder_engine->codec_base->codec_mutex, portMAX_DELAY);
|
|
|
|
|
jpeg_ll_soft_rst(hal->dev);
|
|
|
|
|
jpeg_ll_set_codec_mode(hal->dev, JPEG_CODEC_ENCODER);
|
|
|
|
@@ -198,6 +223,9 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_
|
|
|
|
|
ret = ESP_ERR_NOT_SUPPORTED;
|
|
|
|
|
goto err2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ESP_GOTO_ON_ERROR(jpeg_enc_validate_sub_sample(encoder_engine->color_space, encode_cfg->sub_sample), err2, TAG, "format and subsampling check failed");
|
|
|
|
|
|
|
|
|
|
encoder_engine->header_info->sub_sample = encode_cfg->sub_sample;
|
|
|
|
|
encoder_engine->header_info->quality = encode_cfg->image_quality;
|
|
|
|
|
encoder_engine->header_info->origin_h = encode_cfg->width;
|
|
|
|
@@ -208,12 +236,14 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_
|
|
|
|
|
s_jpeg_enc_select_sample_mode(encoder_engine);
|
|
|
|
|
jpeg_ll_set_picture_height(hal->dev, encoder_engine->header_info->origin_v);
|
|
|
|
|
jpeg_ll_set_picture_width(hal->dev, encoder_engine->header_info->origin_h);
|
|
|
|
|
jpeg_ll_pixel_reverse(hal->dev, false);
|
|
|
|
|
jpeg_ll_pixel_reverse(hal->dev, encode_cfg->pixel_reverse);
|
|
|
|
|
jpeg_ll_add_tail(hal->dev, true);
|
|
|
|
|
jpeg_ll_enable_ff_check(hal->dev, true);
|
|
|
|
|
jpeg_ll_set_qnr_presition(hal->dev, 0);
|
|
|
|
|
ESP_GOTO_ON_ERROR(s_jpeg_set_header_info(encoder_engine), err2, 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]);
|
|
|
|
|
ESP_GOTO_ON_FALSE(outbuf_size > encoder_engine->header_info->header_len, ESP_ERR_INVALID_ARG, err2, TAG, "output buffer is too small for jpeg header");
|
|
|
|
|
payload_buf_size = outbuf_size - encoder_engine->header_info->header_len;
|
|
|
|
|
|
|
|
|
|
uint8_t sample_method_idx = 0;
|
|
|
|
|
switch (encoder_engine->header_info->sub_sample) {
|
|
|
|
@@ -240,11 +270,11 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_
|
|
|
|
|
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, err2, TAG, "The header is not cache line aligned, please check");
|
|
|
|
|
|
|
|
|
|
// 1D direction
|
|
|
|
|
memset(encoder_engine->rxlink, 0, sizeof(dma2d_descriptor_t));
|
|
|
|
|
s_cfg_desc(encoder_engine, encoder_engine->rxlink, JPEG_DMA2D_2D_DISABLE, DMA2D_DESCRIPTOR_BLOCK_RW_MODE_MULTIPLE, outbuf_size & JPEG_DMA2D_MAX_SIZE, 0, JPEG_DMA2D_EOF_NOT_LAST, 1, DMA2D_DESCRIPTOR_BUFFER_OWNER_DMA, outbuf_size >> JPEG_DMA2D_1D_HIGH_14BIT, 0, bit_stream + encoder_engine->header_info->header_len, NULL);
|
|
|
|
|
memset(encoder_engine->rxlink, 0, encoder_engine->dma_desc_size);
|
|
|
|
|
s_cfg_desc(encoder_engine, encoder_engine->rxlink, JPEG_DMA2D_2D_DISABLE, DMA2D_DESCRIPTOR_BLOCK_RW_MODE_SINGLE, payload_buf_size & JPEG_DMA2D_MAX_SIZE, 0, JPEG_DMA2D_EOF_NOT_LAST, 1, DMA2D_DESCRIPTOR_BUFFER_OWNER_DMA, payload_buf_size >> JPEG_DMA2D_1D_HIGH_14BIT, 0, bit_stream + encoder_engine->header_info->header_len, NULL);
|
|
|
|
|
|
|
|
|
|
// 2D direction
|
|
|
|
|
memset(encoder_engine->txlink, 0, sizeof(dma2d_descriptor_t));
|
|
|
|
|
memset(encoder_engine->txlink, 0, encoder_engine->dma_desc_size);
|
|
|
|
|
s_cfg_desc(encoder_engine, encoder_engine->txlink, JPEG_DMA2D_2D_ENABLE, DMA2D_DESCRIPTOR_BLOCK_RW_MODE_MULTIPLE, dma_vb, dma_hb, JPEG_DMA2D_EOF_NOT_LAST, dma2d_desc_pixel_format_to_pbyte_value(encoder_engine->picture_format), DMA2D_DESCRIPTOR_BUFFER_OWNER_DMA, encoder_engine->header_info->origin_v, encoder_engine->header_info->origin_h, raw_buffer, NULL);
|
|
|
|
|
|
|
|
|
|
ret = esp_cache_msync((void*)raw_buffer, inbuf_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
|
|
|
|
|