[vlc-commits] [Git][videolan/vlc][master] 4 commits: test: input_decoder: add a pf_getcc test
Steve Lhomme (@robUx4)
gitlab at videolan.org
Thu Aug 31 10:36:19 UTC 2023
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
e3057533 by Alaric Senat at 2023-08-31T09:58:35+00:00
test: input_decoder: add a pf_getcc test
The test checks that the closed-captions are correctly forwarded to the
stream output chain when they are output from the packetizer.
As a side effect, it also checks that a packetizer is used in the stream
output pipeline, even when the input has already been packetized.
Co-authored-by: Alexandre Janniaux <ajanni at videolabs.io>
- - - - -
61750113 by Alexandre Janniaux at 2023-08-31T09:58:35+00:00
input: decoder: use early return
- - - - -
2ed6c7eb by Alexandre Janniaux at 2023-08-31T09:58:35+00:00
input: decoder: unlock before playing CC
Regression from 6369ea50377624694572d6ba5f5bcae26d278fe4. This commit
introduced a lock re-entrancy to the fifo lock, which is not allowed,
when DecoderPlayCc is used to play a closed caption from the packetizer.
- - - - -
998b623d by Alexandre Janniaux at 2023-08-31T09:58:35+00:00
test: input_decoder: add a get_cc test for playback
This check the path where pf_getcc() is called from the packetizer and
then DecoderPlayCc() is used to play the closed-caption.
This is a non-regression test, checking what's fixed from the previous
commit and introduced in 6369ea50377624694572d6ba5f5bcae26d278fe4.
- - - - -
4 changed files:
- src/input/decoder.c
- test/src/input/decoder/input_decoder.c
- test/src/input/decoder/input_decoder.h
- test/src/input/decoder/input_decoder_scenarios.c
Changes:
=====================================
src/input/decoder.c
=====================================
@@ -1227,7 +1227,10 @@ static void PacketizerGetCc( vlc_input_decoder_t *p_owner, decoder_t *p_dec_cc )
p_cc = p_dec_cc->pf_get_cc( p_dec_cc, &desc );
if( !p_cc )
return;
+
+ vlc_fifo_Unlock(p_owner->p_fifo);
DecoderPlayCc( p_owner, p_cc, &desc );
+ vlc_fifo_Lock(p_owner->p_fifo);
}
static void ModuleThread_QueueCc( decoder_t *p_videodec, vlc_frame_t *p_cc,
@@ -1235,14 +1238,17 @@ static void ModuleThread_QueueCc( decoder_t *p_videodec, vlc_frame_t *p_cc,
{
vlc_input_decoder_t *p_owner = dec_get_owner( p_videodec );
- if( unlikely( p_cc != NULL ) )
+ if (likely(p_cc == NULL))
+ return;
+
+ if (!p_owner->cc.b_supported ||
+ (p_owner->p_packetizer != NULL && p_owner->p_packetizer->pf_get_cc == NULL))
{
- if( p_owner->cc.b_supported &&
- ( !p_owner->p_packetizer || !p_owner->p_packetizer->pf_get_cc ) )
- DecoderPlayCc( p_owner, p_cc, p_desc );
- else
- block_Release( p_cc );
+ block_Release(p_cc);
+ return;
}
+
+ DecoderPlayCc(p_owner, p_cc, p_desc);
}
static int ModuleThread_PlayVideo( vlc_input_decoder_t *p_owner, picture_t *p_picture )
=====================================
test/src/input/decoder/input_decoder.c
=====================================
@@ -1,7 +1,7 @@
/*****************************************************************************
* input_decoder.c: test for vlc_input_decoder state machine
*****************************************************************************
- * Copyright (C) 2022 VideoLabs
+ * Copyright (C) 2022-2023 VideoLabs
*
* Author: Alexandre Janniaux <ajanni at videolabs.io>
*
@@ -112,6 +112,39 @@ static void CloseDecoder(vlc_object_t *obj)
vlc_video_context_Release(vctx);
}
+static vlc_frame_t *PacketizerPacketize(decoder_t *dec, vlc_frame_t **in)
+{
+ (void)dec;
+ if (in == NULL)
+ return NULL;
+
+ vlc_frame_t *ret = *in;
+ if (ret != NULL)
+ *in = NULL;
+ return ret;
+}
+
+static vlc_frame_t *PacketizerGetCC(decoder_t *dec, decoder_cc_desc_t *cc_desc)
+{
+ struct input_decoder_scenario *scenario = &input_decoder_scenarios[current_scenario];
+ if (scenario->packetizer_getcc != NULL)
+ return scenario->packetizer_getcc(dec, cc_desc);
+ return NULL;
+}
+
+static int OpenPacketizer(vlc_object_t *obj)
+{
+ decoder_t *dec = (decoder_t*)obj;
+
+ dec->pf_packetize = PacketizerPacketize;
+ dec->pf_get_cc = PacketizerGetCC;
+ dec->pf_flush = NULL;
+ es_format_Clean(&dec->fmt_out);
+ es_format_Copy(&dec->fmt_out, dec->fmt_in);
+
+ return VLC_SUCCESS;
+}
+
static int OpenDecoder(vlc_object_t *obj)
{
decoder_t *dec = (decoder_t*)obj;
@@ -121,6 +154,7 @@ static int OpenDecoder(vlc_object_t *obj)
vlc_decoder_device_Release(device);
dec->pf_decode = DecoderDecode;
+ dec->pf_get_cc = NULL;
dec->pf_flush = DecoderFlush;
es_format_Clean(&dec->fmt_out);
es_format_Copy(&dec->fmt_out, dec->fmt_in);
@@ -179,9 +213,10 @@ static int OpenWindow(vlc_window_t *wnd)
static void *SoutFilterAdd(sout_stream_t *stream, const es_format_t *fmt,
const char *es_id)
{
- (void)stream; (void)fmt; (void)es_id;
- void *id = malloc(1);
+ (void)stream; (void)es_id;
+ vlc_fourcc_t *id = malloc(sizeof(*id));
assert(id != NULL);
+ *id = fmt->i_codec;
return id;
}
@@ -207,6 +242,15 @@ static void SoutFilterFlush(sout_stream_t *stream, void *id)
scenario->sout_filter_flush(stream, id);
}
+static int SoutFilterControl(sout_stream_t *stream, int query, va_list args)
+{
+ (void)stream;
+ if (query != SOUT_STREAM_WANTS_SUBSTREAMS)
+ return VLC_EGENERIC;
+ *va_arg(args, bool *) = true;
+ return VLC_SUCCESS;
+}
+
static int OpenSoutFilter(vlc_object_t *obj)
{
sout_stream_t *stream = (sout_stream_t *)obj;
@@ -215,6 +259,7 @@ static int OpenSoutFilter(vlc_object_t *obj)
.del = SoutFilterDel,
.send = SoutFilterSend,
.flush = SoutFilterFlush,
+ .control = SoutFilterControl,
};
stream->ops = &ops;
return VLC_SUCCESS;
@@ -226,6 +271,17 @@ static void on_state_changed(vlc_player_t *player, enum vlc_player_state state,
vlc_cond_signal(&player_cond);
}
+static void on_track_list_changed(vlc_player_t *player,
+ enum vlc_player_list_action action,
+ const struct vlc_player_track *track,
+ void *data)
+{
+ (void)player; (void)data;
+ struct input_decoder_scenario *scenario = &input_decoder_scenarios[current_scenario];
+ if (scenario->on_track_list_changed != NULL)
+ scenario->on_track_list_changed(action, track);
+}
+
static void play_scenario(intf_thread_t *intf, struct input_decoder_scenario *scenario)
{
input_decoder_scenario_init();
@@ -251,6 +307,7 @@ static void play_scenario(intf_thread_t *intf, struct input_decoder_scenario *sc
static const struct vlc_player_cbs player_cbs = {
.on_state_changed = on_state_changed,
+ .on_track_list_changed = on_track_list_changed,
};
vlc_player_Lock(player);
@@ -311,6 +368,10 @@ vlc_module_begin()
set_callbacks(OpenDecoder, CloseDecoder)
set_capability("video decoder", INT_MAX)
+ add_submodule()
+ set_callback(OpenPacketizer)
+ set_capability("packetizer", INT_MAX)
+
add_submodule()
set_callback(OpenWindow)
set_capability("vout window", INT_MAX)
=====================================
test/src/input/decoder/input_decoder.h
=====================================
@@ -1,7 +1,7 @@
/*****************************************************************************
* input_decoder.h: test for input_decoder state machine
*****************************************************************************
- * Copyright (C) 2022 VideoLabs
+ * Copyright (C) 2022-2023 VideoLabs
*
* Author: Alexandre Janniaux <ajanni at videolabs.io>
*
@@ -27,6 +27,7 @@
typedef struct vout_display_t vout_display_t;
typedef struct intf_thread_t intf_thread_t;
+typedef struct decoder_cc_desc_t decoder_cc_desc_t;
struct input_decoder_scenario {
const char *source;
@@ -34,11 +35,14 @@ struct input_decoder_scenario {
void (*decoder_setup)(decoder_t *);
void (*decoder_destroy)(decoder_t *);
int (*decoder_decode)(decoder_t *, picture_t *);
+ 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 (*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);
+ void (*on_track_list_changed)(enum vlc_player_list_action action,
+ const struct vlc_player_track *track);
};
=====================================
test/src/input/decoder/input_decoder_scenarios.c
=====================================
@@ -1,7 +1,7 @@
/*****************************************************************************
* input_decoder_scenario.c: testflight for input_decoder state machine
*****************************************************************************
- * Copyright (C) 2022 VideoLabs
+ * Copyright (C) 2022-2023 VideoLabs
*
* Author: Alexandre Janniaux <ajanni at videolabs.io>
*
@@ -30,6 +30,7 @@
#include <vlc_messages.h>
#include <vlc_player.h>
#include <vlc_interface.h>
+#include <vlc_frame.h>
#include <vlc_codec.h>
#include <vlc_vout_display.h>
@@ -317,6 +318,19 @@ static int sout_filter_send(sout_stream_t *stream, void *id, block_t *block)
return VLC_SUCCESS;
}
+static int sout_filter_wait_cc(sout_stream_t *stream, void *id, block_t *block)
+{
+ (void)stream; (void)id;
+ block_Release(block);
+ vlc_fourcc_t *codec = id;
+ if (*codec == VLC_CODEC_CEA608)
+ {
+ scenario_data.stream_out_sent = true;
+ vlc_sem_post(&scenario_data.wait_ready_to_flush);
+ }
+ return VLC_SUCCESS;
+}
+
static void sout_filter_flush(sout_stream_t *stream, void *id)
{
(void)stream; (void)id;
@@ -324,7 +338,34 @@ static void sout_filter_flush(sout_stream_t *stream, void *id)
vlc_sem_post(&scenario_data.wait_stop);
}
-const char source_800_600[] = "mock://video_track_count=1;length=100000000000;video_width=800;video_height=600";
+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;
+
+ vlc_frame_t *f = vlc_frame_Alloc(1);
+ assert(f != NULL);
+
+ return f;
+}
+
+static void on_track_list_changed_check_cea608(
+ enum vlc_player_list_action action,
+ const struct vlc_player_track *track)
+{
+ if (action != VLC_PLAYER_LIST_ADDED)
+ return;
+
+ if (strcmp(vlc_es_id_GetStrId(track->es_id), "video/0/cc/spu/auto/0") != 0)
+ return;
+
+ assert(track->fmt.i_codec == VLC_CODEC_CEA608);
+ vlc_sem_post(&scenario_data.wait_stop);
+}
+
+#define source_800_600 "mock://video_track_count=1;length=100000000000;video_width=800;video_height=600"
struct input_decoder_scenario input_decoder_scenarios[] =
{{
.source = source_800_600,
@@ -371,6 +412,21 @@ struct input_decoder_scenario input_decoder_scenarios[] =
.decoder_setup = decoder_i420_800_600,
.decoder_decode = decoder_decode_trigger_reload,
.decoder_destroy = decoder_destroy_trigger_update,
+},
+{
+ .source = source_800_600,
+ .sout = "#" MODULE_STRING,
+ .packetizer_getcc = packetizer_getcc,
+ .sout_filter_send = sout_filter_wait_cc,
+ .sout_filter_flush = sout_filter_flush,
+ .interface_setup = interface_setup_check_flush,
+},
+{
+ .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,
}};
size_t input_decoder_scenarios_count = ARRAY_SIZE(input_decoder_scenarios);
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/e1c8bf95d02e42f0743e9d27adb49c083ddb0128...998b623df50ed3ca7a6296e3bfd2808ffcaf50a8
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/e1c8bf95d02e42f0743e9d27adb49c083ddb0128...998b623df50ed3ca7a6296e3bfd2808ffcaf50a8
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