Commit f8bf106d authored by Laurent Aimar's avatar Laurent Aimar

Added stream output. (common work with titer).

parent 3f126864
......@@ -135,6 +135,7 @@ case "x${target_os}" in
LDFLAGS_access_mms="${LDFLAGS_access_mms} -lws2_32"
LDFLAGS_access_rtp="${LDFLAGS_access_rtp} -lws2_32"
LDFLAGS_access_udp="${LDFLAGS_access_udp} -lws2_32"
LDFLAGS_access_output_udp="${LDFLAGS_access_output_udp} -lws2_32"
LDFLAGS_rc="${LDFLAGS_rc} -lws2_32"
LDFLAGS_sap="${LDFLAGS_sap} -lws2_32"
fi
......@@ -273,6 +274,7 @@ AC_CHECK_FUNC(send,,[
LDFLAGS_access_rtp="${LDFLAGS_access_rtp} -lsocket"
LDFLAGS_access_udp="${LDFLAGS_access_udp} -lsocket"
LDFLAGS_sap="${LDFLAGS_sap} -lsocket"
LDFLAGS_access_output_udp="${LDFLAGS_access_output_udp} -lsocket"
)])
AC_CHECK_FUNC(gethostbyname,,[
......@@ -865,6 +867,20 @@ AC_ARG_ENABLE(release,
[ --enable-release activate extra optimizations (default disabled)])
AM_CONDITIONAL(RELEASE, test "x${enable_release}" = "xyes")
dnl
dnl Stream output
dnl
AC_ARG_ENABLE(sout,
[ --enable-sout Stream output modules (default enabled)])
if test "x${enable_sout}" != "xno"
then
PLUGINS="${PLUGINS} access_output_dummy access_output_udp access_output_file"
PLUGINS="${PLUGINS} mux_ts mux_ps mux_dummy"
PLUGINS="${PLUGINS} packetizer_mpegaudio packetizer_mpegvideo packetizer_a52"
PLUGINS="${PLUGINS} packetizer_mpeg4video packetizer_copy"
fi
dnl
dnl Input plugins
dnl
......
......@@ -2,15 +2,17 @@
* stream_output.h : stream output module
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: stream_output.h,v 1.1 2002/08/12 22:12:50 massiot Exp $
* $Id: stream_output.h,v 1.2 2002/12/14 21:32:41 fenrir Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
*
* 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
......@@ -24,6 +26,59 @@
/*****************************************************************************
* sout_instance_t: stream output thread descriptor
*****************************************************************************/
struct sout_buffer_t
{
size_t i_allocated_size;
byte_t *p_buffer;
size_t i_size;
// mtime_t i_date;
mtime_t i_length;
mtime_t i_dts;
mtime_t i_pts;
int i_bitrate;
struct sout_buffer_t *p_next;
};
struct sout_packet_format_t
{
int i_cat; // AUDIO_ES, VIDEO_ES, SPU_ES
vlc_fourcc_t i_fourcc;
void *p_format; // WAVEFORMATEX or BITMAPINFOHEADER
};
struct sout_fifo_t
{
vlc_mutex_t lock; /* fifo data lock */
vlc_cond_t wait; /* fifo data conditional variable */
int i_depth;
sout_buffer_t *p_first;
sout_buffer_t **pp_last;
};
struct sout_input_t
{
vlc_mutex_t lock;
sout_instance_t *p_sout;
sout_packet_format_t input_format;
sout_fifo_t *p_fifo;
void *p_mux_data;
};
#define SOUT_METHOD_NONE 0x00
#define SOUT_METHOD_FILE 0x10
#define SOUT_METHOD_NETWORK 0x20
struct sout_instance_t
{
VLC_COMMON_MEMBERS
......@@ -33,10 +88,30 @@ struct sout_instance_t
char * psz_mux;
char * psz_name;
module_t * p_access;
module_t * p_mux;
module_t *p_access;
int i_method;
void *p_access_data;
int (* pf_write )( sout_instance_t *, sout_buffer_t * );
int (* pf_seek )( sout_instance_t *, off_t );
module_t *p_mux;
void *p_mux_data;
int (* pf_mux_addstream )( sout_instance_t *,
sout_input_t * );
int (* pf_mux_delstream )( sout_instance_t *,
sout_input_t * );
int (* pf_mux ) ( sout_instance_t * );
vlc_mutex_t lock;
int i_nb_inputs;
sout_input_t **pp_inputs;
};
/*****************************************************************************
* Prototypes
*****************************************************************************/
......@@ -44,7 +119,21 @@ struct sout_instance_t
VLC_EXPORT( sout_instance_t *, __sout_NewInstance, ( vlc_object_t *, char * ) );
VLC_EXPORT( void, sout_DeleteInstance, ( sout_instance_t * ) );
sout_fifo_t * sout_CreateFifo ( void );
void sout_DestroyFifo ( sout_fifo_t * );
void sout_FreeFifo ( sout_fifo_t * );
VLC_EXPORT( sout_fifo_t *, sout_FifoCreate, ( sout_instance_t * ) );
VLC_EXPORT( void, sout_FifoDestroy, ( sout_instance_t *, sout_fifo_t * ) );
VLC_EXPORT( void, sout_FifoFree, ( sout_instance_t *,sout_fifo_t * ) );
VLC_EXPORT( void, sout_FifoPut, ( sout_fifo_t *, sout_buffer_t* ) );
VLC_EXPORT( sout_buffer_t *, sout_FifoGet, ( sout_fifo_t * ) );
VLC_EXPORT( sout_buffer_t *, sout_FifoShow, ( sout_fifo_t * ) );
#define sout_InputNew( a, b ) __sout_InputNew( VLC_OBJECT(a), b )
VLC_EXPORT( sout_input_t *, __sout_InputNew, ( vlc_object_t *, sout_packet_format_t * ) );
VLC_EXPORT( int, sout_InputDelete, ( sout_input_t * ) );
VLC_EXPORT( int, sout_InputSendBuffer, ( sout_input_t *, sout_buffer_t* ) );
VLC_EXPORT( sout_buffer_t*, sout_BufferNew, ( sout_instance_t *, size_t ) );
VLC_EXPORT( int, sout_BufferRealloc,( sout_instance_t *, sout_buffer_t*, size_t ) );
VLC_EXPORT( int, sout_BufferDelete, ( sout_instance_t *, sout_buffer_t* ) );
VLC_EXPORT( sout_buffer_t*, sout_BufferDuplicate,(sout_instance_t *, sout_buffer_t * ) );
......@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vlc_common.h,v 1.43 2002/12/13 01:56:29 gbazin Exp $
* $Id: vlc_common.h,v 1.44 2002/12/14 21:32:41 fenrir Exp $
*
* Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr>
......@@ -241,6 +241,9 @@ typedef struct subpicture_sys_t subpicture_sys_t;
/* Stream output */
typedef struct sout_instance_t sout_instance_t;
typedef struct sout_fifo_t sout_fifo_t;
typedef struct sout_input_t sout_input_t;
typedef struct sout_buffer_t sout_buffer_t;
typedef struct sout_packet_format_t sout_packet_format_t;
/* Decoders */
typedef struct decoder_fifo_t decoder_fifo_t;
......
......@@ -8,6 +8,7 @@ EXTRA_DIST = \
access/satellite/Modules.am \
access/v4l/Modules.am \
access/vcd/Modules.am \
access_output/Modules.am \
audio_filter/channel_mixer/Modules.am \
audio_filter/converter/Modules.am \
audio_filter/resampler/Modules.am \
......@@ -53,6 +54,9 @@ EXTRA_DIST = \
misc/memcpy/Modules.am \
misc/network/Modules.am \
misc/testsuite/Modules.am \
mux/Modules.am \
mux/mpeg/Modules.am \
packetizer/Modules.am \
video_chroma/Modules.am \
video_filter/Modules.am \
video_filter/deinterlace/Modules.am \
......
SOURCES_access_output_dummy = modules/access_output/dummy.c
SOURCES_access_output_file = modules/access_output/file.c
SOURCES_access_output_udp = modules/access_output/udp.c
/*****************************************************************************
* dummy.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: dummy.c,v 1.1 2002/12/14 21:32:41 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <vlc/vlc.h>
#include <vlc/input.h>
#include <vlc/sout.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#elif defined( _MSC_VER ) && defined( _WIN32 ) && !defined( UNDER_CE )
# include <io.h>
#endif
/*****************************************************************************
* Exported prototypes
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static int Write( sout_instance_t *, sout_buffer_t * );
static int Seek( sout_instance_t *, off_t );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("Dummy stream ouput") );
set_capability( "sout access", 0 );
add_shortcut( "dummy" );
set_callbacks( Open, Close );
vlc_module_end();
/*****************************************************************************
* Open: open the file
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
p_sout->i_method = SOUT_METHOD_NONE;
p_sout->p_access_data = NULL;
p_sout->pf_write = Write;
p_sout->pf_seek = Seek;
msg_Info( p_sout, "dummy stream output access launched" );
return VLC_SUCCESS;
}
/*****************************************************************************
* Close: close the target
*****************************************************************************/
static void Close( vlc_object_t * p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
msg_Info( p_sout, "Close" );
}
/*****************************************************************************
* Read: standard read on a file descriptor.
*****************************************************************************/
static int Write( sout_instance_t *p_sout, sout_buffer_t *p_buffer )
{
size_t i_write = 0;
do
{
sout_buffer_t *p_next;
i_write += p_buffer->i_size;
p_next = p_buffer->p_next;
sout_BufferDelete( p_sout, p_buffer );
p_buffer = p_next;
} while( p_buffer );
msg_Dbg( p_sout, "Dummy Skipped: len:%d", (uint32_t)i_write );
return( i_write );
}
/*****************************************************************************
* Seek: seek to a specific location in a file
*****************************************************************************/
static int Seek( sout_instance_t *p_sout, off_t i_pos )
{
msg_Dbg( p_sout, "Seek: pos:%lld", (int64_t)i_pos );
return( 0 );
}
/*****************************************************************************
* file.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: file.c,v 1.1 2002/12/14 21:32:41 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <vlc/vlc.h>
#include <vlc/input.h>
#include <vlc/sout.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#elif defined( _MSC_VER ) && defined( _WIN32 ) && !defined( UNDER_CE )
# include <io.h>
#endif
/*****************************************************************************
* Exported prototypes
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static int Write( sout_instance_t *, sout_buffer_t * );
static int Seek( sout_instance_t *, off_t );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("File stream ouput") );
set_capability( "sout access", 50 );
add_shortcut( "file" );
set_callbacks( Open, Close );
vlc_module_end();
typedef struct sout_access_data_s
{
FILE *p_file;
} sout_access_data_t;
/*****************************************************************************
* Open: open the file
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_access_data_t *p_access;
char * psz_name = p_sout->psz_name;
p_access = malloc( sizeof( sout_access_data_t ) );
if( !( p_access->p_file = fopen( psz_name, "wb" ) ) )
{
msg_Err( p_sout, "cannot open `%s'", psz_name );
free( p_access );
return( -1 );
}
p_sout->i_method = SOUT_METHOD_FILE;
p_sout->p_access_data = p_access;
p_sout->pf_write = Write;
p_sout->pf_seek = Seek;
msg_Info( p_sout, "Open: name:`%s'", psz_name );
return VLC_SUCCESS;
}
/*****************************************************************************
* Close: close the target
*****************************************************************************/
static void Close( vlc_object_t * p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_access_data_t *p_access = (sout_access_data_t*)p_sout->p_access_data;
if( p_access->p_file )
{
fclose( p_access->p_file );
}
msg_Info( p_sout, "Close" );
}
/*****************************************************************************
* Read: standard read on a file descriptor.
*****************************************************************************/
static int Write( sout_instance_t *p_sout, sout_buffer_t *p_buffer )
{
sout_access_data_t *p_access = (sout_access_data_t*)p_sout->p_access_data;
size_t i_write = 0;
do
{
sout_buffer_t *p_next;
i_write += fwrite( p_buffer->p_buffer, 1, p_buffer->i_size,
p_access->p_file );
p_next = p_buffer->p_next;
sout_BufferDelete( p_sout, p_buffer );
p_buffer = p_next;
} while( p_buffer );
msg_Dbg( p_sout, "Write: len:%d", (uint32_t)i_write );
return( i_write );
}
/*****************************************************************************
* Seek: seek to a specific location in a file
*****************************************************************************/
static int Seek( sout_instance_t *p_sout, off_t i_pos )
{
sout_access_data_t *p_access = (sout_access_data_t*)p_sout->p_access_data;
msg_Dbg( p_sout, "Seek: pos:%lld", (int64_t)i_pos );
return( fseek( p_access->p_file, i_pos, SEEK_SET ) );
}
/*****************************************************************************
* udp.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: udp.c,v 1.1 2002/12/14 21:32:41 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <vlc/vlc.h>
#include <vlc/input.h>
#include <vlc/sout.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#elif defined( _MSC_VER ) && defined( _WIN32 ) && !defined( UNDER_CE )
# include <io.h>
#endif
#ifdef WIN32
# include <winsock2.h>
# include <ws2tcpip.h>
# ifndef IN_MULTICAST
# define IN_MULTICAST(a) IN_CLASSD(a)
# endif
#else
# include <sys/socket.h>
#endif
#include "network.h"
#define DEFAULT_PORT 1234
#define LATENCY 100000
#define MAX_ERROR 500000
/*****************************************************************************
* Exported prototypes
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static int Write( sout_instance_t *, sout_buffer_t * );
static int Seek( sout_instance_t *, off_t );
static void ThreadWrite( vlc_object_t *p_this );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("UDP stream ouput") );
set_capability( "sout access", 100 );
add_shortcut( "udp" );
add_shortcut( "rtp" ); // Will work only with ts muxer
set_callbacks( Open, Close );
vlc_module_end();
typedef struct sout_access_thread_s
{
VLC_COMMON_MEMBERS
sout_instance_t *p_sout;
sout_fifo_t *p_fifo;
int i_handle;
} sout_access_thread_t;
typedef struct sout_access_data_s
{
int b_rtpts; // 1 if add rtp/ts header
uint16_t i_sequence_number;
uint32_t i_ssrc;
int i_mtu;
sout_buffer_t *p_buffer;
sout_access_thread_t *p_thread;
} sout_access_data_t;
/*****************************************************************************
* Open: open the file
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_access_data_t *p_access;
char *psz_parser;
char *psz_dst_addr;
int i_dst_port;
module_t *p_network;
network_socket_t socket_desc;
if( !( p_access = malloc( sizeof( sout_access_data_t ) ) ) )
{
msg_Err( p_sout, "Not enough memory" );
return( -1 );
}
if( p_sout->psz_access != NULL &&
!strcmp( p_sout->psz_access, "rtp" ) )
{
if( p_sout->psz_mux != NULL &&
strcmp( p_sout->psz_mux, "ts" ) )
{
msg_Err( p_sout, "rtp ouput work only with ts payload" );
free( p_access );
return( -1 );
}
p_access->b_rtpts = 1;
}
else
{
p_access->b_rtpts = 0;
}
psz_parser = strdup( p_sout->psz_name );
psz_dst_addr = psz_parser;
i_dst_port = 0;
while( *psz_parser && *psz_parser != ':' )
{
psz_parser++;
}
if( *psz_parser == ':' )
{
*psz_parser = '\0';
psz_parser++;
i_dst_port = atoi( psz_parser );
}
if( i_dst_port <= 0 )
{
i_dst_port = DEFAULT_PORT;
}
p_access->p_thread = vlc_object_create( p_sout,
sizeof( sout_access_thread_t ) );
if( !p_access->p_thread )
{
msg_Err( p_sout, "out of memory" );
return( -1 );
}
p_access->p_thread->p_sout = p_sout;
p_access->p_thread->b_die = 0;
p_access->p_thread->b_error= 0;
p_access->p_thread->p_fifo = sout_FifoCreate( p_sout );
socket_desc.i_type = NETWORK_UDP;
socket_desc.psz_server_addr = psz_dst_addr;
socket_desc.i_server_port = i_dst_port;
socket_desc.psz_bind_addr = "";
socket_desc.i_bind_port = 0;
p_access->p_thread->p_private = (void*)&socket_desc;
if( !( p_network = module_Need( p_access->p_thread,
"network", "" ) ) )
{
msg_Err( p_sout, "failed to open a connection (udp)" );
return( -1 );
}
module_Unneed( p_access->p_thread, p_network );
p_access->p_thread->i_handle = socket_desc.i_handle;
p_access->i_mtu = socket_desc.i_mtu;
if( vlc_thread_create( p_access->p_thread, "sout write thread",
ThreadWrite, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
{
msg_Err( p_sout, "cannot spawn sout access thread" );
vlc_object_destroy( p_access->p_thread );
return( -1 );
}
p_access->p_buffer = NULL;
p_access->i_sequence_number = 12; // FIXME should be random, used by rtp
p_access->i_ssrc = 4212; // FIXME " " " " " "
p_sout->i_method = SOUT_METHOD_NETWORK;
p_sout->p_access_data = (void*)p_access;
p_sout->pf_write = Write;
p_sout->pf_seek = Seek;
msg_Info( p_sout,
"Open: addr:`%s' port:`%d'",
psz_dst_addr, i_dst_port );
free( psz_dst_addr );
return VLC_SUCCESS;
}
/*****************************************************************************
* Close: close the target
*****************************************************************************/
static void Close( vlc_object_t * p_this )
{
sout_instance_t *p_sout = (sout_instance_t*)p_this;
sout_access_data_t *p_access = (sout_access_data_t*)p_sout->p_access_data;
int i;
p_access->p_thread->b_die = 1;
for( i = 0; i < 10; i++ )
{
sout_buffer_t *p_dummy;
p_dummy = sout_BufferNew( p_sout, p_access->i_mtu );
p_dummy->i_dts = 0;
p_dummy->i_pts = 0;
p_dummy->i_length = 0;
sout_FifoPut( p_access->p_thread->p_fifo, p_dummy );
}
vlc_thread_join( p_access->p_thread );
sout_FifoDestroy( p_sout, p_access->p_thread->p_fifo );
if( p_access->p_buffer )
{
sout_BufferDelete( p_sout, p_access->p_buffer );
}
#if defined( UNDER_CE )
CloseHandle( (HANDLE)p_access->p_thread->i_handle );
#elif defined( WIN32 )