34
34
#include "video_render.h"
35
35
#include "audio_resample.h"
36
36
#include "esp_timer.h"
37
+ #include "color_convert.h"
37
38
#include "esp_log.h"
38
39
39
40
#define TAG "AV_RENDER"
@@ -88,10 +89,15 @@ typedef struct {
88
89
} av_render_adec_res_t ;
89
90
90
91
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 ;
95
101
} av_render_vdec_res_t ;
96
102
97
103
struct _av_render ;
@@ -704,6 +710,15 @@ static int v_render_body(av_render_thread_res_t *res, bool drop)
704
710
int ret = read_for_v_render (res -> data_q , & data );
705
711
RETURN_ON_FAIL (ret );
706
712
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
+ }
707
722
ret = _render_write_video (res , & data );
708
723
if (ret != 0 ) {
709
724
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
1055
1070
ESP_LOGE (TAG , "Fail to get video frame information" );
1056
1071
return ret ;
1057
1072
}
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
+ }
1058
1100
if (v_render -> video_frame_info .fps == 0 ) {
1059
1101
v_render -> video_frame_info .fps = old_fps ;
1060
1102
}
@@ -1096,6 +1138,15 @@ static int av_render_video_frame_reached(av_render_video_frame_t *frame, void *c
1096
1138
ret = put_to_v_render (v_render -> thread_res .data_q , frame );
1097
1139
}
1098
1140
} 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
+ }
1099
1150
ret = _render_write_video (& v_render -> thread_res , frame );
1100
1151
}
1101
1152
}
@@ -1306,16 +1357,42 @@ int av_render_set_fixed_frame_info(av_render_handle_t h, av_render_audio_frame_i
1306
1357
return ret ;
1307
1358
}
1308
1359
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 )
1310
1361
{
1311
1362
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
+ }
1312
1377
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 ;
1317
1380
}
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;
1318
1394
}
1395
+ return false;
1319
1396
}
1320
1397
1321
1398
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
1357
1434
}
1358
1435
vdec_close (vdec_res -> vdec );
1359
1436
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
+ }
1360
1441
}
1361
1442
// Clear frame number
1362
1443
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
1382
1463
.frame_cb = av_render_video_frame_reached ,
1383
1464
.ctx = render ,
1384
1465
};
1385
- get_support_output_format (render , & cfg );
1466
+ if (get_support_output_format (render , video_info , & cfg ) == false) {
1467
+ break ;
1468
+ }
1386
1469
vdec_res -> vdec = vdec_open (& cfg );
1387
1470
if (vdec_res -> vdec == NULL ) {
1388
1471
ESP_LOGE (TAG , "Fail to create video decoder" );
@@ -1994,9 +2077,18 @@ int av_render_reset(av_render_handle_t h)
1994
2077
render -> adec_res = NULL ;
1995
2078
}
1996
2079
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 ;
2000
2092
}
2001
2093
destroy_thread_res (& render -> vdec_res -> thread_res );
2002
2094
media_lib_free (render -> vdec_res );
0 commit comments