]> git.sesse.net Git - vlc/commitdiff
Smem sout module to memory buffer video only
authorChristophe Courtaut <christophe.courtaut@gmail.com>
Sun, 13 Sep 2009 22:25:35 +0000 (00:25 +0200)
committerRémi Denis-Courmont <remi@remlab.net>
Mon, 14 Sep 2009 15:32:34 +0000 (18:32 +0300)
The smem sout module allows you to stream out to memory buffer.
Currently only video is implemented. This module should be used
with the transcode sout module, to get raw data from it.

Signed-off-by: Rémi Denis-Courmont <remi@remlab.net>
modules/stream_out/Modules.am
modules/stream_out/smem.c [new file with mode: 0644]

index fd09f9e0f3716cbe7f71763039a846065e3f7b22..36625b359736997b8934fd2dab6edb2db4f32153 100644 (file)
@@ -12,6 +12,7 @@ SOURCES_stream_out_mosaic_bridge = mosaic_bridge.c
 SOURCES_stream_out_autodel = autodel.c
 SOURCES_stream_out_record = record.c
 SOURCES_stream_out_raop = raop.c
+SOURCES_stream_out_smem = smem.c
 
 libvlc_LTLIBRARIES += \
        libstream_out_dummy_plugin.la \
@@ -26,6 +27,7 @@ libvlc_LTLIBRARIES += \
        libstream_out_mosaic_bridge_plugin.la \
        libstream_out_autodel_plugin.la \
        libstream_out_record_plugin.la \
+       libstream_out_smem_plugin.la \
        $(NULL)
 
 if HAVE_LIBGCRYPT
diff --git a/modules/stream_out/smem.c b/modules/stream_out/smem.c
new file mode 100644 (file)
index 0000000..5d9b79e
--- /dev/null
@@ -0,0 +1,321 @@
+/*****************************************************************************
+ * smem.c: stream output to memory buffer module
+ *****************************************************************************
+ * Copyright (C) 2009 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Christophe Courtaut <christophe.courtaut@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * How to use it
+ *****************************************************************************
+ *
+ * You should use this module in combination with the transcode module, to get
+ * raw datas from it. This module does not make any conversion at all, so you
+ * need to use the transcode module for this purpose.
+ *
+ * For example, you can use smem as it :
+ * --sout="#transcode{vcodec=RV24,acodec=s16l}:smem{smem-options}"
+ *
+ * Into each lock function (audio and video), you will have all the informations
+ * you need to allocate a buffer, so that this module will copy data in it.
+ *
+ * the video-data and audio-data pointers will be passed to lock/unlock function
+ *
+ * For now, audio is NOT IMPLEMENTED.
+ *
+ ******************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_sout.h>
+#include <vlc_block.h>
+#include <vlc_codec.h>
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+
+#define T_VIDEO_PRERENDER_CALLBACK N_( "Video prerender callback" )
+#define LT_VIDEO_PRERENDER_CALLBACK N_( "Address of the video prerender callback function" \
+                                "this function will set the buffer where render will be done" )
+
+#define T_AUDIO_PRERENDER_CALLBACK N_( "Audio prerender callback" )
+#define LT_AUDIO_PRERENDER_CALLBACK N_( "Address of the audio prerender callback function." \
+                                        "this function will set the buffer where render will be done" )
+
+#define T_VIDEO_POSTRENDER_CALLBACK N_( "Video postrender callback" )
+#define LT_VIDEO_POSTRENDER_CALLBACK N_( "Address of the video postrender callback function." \
+                                        "this function will be called when the render is into the buffer" )
+
+#define T_AUDIO_POSTRENDER_CALLBACK N_( "Audio postrender callback" )
+#define LT_AUDIO_POSTRENDER_CALLBACK N_( "Address of the audio postrender callback function." \
+                                        "this function will be called when the render is into the buffer" )
+
+#define T_VIDEO_DATA N_( "Video Callback data" )
+#define LT_VIDEO_DATA N_( "Data for the video callback function." )
+
+#define T_AUDIO_DATA N_( "Audio callback data" )
+#define LT_AUDIO_DATA N_( "Data for the audio callback function." )
+
+#define T_TIME_SYNC N_( "Time Synchronized output" )
+#define LT_TIME_SYNC N_( "Time Synchronisation option for output. " \
+                        "If true, stream will render as usual, else " \
+                        "it will be rendered as fast as possible.")
+
+static int  Open ( vlc_object_t * );
+static void Close( vlc_object_t * );
+
+#define SOUT_CFG_PREFIX "sout-smem-"
+#define SOUT_PREFIX_VIDEO SOUT_CFG_PREFIX"video-"
+#define SOUT_PREFIX_AUDIO SOUT_CFG_PREFIX"audio-"
+
+vlc_module_begin ()
+    set_shortname( N_("smem"))
+    set_description( N_("Stream output to memory buffer") )
+    set_capability( "sout stream", 50 )
+    add_shortcut( "smem" )
+    set_category( CAT_SOUT )
+    set_subcategory( SUBCAT_SOUT_STREAM )
+    add_string( SOUT_PREFIX_VIDEO "prerender-callback", "0", NULL, T_VIDEO_PRERENDER_CALLBACK, LT_VIDEO_PRERENDER_CALLBACK, true )
+    add_string( SOUT_PREFIX_AUDIO "prerender-callback", "0", NULL, T_AUDIO_PRERENDER_CALLBACK, LT_AUDIO_PRERENDER_CALLBACK, true )
+    add_string( SOUT_PREFIX_VIDEO "postrender-callback", "0", NULL, T_VIDEO_POSTRENDER_CALLBACK, LT_VIDEO_POSTRENDER_CALLBACK, true )
+    add_string( SOUT_PREFIX_AUDIO "postrender-callback", "0", NULL, T_AUDIO_POSTRENDER_CALLBACK, LT_AUDIO_POSTRENDER_CALLBACK, true )
+    add_string( SOUT_PREFIX_VIDEO "data", "0", NULL, T_VIDEO_DATA, LT_VIDEO_DATA, true )
+    add_string( SOUT_PREFIX_AUDIO "data", "0", NULL, T_AUDIO_DATA, LT_VIDEO_DATA, true )
+    add_bool( SOUT_CFG_PREFIX "time-sync", true, NULL, T_TIME_SYNC, LT_TIME_SYNC, true );
+    set_callbacks( Open, Close )
+vlc_module_end ()
+
+
+/*****************************************************************************
+ * Exported prototypes
+ *****************************************************************************/
+static const char *const ppsz_sout_options[] = {
+    "video-prerender-callback", "audio-prerender-callback",
+    "video-postrender-callback", "audio-postrender-callback", "video-data", "audio-data", "time-sync", NULL
+};
+
+static sout_stream_id_t *Add ( sout_stream_t *, es_format_t * );
+static int               Del ( sout_stream_t *, sout_stream_id_t * );
+static int               Send( sout_stream_t *, sout_stream_id_t *, block_t* );
+
+static sout_stream_id_t *AddVideo( sout_stream_t *p_stream, es_format_t *p_fmt );
+static sout_stream_id_t *AddAudio( sout_stream_t *p_stream, es_format_t *p_fmt );
+
+static int SendVideo( sout_stream_t *p_stream, sout_stream_id_t *id,
+                      block_t *p_buffer );
+static int SendAudio( sout_stream_t *p_stream, sout_stream_id_t *id,
+                      block_t *p_buffer );
+
+struct sout_stream_id_t
+{
+    es_format_t* format;
+};
+
+struct sout_stream_sys_t
+{
+    vlc_mutex_t *p_lock;
+    void ( *pf_video_prerender_callback ) ( void* p_video_data , uint8_t** pp_pixel_buffer , int size );
+    void ( *pf_audio_prerender_callback ) ( void* p_audio_data , uint8_t** pp_pcm_buffer , unsigned int );
+    void ( *pf_video_postrender_callback ) ( void* p_video_data, uint8_t* p_pixel_buffer, int width, int height, int pixel_pitch, int size, int pts );
+    void ( *pf_audio_postrender_callback ) ( void*, unsigned int, unsigned int, unsigned int, unsigned int );
+    void *p_audio_data;
+    void *p_video_data;
+    bool time_sync;
+};
+
+/*****************************************************************************
+ * Open:
+ *****************************************************************************/
+static int Open( vlc_object_t *p_this )
+{
+    char* psz_tmp;
+    sout_stream_t *p_stream = (sout_stream_t*)p_this;
+    sout_stream_sys_t *p_sys;
+
+    p_sys = calloc( 1, sizeof( sout_stream_sys_t ) );
+    if( !p_sys )
+        return VLC_ENOMEM;
+    p_stream->p_sys = p_sys;
+
+    p_sys->time_sync = var_CreateGetBool( p_stream, SOUT_CFG_PREFIX "time-sync" );
+
+    psz_tmp = var_CreateGetString( p_stream, SOUT_PREFIX_VIDEO "prerender-callback" );
+    p_sys->pf_video_prerender_callback = (void (*) (void *, uint8_t**, int))(intptr_t)atoll( psz_tmp );
+    free( psz_tmp );
+
+    psz_tmp = var_CreateGetString( p_stream, SOUT_PREFIX_AUDIO "prerender-callback" );
+    p_sys->pf_audio_prerender_callback = (void (*) (void* , uint8_t**, unsigned int))(intptr_t)atoll( psz_tmp );
+    free( psz_tmp );
+
+    psz_tmp = var_CreateGetString( p_stream, SOUT_PREFIX_VIDEO "postrender-callback" );
+    p_sys->pf_video_postrender_callback = (void (*) (void*, uint8_t*, int, int, int, int, int))(intptr_t)atoll( psz_tmp );
+    free( psz_tmp );
+
+    psz_tmp = var_CreateGetString( p_stream, SOUT_PREFIX_AUDIO "postrender-callback" );
+    p_sys->pf_audio_postrender_callback = (void (*) (void*, unsigned int, unsigned int, unsigned int, unsigned int))(intptr_t)atoll( psz_tmp );
+    free( psz_tmp );
+
+    psz_tmp = var_CreateGetString( p_stream, SOUT_PREFIX_VIDEO "data" );
+    p_sys->p_video_data = (void *)( intptr_t )atoll( psz_tmp );
+    free( psz_tmp );
+
+    psz_tmp = var_CreateGetString( p_stream, SOUT_PREFIX_AUDIO "data" );
+    p_sys->p_audio_data = (void *)( intptr_t )atoll( psz_tmp );
+    free( psz_tmp );
+
+    /* Setting stream out module callbacks */
+    p_stream->pf_add    = Add;
+    p_stream->pf_del    = Del;
+    p_stream->pf_send   = Send;
+
+    /* Does the module need out_pace_control? */
+    if ( p_sys->time_sync )
+        p_stream->p_sout->i_out_pace_nocontrol++;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close:
+ *****************************************************************************/
+static void Close( vlc_object_t * p_this )
+{
+    sout_stream_t *p_stream = (sout_stream_t*)p_this;
+    if ( p_stream->p_sys->time_sync )
+        p_stream->p_sout->i_out_pace_nocontrol--;
+    free( p_stream->p_sys );
+}
+
+static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt )
+{
+    sout_stream_id_t *id = NULL;
+
+    if ( p_fmt->i_cat == VIDEO_ES )
+        id = AddVideo( p_stream, p_fmt );
+    else if ( p_fmt->i_cat == AUDIO_ES )
+        id = AddAudio( p_stream, p_fmt );
+    return id;
+}
+
+static sout_stream_id_t *AddVideo( sout_stream_t *p_stream, es_format_t *p_fmt )
+{
+    sout_stream_id_t    *id;
+    int i_bits_per_pixel;
+
+    switch( p_fmt->i_codec )
+    {
+        case VLC_CODEC_RGB32:
+            i_bits_per_pixel = 32;
+            break;
+        case VLC_CODEC_I444:
+        case VLC_CODEC_RGB24:
+            i_bits_per_pixel = 24;
+            break;
+        case VLC_CODEC_RGB16:
+        case VLC_CODEC_RGB15:
+        case VLC_CODEC_RGB8:
+        case VLC_CODEC_I422:
+            i_bits_per_pixel = 16;
+            break;
+        case VLC_CODEC_YV12:
+        case VLC_CODEC_I420:
+            i_bits_per_pixel = 12;
+            break;
+        case VLC_CODEC_RGBP:
+            i_bits_per_pixel = 8;
+            break;
+        default:
+            msg_Err( p_stream, "Smem does only support raw video format" );
+            return NULL;
+    }
+
+    id = calloc( 1, sizeof( sout_stream_id_t ) );
+    if( !id )
+        return NULL;
+
+    id->format = p_fmt;
+    id->format->video.i_bits_per_pixel = i_bits_per_pixel;
+    return id;
+}
+
+static sout_stream_id_t *AddAudio( sout_stream_t *p_stream, es_format_t *p_fmt )
+{
+    VLC_UNUSED( p_stream );
+    VLC_UNUSED( p_fmt );
+    return NULL;
+}
+
+static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
+{
+    VLC_UNUSED( p_stream );
+    if ( id != NULL )
+        free( id );
+    return VLC_SUCCESS;
+}
+
+static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
+                 block_t *p_buffer )
+{
+    if ( id->format->i_cat == VIDEO_ES )
+        return SendVideo( p_stream, id, p_buffer );
+    else if ( id->format->i_cat == AUDIO_ES )
+        return SendAudio( p_stream, id, p_buffer );
+    return VLC_SUCCESS;
+}
+
+static int SendVideo( sout_stream_t *p_stream, sout_stream_id_t *id,
+                      block_t *p_buffer )
+{
+    sout_stream_sys_t *p_sys = p_stream->p_sys;
+    int i_line, i_line_size, i_size, i_pixel_pitch;
+    uint8_t* p_pixels;
+
+    i_line = id->format->video.i_height;
+    i_pixel_pitch = id->format->video.i_bits_per_pixel / 8;
+    i_line_size = i_pixel_pitch * id->format->video.i_width;
+    i_size = i_line * i_line_size;
+    /* Calling the prerender callback to get user buffer */
+    p_sys->pf_video_prerender_callback( p_sys->p_video_data, &p_pixels , i_size );
+    /* Copying data into user buffer */
+    for ( int line = 0; line < i_line; line++, p_pixels += i_line_size )
+        vlc_memcpy( p_pixels, p_buffer->p_buffer + i_line_size * line , i_line_size );
+    /* Calling the postrender callback to tell the user his buffer is ready */
+    p_sys->pf_video_postrender_callback( p_sys->p_video_data, p_pixels,
+                                         id->format->video.i_width, id->format->video.i_height,
+                                         id->format->video.i_bits_per_pixel, i_size, p_buffer->i_pts );
+    return VLC_SUCCESS;
+}
+
+static int SendAudio( sout_stream_t *p_stream, sout_stream_id_t *id,
+                      block_t *p_buffer )
+{
+    VLC_UNUSED( p_stream );
+    VLC_UNUSED( id );
+    VLC_UNUSED( p_buffer );
+    return VLC_SUCCESS;
+}