Skip to content

Commit c7f9878

Browse files
committed
Add color convert in render configuration
1 parent 73ffcf7 commit c7f9878

File tree

15 files changed

+229
-35
lines changed

15 files changed

+229
-35
lines changed

components/av_render/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,9 @@ set(COMPONENT_ADD_INCLUDEDIRS ./include)
66
set(COMPONENT_PRIV_REQUIRES media_lib_sal esp_timer esp_audio_codec esp_video_codec)
77

88
register_component()
9+
10+
# Add color convert ASM optimized lib
11+
IF (${IDF_TARGET} STREQUAL "esp32p4")
12+
set(TARGET_LIB_NAME "${CMAKE_CURRENT_SOURCE_DIR}/libs/${IDF_TARGET}/libesp_image_i420_2_rgb565le.a")
13+
target_link_libraries(${COMPONENT_TARGET} "-Wl,--start-group" ${TARGET_LIB_NAME} "-Wl,--end-group")
14+
ENDIF ()

components/av_render/include/av_render.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ typedef struct {
5959
bool pause_render_only; /*!< If call `av_render_pause` only pause render thread or pause all thread */
6060
bool pause_on_first_frame; /*!< Whether automatically pause when render receive first frame */
6161
void *ctx; /*!< User context */
62+
bool video_cvt_in_render; /*!< Convert color in render*/
6263
} av_render_cfg_t;
6364

6465
/**

components/av_render/include/av_render_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ typedef struct {
8181
uint8_t channel; /*!< Audio channel */
8282
uint8_t bits_per_sample; /*!< Audio bits per sample */
8383
uint32_t sample_rate; /*!< Audio sample rate */
84+
uint32_t aac_no_adts : 1; /*!< AAC no adts */
8485
void *codec_spec_info; /*!< Audio codec specified information */
8586
int spec_info_len; /*!< Audio codec specified information length */
8687
} av_render_audio_info_t;

components/av_render/include/video_decoder.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ typedef struct {
5858
*/
5959
typedef void *vdec_handle_t;
6060

61+
/**
62+
* @brief Get video decoder output formats according decode type
63+
*
64+
* @param[in] codec Decode type
65+
* @param[out] fmts Output formats to be filled
66+
* @param[in,out] fmts Output formats number
67+
* @return
68+
* - NULL No resource for decoder
69+
* - Others Video decoder handle
70+
*/
71+
int vdec_get_output_formats(av_render_video_codec_t codec, av_render_video_frame_type_t* fmts, uint8_t* num);
72+
6173
/**
6274
* @brief Open video decoder
6375
*
Binary file not shown.

components/av_render/src/audio_decoder.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,19 @@ static int _open_audio_dec(adec_t *adec, av_render_audio_info_t *stream_info)
142142
dec_cfg.cfg = &alac_cfg;
143143
dec_cfg.cfg_sz = sizeof(esp_alac_dec_cfg_t);
144144
esp_audio_dec_open(&dec_cfg, &adec->dec_handle);
145+
} break;
146+
case ESP_AUDIO_TYPE_AAC: {
147+
esp_aac_dec_cfg_t aac_cfg = {
148+
.channel = stream_info->channel,
149+
.sample_rate = stream_info->sample_rate,
150+
.bits_per_sample = stream_info->bits_per_sample,
151+
.no_adts_header = stream_info->aac_no_adts,
152+
};
153+
if (stream_info->aac_no_adts) {
154+
dec_cfg.cfg = &aac_cfg;
155+
dec_cfg.cfg_sz = sizeof(esp_alac_dec_cfg_t);
156+
}
157+
esp_audio_dec_open(&dec_cfg, &adec->dec_handle);
145158
} break;
146159
default:
147160
esp_audio_dec_open(&dec_cfg, &adec->dec_handle);

components/av_render/src/av_render.c

Lines changed: 105 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "video_render.h"
3535
#include "audio_resample.h"
3636
#include "esp_timer.h"
37+
#include "color_convert.h"
3738
#include "esp_log.h"
3839

3940
#define TAG "AV_RENDER"
@@ -88,10 +89,15 @@ typedef struct {
8889
} av_render_adec_res_t;
8990

9091
typedef struct {
91-
av_render_thread_res_t thread_res;
92-
vdec_handle_t vdec;
93-
int video_err_cnt;
94-
av_render_video_frame_t *fb_frame;
92+
av_render_thread_res_t thread_res;
93+
vdec_handle_t vdec;
94+
int video_err_cnt;
95+
av_render_video_frame_t *fb_frame;
96+
av_render_video_frame_type_t dec_out_fmt;
97+
av_render_video_frame_type_t out_fmt;
98+
color_convert_table_t *vid_convert;
99+
uint8_t *vid_convert_out;
100+
int vid_convert_out_size;
95101
} av_render_vdec_res_t;
96102

97103
struct _av_render;
@@ -704,6 +710,15 @@ static int v_render_body(av_render_thread_res_t *res, bool drop)
704710
int ret = read_for_v_render(res->data_q, &data);
705711
RETURN_ON_FAIL(ret);
706712
if (drop == false && (data.size || data.eos)) {
713+
av_render_vdec_res_t *vdec_res = res->render->vdec_res;
714+
if (vdec_res && vdec_res->vid_convert) {
715+
// Do color convert firstly
716+
ret = convert_color(vdec_res->vid_convert,
717+
data.data, data.size,
718+
vdec_res->vid_convert_out, vdec_res->vid_convert_out_size);
719+
data.data = vdec_res->vid_convert_out;
720+
data.size = vdec_res->vid_convert_out_size;
721+
}
707722
ret = _render_write_video(res, &data);
708723
if (ret != 0) {
709724
ESP_LOGE(TAG, "Fail to render video");
@@ -1055,6 +1070,33 @@ static int av_render_video_frame_reached(av_render_video_frame_t *frame, void *c
10551070
ESP_LOGE(TAG, "Fail to get video frame information");
10561071
return ret;
10571072
}
1073+
if (vdec_res->dec_out_fmt != vdec_res->out_fmt) {
1074+
color_convert_cfg_t convert_cfg = {
1075+
.from = vdec_res->dec_out_fmt,
1076+
.to = vdec_res->out_fmt,
1077+
.width = v_render->video_frame_info.width,
1078+
.height = v_render->video_frame_info.height,
1079+
};
1080+
vdec_res->vid_convert = init_convert_table(&convert_cfg);
1081+
if (vdec_res->vid_convert == NULL) {
1082+
ESP_LOGE(TAG, "Fail to init video convert");
1083+
return ESP_MEDIA_ERR_NO_MEM;
1084+
}
1085+
}
1086+
if (vdec_res && vdec_res->vid_convert) {
1087+
// Delay to malloc video convert output size
1088+
int image_size = convert_table_get_image_size(vdec_res->out_fmt,
1089+
v_render->video_frame_info.width,
1090+
v_render->video_frame_info.height);
1091+
uint8_t* vid_cvt_out = media_lib_realloc(vdec_res->vid_convert_out, image_size);
1092+
if (vid_cvt_out == NULL) {
1093+
ESP_LOGE(TAG, "Fail to allocate video convert output");
1094+
return ESP_MEDIA_ERR_NO_MEM;
1095+
}
1096+
vdec_res->vid_convert_out = vid_cvt_out;
1097+
vdec_res->vid_convert_out_size = image_size;
1098+
v_render->video_frame_info.type = vdec_res->out_fmt;
1099+
}
10581100
if (v_render->video_frame_info.fps == 0) {
10591101
v_render->video_frame_info.fps = old_fps;
10601102
}
@@ -1096,6 +1138,15 @@ static int av_render_video_frame_reached(av_render_video_frame_t *frame, void *c
10961138
ret = put_to_v_render(v_render->thread_res.data_q, frame);
10971139
}
10981140
} else {
1141+
av_render_vdec_res_t *vdec_res = render->vdec_res;
1142+
if (vdec_res && vdec_res->vid_convert) {
1143+
// Do color convert firstly
1144+
ret = convert_color(vdec_res->vid_convert,
1145+
frame->data, frame->size,
1146+
vdec_res->vid_convert_out, vdec_res->vid_convert_out_size);
1147+
frame->data = vdec_res->vid_convert_out;
1148+
frame->size = vdec_res->vid_convert_out_size;
1149+
}
10991150
ret = _render_write_video(&v_render->thread_res, frame);
11001151
}
11011152
}
@@ -1306,16 +1357,42 @@ int av_render_set_fixed_frame_info(av_render_handle_t h, av_render_audio_frame_i
13061357
return ret;
13071358
}
13081359

1309-
static void get_support_output_format(av_render_t *render, vdec_cfg_t *cfg)
1360+
static bool get_support_output_format(av_render_t *render, av_render_video_info_t *video_info, vdec_cfg_t *cfg)
13101361
{
13111362
av_render_video_frame_type_t out_type;
1363+
av_render_video_frame_type_t out_fmts[6];
1364+
av_render_vdec_res_t *vdec_res = render->vdec_res;
1365+
uint8_t num = sizeof(out_fmts)/sizeof(out_fmts[0]);
1366+
vdec_get_output_formats(video_info->codec, out_fmts, &num);
1367+
// Try to match decoder supported formats
1368+
for (int i = 0; i < num; i++) {
1369+
if (video_render_format_supported(render->cfg.video_render, out_fmts[i])) {
1370+
ESP_LOGI(TAG, "Set video decoder prefer output format %d", out_fmts[i]);
1371+
cfg->out_type = out_fmts[i];
1372+
vdec_res->out_fmt = out_fmts[i];
1373+
vdec_res->dec_out_fmt = out_fmts[i];
1374+
return true;
1375+
}
1376+
}
13121377
for (out_type = AV_RENDER_VIDEO_RAW_TYPE_NONE + 1; out_type < AV_RENDER_VIDEO_RAW_TYPE_MAX; out_type++) {
1313-
if (video_render_format_supported(render->cfg.video_render, out_type)) {
1314-
ESP_LOGI(TAG, "Set video decoder output format %d", out_type);
1315-
cfg->out_type = out_type;
1316-
break;
1378+
if (video_render_format_supported(render->cfg.video_render, out_type) == false) {
1379+
continue;
13171380
}
1381+
ESP_LOGI(TAG, "Set video render output format %d", out_type);
1382+
// Let decoder do color convert
1383+
if (render->cfg.video_cvt_in_render == false) {
1384+
cfg->out_type = out_type;
1385+
vdec_res->out_fmt = out_type;
1386+
vdec_res->dec_out_fmt = out_type;
1387+
return true;
1388+
}
1389+
// User codec prefer one
1390+
cfg->out_type = out_fmts[0];
1391+
vdec_res->out_fmt = out_type;
1392+
vdec_res->dec_out_fmt = out_fmts[0];
1393+
return true;
13181394
}
1395+
return false;
13191396
}
13201397

13211398
int av_render_add_video_stream(av_render_handle_t h, av_render_video_info_t *video_info)
@@ -1357,6 +1434,10 @@ int av_render_add_video_stream(av_render_handle_t h, av_render_video_info_t *vid
13571434
}
13581435
vdec_close(vdec_res->vdec);
13591436
vdec_res->vdec = NULL;
1437+
if (vdec_res->vid_convert) {
1438+
deinit_convert_table(vdec_res->vid_convert);
1439+
vdec_res->vid_convert = NULL;
1440+
}
13601441
}
13611442
// Clear frame number
13621443
v_render->video_packet_reached = false;
@@ -1382,7 +1463,9 @@ int av_render_add_video_stream(av_render_handle_t h, av_render_video_info_t *vid
13821463
.frame_cb = av_render_video_frame_reached,
13831464
.ctx = render,
13841465
};
1385-
get_support_output_format(render, &cfg);
1466+
if (get_support_output_format(render, video_info, &cfg) == false) {
1467+
break;
1468+
}
13861469
vdec_res->vdec = vdec_open(&cfg);
13871470
if (vdec_res->vdec == NULL) {
13881471
ESP_LOGE(TAG, "Fail to create video decoder");
@@ -1994,9 +2077,18 @@ int av_render_reset(av_render_handle_t h)
19942077
render->adec_res = NULL;
19952078
}
19962079
if (render->vdec_res) {
1997-
if (render->vdec_res->vdec) {
1998-
vdec_close(render->vdec_res->vdec);
1999-
render->vdec_res->vdec = NULL;
2080+
av_render_vdec_res_t *vdec_res = render->vdec_res;
2081+
if (vdec_res->vdec) {
2082+
vdec_close(vdec_res->vdec);
2083+
vdec_res->vdec = NULL;
2084+
}
2085+
if (vdec_res->vid_convert) {
2086+
deinit_convert_table(vdec_res->vid_convert);
2087+
vdec_res->vid_convert = NULL;
2088+
}
2089+
if (vdec_res->vid_convert_out) {
2090+
media_lib_free(vdec_res->vid_convert_out);
2091+
vdec_res->vid_convert_out = NULL;
20002092
}
20012093
destroy_thread_res(&render->vdec_res->thread_res);
20022094
media_lib_free(render->vdec_res);

components/av_render/src/color_convert.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@
2121
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2222
*
2323
*/
24-
24+
#include <sdkconfig.h>
2525
#include "color_convert.h"
2626
#include "esp_log.h"
2727

28+
#if CONFIG_IDF_TARGET_ESP32P4
29+
extern void i420_to_rgb565le(uint8_t *in_image, uint8_t *out_image, int16_t width, int16_t height);
30+
#endif
31+
2832
#define TAG "CLR_CONVERT"
2933

3034
#define COLOR_LIMIT(a) (a > 255 ? 255 : a < 0 ? 0 \
@@ -99,6 +103,21 @@ static int init_table(color_convert_t *convert)
99103
return 0;
100104
}
101105

106+
int convert_table_get_image_size(av_render_video_frame_type_t fmt, int width, int height)
107+
{
108+
switch (fmt) {
109+
case AV_RENDER_VIDEO_RAW_TYPE_YUV420:
110+
return width * height * 3 / 2;
111+
case AV_RENDER_VIDEO_RAW_TYPE_RGB565:
112+
case AV_RENDER_VIDEO_RAW_TYPE_RGB565_BE:
113+
return width * height * 2;
114+
default:
115+
ESP_LOGE(TAG, "Not supported format %d", fmt);
116+
break;
117+
}
118+
return 0;
119+
}
120+
102121
color_convert_table_t init_convert_table(color_convert_cfg_t *cfg)
103122
{
104123
color_convert_t *convert = (color_convert_t *)calloc(1, sizeof(color_convert_t));
@@ -110,6 +129,11 @@ color_convert_table_t init_convert_table(color_convert_cfg_t *cfg)
110129
convert->to = cfg->to;
111130
convert->width = cfg->width;
112131
convert->height = cfg->height;
132+
#if CONFIG_IDF_TARGET_ESP32P4
133+
if (convert->from == AV_RENDER_VIDEO_RAW_TYPE_YUV420 && convert->to == AV_RENDER_VIDEO_RAW_TYPE_RGB565) {
134+
return (color_convert_table_t)convert;
135+
}
136+
#endif
113137
int table_size = get_table_size(cfg->from, cfg->to);
114138
if (table_size) {
115139
convert->table = (uint8_t *)malloc(table_size);
@@ -158,6 +182,13 @@ static void yuv420_to_rgb565(color_convert_t *convert, uint8_t *src, uint8_t *ds
158182
int convert_color(color_convert_table_t table, uint8_t *src, int src_size, uint8_t *dst, int dst_size)
159183
{
160184
color_convert_t *convert = (color_convert_t *)table;
185+
if (convert->from == AV_RENDER_VIDEO_RAW_TYPE_YUV420 && convert->to == AV_RENDER_VIDEO_RAW_TYPE_RGB565) {
186+
#if CONFIG_IDF_TARGET_ESP32P4
187+
i420_to_rgb565le(src, dst, convert->width, convert->height);
188+
return 0;
189+
#endif
190+
}
191+
161192
switch (convert->from) {
162193
case AV_RENDER_VIDEO_RAW_TYPE_YUV420: {
163194
int src_need = convert->width * convert->height * 3 / 2;

components/av_render/src/color_convert.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ typedef struct {
3636
int height;
3737
} color_convert_cfg_t;
3838

39+
int convert_table_get_image_size(av_render_video_frame_type_t fmt, int width, int height);
40+
3941
color_convert_table_t init_convert_table(color_convert_cfg_t *cfg);
4042

4143
int convert_color(color_convert_table_t table, uint8_t *src, int src_size, uint8_t *dst, int dst_size);

components/av_render/src/video_decoder.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ static esp_video_codec_type_t get_codec_type(av_render_video_codec_t codec)
6767
static esp_video_codec_pixel_fmt_t get_out_fmt(av_render_video_frame_type_t out_type)
6868
{
6969
switch (out_type) {
70+
case AV_RENDER_VIDEO_RAW_TYPE_YUV420:
71+
return ESP_VIDEO_CODEC_PIXEL_FMT_YUV420P;
7072
case AV_RENDER_VIDEO_RAW_TYPE_RGB565:
7173
return ESP_VIDEO_CODEC_PIXEL_FMT_RGB565_LE;
7274
case AV_RENDER_VIDEO_RAW_TYPE_RGB565_BE:
@@ -227,6 +229,26 @@ static int check_input_format_support(vdec_t *vdec, esp_video_dec_cfg_t *dec_cfg
227229
return ESP_MEDIA_ERR_OK;
228230
}
229231

232+
int vdec_get_output_formats(av_render_video_codec_t codec, av_render_video_frame_type_t* fmts, uint8_t* num)
233+
{
234+
esp_video_codec_query_t query = {
235+
.codec_type = get_codec_type(codec),
236+
};
237+
esp_video_dec_caps_t caps = {};
238+
esp_video_dec_query_caps(&query, &caps);
239+
if (caps.out_fmt_num == 0) {
240+
return ESP_MEDIA_ERR_NOT_SUPPORT;
241+
}
242+
if (*num < caps.out_fmt_num) {
243+
return ESP_MEDIA_ERR_EXCEED_LIMIT;
244+
}
245+
for (int i = 0; i < caps.out_fmt_num; i++) {
246+
fmts[i] = get_frame_type(caps.out_fmts[i]);
247+
}
248+
*num = caps.out_fmt_num;
249+
return ESP_MEDIA_ERR_OK;
250+
}
251+
230252
vdec_handle_t vdec_open(vdec_cfg_t *cfg)
231253
{
232254
if (cfg == NULL) {
@@ -351,4 +373,4 @@ int vdec_close(vdec_handle_t h)
351373
}
352374
media_lib_free(vdec);
353375
return ESP_MEDIA_ERR_OK;
354-
}
376+
}

0 commit comments

Comments
 (0)