From 33fc5b20515000b8d602373f9cb425eae68c60d6 Mon Sep 17 00:00:00 2001 From: Thomas Guillem Date: Fri, 12 May 2023 09:22:54 +0200 Subject: [PATCH] mock: add subitems/node support Example: "mock://node[2]{video_track_count=1};node_count=4;length=1000000;node[1]{length=2000000}" Will create the following sub items: - input_item_New(mock://length=1000000, submock[0]); - input_item_New(mock://length=2000000, submock[1]); - input_item_New(mock://video_track_count=1, submock[2]); - input_item_New(mock://length=1000000, submock[3]); If specified with node[]{}, a sub item will use the params between "{}". If not specified, all subitems will use the same params from the url (here: "length=1000000"). This will be needed for the future and reworked media_list_player test. --- modules/demux/mock.c | 158 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/modules/demux/mock.c b/modules/demux/mock.c index c927265f5f..c68d164944 100644 --- a/modules/demux/mock.c +++ b/modules/demux/mock.c @@ -148,6 +148,7 @@ var_Read_float(const char *psz) /* var_name, type, module_header_type, getter, default_value */ #define OPTIONS_GLOBAL(X) \ + X(node_count, ssize_t, add_integer, Ssize, 0) \ X(length, vlc_tick_t, add_integer, Integer, VLC_TICK_FROM_MS(5000)) \ X(audio_track_count, ssize_t, add_integer, Ssize, 0) \ X(video_track_count, ssize_t, add_integer, Ssize, 0) \ @@ -971,6 +972,156 @@ Demux(demux_t *demux) return eof ? VLC_DEMUXER_EOF : VLC_DEMUXER_SUCCESS; } +static char * +StripNodeParams(const char *orignal_url) +{ + char *url = strdup(orignal_url); + if (url == NULL) + return NULL; + + /* Strip "node_count=xxx" */ + char *substr_start = strcasestr(url, "node_count="); + assert(substr_start != NULL); + + char *substr_end = strchr(substr_start, ';'); + if (substr_end != NULL) + substr_end++; + else + substr_end = strchr(substr_start, '\0'); + + assert(substr_end != NULL); + memmove(substr_start, substr_end, strlen(substr_end) + 1); + + /* Strip "node[xxx]={xxx}" */ + while ((substr_start = strcasestr(url, "node[")) != NULL) + { + substr_end = strchr(substr_start, '{'); + if (substr_end != NULL) + { + substr_end = strchr(substr_start, '}'); + substr_end++; + if (*substr_end == ';') + substr_end++; + } + + if (substr_end == NULL) + { + free(url); + return NULL; + } + + memmove(substr_start, substr_end, strlen(substr_end) + 1); + } + + return url; +} + +/* + * Create sub items from the demux URL + * + * Example: + * "mock://node[2]{video_track_count=1};node_count=4;length=1000000;node[1]{length=2000000}" + * Will create the following sub items: + * - input_item_New(mock://length=1000000, submock[0]); + * - input_item_New(mock://length=2000000, submock[1]); + * - input_item_New(mock://video_track_count=1, submock[2]); + * - input_item_New(mock://length=1000000, submock[3]); + * + * If specified with node[]{}, a sub item will use the params between "{}". + * If not specified, all subitems will use the same params from the url (here: + * "length=1000000"). + */ +static int +Readdir(stream_t *demux, input_item_node_t *node) +{ + struct demux_sys *sys = demux->p_sys; + + char *default_url = StripNodeParams(demux->psz_url); + if (default_url == NULL) + return VLC_EGENERIC; + + int ret = VLC_ENOMEM; + for (ssize_t i = 0; i < sys->node_count; ++i) + { + const char *url; + char *name, *option_name, *url_buf = NULL; + int len; + + len = asprintf(&option_name, "node[%zd]{", i); + if (len < 0) + goto error; + char *option = strstr(demux->psz_url, option_name); + free(option_name); + + if (option != NULL) + { + option = strchr(option, '{'); + assert(option != NULL); + option++; + char *option_end = strchr(option, '}'); + if (option_end == NULL) + { + ret = VLC_EINVAL; + goto error; + } + + ptrdiff_t option_size = option_end - option; + if (option_size > INT_MAX) + { + ret = VLC_EINVAL; + goto error; + } + + len = asprintf(&url_buf, "mock://%.*s", (int) option_size, option); + if (len < 0) + goto error; + url = url_buf; + } + else + url = default_url; + + len = asprintf(&name, "submock[%zd]", i); + if (len < 0) + { + free(url_buf); + goto error; + } + + input_item_t *item = input_item_New(url, name); + free(name); + free(url_buf); + + if (item == NULL) + goto error; + + input_item_node_AppendItem(node, item); + input_item_Release(item); + } + + ret = VLC_SUCCESS; +error: + free(default_url); + return ret; +} + +static int +ReaddirControl(demux_t *demux, int query, va_list args) +{ + (void) demux; + switch (query) + { + case DEMUX_GET_META: + case DEMUX_GET_TYPE: + return VLC_EGENERIC; + case DEMUX_HAS_UNSUPPORTED_META: + { + *(va_arg(args, bool *)) = false; + return VLC_SUCCESS; + } + } + return VLC_EGENERIC; +} + static void Close(vlc_object_t *obj) { @@ -1010,6 +1161,13 @@ Open(vlc_object_t *obj) OPTIONS_VIDEO(READ_SUBOPTION) OPTIONS_SUB(READ_SUBOPTION) + if (sys->node_count > 0) + { + demux->pf_control = ReaddirControl; + demux->pf_readdir = Readdir; + return VLC_SUCCESS; + } + if (sys->chapter_count > 0 && sys->title_count == 0) sys->title_count++;