Page 1 of 1

Take Snapshot

Posted: 06 Oct 2008 19:23
by davidhoyt
Is there a way to take a snapshot using libvlc that doesn't require saving it to disk first? IOW, can I retrieve an in-memory snapshot?

Re: Take Snapshot

Posted: 06 Oct 2008 21:24
by The DJ
No this is not possible

Re: Take Snapshot

Posted: 08 Oct 2008 20:01
by Erwan100
Hello,

Actually, I came across an interesting piece of code in vlc 0.9.3 sources.
The snapshot-path option has been designed to accept in-memory snapshot. The syntax is snapshot-path = "object:<id>" where id refers to a vlc object. I don't know whether this is deprecated or a new feature yet to come.

Anyway, I wrote the following C program to test it. And it works fine.

In a few words, I use libvlc whenever possible and some extra functions available in the vlc/plugins directory to access the vlc object architecture. The idea is the create my own vlc object and ask vlc to write the snapshot into it.
/*###########################################################################
*# Author : Erwan100
*# date : october 08, 2008
*# Object : retrieve a snapshot inside the program through the use of
*# snapshot-path = object:<id>
*# softw : VLC 0.9.3 (Ubuntu 7.10)
*# compilation :
*# gcc -std=gnu99 -I/usr/local/include/vlc/plugins -o snap snap.c -lvlc
*###########################################################################
*/

#include <vlc/vlc.h>
#include <vlc/plugins/vlc_common.h>

typedef struct snapshot_t {
char *p_data; /* Data area */

int i_width; /* In pixels */
int i_height; /* In pixels */
int i_datasize; /* In bytes */
mtime_t date; /* Presentation time */
} snapshot_t;


libvlc_exception_t vlc_excep;
libvlc_instance_t* p_vlc_instance;

libvlc_media_t* media;
libvlc_media_player_t* media_player;

int object_id;
vlc_object_t* p_libvlc;

char* myobj_name = "my_object";


/*****************************************************************************
* to handle errors ....
* **************************************************************************/
#define catch_vlc_error() _catch_vlc_error(__FILE__, __LINE__)
void _catch_vlc_error ( char* file, int line )
{
if (libvlc_exception_raised (&vlc_excep))
{
fprintf(stderr,"-- VLC ERROR : file=%s , line=%d --\n",file,line);
fprintf(stderr,"%s\n", libvlc_exception_get_message(&vlc_excep));
exit(-1);
}

libvlc_exception_clear (&vlc_excep);
}

#define gen_error() _gen_error(__FILE__, __LINE__)
void _gen_error ( char* file, int line )
{
fprintf(stderr,"-- ERROR : file=%s , line=%d --\n",file,line);
exit(-1);
}


/*****************************************************************************
* main program ....
* **************************************************************************/
int main()
{
/* initialize vlc error handling */
libvlc_exception_init (&vlc_excep);

/* libvlc settings */
const char* const args[] = {
"--verbose=0",
"--no-media-library",
"--services-discovery=",
"--ignore-config",
"--intf=dummy",
"--extraintf=rc"
};

int nargs = sizeof(args) / sizeof(args[0]);

/* create a libvlc instance */
p_vlc_instance = libvlc_new( nargs, args, &vlc_excep );
catch_vlc_error();

/* retrieve the libvlc internal references */
object_id = libvlc_get_vlc_id( p_vlc_instance );
p_libvlc = (vlc_object_t *) vlc_object_get ( object_id );
if (!p_libvlc) gen_error();

/* create a media player */
media_player = libvlc_media_player_new( p_vlc_instance, &vlc_excep );
catch_vlc_error();

/* create a media item */
media = libvlc_media_new(p_vlc_instance, "file:///home/movie.avi" , &vlc_excep);
catch_vlc_error();

libvlc_media_player_set_media( media_player, media , &vlc_excep);
catch_vlc_error();

/* start playing the media */
libvlc_media_player_play( media_player, &vlc_excep );
catch_vlc_error();

/* create MY OWN VLC OBJECT named myobj */
vlc_object_t* p_myobj = vlc_object_create( p_libvlc, sizeof(vlc_object_t) );
vlc_object_attach( p_myobj, p_libvlc );
if ( !p_myobj ) gen_error();
p_myobj->psz_object_name = myobj_name;


/***********************************
* - start a infinite loop
* - take a snapshot every 2 sec
* - retrieve the snapshot
* - write the png image into a file
* *********************************/
int count=0;
while(1)
{
count++;
sleep(2);

/* retrieve width of video */
int width = libvlc_video_get_width (media_player, &vlc_excep );
catch_vlc_error();

/* retrieve height of video */
int height = libvlc_video_get_height (media_player, &vlc_excep );
catch_vlc_error();

/* set snapshot_path to object:<id> */
char snapshot_path[30];
sprintf(snapshot_path,"object:%d",p_myobj->i_object_id);

/* lock */
vlc_object_lock (p_myobj);

/* take snapshot */
libvlc_video_take_snapshot( media_player , snapshot_path , width, height, &vlc_excep );
catch_vlc_error();

/* wait for vlc to signal end of work */
vlc_object_wait (p_myobj);

/* unlock */
vlc_object_unlock (p_myobj);

/* retrieve the snapshot from the myobj object */
snapshot_t* p_snapshot = (snapshot_t*) p_myobj->p_private;
if (!p_snapshot) gen_error();

/* From now on, we've got the image and its size */
char* p_image = p_snapshot->p_data;
int image_size = p_snapshot->i_datasize;

/* dump the image into a file to check it works */
char filename[30]; FILE *p;
sprintf(filename,"/tmp/image%d.png",count);
if ( ! ( p = fopen( filename,"w" ) ) ) gen_error();
fwrite(p_image, image_size, 1, p);

fprintf(stderr,"Taking a snapshot (saved in %s)\n",filename);

/* cleaning up */
fclose(p);
free (p_snapshot->p_data);
free (p_snapshot);
}

return 0;
}

Re: Take Snapshot

Posted: 10 Oct 2008 00:02
by davidhoyt
Awesome! Thanks so much! This is a good starting point.

Re: Take Snapshot

Posted: 15 Oct 2008 16:41
by Erwan100
Hi,

As a follow-up to this in-memory snapshot issue, things may even be easier than expected. The mediacontrol vlc API implements this in-memory function (see mediacontrol.h) :

Code: Select all

VLC_PUBLIC_API mediacontrol_RGBPicture * mediacontrol_snapshot( mediacontrol_Instance *self, const mediacontrol_Position *a_position, mediacontrol_Exception *exception );
It works fine (tested).
the only problem I found is that width/height cannot be passed on to this function. If this is of importance, you still have to do it at a lower level as described previously.

Re: Take Snapshot

Posted: 02 Sep 2011 09:27
by ma_partha
libvlc_get_vlc_id and vlc_object_get are now deprecated. How should I modify the sample code to work with newer vlc versions ?