Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  imem.c   Sprache: C

 

/*****************************************************************************
 * imem.c : Memory input for VLC
 *****************************************************************************
 * Copyright (C) 2009-2010 Laurent Aimar
 *
 * Author: Laurent Aimar <fenrir _AT_ videolan _DOT org>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/


/*****************************************************************************
 * Preamble
 *****************************************************************************/


#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <limits.h>
#include <math.h>

#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_access.h>
#include <vlc_demux.h>
#include <vlc_charset.h>

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/

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 ID_TEXT N_("ID")
#define ID_LONGTEXT N_(\
    "Set the ID of the elementary stream")

#define GROUP_TEXT N_("Group")
#define GROUP_LONGTEXT N_(\
    "Set the group of the elementary stream")

#define CAT_TEXT N_("Category")
#define CAT_LONGTEXT N_(\
    "Set the category of the elementary stream")
static const int cat_values[] = {
    0, 1, 2, 3, 4,
};
static const char *cat_texts[] = {
    N_("Unknown"), N_("Audio"), N_("Video"), N_("Subtitle"), N_("Data")
};

#define CODEC_TEXT N_("Codec")
#define CODEC_LONGTEXT N_(\
    "Set the codec of the elementary stream")

#define LANGUAGE_TEXT N_("Language")
#define LANGUAGE_LONGTEXT N_(\
    "Language of the elementary stream as described by ISO639")

#define SAMPLERATE_TEXT N_("Sample rate")
#define SAMPLERATE_LONGTEXT N_(\
    "Sample rate of an audio elementary stream")

#define CHANNELS_TEXT N_("Channels count")
#define CHANNELS_LONGTEXT N_(\
    "Channels count of an audio elementary stream")

#define WIDTH_TEXT N_("Width")
#define WIDTH_LONGTEXT N_("Width of video or subtitle elementary streams")

#define HEIGHT_TEXT N_("Height")
#define HEIGHT_LONGTEXT N_("Height of video or subtitle elementary streams")

#define DAR_TEXT N_("Display aspect ratio")
#define DAR_LONGTEXT N_(\
    "Display aspect ratio of a video elementary stream")

#define FPS_TEXT N_("Frame rate")
#define FPS_LONGTEXT N_(\
    "Frame rate of a video elementary stream")

#define COOKIE_TEXT N_("Callback cookie string")
#define COOKIE_LONGTEXT N_(\
    "Text identifier for the callback functions")

#define DATA_TEXT N_("Callback data")
#define DATA_LONGTEXT N_(\
    "Data for the get and release functions")

#define GET_TEXT N_("Get function")
#define GET_LONGTEXT N_(\
    "Address of the get callback function")

#define RELEASE_TEXT N_("Release function")
#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"))
    set_subcategory(SUBCAT_INPUT_ACCESS)

    add_string ("imem-get", "0", GET_TEXT, GET_LONGTEXT)
        change_volatile()
    add_string ("imem-release", "0", RELEASE_TEXT, RELEASE_LONGTEXT)
        change_volatile()
    add_string ("imem-cookie", NULL, COOKIE_TEXT, COOKIE_LONGTEXT)
        change_volatile()
        change_safe()
    add_string ("imem-data", "0", DATA_TEXT, DATA_LONGTEXT)
        change_volatile()

    add_integer("imem-id", -1, ID_TEXT, ID_LONGTEXT)
        change_private()
        change_safe()
    add_integer("imem-group", 0, GROUP_TEXT, GROUP_LONGTEXT)
        change_private()
        change_safe()
    add_integer("imem-cat", 0, CAT_TEXT, CAT_LONGTEXT)
        change_integer_list(cat_values, cat_texts)
        change_private()
        change_safe()
    add_string ("imem-codec", NULL, CODEC_TEXT, CODEC_LONGTEXT)
        change_private()
        change_safe()
    add_string( "imem-language", NULL, LANGUAGE_TEXT, LANGUAGE_LONGTEXT)
        change_private()
        change_safe()

    add_integer("imem-samplerate", 0, SAMPLERATE_TEXT, SAMPLERATE_LONGTEXT)
        change_private()
        change_safe()
    add_integer("imem-channels", 0, CHANNELS_TEXT, CHANNELS_LONGTEXT)
        change_private()
        change_safe()

    add_integer_with_range("imem-width", 0, 0, UINT_MAX, WIDTH_TEXT, WIDTH_LONGTEXT)
        change_private()
        change_safe()
    add_integer_with_range("imem-height", 0, 0, UINT_MAX, HEIGHT_TEXT, HEIGHT_LONGTEXT)
        change_private()
        change_safe()
    add_string ("imem-dar", NULL, DAR_TEXT, DAR_LONGTEXT)
        change_private()
        change_safe()
    add_string ("imem-fps", NULL, FPS_TEXT, FPS_LONGTEXT)
        change_private()
        change_safe()

    add_integer ("imem-size", 0, SIZE_TEXT, SIZE_LONGTEXT)
        change_private()
        change_safe()

    add_shortcut("imem")
    set_capability("access", 1)
    set_callbacks(OpenDemux, CloseDemux)

    add_submodule()
        add_shortcut("imem")
        set_capability("access", 0)
        set_callbacks(OpenAccess, CloseAccess)
vlc_module_end()

/*****************************************************************************
 * Exported API
 *****************************************************************************/


/* The clock origin for the DTS and PTS is assumed to be 0.
 * A negative value means unknown.
 *
 * TODO define flags
 */

typedef int  (*imem_get_t)(void *data, const char *cookie,
                           int64_t *dts, int64_t *pts, unsigned *flags,
                           size_t *, void **);
typedef void (*imem_release_t)(void *data, const char *cookie, size_t, void *);

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/


/* */
static block_t *Block(stream_t *, bool * restrict);
static int ControlAccess(stream_t *, int, va_list);

static int Demux(demux_t *);
static int ControlDemux(demux_t *, int, va_list);

/* */
typedef struct {
    struct {
        imem_get_t      get;
        imem_release_t  release;
        void           *data;
        char           *cookie;
    } source;

    es_out_id_t  *es;

    vlc_tick_t   dts;

    vlc_tick_t   deadline;
} imem_sys_t;

static void ParseMRL(vlc_object_t *, const char *);

/**
 * It closes the common part of the access and access_demux
 */

static void CloseCommon(imem_sys_t *sys)
{
    free(sys->source.cookie);
}

/**
 * It initializes the common part for imem access/access_demux.
 */

static int OpenCommon(vlc_object_t *object, imem_sys_t **sys_ptr, const char *psz_path)
{
    char *tmp;

    /* */
    imem_sys_t *sys = vlc_obj_calloc(object, 1, sizeof(*sys));
    if (!sys)
        return VLC_ENOMEM;

    /* Read the user functions */
    tmp = var_InheritString(object, "imem-get");
    if (tmp)
        sys->source.get = (imem_get_t)(intptr_t)strtoll(tmp, NULL, 0);
    free(tmp);

    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) {
        return VLC_EGENERIC;
    }

    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 (*psz_path)
        ParseMRL(object, psz_path);

    sys->source.cookie = var_InheritString(object, "imem-cookie");

    msg_Dbg(object, "Using get(%p), release(%p), data(%p), cookie(%s)",
            (void *)sys->source.get, (void *)sys->source.release,
            sys->source.data,
            sys->source.cookie ? sys->source.cookie : "(null)");

    /* */
    sys->dts       = 0;
    sys->deadline  = VLC_TICK_INVALID;

    *sys_ptr = sys;
    return VLC_SUCCESS;
}

/**
 * It opens an imem access.
 */

static int OpenAccess(vlc_object_t *object)
{
    stream_t   *access = (stream_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->pf_control = ControlAccess;
    access->pf_read    = NULL;
    access->pf_block   = Block;
    access->pf_seek    = NULL;
    access->p_sys      = sys;

    return VLC_SUCCESS;
}

/**
 * It closes an imem access
 */

static void CloseAccess(vlc_object_t *object)
{
    stream_t *access = (stream_t *)object;

    CloseCommon((imem_sys_t*)access->p_sys);
}

/**
 * It controls an imem access
 */

static int ControlAccess(stream_t *access, int i_query, va_list args)
{
    (void) access;
    switch (i_query)
    {
    case STREAM_CAN_SEEK:
    case STREAM_CAN_FASTSEEK: {
        bool *b = va_arg( args, bool* );
        *b = false;
        return VLC_SUCCESS;
    }
    case STREAM_CAN_PAUSE:
    case STREAM_CAN_CONTROL_PACE: {
        bool *b = va_arg( args, bool* );
        *b = true;
        return VLC_SUCCESS;
    }
    case STREAM_GET_SIZE: {
        uint64_t *s = va_arg(args, uint64_t *);
        *s = var_InheritInteger(access, "imem-size");
        return *s ? VLC_SUCCESS : VLC_EGENERIC;
    }
    case STREAM_GET_PTS_DELAY:
        *va_arg(args, vlc_tick_t *) = DEFAULT_PTS_DELAY; /* FIXME? */
        return VLC_SUCCESS;

    case STREAM_SET_PAUSE_STATE:
        return VLC_SUCCESS;

    default:
        return VLC_EGENERIC;
    }
}

/**
 * It retrieves data using the get() callback, copies them,
 * and then release them using the release() callback.
 */

static block_t *Block(stream_t *access, bool *restrict eof)
{
    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)) {
        *eof = true;
        return NULL;
    }

    block_t *block = NULL;
    if (buffer_size > 0) {
        block = block_Alloc(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;
}

static inline int GetCategory(vlc_object_t *object)
{
    const int cat = var_InheritInteger(object, "imem-cat");
    switch (cat)
    {
    case 1:
        return AUDIO_ES;
    case 2:
        return VIDEO_ES;
    case 3:
        return SPU_ES;
    default:
        msg_Err(object, "Invalid ES category");
        /* fall through */
    case 4:
        return UNKNOWN_ES;
    }
}

/**
 * It opens an imem access_demux.
 */

static int OpenDemux(vlc_object_t *object)
{
    demux_t    *demux = (demux_t *)object;
    imem_sys_t *sys;

    if (demux->out == NULL)
        return VLC_EGENERIC;

    if (OpenCommon(object, &sys, demux->psz_location))
        return VLC_EGENERIC;

    /* ES format */
    es_format_t fmt;
    es_format_Init(&fmt, GetCategory(object), 0);

    fmt.i_id = var_InheritInteger(object, "imem-id");
    fmt.i_group = var_InheritInteger(object, "imem-group");

    char *tmp = var_InheritString(object, "imem-codec");
    if (tmp)
        fmt.i_codec = vlc_fourcc_GetCodecFromString(fmt.i_cat, tmp);
    free(tmp);

    switch (fmt.i_cat) {
    case AUDIO_ES: {
        fmt.audio.i_channels = var_InheritInteger(object, "imem-channels");
        fmt.audio.i_rate = var_InheritInteger(object, "imem-samplerate");

        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 VIDEO_ES: {
        fmt.video.i_width  = var_InheritInteger(object, "imem-width");
        fmt.video.i_height = var_InheritInteger(object, "imem-height");
        unsigned num, den;
        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_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(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,
                fmt.video.i_frame_rate, fmt.video.i_frame_rate_base);
        break;
    }
    case SPU_ES: {
        fmt.subs.spu.i_original_frame_width =
            var_InheritInteger(object, "imem-width");
        fmt.subs.spu.i_original_frame_height =
            var_InheritInteger(object, "imem-height");

        msg_Dbg(object, "Subtitle %4.4s",
                (const char *)&fmt.i_codec);
        break;
    }
    default:
        es_format_Clean(&fmt);
        CloseCommon(sys);
        return VLC_EGENERIC;
    }

    fmt.psz_language = var_InheritString(object, "imem-language");

    sys->es = es_out_Add(demux->out, &fmt);
    es_format_Clean(&fmt);

    if (!sys->es) {
        CloseCommon(sys);
        return VLC_EGENERIC;
    }

    /* */
    demux->pf_control = ControlDemux;
    demux->pf_demux   = Demux;
    demux->p_sys      = sys;

    return VLC_SUCCESS;
}

/**
 * It closes an imem access_demux
 */

static void CloseDemux(vlc_object_t *object)
{
    demux_t *demux = (demux_t *)object;

    CloseCommon((imem_sys_t*)demux->p_sys);
}

/**
 * It controls an imem access_demux
 */

static int ControlDemux(demux_t *demux, int i_query, va_list args)
{
    imem_sys_t *sys = (imem_sys_t*)demux->p_sys;

    switch (i_query)
    {
    case DEMUX_CAN_PAUSE:
    case DEMUX_CAN_CONTROL_PACE: {
        bool *b = va_arg(args, bool *);
        *b = true;
        return VLC_SUCCESS;
    }
    case DEMUX_SET_PAUSE_STATE:
        return VLC_SUCCESS;

    case DEMUX_GET_PTS_DELAY: {
        *va_arg(args, vlc_tick_t *) = DEFAULT_PTS_DELAY; /* FIXME? */
        return VLC_SUCCESS;
    }
    case DEMUX_GET_POSITION: {
        double *position = va_arg(args, double *);
        *position = 0.0;
        return VLC_SUCCESS;
    }
    case DEMUX_GET_TIME: {
        *va_arg(args, vlc_tick_t *) = sys->dts;
        return VLC_SUCCESS;
    }
    case DEMUX_GET_LENGTH: {
        *va_arg(args, vlc_tick_t *) = 0;
        return VLC_SUCCESS;
    }
    case DEMUX_SET_NEXT_DEMUX_TIME:
        sys->deadline = va_arg(args, vlc_tick_t);
        return VLC_SUCCESS;

    /* */
    case DEMUX_CAN_SEEK:
    case DEMUX_SET_POSITION:
    case DEMUX_SET_TIME:
    default:
        return VLC_EGENERIC;
    }

    return VLC_EGENERIC;
}

/**
 * It retrieves data using the get() callback, sends them to es_out
 * and the release it using the release() callback.
 */

static int Demux(demux_t *demux)
{
    imem_sys_t *sys = (imem_sys_t*)demux->p_sys;

    if (sys->deadline == VLC_TICK_INVALID)
        sys->deadline = sys->dts + 1;

    for (;;) {
        if (sys->deadline <= sys->dts)
            break;

        /* */
        int64_t dts, pts;
        unsigned flags;
        size_t buffer_size;
        void   *buffer;

        if (sys->source.get(sys->source.data, sys->source.cookie,
                            &dts, &pts, &flags, &buffer_size, &buffer))
            return VLC_DEMUXER_EOF;

        if (dts < 0)
            dts = pts;

        if (buffer_size > 0) {
            block_t *block = block_Alloc(buffer_size);
            if (block) {
                block->i_dts = dts >= 0 ? (1 + dts) : VLC_TICK_INVALID;
                block->i_pts = pts >= 0 ? (1 + pts) : VLC_TICK_INVALID;
                memcpy(block->p_buffer, buffer, buffer_size);

                es_out_SetPCR(demux->out, block->i_dts);
                es_out_Send(demux->out, sys->es, block);
            }
        }

        sys->dts = dts;

        sys->source.release(sys->source.data, sys->source.cookie,
                            buffer_size, buffer);
    }
    sys->deadline = VLC_TICK_INVALID;
    return VLC_DEMUXER_SUCCESS;
}

/**
 * Parse the MRL and extract configuration from it.
 *
 * Syntax: option1=value1[:option2=value2[...]]
 *
 * XXX get and release are not supported on purpose.
 */

static void ParseMRL(vlc_object_t *object, const char *psz_path)
{
    static const struct {
        const char *name;
        int        type;
    } options[] = {
        { "id",         VLC_VAR_INTEGER },
        { "group",      VLC_VAR_INTEGER },
        { "cat",        VLC_VAR_INTEGER },
        { "samplerate", VLC_VAR_INTEGER },
        { "channels",   VLC_VAR_INTEGER },
        { "width",      VLC_VAR_INTEGER },
        { "height",     VLC_VAR_INTEGER },
        { "cookie",     VLC_VAR_STRING },
        { "codec",      VLC_VAR_STRING },
        { "language",   VLC_VAR_STRING },
        { "dar",        VLC_VAR_STRING },
        { "fps",        VLC_VAR_STRING },
        { NULL, -1 }
    };

    char *dup = strdup(psz_path);
    if (!dup)
        return;
    char *current = dup;

    while (current) {
        char *next = strchr(current, ':');
        if (next)
            *next++ = '\0';

        char *option = current;
        char *value = strchr(current, '=');
        if (value) {
            *value++ = '\0';
            msg_Dbg(object, "option '%s' value '%s'", option, value);
        } else {
            msg_Dbg(object, "option '%s' without value (unsupported)", option);
        }

        char *name;
        if (asprintf(&name, "imem-%s", option) < 0)
            name = NULL;
        for (unsigned i = 0; name && options[i].name; i++) {
            if (strcmp(options[i].name, option))
                continue;
            /* */
            var_Create(object, name, options[i].type | VLC_VAR_DOINHERIT);
            if (options[i].type == VLC_VAR_INTEGER && value) {
                var_SetInteger(object, name, strtol(value, NULL, 0));
            } else if (options[i].type == VLC_VAR_STRING && value) {
                var_SetString(object, name, value);
            }
            break;
        }
        free(name);

        /* */
        current = next;
    }
    free(dup);
}

Messung
CHZG
84969993

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104852
#Domains=417161