X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fimem.c;h=b6cd5890c2bbd6a4d1aa80c53c05fd25eff4ab93;hb=f3ad50e8a846bd4de3c36a31bae26c1042b52c7c;hp=222a7708fbb37f373d09c49c27ffe8ec114e0ef5;hpb=0ba6c728e068c462bcaf51c52e2e7bfb9d77aee9;p=vlc diff --git a/modules/access/imem.c b/modules/access/imem.c index 222a7708fb..b6cd5890c2 100644 --- a/modules/access/imem.c +++ b/modules/access/imem.c @@ -1,7 +1,7 @@ /***************************************************************************** * imem.c : Memory input for VLC ***************************************************************************** - * Copyright (C) 2009 Laurent Aimar + * Copyright (C) 2009-2010 Laurent Aimar * $Id$ * * Author: Laurent Aimar @@ -33,14 +33,18 @@ #include #include +#include #include #include /***************************************************************************** * Module descriptior *****************************************************************************/ -static int Open (vlc_object_t *); -static void Close(vlc_object_t *); +static int OpenAccess (vlc_object_t *); +static void CloseAccess(vlc_object_t *); + +static int OpenDemux (vlc_object_t *); +static void CloseDemux(vlc_object_t *); #define CACHING_TEXT N_("Caching value in ms") #define CACHING_LONGTEXT N_(\ @@ -59,10 +63,10 @@ static void Close(vlc_object_t *); #define CAT_LONGTEXT N_(\ "Set the category of the elementary stream") static const int cat_values[] = { - 0, 1, 2, 3 + 0, 1, 2, 3, 4, }; static const char *cat_texts[] = { - N_("Unknown"), N_("Audio"), N_("Video"), N_("Subtitle") + N_("Unknown"), N_("Audio"), N_("Video"), N_("Subtitle"), N_("Data") }; #define CODEC_TEXT N_("Codec") @@ -111,6 +115,10 @@ static const char *cat_texts[] = { #define RELEASE_LONGTEXT N_(\ "Address of the release callback function") +#define SIZE_TEXT N_("Size") +#define SIZE_LONGTEXT N_(\ + "Size of stream in bytes") + vlc_module_begin() set_shortname(N_("Memory input")) set_description(N_("Memory input")) @@ -166,9 +174,18 @@ vlc_module_begin() change_private() change_safe() + add_integer ("imem-size", 0, NULL, SIZE_TEXT, SIZE_LONGTEXT, true) + change_private() + change_safe() + add_shortcut("imem") set_capability("access_demux", 0) - set_callbacks(Open, Close) + set_callbacks(OpenDemux, CloseDemux) + + add_submodule() + add_shortcut("imem") + set_capability("access", 0) + set_callbacks(OpenAccess, CloseAccess) vlc_module_end() /***************************************************************************** @@ -190,11 +207,14 @@ typedef void (*imem_release_t)(void *data, const char *cookie, size_t, void *); *****************************************************************************/ /* */ +static block_t *Block(access_t *); +static int ControlAccess(access_t *, int, va_list); + static int Demux(demux_t *); -static int Control(demux_t *, int, va_list); +static int ControlDemux(demux_t *, int, va_list); /* */ -struct demux_sys_t { +typedef struct { struct { imem_get_t get; imem_release_t release; @@ -209,104 +229,234 @@ struct demux_sys_t { mtime_t dts; mtime_t deadline; -}; +} imem_sys_t; + +static void ParseMRL(vlc_object_t *, const char *); -static void ParseMRL(demux_t *); -static int var_CreateGetRational(demux_t *, - unsigned *num, unsigned *den, - const char *var); +/** + * It closes the common part of the access and access_demux + */ +static void CloseCommon(imem_sys_t *sys) +{ + free(sys->source.cookie); + free(sys); +} /** - * It opens an imem access_demux + * It initializes the common part for imem access/access_demux. */ -static int Open(vlc_object_t *object) +static int OpenCommon(vlc_object_t *object, imem_sys_t **sys_ptr, const char *psz_path) { - demux_t *demux = (demux_t*)object; char *tmp; - /* */ - demux_sys_t *sys = calloc(1, sizeof(*sys)); - if (!sys) - return VLC_ENOMEM; + /* */ + imem_sys_t *sys = calloc(1, sizeof(*sys)); + if (!sys) + return VLC_ENOMEM; /* Read the user functions */ - tmp = var_CreateGetString(demux, "imem-get"); + tmp = var_InheritString(object, "imem-get"); if (tmp) sys->source.get = (imem_get_t)(intptr_t)strtoll(tmp, NULL, 0); free(tmp); - tmp = var_CreateGetString(demux, "imem-release"); + tmp = var_InheritString(object, "imem-release"); if (tmp) sys->source.release = (imem_release_t)(intptr_t)strtoll(tmp, NULL, 0); free(tmp); if (!sys->source.get || !sys->source.release) { - msg_Err(demux, "Invalid get/release function pointers"); + msg_Err(object, "Invalid get/release function pointers"); free(sys); return VLC_EGENERIC; } - tmp = var_CreateGetString(demux, "imem-data"); + tmp = var_InheritString(object, "imem-data"); if (tmp) sys->source.data = (void *)(uintptr_t)strtoull(tmp, NULL, 0); free(tmp); /* Now we can parse the MRL (get/release must not be parsed to avoid * security risks) */ - if (*demux->psz_path) - ParseMRL(demux); + if (*psz_path) + ParseMRL(object, psz_path); - /* Now we can parse the MRL (get/release must not be parsed to avoid - * security risks) */ - if (*demux->psz_path) - ParseMRL(demux); + sys->source.cookie = var_InheritString(object, "imem-cookie"); - sys->source.cookie = var_InheritString(demux, "imem-cookie"); - - msg_Dbg(demux, "Using get(%p), release(%p), data(%p), cookie(%s)", + msg_Dbg(object, "Using get(%p), release(%p), data(%p), cookie(%s)", sys->source.get, sys->source.release, sys->source.data, sys->source.cookie ? sys->source.cookie : "(null)"); - /* ES format */ + /* */ + sys->pts_delay = var_InheritInteger(object, "imem-caching") * INT64_C(1000); + sys->dts = 0; + sys->deadline = VLC_TS_INVALID; + + *sys_ptr = sys; + return VLC_SUCCESS; +} + +/** + * It opens an imem access. + */ +static int OpenAccess(vlc_object_t *object) +{ + access_t *access = (access_t *)object; + imem_sys_t *sys; + + if (OpenCommon(object, &sys, access->psz_location)) + return VLC_EGENERIC; + + if (var_InheritInteger(object, "imem-cat") != 4) { + CloseCommon(sys); + return VLC_EGENERIC; + } + + /* */ + access_InitFields(access); + access->pf_control = ControlAccess; + access->pf_read = NULL; + access->pf_block = Block; + access->pf_seek = NULL; + access->p_sys = (access_sys_t*)sys; + access->info.i_size = var_InheritInteger(object, "imem-size"); + + return VLC_SUCCESS; +} + +/** + * It closes an imem access + */ +static void CloseAccess(vlc_object_t *object) +{ + access_t *access = (access_t *)object; + + CloseCommon((imem_sys_t*)access->p_sys); +} + +/** + * It controls an imem access + */ +static int ControlAccess(access_t *access, int i_query, va_list args) +{ + imem_sys_t *sys = (imem_sys_t*)access->p_sys; + + switch (i_query) + { + case ACCESS_CAN_SEEK: + case ACCESS_CAN_FASTSEEK: { + bool *b = va_arg( args, bool* ); + *b = false; + return VLC_SUCCESS; + } + case ACCESS_CAN_PAUSE: + case ACCESS_CAN_CONTROL_PACE: { + bool *b = va_arg( args, bool* ); + *b = true; + return VLC_SUCCESS; + } + case ACCESS_GET_PTS_DELAY: { + int64_t *delay = va_arg(args, int64_t *); + *delay = sys->pts_delay; + return VLC_SUCCESS; + } + case ACCESS_SET_PAUSE_STATE: + return VLC_SUCCESS; + + case ACCESS_GET_TITLE_INFO: + case ACCESS_SET_TITLE: + case ACCESS_SET_SEEKPOINT: + case ACCESS_SET_PRIVATE_ID_STATE: + case ACCESS_GET_META: + case ACCESS_GET_PRIVATE_ID_STATE: + case ACCESS_GET_CONTENT_TYPE: + default: + return VLC_EGENERIC; + } +} + +/** + * It retreives data using the get() callback, copies them, + * and then release them using the release() callback. + */ +static block_t *Block(access_t *access) +{ + imem_sys_t *sys = (imem_sys_t*)access->p_sys; + + unsigned flags; + size_t buffer_size; + void *buffer; + + if (sys->source.get(sys->source.data, sys->source.cookie, + NULL, NULL, &flags, &buffer_size, &buffer)) { + access->info.b_eof = true; + return NULL; + } + + block_t *block = NULL; + if (buffer_size > 0) { + block = block_New(access, buffer_size); + if (block) + memcpy(block->p_buffer, buffer, buffer_size); + } + + sys->source.release(sys->source.data, sys->source.cookie, + buffer_size, buffer); + return block; +} + +/** + * It opens an imem access_demux. + */ +static int OpenDemux(vlc_object_t *object) +{ + demux_t *demux = (demux_t *)object; + imem_sys_t *sys; + + if (OpenCommon(object, &sys, demux->psz_location)) + return VLC_EGENERIC; + + /* ES format */ es_format_t fmt; - es_format_Init(&fmt, UNKNOWN_ES, 0); + es_format_Init(&fmt, UNKNOWN_ES, 0); - fmt.i_id = var_CreateGetInteger(demux, "imem-id"); - fmt.i_group = var_CreateGetInteger(demux, "imem-group"); + fmt.i_id = var_InheritInteger(object, "imem-id"); + fmt.i_group = var_InheritInteger(object, "imem-group"); - tmp = var_CreateGetString(demux, "imem-codec"); + char *tmp = var_InheritString(object, "imem-codec"); if (tmp) fmt.i_codec = vlc_fourcc_GetCodecFromString(UNKNOWN_ES, tmp); free(tmp); - switch (var_CreateGetInteger(demux, "imem-cat")) { + const int cat = var_InheritInteger(object, "imem-cat"); + switch (cat) { case 1: { fmt.i_cat = AUDIO_ES; - fmt.audio.i_channels = var_CreateGetInteger(demux, "imem-channels"); - fmt.audio.i_rate = var_CreateGetInteger(demux, "imem-samplerate"); + fmt.audio.i_channels = var_InheritInteger(object, "imem-channels"); + fmt.audio.i_rate = var_InheritInteger(object, "imem-samplerate"); - msg_Dbg(demux, "Audio %4.4s %d channels %d Hz", + msg_Dbg(object, "Audio %4.4s %d channels %d Hz", (const char *)&fmt.i_codec, fmt.audio.i_channels, fmt.audio.i_rate); break; } case 2: { fmt.i_cat = VIDEO_ES; - fmt.video.i_width = var_CreateGetInteger(demux, "imem-width"); - fmt.video.i_height = var_CreateGetInteger(demux, "imem-height"); + fmt.video.i_width = var_InheritInteger(object, "imem-width"); + fmt.video.i_height = var_InheritInteger(object, "imem-height"); unsigned num, den; - if (!var_CreateGetRational(demux, &num, &den, "imem-dar") && num > 0 && den > 0) { + if (!var_InheritURational(object, &num, &den, "imem-dar") && num > 0 && den > 0) { if (fmt.video.i_width > 0 && fmt.video.i_height > 0) { fmt.video.i_sar_num = num * fmt.video.i_height; fmt.video.i_sar_den = den * fmt.video.i_width; } } - if (!var_CreateGetRational(demux, &num, &den, "imem-fps") && num > 0 && den > 0) { + if (!var_InheritURational(object, &num, &den, "imem-fps") && num > 0 && den > 0) { fmt.video.i_frame_rate = num; fmt.video.i_frame_rate_base = den; } - msg_Dbg(demux, "Video %4.4s %dx%d SAR %d:%d frame rate %u/%u", + msg_Dbg(object, "Video %4.4s %dx%d SAR %d:%d frame rate %u/%u", (const char *)&fmt.i_codec, fmt.video.i_width, fmt.video.i_height, fmt.video.i_sar_num, fmt.video.i_sar_den, @@ -316,42 +466,36 @@ static int Open(vlc_object_t *object) case 3: { fmt.i_cat = SPU_ES; fmt.subs.spu.i_original_frame_width = - var_CreateGetInteger(demux, "imem-width"); + var_InheritInteger(object, "imem-width"); fmt.subs.spu.i_original_frame_height = - var_CreateGetInteger(demux, "imem-height"); + var_InheritInteger(object, "imem-height"); - msg_Dbg(demux, "Subtitle %4.4s", + msg_Dbg(object, "Subtitle %4.4s", (const char *)&fmt.i_codec); break; } default: - msg_Err(demux, "Invalid ES category"); + if (cat != 4) + msg_Err(object, "Invalid ES category"); es_format_Clean(&fmt); - free(sys); + CloseCommon(sys); return VLC_EGENERIC; } - fmt.psz_language = var_CreateGetString(demux, "imem-language"); + fmt.psz_language = var_InheritString(object, "imem-language"); - /* */ - sys->es = es_out_Add(demux->out, &fmt); + sys->es = es_out_Add(demux->out, &fmt); es_format_Clean(&fmt); if (!sys->es) { - free(sys->source.data); - free(sys); + CloseCommon(sys); return VLC_EGENERIC; } /* */ - sys->pts_delay = var_CreateGetInteger(demux, "imem-caching") * INT64_C(1000); - sys->dts = 0; - sys->deadline = VLC_TS_INVALID; - - /* Set up demux */ - demux->pf_control = Control; + demux->pf_control = ControlDemux; demux->pf_demux = Demux; - demux->p_sys = sys; + demux->p_sys = (demux_sys_t*)sys; demux->info.i_update = 0; demux->info.i_title = 0; @@ -362,21 +506,19 @@ static int Open(vlc_object_t *object) /** * It closes an imem access_demux */ -static void Close(vlc_object_t *object) +static void CloseDemux(vlc_object_t *object) { - demux_t *demux = (demux_t *)object; - demux_sys_t *sys = demux->p_sys; + demux_t *demux = (demux_t *)object; - free(sys->source.cookie); - free(sys); + CloseCommon((imem_sys_t*)demux->p_sys); } /** - * It controls imem + * It controls an imem access_demux */ -static int Control(demux_t *demux, int i_query, va_list args) +static int ControlDemux(demux_t *demux, int i_query, va_list args) { - demux_sys_t *sys = demux->p_sys; + imem_sys_t *sys = (imem_sys_t*)demux->p_sys; switch (i_query) { @@ -430,7 +572,7 @@ static int Control(demux_t *demux, int i_query, va_list args) */ static int Demux(demux_t *demux) { - demux_sys_t *sys = demux->p_sys; + imem_sys_t *sys = (imem_sys_t*)demux->p_sys; if (sys->deadline == VLC_TS_INVALID) sys->deadline = sys->dts + 1; @@ -473,55 +615,6 @@ static int Demux(demux_t *demux) return 1; } -/** - * It parses a rational number (it also accepts basic float number). - * - * It returns an error if the rational number cannot be parsed (0/0 is valid). - */ -static int var_CreateGetRational(demux_t *demux, - unsigned *num, unsigned *den, - const char *var) -{ - /* */ - *num = 0; - *den = 0; - - /* */ - char *tmp = var_CreateGetString(demux, var); - if (!tmp) - goto error; - - char *next; - unsigned n = strtol(tmp, &next, 0); - unsigned d = strtol(*next ? &next[1] : "0", NULL, 0); - - if (*next == '.') { - /* Interpret as a float number */ - double r = us_atof(tmp); - double c = ceil(r); - if (c >= UINT_MAX) - goto error; - unsigned m = c; - if (m > 0) { - d = UINT_MAX / m; - n = r * d; - } else { - n = 0; - d = 0; - } - } - - if (n > 0 && d > 0) - vlc_ureduce(num, den, n, d, 0); - - free(tmp); - return VLC_SUCCESS; - -error: - free(tmp); - return VLC_EGENERIC; -} - /** * Parse the MRL and extract configuration from it. * @@ -529,7 +622,7 @@ error: * * XXX get and release are not supported on purpose. */ -static void ParseMRL(demux_t *demux) +static void ParseMRL(vlc_object_t *object, const char *psz_path) { static const struct { const char *name; @@ -551,7 +644,7 @@ static void ParseMRL(demux_t *demux) { NULL, -1 } }; - char *dup = strdup(demux->psz_path); + char *dup = strdup(psz_path); if (!dup) return; char *current = dup; @@ -565,9 +658,9 @@ static void ParseMRL(demux_t *demux) char *value = strchr(current, '='); if (value) { *value++ = '\0'; - msg_Dbg(demux, "option '%s' value '%s'", option, value); + msg_Dbg(object, "option '%s' value '%s'", option, value); } else { - msg_Dbg(demux, "option '%s' without value (unsupported)", option); + msg_Dbg(object, "option '%s' without value (unsupported)", option); } char *name; @@ -577,11 +670,11 @@ static void ParseMRL(demux_t *demux) if (strcmp(options[i].name, option)) continue; /* */ - var_Create(demux, name, options[i].type | VLC_VAR_DOINHERIT); + var_Create(object, name, options[i].type | VLC_VAR_DOINHERIT); if (options[i].type == VLC_VAR_INTEGER && value) { - var_SetInteger(demux, name, strtol(value, NULL, 0)); + var_SetInteger(object, name, strtol(value, NULL, 0)); } else if (options[i].type == VLC_VAR_STRING && value) { - var_SetString(demux, name, value); + var_SetString(object, name, value); } break; }