[vlc-commits] [Git][videolan/vlc][master] 16 commits: test: input_decoder: remove some options
Steve Lhomme (@robUx4)
gitlab at videolan.org
Tue Oct 10 15:13:39 UTC 2023
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
8157c2e3 by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: remove some options
This will allow to test if a spu is rendered.
- - - - -
d34dc61c by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: add player_setup_before_start
For example, it can be used to select a specific track, like a CC track
that is not automatically enabled.
- - - - -
75b475fe by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: add callbacks to test CC decoders
- - - - -
c455323a by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: add a callback to test the text renderer
- - - - -
b1566309 by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: factor cc frame creation
- - - - -
c80a3d1f by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: use a valid ts from packetizer_getcc
- - - - -
e8f4522b by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: use a valid length for the cc frame
- - - - -
bbd90403 by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: fill the cc frame with valid data
- - - - -
5c28ff1d by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: use a valid i_reorder_depth
Better to assert for 4 than -1 (since it might be initialized to -1 in
the core).
- - - - -
b565df7c by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: add scenario->subpicture_chromas
Scenarios can now specify the subpicture_chromas array.
- - - - -
f173e9b8 by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: check that CC frames from pkt can be rendered
- - - - -
284dda6e by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: split decoder_decode_check_cc
- - - - -
cd83c2d9 by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: check that CC frames from dec can be rendered
- - - - -
222f24f3 by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: check that 4 CEA608 tracks can be added
- - - - -
b2a74c41 by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: print the name of the running scenario
Make it easier to identify the failing scenario.
- - - - -
aa6b665c by Thomas Guillem at 2023-10-10T14:54:43+00:00
test: input_decoder: remove unused sem
- - - - -
3 changed files:
- test/src/input/decoder/input_decoder.c
- test/src/input/decoder/input_decoder.h
- test/src/input/decoder/input_decoder_scenarios.c
Changes:
=====================================
test/src/input/decoder/input_decoder.c
=====================================
@@ -93,6 +93,19 @@ static int DecoderDecode(decoder_t *dec, block_t *block)
return ret;
}
+static int CcDecoderDecode(decoder_t *dec, vlc_frame_t *frame)
+{
+ if (frame == NULL)
+ return VLC_SUCCESS;
+
+ struct input_decoder_scenario *scenario = &input_decoder_scenarios[current_scenario];
+ assert(scenario->cc_decoder_decode != NULL);
+ int ret = scenario->cc_decoder_decode(dec, frame);
+ if (ret != VLCDEC_RELOAD)
+ vlc_frame_Release(frame);
+ return ret;
+}
+
static void DecoderFlush(decoder_t *dec)
{
struct input_decoder_scenario *scenario = &input_decoder_scenarios[current_scenario];
@@ -112,6 +125,15 @@ static void CloseDecoder(vlc_object_t *obj)
vlc_video_context_Release(vctx);
}
+static void CloseCcDecoder(vlc_object_t *obj)
+{
+ struct input_decoder_scenario *scenario = &input_decoder_scenarios[current_scenario];
+ decoder_t *dec = (decoder_t*)obj;
+
+ if (scenario->cc_decoder_destroy != NULL)
+ scenario->cc_decoder_destroy(dec);
+}
+
static vlc_frame_t *PacketizerPacketize(decoder_t *dec, vlc_frame_t **in)
{
(void)dec;
@@ -171,6 +193,29 @@ static int OpenDecoder(vlc_object_t *obj)
return VLC_SUCCESS;
}
+static int OpenCcDecoder(vlc_object_t *obj)
+{
+ struct input_decoder_scenario *scenario = &input_decoder_scenarios[current_scenario];
+ if (scenario->cc_decoder_setup == NULL)
+ return VLC_EGENERIC;
+
+ decoder_t *dec = (decoder_t*)obj;
+
+ dec->pf_decode = CcDecoderDecode;
+ dec->pf_get_cc = NULL;
+ dec->pf_flush = NULL;
+ es_format_Clean(&dec->fmt_out);
+ es_format_Copy(&dec->fmt_out, dec->fmt_in);
+
+ scenario->cc_decoder_setup(dec);
+
+ msg_Dbg(obj, "Decoder chroma %4.4s -> %4.4s",
+ (const char *)&dec->fmt_in->i_codec,
+ (const char *)&dec->fmt_out.i_codec);
+
+ return VLC_SUCCESS;
+}
+
static void DisplayPrepare(vout_display_t *vd, picture_t *picture,
subpicture_t *subpic, vlc_tick_t date)
{
@@ -191,12 +236,15 @@ static int OpenDisplay(vout_display_t *vd, video_format_t *fmtp, vlc_video_conte
{
(void)fmtp; (void)context;
+ struct input_decoder_scenario *scenario = &input_decoder_scenarios[current_scenario];
static const struct vlc_display_operations ops = {
.prepare = DisplayPrepare,
.control = DisplayControl,
};
vd->ops = &ops;
+ vd->info.subpicture_chromas = scenario->subpicture_chromas;
+
return VLC_SUCCESS;
}
@@ -210,6 +258,28 @@ static int OpenWindow(vlc_window_t *wnd)
return VLC_SUCCESS;
}
+static int TextRendererRender(filter_t *filter, subpicture_region_t *region_out,
+ subpicture_region_t *region_in,
+ const vlc_fourcc_t *chroma_list)
+{
+ (void) region_out; (void) chroma_list;
+ struct input_decoder_scenario *scenario = &input_decoder_scenarios[current_scenario];
+ if (scenario->text_renderer_render != NULL)
+ scenario->text_renderer_render(filter, region_in);
+ return VLC_EGENERIC;
+}
+
+static int OpenTextRenderer(filter_t *filter)
+{
+ static const struct vlc_filter_operations ops =
+ {
+ .render = TextRendererRender,
+ };
+
+ filter->ops = &ops;
+ return VLC_SUCCESS;
+}
+
static void *SoutFilterAdd(sout_stream_t *stream, const es_format_t *fmt,
const char *es_id)
{
@@ -284,6 +354,8 @@ static void on_track_list_changed(vlc_player_t *player,
static void play_scenario(intf_thread_t *intf, struct input_decoder_scenario *scenario)
{
+ assert(scenario->name != NULL);
+ fprintf(stderr, "\nChecking '%s'\n\n", scenario->name);
input_decoder_scenario_init();
input_item_t *media = input_item_New(scenario->source, "dummy");
assert(media);
@@ -314,6 +386,8 @@ static void play_scenario(intf_thread_t *intf, struct input_decoder_scenario *sc
vlc_player_listener_id *listener =
vlc_player_AddListener(player, &player_cbs, NULL);
vlc_player_SetCurrentMedia(player, media);
+ if (scenario->player_setup_before_start != NULL)
+ scenario->player_setup_before_start(player);
vlc_player_Start(player);
vlc_player_Unlock(player);
@@ -368,6 +442,10 @@ vlc_module_begin()
set_callbacks(OpenDecoder, CloseDecoder)
set_capability("video decoder", INT_MAX)
+ add_submodule()
+ set_callbacks(OpenCcDecoder, CloseCcDecoder)
+ set_capability("spu decoder", INT_MAX)
+
add_submodule()
set_callback(OpenPacketizer)
set_capability("packetizer", INT_MAX)
@@ -379,6 +457,9 @@ vlc_module_begin()
add_submodule()
set_callback_display(OpenDisplay, 0)
+ add_submodule()
+ set_callback_text_renderer(OpenTextRenderer, INT_MAX)
+
add_submodule()
set_callback(OpenSoutFilter)
set_capability("sout output", 0)
@@ -400,9 +481,7 @@ int main( int argc, char **argv )
"--vout=" MODULE_STRING,
"--dec-dev=" MODULE_STRING,
"--aout=dummy",
- "--text-renderer=dummy",
"--no-auto-preparse",
- "--no-spu",
"--no-osd",
};
=====================================
test/src/input/decoder/input_decoder.h
=====================================
@@ -30,14 +30,21 @@ typedef struct intf_thread_t intf_thread_t;
typedef struct decoder_cc_desc_t decoder_cc_desc_t;
struct input_decoder_scenario {
+ const char *name;
const char *source;
const char *sout;
+ const vlc_fourcc_t *subpicture_chromas;
void (*decoder_setup)(decoder_t *);
void (*decoder_destroy)(decoder_t *);
int (*decoder_decode)(decoder_t *, picture_t *);
+ void (*cc_decoder_setup)(decoder_t *);
+ void (*cc_decoder_destroy)(decoder_t *);
+ int (*cc_decoder_decode)(decoder_t *, vlc_frame_t *in);
vlc_frame_t * (*packetizer_getcc)(decoder_t *, decoder_cc_desc_t *);
void (*decoder_flush)(decoder_t *);
void (*display_prepare)(vout_display_t *vd, picture_t *pic);
+ void (*text_renderer_render)(filter_t *filter, subpicture_region_t *region_in);
+ void (*player_setup_before_start)(vlc_player_t *);
void (*interface_setup)(intf_thread_t *intf);
int (*sout_filter_send)(sout_stream_t *stream, void *id, block_t *block);
void (*sout_filter_flush)(sout_stream_t *stream, void *id);
=====================================
test/src/input/decoder/input_decoder_scenarios.c
=====================================
@@ -39,13 +39,13 @@
static struct scenario_data
{
vlc_sem_t wait_stop;
- vlc_sem_t display_prepare_signal;
vlc_sem_t wait_ready_to_flush;
struct vlc_video_context *decoder_vctx;
bool skip_decoder;
bool has_reload;
bool stream_out_sent;
size_t decoder_image_sent;
+ size_t cc_track_idx;
} scenario_data;
static void decoder_fixed_size(decoder_t *dec, vlc_fourcc_t chroma,
@@ -65,33 +65,61 @@ static void decoder_fixed_size(decoder_t *dec, vlc_fourcc_t chroma,
static void decoder_i420_800_600(decoder_t *dec)
{ decoder_fixed_size(dec, VLC_CODEC_I420, 800, 600); }
+static void decoder_i420_800_600_update(decoder_t *dec)
+{
+ decoder_fixed_size(dec, VLC_CODEC_I420, 800, 600);
+ int ret = decoder_UpdateVideoOutput(dec, NULL);
+ assert(ret == VLC_SUCCESS);
+}
+
static void decoder_i420_800_600_stop(decoder_t *dec)
{
decoder_i420_800_600(dec);
vlc_sem_post(&scenario_data.wait_stop);
}
-static int decoder_decode_check_cc(decoder_t *dec, picture_t *pic)
+static const char cc_block_input[] = "cc01_input";
+static vlc_frame_t *create_cc_frame(vlc_tick_t ts)
{
- vlc_tick_t date = pic->date;
- picture_Release(pic);
+ vlc_frame_t *f = vlc_frame_Alloc(sizeof(cc_block_input));
+ assert(f != NULL);
+ memcpy(f->p_buffer, cc_block_input, sizeof(cc_block_input));
+ f->i_dts = f->i_pts = ts;
+ f->i_length = VLC_TICK_FROM_MS(20);
+ return f;
+}
- block_t *p_cc = block_Alloc( 1 );
- if (p_cc == NULL)
- return VLC_ENOMEM;
+static void decoder_decode_check_cc_common(decoder_t *dec, picture_t *pic)
+{
+ vlc_tick_t date = pic->date;
- p_cc->i_dts = p_cc->i_pts = date;
+ vlc_frame_t *cc = create_cc_frame(date);
decoder_cc_desc_t desc = {
.i_608_channels = 1,
+ .i_reorder_depth = 4,
};
- decoder_QueueCc( dec, p_cc, &desc );
+ decoder_QueueCc(dec, cc, &desc);
+}
+
+static int decoder_decode_check_cc(decoder_t *dec, picture_t *pic)
+{
+ decoder_decode_check_cc_common(dec, pic);
+ picture_Release(pic);
vlc_sem_post(&scenario_data.wait_ready_to_flush);
return VLC_SUCCESS;
}
+static int decoder_decode_check_cc_queue_video(decoder_t *dec, picture_t *pic)
+{
+ decoder_decode_check_cc_common(dec, pic);
+ decoder_QueueVideo(dec, pic);
+
+ return VLC_SUCCESS;
+}
+
struct picture_watcher_context {
picture_context_t context;
vlc_sem_t wait_picture;
@@ -123,6 +151,12 @@ static int decoder_decode_drop(decoder_t *dec, picture_t *pic)
return VLC_SUCCESS;
}
+static int decoder_decode(decoder_t *dec, picture_t *pic)
+{
+ decoder_QueueVideo(dec, pic);
+ return VLC_SUCCESS;
+}
+
static int decoder_decode_check_flush_video(decoder_t *dec, picture_t *pic)
{
if (scenario_data.skip_decoder)
@@ -343,12 +377,21 @@ static vlc_frame_t *packetizer_getcc(decoder_t *dec, decoder_cc_desc_t *cc_desc)
(void)dec;
cc_desc->i_608_channels = 1;
- cc_desc->i_reorder_depth = -1;
+ cc_desc->i_708_channels = 0;
+ cc_desc->i_reorder_depth = 4;
- vlc_frame_t *f = vlc_frame_Alloc(1);
- assert(f != NULL);
+ return create_cc_frame(VLC_TICK_0);
+}
- return f;
+static vlc_frame_t *packetizer_getcc_cea608_max(decoder_t *dec, decoder_cc_desc_t *cc_desc)
+{
+ (void)dec;
+
+ cc_desc->i_608_channels = 0xF;
+ cc_desc->i_708_channels = 0;
+ cc_desc->i_reorder_depth = 4;
+
+ return create_cc_frame(VLC_TICK_0);
}
static void on_track_list_changed_check_cea608(
@@ -365,9 +408,94 @@ static void on_track_list_changed_check_cea608(
vlc_sem_post(&scenario_data.wait_stop);
}
+static void on_track_list_changed_check_count(
+ enum vlc_player_list_action action,
+ const struct vlc_player_track *track,
+ vlc_fourcc_t codec, unsigned track_max)
+{
+ if (action != VLC_PLAYER_LIST_ADDED)
+ return;
+
+ char buffer[] = "video/0/cc/spu/auto/xx";
+ assert(scenario_data.cc_track_idx < 100);
+ sprintf(buffer, "video/0/cc/spu/auto/%zu", scenario_data.cc_track_idx);
+
+ if (strcmp(vlc_es_id_GetStrId(track->es_id), buffer) != 0)
+ return;
+
+ assert(track->fmt.i_codec == codec);
+
+ scenario_data.cc_track_idx++;
+
+ if (scenario_data.cc_track_idx == track_max)
+ vlc_sem_post(&scenario_data.wait_stop);
+}
+
+static void on_track_list_changed_check_cea608_count(
+ enum vlc_player_list_action action,
+ const struct vlc_player_track *track)
+{
+ on_track_list_changed_check_count(action, track, VLC_CODEC_CEA608, 4);
+}
+
+static void player_setup_select_cc(vlc_player_t *player)
+{
+ vlc_player_SelectTracksByStringIds(player, SPU_ES, "video/0/cc/spu/auto/0");
+}
+
+static void cc_decoder_setup_01(decoder_t *dec)
+{
+ assert(dec->fmt_in->i_codec == VLC_CODEC_CEA608);
+ assert(dec->fmt_in->subs.cc.i_channel == 0);
+ assert(dec->fmt_in->subs.cc.i_reorder_depth == 4);
+
+ dec->fmt_out.i_codec = VLC_CODEC_TEXT;
+}
+
+static const char cc_block_decoded[] = "cc01_dec";
+static int cc_decoder_decode(decoder_t *dec, vlc_frame_t *in)
+{
+ assert(memcmp(in->p_buffer, cc_block_input, sizeof(cc_block_input)) == 0);
+
+ subpicture_t *subpic = decoder_NewSubpicture(dec, NULL);
+ assert(subpic != NULL);
+
+ subpic->i_start = in->i_pts;
+ subpic->i_stop = subpic->i_start + in->i_length;
+
+ video_format_t fmt;
+ video_format_Init(&fmt, VLC_CODEC_TEXT);
+ subpic->p_region = subpicture_region_New(&fmt);
+ assert(subpic->p_region != NULL);
+
+ subpic->p_region->p_text = text_segment_New(cc_block_decoded);
+ assert(subpic->p_region->p_text != NULL);
+
+ decoder_QueueSub(dec, subpic);
+
+ return VLC_SUCCESS;
+}
+
+static void display_prepare_noop(vout_display_t *vd, picture_t *pic)
+{
+ (void)vd; (void) pic;
+}
+
+static void cc_text_renderer_render(filter_t *filter, subpicture_region_t *region_in)
+{
+ (void) filter;
+ assert(strcmp(region_in->p_text->psz_text, cc_block_decoded) == 0);
+ vlc_sem_post(&scenario_data.wait_stop);
+}
+
+static const vlc_fourcc_t subpicture_chromas[] = {
+ VLC_CODEC_RGBA, 0
+};
+
#define source_800_600 "mock://video_track_count=1;length=100000000000;video_width=800;video_height=600"
struct input_decoder_scenario input_decoder_scenarios[] =
{{
+ .name = "decoder is flushed",
.source = source_800_600,
.decoder_setup = decoder_i420_800_600,
.decoder_flush = decoder_flush_signal,
@@ -375,6 +503,7 @@ struct input_decoder_scenario input_decoder_scenarios[] =
.interface_setup = interface_setup_select_cc,
},
{
+ .name = "video output is flushed",
.source = source_800_600,
.decoder_setup = decoder_i420_800_600,
.decoder_decode = decoder_decode_check_flush_video,
@@ -389,6 +518,7 @@ struct input_decoder_scenario input_decoder_scenarios[] =
- the interface change player position to trigger a flush
- the flush is signaled to the stream_out filter
- the stream_out filter signal the end of the test */
+ .name = "stream output is also flushed",
.source = source_800_600,
.sout = "#" MODULE_STRING,
.sout_filter_send = sout_filter_send,
@@ -399,6 +529,7 @@ struct input_decoder_scenario input_decoder_scenarios[] =
/* Check that releasing a decoder while it is triggering an update
* of the video output format doesn't lead to a crash. Non-regression
* test from issue #27532. */
+ .name = "releasing a decoder while updating the vout doesn't lead to a crash",
.source = source_800_600,
.decoder_setup = decoder_i420_800_600_stop,
.decoder_decode = decoder_decode_drop,
@@ -408,12 +539,14 @@ struct input_decoder_scenario input_decoder_scenarios[] =
/* Check that reloading a decoder while it is triggering an update
* of the video output format doesn't lead to a crash. Non-regression
* test from issue #27532. */
+ .name = "reloading a decoder while updating the vout doesn't lead to a crash",
.source = source_800_600,
.decoder_setup = decoder_i420_800_600,
.decoder_decode = decoder_decode_trigger_reload,
.decoder_destroy = decoder_destroy_trigger_update,
},
{
+ .name = "CC frames are sent to the sout",
.source = source_800_600,
.sout = "#" MODULE_STRING,
.packetizer_getcc = packetizer_getcc,
@@ -422,12 +555,57 @@ struct input_decoder_scenario input_decoder_scenarios[] =
.interface_setup = interface_setup_check_flush,
},
{
+ .name = "CC tracks are added",
.source = source_800_600 ";video_packetized=false",
.packetizer_getcc = packetizer_getcc,
.decoder_setup = decoder_i420_800_600,
.decoder_decode = decoder_decode_drop,
.on_track_list_changed = on_track_list_changed_check_cea608,
-}};
+},
+{
+ /* Check that the CC coming from the packetizer is decoded and rendered:
+ * - A valid vout is needed (to blend subtitles into)
+ * - Text vlc_frames are passed from the packetizer to the cc decoder to
+ * the text renderer and are checked at each step
+ * - A text renderer is used, this is the last place a text can be checked
+ * before it is rendered (and converted to RGB/YUV)
+ */
+ .name = "CC coming from the packetizer is decoded and rendered",
+ .source = source_800_600 ";video_packetized=false",
+ .subpicture_chromas = subpicture_chromas,
+ .packetizer_getcc = packetizer_getcc,
+ .decoder_setup = decoder_i420_800_600_update,
+ .decoder_decode = decoder_decode,
+ .cc_decoder_setup = cc_decoder_setup_01,
+ .cc_decoder_decode = cc_decoder_decode,
+ .display_prepare = display_prepare_noop,
+ .text_renderer_render = cc_text_renderer_render,
+ .player_setup_before_start = player_setup_select_cc,
+},
+{
+ /* Check that the CC coming from the video decoder is decoded and rendered,
+ * cf. the previous scenario for more details. */
+ .name = "CC coming from the video decoder is decoded and rendered",
+ .source = source_800_600,
+ .subpicture_chromas = subpicture_chromas,
+ .decoder_setup = decoder_i420_800_600_update,
+ .decoder_decode = decoder_decode_check_cc_queue_video,
+ .cc_decoder_setup = cc_decoder_setup_01,
+ .cc_decoder_decode = cc_decoder_decode,
+ .display_prepare = display_prepare_noop,
+ .text_renderer_render = cc_text_renderer_render,
+ .player_setup_before_start = player_setup_select_cc,
+},
+{
+ .name = "we can create 4 cea608 tracks",
+ .source = source_800_600 ";video_packetized=false",
+ .packetizer_getcc = packetizer_getcc_cea608_max,
+ .decoder_setup = decoder_i420_800_600,
+ .decoder_decode = decoder_decode_drop,
+ .on_track_list_changed = on_track_list_changed_check_cea608_count,
+},
+};
+
size_t input_decoder_scenarios_count = ARRAY_SIZE(input_decoder_scenarios);
void input_decoder_scenario_init(void)
@@ -437,8 +615,8 @@ void input_decoder_scenario_init(void)
scenario_data.has_reload = false;
scenario_data.stream_out_sent = false;
scenario_data.decoder_image_sent = 0;
+ scenario_data.cc_track_idx = 0;
vlc_sem_init(&scenario_data.wait_stop, 0);
- vlc_sem_init(&scenario_data.display_prepare_signal, 0);
vlc_sem_init(&scenario_data.wait_ready_to_flush, 0);
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/1eed0681cdc5da8e3ce7bc5d6b59c2658206c186...aa6b665c1d3b84f8e7c36ca39760b24678b44968
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/1eed0681cdc5da8e3ce7bc5d6b59c2658206c186...aa6b665c1d3b84f8e7c36ca39760b24678b44968
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list