mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/improve_jpeg_dec' into 'master'
fix(jpeg_decoder): Improve apis for better align strategy and provide buffer size parameter See merge request espressif/esp-idf!29687
This commit is contained in:
commit
61bb752cdb
@ -19,7 +19,7 @@ extern "C" {
|
||||
*/
|
||||
typedef struct {
|
||||
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_decode_cfg_t;
|
||||
|
||||
@ -39,6 +39,13 @@ typedef struct {
|
||||
uint32_t height; /*!< Number of pixels in the vertical direction */
|
||||
} 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.
|
||||
*
|
||||
@ -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
|
||||
* 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] decode_cfg Config structure of decoder.
|
||||
* @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[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.
|
||||
* @return
|
||||
* - ESP_OK: JPEG decoder process successfully.
|
||||
* - 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.
|
||||
@ -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.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
@ -36,7 +36,15 @@ 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_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
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "soc/dma2d_channel.h"
|
||||
#include "soc/interrupts.h"
|
||||
#include "esp_dma_utils.h"
|
||||
#include "esp_private/esp_cache_private.h"
|
||||
#if CONFIG_JPEG_ENABLE_DEBUG_LOG
|
||||
// The local log level must be defined before including esp_log.h
|
||||
// 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;
|
||||
}
|
||||
|
||||
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(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(((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(((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_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_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_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 = {
|
||||
.tx_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);
|
||||
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");
|
||||
bool need_yield;
|
||||
// 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) {
|
||||
ret = esp_cache_msync((void*)decoder_engine->decoded_buf, outbuf_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
|
||||
assert(ret == ESP_OK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*out_size = decoder_engine->header_info->process_h * decoder_engine->header_info->process_v * decoder_engine->pixel;
|
||||
|
||||
err:
|
||||
xSemaphoreGive(decoder_engine->codec_base->codec_mutex);
|
||||
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;
|
||||
}
|
||||
|
||||
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_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 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
|
||||
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,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
memcpy(tx_buf_1080p, image_esp1080_jpg_start, bit_stream_length);
|
||||
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
|
||||
uint8_t cnt = 50;
|
||||
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();
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
uint8_t *bit_stream = (uint8_t*)heap_caps_aligned_calloc(JPEG_BUFFER_MALLOC_ALIGN_VALUE, 1, bit_stream_size, MALLOC_CAP_SPIRAM);
|
||||
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 tx_buffer_size;
|
||||
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;
|
||||
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::
|
||||
|
||||
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.
|
||||
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
|
||||
^^^^^^^^^^^^^
|
||||
|
@ -88,6 +88,14 @@ void app_main(void)
|
||||
.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");
|
||||
ESP_LOGI(TAG, "jpg_file_1080:%s", jpg_file_1080);
|
||||
if (file_jpg_1080p == NULL) {
|
||||
@ -98,7 +106,8 @@ void app_main(void)
|
||||
fseek(file_jpg_1080p, 0, SEEK_END);
|
||||
int jpeg_size_1080p = ftell(file_jpg_1080p);
|
||||
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) {
|
||||
ESP_LOGE(TAG, "alloc 1080p tx buffer error");
|
||||
return;
|
||||
@ -115,7 +124,8 @@ void app_main(void)
|
||||
fseek(file_jpg_720p, 0, SEEK_END);
|
||||
int jpeg_size_720p = ftell(file_jpg_720p);
|
||||
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) {
|
||||
ESP_LOGE(TAG, "alloc 720p tx buffer error");
|
||||
return;
|
||||
@ -123,8 +133,10 @@ void app_main(void)
|
||||
fread(tx_buf_720p, 1, jpeg_size_720p, file_jpg_720p);
|
||||
fclose(file_jpg_720p);
|
||||
|
||||
uint8_t *rx_buf_1080p = (uint8_t*)jpeg_alloc_decoder_mem(1920 * 1080 * 3);
|
||||
uint8_t *rx_buf_720p = (uint8_t*)jpeg_alloc_decoder_mem(720 * 1280);
|
||||
size_t rx_buffer_size_1080p = 0;
|
||||
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) {
|
||||
ESP_LOGE(TAG, "alloc 1080p rx buffer error");
|
||||
return;
|
||||
@ -141,8 +153,8 @@ void app_main(void)
|
||||
|
||||
uint32_t out_size_1080p = 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_gray, tx_buf_720p, jpeg_size_720p, rx_buf_720p, &out_size_720p));
|
||||
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, rx_buffer_size_720p, &out_size_720p));
|
||||
|
||||
// Write two pictures.
|
||||
FILE *file_rgb_1080p = fopen(raw_file_1080, "wb");
|
||||
|
Loading…
Reference in New Issue
Block a user