/*****************************************************************************
* Copyright © 2011 Rémi Denis-Courmont
*
- * This library 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 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 library is distributed in the hope that it will be useful,
+ * 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 General Public License for more details.
+ * 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+ * 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
#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 <sys/mman.h>
#include <vlc_common.h>
#include <vlc_demux.h>
#include <vlc_fs.h>
#include <vlc_plugin.h>
-#define CACHING_TEXT N_("Caching value in ms")
-#define CACHING_LONGTEXT N_( \
- "Caching value for frame buffer capture. " \
- "This value should be set in milliseconds.")
-
#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")
+ "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")
-
-#define DEPTH_TEXT N_("Frame buffer depth")
-#define DEPTH_LONGTEXT N_( \
- "Pixel depth of the frame buffer")
+ "Pixel height of the frame buffer (ignored for XWD file)")
#define ID_TEXT N_("Frame buffer segment ID")
#define ID_LONGTEXT N_( \
static void Close (vlc_object_t *);
static const int depths[] = {
- 8, 15, 16, 24, 32,
+ 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"),
};
set_capability ("access_demux", 0)
set_callbacks (Open, Close)
- add_integer ("shm-caching", DEFAULT_PTS_DELAY * 1000 / CLOCK_FREQ,
- CACHING_TEXT, CACHING_LONGTEXT, true)
add_float ("shm-fps", 10.0, FPS_TEXT, FPS_LONGTEXT, true)
+ add_integer ("shm-depth", 0, DEPTH_TEXT, DEPTH_LONGTEXT, true)
+ change_integer_list (depths, depth_texts)
+ change_safe ()
add_integer ("shm-width", 800, WIDTH_TEXT, WIDTH_LONGTEXT, false)
change_integer_range (0, 65535)
change_safe ()
add_integer ("shm-height", 480, HEIGHT_TEXT, HEIGHT_LONGTEXT, false)
change_integer_range (0, 65535)
change_safe ()
- add_integer ("shm-depth", 32, DEPTH_TEXT, DEPTH_LONGTEXT, true)
- change_integer_list (depths, depth_texts)
- 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
add_shortcut ("shm")
vlc_module_end ()
-static void Demux (void *);
static int Control (demux_t *, int, va_list);
-static void map_detach (demux_sys_t *);
+static void DemuxFile (void *);
+static void CloseFile (demux_sys_t *);
#ifdef HAVE_SYS_SHM_H
-static void sysv_detach (demux_sys_t *);
+static void DemuxIPC (void *);
+static void CloseIPC (demux_sys_t *);
#endif
static void no_detach (demux_sys_t *);
struct demux_sys_t
{
- const void *addr;
- size_t length;
+ /* Everything is read-only when timer is armed. */
+ union
+ {
+ int fd;
+ struct
+ {
+ const void *addr;
+ size_t length;
+ } mem;
+ };
es_out_id_t *es;
- mtime_t pts, interval;
- /* pts is protected by the lock. The rest is read-only. */
- vlc_mutex_t lock;
vlc_timer_t timer;
void (*detach) (demux_sys_t *);
};
static int Open (vlc_object_t *obj)
{
demux_t *demux = (demux_t *)obj;
-
- long pagesize = sysconf (_SC_PAGE_SIZE);
- if (pagesize == -1)
- return VLC_EGENERIC;
-
demux_sys_t *sys = malloc (sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
sys->detach = no_detach;
- uint16_t width = var_InheritInteger (demux, "shm-width");
- uint16_t height = var_InheritInteger (demux, "shm-height");
uint32_t chroma;
+ uint16_t width = 0, height = 0;
uint8_t bpp;
switch (var_InheritInteger (demux, "shm-depth"))
{
case 8:
chroma = VLC_CODEC_RGB8; bpp = 8;
break;
+ case 0:
+ chroma = VLC_CODEC_XWD; bpp = 0;
+ break;
default:
goto error;
}
+ if (bpp != 0)
+ {
+ width = var_InheritInteger (demux, "shm-width");
+ height = var_InheritInteger (demux, "shm-height");
+ }
- sys->length = width * height * (bpp >> 3);
- if (sys->length == 0)
- goto error;
- pagesize--;
- sys->length = (sys->length + pagesize) & ~pagesize; /* pad */
+ static void (*Demux) (void *);
char *path = var_InheritString (demux, "shm-file");
if (path != NULL)
{
- int fd = vlc_open (path, O_RDONLY);
- if (fd == -1)
- {
- msg_Err (demux, "cannot open file %s: %m", path);
- free (path);
+ 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)
goto error;
- }
- void *mem = mmap (NULL, sys->length, PROT_READ, MAP_SHARED, fd, 0);
- close (fd);
- if (mem == MAP_FAILED)
- {
- msg_Err (demux, "cannot map file %s: %m", path);
- free (path);
- goto error;
- }
- free (path);
- sys->addr = mem;
- sys->detach = map_detach;
+ sys->detach = CloseFile;
+ Demux = DemuxFile;
}
else
{
#ifdef HAVE_SYS_SHM_H
+ sys->mem.length = width * height * (bpp >> 3);
+ if (sys->mem.length == 0)
+ goto error;
+
int id = var_InheritInteger (demux, "shm-id");
if (id == IPC_PRIVATE)
goto error;
if (mem == (const void *)(-1))
{
- msg_Err (demux, "cannot attach segment %d: %m", id);
+ msg_Err (demux, "cannot attach segment %d: %s", id,
+ vlc_strerror_c(errno));
goto error;
}
- sys->addr = mem;
- sys->detach = sysv_detach;
+ 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.)
+ if (rate <= 0.f)
goto error;
- sys->interval = (float)CLOCK_FREQ / rate;
- if (!sys->interval)
+ mtime_t interval = llroundf((float)CLOCK_FREQ / rate);
+ if (!interval)
goto error;
- sys->pts = VLC_TS_INVALID;
es_format_t fmt;
es_format_Init (&fmt, VIDEO_ES, chroma);
sys->es = es_out_Add (demux->out, &fmt);
/* Initializes demux */
- var_Create (obj, "shm-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT);
-
- vlc_mutex_init (&sys->lock);
if (vlc_timer_create (&sys->timer, Demux, demux))
goto error;
- vlc_timer_schedule (sys->timer, false, 1, sys->interval);
+ vlc_timer_schedule (sys->timer, false, 1, interval);
demux->p_sys = sys;
demux->pf_demux = NULL;
demux_sys_t *sys = demux->p_sys;
vlc_timer_destroy (sys->timer);
- vlc_mutex_destroy (&sys->lock);
sys->detach (sys);
free (sys);
}
-
-static void map_detach (demux_sys_t *sys)
-{
- munmap ((void *)sys->addr, sys->length);
-}
-
-#ifdef HAVE_SYS_SHM_H
-static void sysv_detach (demux_sys_t *sys)
-{
- shmdt (sys->addr);
-}
-#endif
-
static void no_detach (demux_sys_t *sys)
{
(void) sys;
*/
static int Control (demux_t *demux, int query, va_list args)
{
- demux_sys_t *sys = demux->p_sys;
-
switch (query)
{
case DEMUX_GET_POSITION:
case DEMUX_GET_PTS_DELAY:
{
int64_t *v = va_arg (args, int64_t *);
- *v = var_GetInteger (demux, "shm-caching") * UINT64_C(1000);
+ *v = INT64_C(1000) * var_InheritInteger (demux, "live-caching");
return VLC_SUCCESS;
}
case DEMUX_CAN_PAUSE:
- {
- bool *v = (bool *)va_arg (args, bool *);
- *v = true;
- return VLC_SUCCESS;
- }
-
- case DEMUX_SET_PAUSE_STATE:
- {
- bool pausing = va_arg (args, int);
-
- if (!pausing)
- {
- vlc_mutex_lock (&sys->lock);
- sys->pts = VLC_TS_INVALID;
- es_out_Control (demux->out, ES_OUT_RESET_PCR);
- vlc_mutex_unlock (&sys->lock);
- }
- vlc_timer_schedule (sys->timer, false,
- pausing ? 0 : 1, sys->interval);
- return VLC_SUCCESS;
- }
-
case DEMUX_CAN_CONTROL_PACE:
case DEMUX_CAN_CONTROL_RATE:
case DEMUX_CAN_SEEK:
{
- bool *v = (bool *)va_arg (args, bool *);
+ 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 Demux (void *data)
+static void DemuxFile (void *data)
{
demux_t *demux = data;
demux_sys_t *sys = demux->p_sys;
/* Copy frame */
- block_t *block = block_Alloc (sys->length);
+ block_t *block = block_File (sys->fd);
if (block == NULL)
return;
-
- vlc_memcpy (block->p_buffer, sys->addr, sys->length);
+ block->i_pts = block->i_dts = mdate ();
/* Send block */
- vlc_mutex_lock (&sys->lock);
- if (sys->pts == VLC_TS_INVALID)
- sys->pts = mdate ();
- block->i_pts = block->i_dts = sys->pts;
+ es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts);
+ es_out_Send (demux->out, sys->es, block);
+}
- es_out_Control (demux->out, ES_OUT_SET_PCR, sys->pts);
+static void CloseFile (demux_sys_t *sys)
+{
+ 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 = mdate ();
+
+ /* Send block */
+ es_out_Control (demux->out, ES_OUT_SET_PCR, block->i_pts);
es_out_Send (demux->out, sys->es, block);
- sys->pts += sys->interval;
- vlc_mutex_unlock (&sys->lock);
}
+
+static void CloseIPC (demux_sys_t *sys)
+{
+ shmdt (sys->mem.addr);
+}
+#endif