[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