Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/VLC/modules/access/   (VLC Media Plyer ©)  Datei vom 23.9.2026 mit Größe 9 kB image not shown  

Quelle  shm.c   Sprache: C

 

/**
 * @file shm.c
 * @brief Shared memory frame buffer capture module for VLC media player
 */

/*****************************************************************************
 * Copyright © 2011 Rémi Denis-Courmont
 *
 * 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 library; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 ****************************************************************************/


#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <stdarg.h>
#include <math.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#ifdef HAVE_SYS_SHM_H
# include <sys/ipc.h>
# include <sys/shm.h>
#endif

#include <vlc_common.h>
#include <vlc_demux.h>
#include <vlc_fs.h>
#include <vlc_plugin.h>

#define FPS_TEXT N_("Frame rate")
#define FPS_LONGTEXT N_( \
    "How many times the screen content should be refreshed per second.")

#define DEPTH_TEXT N_("Frame buffer depth")
#define DEPTH_LONGTEXT N_( \
    "Pixel depth of the frame buffer, or zero for XWD file")

#define WIDTH_TEXT N_("Frame buffer width")
#define WIDTH_LONGTEXT N_( \
    "Pixel width of the frame buffer (ignored for XWD file)")

#define HEIGHT_TEXT N_("Frame buffer height")
#define HEIGHT_LONGTEXT N_( \
    "Pixel height of the frame buffer (ignored for XWD file)")

#define ID_TEXT N_("Frame buffer segment ID")
#define ID_LONGTEXT N_( \
    "System V shared memory segment ID of the frame buffer " \
    "(this is ignored if --shm-file is specified).")

#define FILE_TEXT N_("Frame buffer file")
#define FILE_LONGTEXT N_( \
    "Path of the memory mapped file of the frame buffer")

static int  Open (vlc_object_t *);
static void Close (vlc_object_t *);

static const int depths[] = {
    0, 8, 15, 16, 24, 32,
};

static const char *const depth_texts[] = {
    N_("XWD file (autodetect)"),
    N_("8 bits"), N_("15 bits"), N_("16 bits"), N_("24 bits"), N_("32 bits"),
};

/*
 * Module descriptor
 */

vlc_module_begin ()
    set_shortname (N_("Framebuffer input"))
    set_description (N_("Shared memory framebuffer"))
    set_subcategory (SUBCAT_INPUT_ACCESS)
    set_capability ("access", 0)
    set_callbacks (Open, Close)

    add_float ("shm-fps", 10.0, FPS_TEXT, FPS_LONGTEXT)
    add_integer ("shm-depth", 0, DEPTH_TEXT, DEPTH_LONGTEXT)
        change_integer_list (depths, depth_texts)
        change_safe ()
    add_integer ("shm-width", 800, WIDTH_TEXT, WIDTH_LONGTEXT)
        change_integer_range (0, 65535)
        change_safe ()
    add_integer ("shm-height", 480, HEIGHT_TEXT, HEIGHT_LONGTEXT)
        change_integer_range (0, 65535)
        change_safe ()

    /* We need to "trust" the memory segment. If it were shrunk while we copy
     * its content our process may crash - or worse. So we pass the shared
     * memory location via an unsafe variable rather than the URL. */

    add_string ("shm-file", NULL, FILE_TEXT, FILE_LONGTEXT)
        change_volatile ()
#ifdef HAVE_SYS_SHM_H
    add_integer ("shm-id", (int64_t)IPC_PRIVATE, ID_TEXT, ID_LONGTEXT)
        change_volatile ()
#endif
    add_shortcut ("shm")
vlc_module_end ()

typedef struct demux_sys_t demux_sys_t;

static int Control (demux_t *, int, va_list);
static void DemuxFile (void *);
static void CloseFile (demux_sys_t *);
#ifdef HAVE_SYS_SHM_H
static void DemuxIPC (void *);
static void CloseIPC (demux_sys_t *);
#endif

struct demux_sys_t
{
    /* Everything is read-only when timer is armed. */
    union
    {
        int fd;
        struct
        {
             const void  *addr;
             size_t       length;
        } mem;
    };
    es_out_id_t *es;
    vlc_timer_t  timer;
    void (*detach) (demux_sys_t *);
};

static int Open (vlc_object_t *obj)
{
    demux_t *demux = (demux_t *)obj;
    if (demux->out == NULL)
        return VLC_EGENERIC;

    demux_sys_t *sys = vlc_obj_malloc(obj, sizeof (*sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;

    uint32_t chroma;
    uint16_t width = 0, height = 0;
    uint8_t bpp;
    switch (var_InheritInteger (demux, "shm-depth"))
    {
        case 32:
            chroma = VLC_CODEC_XRGB; bpp = 32;
            break;
        case 24:
            chroma = VLC_CODEC_RGB24; bpp = 24;
            break;
        case 16:
            chroma = VLC_CODEC_RGB565; bpp = 16;
            break;
        case 15:
            chroma = VLC_CODEC_RGB555; bpp = 16;
            break;
        case 8:
            chroma = VLC_CODEC_RGB233; bpp = 8;
            break;
        case 0:
            chroma = VLC_CODEC_XWD; bpp = 0;
            break;
        default:
            return VLC_EGENERIC;
    }
    if (bpp != 0)
    {
        width = var_InheritInteger (demux, "shm-width");
        height = var_InheritInteger (demux, "shm-height");
    }

    static void (*Demux) (void *);

    char *path = var_InheritString (demux, "shm-file");
    if (path != NULL)
    {
        sys->fd = vlc_open (path, O_RDONLY);
        if (sys->fd == -1)
            msg_Err (demux, "cannot open file %s: %s", path,
                     vlc_strerror_c(errno));
        free (path);
        if (sys->fd == -1)
            return VLC_EGENERIC;

        sys->detach = CloseFile;
        Demux = DemuxFile;
    }
    else
    {
#ifdef HAVE_SYS_SHM_H
        sys->mem.length = width * height * (bpp >> 3);
        if (sys->mem.length == 0)
            return VLC_EGENERIC;

        int id = var_InheritInteger (demux, "shm-id");
        if (id == IPC_PRIVATE)
            return VLC_EGENERIC;
        void *mem = shmat (id, NULL, SHM_RDONLY);

        if (mem == (const void *)(-1))
        {
            msg_Err (demux, "cannot attach segment %d: %s", id,
                     vlc_strerror_c(errno));
            return VLC_EGENERIC;
        }
        sys->mem.addr = mem;
        sys->detach = CloseIPC;
        Demux = DemuxIPC;
#else
        goto error;
#endif
    }

    /* Initializes format */
    float rate = var_InheritFloat (obj, "shm-fps");
    if (rate <= 0.f)
        goto error;

    vlc_tick_t interval = llroundf((float)CLOCK_FREQ / rate);
    if (!interval)
        goto error;

    es_format_t fmt;
    es_format_Init (&fmt, VIDEO_ES, chroma);
    video_format_Setup(&fmt.video, chroma, width, height, width, height, 1, 1);
    fmt.video.i_frame_rate = 1000 * rate;
    fmt.video.i_frame_rate_base = 1000;

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

    /* Initializes demux */
    if (vlc_timer_create (&sys->timer, Demux, demux))
        goto error;
    vlc_timer_schedule_asap (sys->timer, interval);

    demux->p_sys = sys;
    demux->pf_demux   = NULL;
    demux->pf_control = Control;
    return VLC_SUCCESS;

error:
    sys->detach (sys);
    return VLC_EGENERIC;
}


/**
 * Releases resources
 */

static void Close (vlc_object_t *obj)
{
    demux_t *demux = (demux_t *)obj;
    demux_sys_t *sys = demux->p_sys;

    vlc_timer_destroy (sys->timer);
    sys->detach (sys);
}

/**
 * Control callback
 */

static int Control (demux_t *demux, int query, va_list args)
{
    switch (query)
    {
        case DEMUX_GET_POSITION:
        {
            float *v = va_arg (args, float *);
            *v = 0.;
            return VLC_SUCCESS;
        }

        case DEMUX_GET_LENGTH:
        case DEMUX_GET_TIME:
        {
            *va_arg (args, vlc_tick_t *) = 0;
            return VLC_SUCCESS;
        }

        case DEMUX_GET_PTS_DELAY:
        {
            *va_arg (args, vlc_tick_t *) =
                VLC_TICK_FROM_MS( var_InheritInteger (demux, "live-caching") );
            return VLC_SUCCESS;
        }

        case DEMUX_CAN_PAUSE:
        case DEMUX_CAN_CONTROL_PACE:
        case DEMUX_CAN_CONTROL_RATE:
        case DEMUX_CAN_SEEK:
        {
            bool *v = va_arg (args, bool *);
            *v = false;
            return VLC_SUCCESS;
        }

        case DEMUX_SET_PAUSE_STATE:
            return VLC_SUCCESS; /* should not happen */
    }

    return VLC_EGENERIC;
}

/**
 * Processing callback
 */

static void DemuxFile (void *data)
{
    demux_t *demux = data;
    demux_sys_t *sys = demux->p_sys;

    /* Copy frame */
    block_t *block = block_File(sys->fd, true);
    if (block == NULL)
        return;
    block->i_pts = block->i_dts = vlc_tick_now ();

    /* Send block */
    es_out_SetPCR(demux->out, block->i_pts);
    es_out_Send (demux->out, sys->es, block);
}

static void CloseFile (demux_sys_t *sys)
{
    vlc_close (sys->fd);
}

#ifdef HAVE_SYS_SHM_H
static void DemuxIPC (void *data)
{
    demux_t *demux = data;
    demux_sys_t *sys = demux->p_sys;

    /* Copy frame */
    block_t *block = block_Alloc (sys->mem.length);
    if (block == NULL)
        return;
    memcpy (block->p_buffer, sys->mem.addr, sys->mem.length);
    block->i_pts = block->i_dts = vlc_tick_now ();

    /* Send block */
    es_out_SetPCR(demux->out, block->i_pts);
    es_out_Send (demux->out, sys->es, block);
}

static void CloseIPC (demux_sys_t *sys)
{
    shmdt (sys->mem.addr);
}
#endif

Messung
CHZG
849710093

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© 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.