[vlc-devel] [PATCH] Added libvlc_video_take_snapshot_addr to libvlc and related functions to libvlccore
Rémi Denis-Courmont
remi at remlab.net
Mon Nov 28 21:28:50 CET 2011
diff --git a/include/vlc/libvlc_media_player.h
b/include/vlc/libvlc_media_player.h
index a2b5748..30ed0cd 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -1151,6 +1151,25 @@ int libvlc_video_take_snapshot( libvlc_media_player_t
*p_mi, unsigned num,
unsigned int i_height );
/**
+ * Take a snapshot of the current video window and return the snapshot
address.
+ *
+ * If i_width AND i_height is 0, original size is used.
+ * If i_width XOR i_height is 0, original aspect-ratio is preserved.
+ *
+ * \param p_mi media player instance
+ * \param num number of video output (typically 0 for the first/only one)
+ * \param psz_addr place to return the snapshot address (you MUST free it
after use)
+ * \param i_width the snapshot's width
+ * \param i_height the snapshot's height
+ * \return the snapshot memory area size on success, -1 if there was a
problem
+ */
+LIBVLC_API
+size_t
+libvlc_video_take_snapshot_addr( libvlc_media_player_t *p_mi, unsigned num,
+ void **psz_addr, unsigned int i_width,
+ unsigned int i_height );
+
+/**
* Enable or disable deinterlace filter
*
* \param p_mi libvlc media player
diff --git a/lib/libvlc.sym b/lib/libvlc.sym
index 6582a96..0a15838 100644
--- a/lib/libvlc.sym
+++ b/lib/libvlc.sym
@@ -216,6 +216,7 @@ libvlc_video_set_subtitle_file
libvlc_video_set_teletext
libvlc_video_set_track
libvlc_video_take_snapshot
+libvlc_video_take_snapshot_addr
libvlc_video_snapshot or whatever. The function name is long enough as it is.
libvlc_vlm_add_broadcast
libvlc_vlm_add_vod
libvlc_vlm_add_input
diff --git a/lib/video.c b/lib/video.c
index 6e1ea06..deb45b1 100644
--- a/lib/video.c
+++ b/lib/video.c
@@ -34,6 +34,7 @@
#include <vlc/libvlc_media_player.h>
#include <vlc_common.h>
+#include <vlc_block.h>
#include <vlc_input.h>
#include <vlc_vout.h>
@@ -158,6 +159,45 @@ libvlc_video_take_snapshot( libvlc_media_player_t *p_mi,
unsigned num,
return 0;
}
+size_t
+libvlc_video_take_snapshot_addr( libvlc_media_player_t *p_mi, unsigned num,
+ void **psz_addr, unsigned int i_width,
+ unsigned int i_height )
+{
+ block_t *block_buffer;
+ size_t buffer_len = 0;
+ char *buffer = NULL;
+
+ vout_thread_t *p_vout = GetVout( p_mi, num );
+ if (p_vout == NULL)
+ return -1;
+
+ var_SetInteger( p_vout, "snapshot-width", i_width);
+ var_SetInteger( p_vout, "snapshot-height", i_height );
+ var_SetString( p_vout, "snapshot-format", "png" );
+
+ var_TriggerCallback( p_vout, "video-snapshot-addr" );
+
+ block_buffer = (block_t *) var_GetAddress( p_vout, "snapshot-addr" );
You reproduced the bug in the file snapshot code. All those var_* calls are
not atomic, and thus this function is not reentrant.
You should use a single var_SetAddress() with a big fat ugly structure
containing all the input and output parameters as the sole parameter. If you
want to be cleaner, you can define a new dedicated function in the video
output core. Or you can even write a core function with a nice looking
prototype, but that does use a big fat ugly structure internally.
+ if( block_buffer == NULL )
+ return -1;
+
+ buffer_len = block_buffer->i_buffer;
+ if( buffer_len <= 0 )
+ return -1;
+
+ buffer = malloc( buffer_len );
+ if( buffer == NULL )
+ return -1;
+
+ psz_addr[0] = buffer;
+ memcpy( buffer, block_buffer->p_buffer, buffer_len );
+
+ var_TriggerCallback( p_vout, "video-snapshot-addr-free" );
You could call block_Release() directly.
But I would postpone the block_Release() to a dedicated "free" function to
avoid one memory copy.
+
+ return buffer_len;
+}
+
int libvlc_video_get_size( libvlc_media_player_t *p_mi, unsigned num,
unsigned *restrict px, unsigned *restrict py )
{
diff --git a/src/video_output/vout_intf.c b/src/video_output/vout_intf.c
index e53f41e..09525bf 100644
--- a/src/video_output/vout_intf.c
+++ b/src/video_output/vout_intf.c
@@ -63,6 +63,10 @@ static int FullscreenCallback( vlc_object_t *, char const
*,
vlc_value_t, vlc_value_t, void * );
static int SnapshotCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
+static int SnapshotAddrCallback( vlc_object_t *p_this, char const *psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data
);
+static int SnapshotAddrFreeCallback( vlc_object_t *p_this, char const
*psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data
);
static int VideoFilterCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
static int SubSourceCallback( vlc_object_t *, char const *,
@@ -151,6 +155,7 @@ void vout_IntfInit( vout_thread_t *p_vout )
/* Create a few object variables we'll need later on */
var_Create( p_vout, "snapshot-path", VLC_VAR_STRING | VLC_VAR_DOINHERIT
);
+ var_Create( p_vout, "snapshot-addr", VLC_VAR_ADDRESS | VLC_VAR_DOINHERIT
);
var_Create( p_vout, "snapshot-prefix", VLC_VAR_STRING | VLC_VAR_DOINHERIT
);
var_Create( p_vout, "snapshot-format", VLC_VAR_STRING | VLC_VAR_DOINHERIT
);
var_Create( p_vout, "snapshot-preview", VLC_VAR_BOOL | VLC_VAR_DOINHERIT
);
@@ -310,6 +315,18 @@ void vout_IntfInit( vout_thread_t *p_vout )
var_Change( p_vout, "video-snapshot", VLC_VAR_SETTEXT, &text, NULL );
var_AddCallback( p_vout, "video-snapshot", SnapshotCallback, NULL );
+ /* Add a snapshot address variable */
+ var_Create( p_vout, "video-snapshot-addr", VLC_VAR_VOID |
VLC_VAR_ISCOMMAND );
+ text.psz_string = _("Snapshot address");
+ var_Change( p_vout, "video-snapshot-addr", VLC_VAR_SETTEXT, &text, NULL
);
+ var_AddCallback( p_vout, "video-snapshot-addr", SnapshotAddrCallback,
NULL );
+
+ /* Add a free snapshot address variable */
+ var_Create( p_vout, "video-snapshot-addr-free", VLC_VAR_VOID |
VLC_VAR_ISCOMMAND );
+ text.psz_string = _("Free snapshot address");
+ var_Change( p_vout, "video-snapshot-addr-free", VLC_VAR_SETTEXT, &text,
NULL );
+ var_AddCallback( p_vout, "video-snapshot-addr-free",
SnapshotAddrFreeCallback, NULL );
+
/* Add a video-filter variable */
var_Create( p_vout, "video-filter",
VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
@@ -452,6 +469,50 @@ exit:
free( psz_path );
}
+/**
+ * This function will handle a snapshot request and provide the image pointer
+ */
+static void VoutSnapshotAddr( vout_thread_t *p_vout )
+{
+ char *psz_format = var_GetNonEmptyString( p_vout, "snapshot-format" );
+ char *psz_prefix = var_GetNonEmptyString( p_vout, "snapshot-prefix" );
+
+ /* */
+ picture_t *p_picture;
+ block_t *p_image;
+ video_format_t fmt;
+
+ /* 500ms timeout
+ * XXX it will cause trouble with low fps video (< 2fps) */
+ if( vout_GetSnapshot( p_vout, &p_image, &p_picture, &fmt, psz_format,
500*1000 ) )
+ {
+ p_picture = NULL;
+ p_image = NULL;
+ goto exit;
+ }
+
+ var_SetAddress( p_vout, "snapshot-addr", (void *) p_image );
+
+exit:
+ if( p_picture )
+ picture_Release( p_picture );
+ free( psz_prefix );
+ free( psz_format );
+}
+
+/**
+ * This function will free the snapshot addr
+ */
+static void VoutSnapshotAddrFree( vout_thread_t *p_vout )
+{
+ block_t *p_image = NULL;
+
+ p_image = (block_t *) var_GetAddress( p_vout, "snapshot-addr" );
+
+ if( p_image != NULL )
+ block_Release( p_image );
+}
+
/*****************************************************************************
* Handle filters
*****************************************************************************/
@@ -653,6 +714,28 @@ static int SnapshotCallback( vlc_object_t *p_this, char
const *psz_cmd,
return VLC_SUCCESS;
}
+static int SnapshotAddrCallback( vlc_object_t *p_this, char const *psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
+ VLC_UNUSED(newval); VLC_UNUSED(p_data);
+
+ VoutSnapshotAddr( p_vout );
+ return VLC_SUCCESS;
+}
+
+static int SnapshotAddrFreeCallback( vlc_object_t *p_this, char const
*psz_cmd,
+ vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+ vout_thread_t *p_vout = (vout_thread_t *)p_this;
+ VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval);
+ VLC_UNUSED(newval); VLC_UNUSED(p_data);
+
+ VoutSnapshotAddrFree( p_vout );
+ return VLC_SUCCESS;
+}
+
static int VideoFilterCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void
*p_data)
{
--
1.7.4.1
--
Rémi Denis-Courmont
http://www.remlab.net/
http://fi.linkedin.com/in/remidenis
More information about the vlc-devel
mailing list