Commit 8c1b6050 authored by Laurent Aimar's avatar Laurent Aimar

* v4l: updated, now it should grab (and compress if you want) the video.

Audio grabbing part is commented out and untested.
 The syntax is like that:
  v4l:<device>[:option=value:...]
 options: channel,norm (pal, ntsc,secam), frequency (not really there is
          a factor), audio, size (WxH or subqcif,qsif,qcif,sif,cif,vga),
          codec (optional, mpeg1 or mpeg4 and need to have compiled the
          encoders modules)
 ex: v4l:/dev/video:channel=0:frequency=8052:norm=secam:size=vga
 Please test.
 * rawvideo.c: a pseudo decoder for raw video (I420).
 * packetizer/*, mux/*, stream_output.c: fixed (I hope) audio/video
synchro problems.
parent f3dd07bb
...@@ -819,6 +819,7 @@ PLUGINS="${PLUGINS} aout_file" ...@@ -819,6 +819,7 @@ PLUGINS="${PLUGINS} aout_file"
#PLUGINS="${PLUGINS} scope" #PLUGINS="${PLUGINS} scope"
PLUGINS="${PLUGINS} i420_rgb i420_yuy2 i422_yuy2 i420_ymga" PLUGINS="${PLUGINS} i420_rgb i420_yuy2 i422_yuy2 i420_ymga"
PLUGINS="${PLUGINS} id3 m3u" PLUGINS="${PLUGINS} id3 m3u"
PLUGINS="${PLUGINS} rawvideo"
PLUGINS="${PLUGINS} wav araw demuxdump demuxsub adpcm a52sys au" PLUGINS="${PLUGINS} wav araw demuxdump demuxsub adpcm a52sys au"
PLUGINS="${PLUGINS} access_file access_udp access_http ipv4 access_mms" PLUGINS="${PLUGINS} access_file access_udp access_http ipv4 access_mms"
PLUGINS="${PLUGINS} access_ftp access_directory sap httpd" PLUGINS="${PLUGINS} access_ftp access_directory sap httpd"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* v4l.c : Video4Linux input module for vlc * v4l.c : Video4Linux input module for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: v4l.c,v 1.4 2003/03/30 18:14:36 gbazin Exp $ * $Id: v4l.c,v 1.5 2003/03/31 03:46:11 fenrir Exp $
* *
* Author: Samuel Hocevar <sam@zoy.org> * Author: Samuel Hocevar <sam@zoy.org>
* *
...@@ -24,43 +24,745 @@ ...@@ -24,43 +24,745 @@
/***************************************************************************** /*****************************************************************************
* Preamble * Preamble
*****************************************************************************/ *****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/input.h> #include <vlc/input.h>
#include <vlc/vout.h>
#include <codecs.h>
#include "encoder.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/videodev.h>
/* enable audio grabbing */
#undef _V4L_AUDIO_
#ifdef _V4L_AUDIO_
#include <sys/soundcard.h>
#endif
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
static int V4lOpen ( vlc_object_t * ); static int AccessOpen ( vlc_object_t * );
static void V4lClose ( vlc_object_t * ); static void AccessClose ( vlc_object_t * );
static int V4lRead ( input_thread_t *, byte_t *, size_t ); static int Read ( input_thread_t *, byte_t *, size_t );
static int DemuxOpen ( vlc_object_t * );
static void DemuxClose ( vlc_object_t * );
static int Demux ( input_thread_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptior * Module descriptior
*****************************************************************************/ *****************************************************************************/
#define CACHING_TEXT N_("caching value in ms")
#define CACHING_LONGTEXT N_( \
"Allows you to modify the default caching value for v4l streams. This " \
"value should be set in miliseconds units." )
vlc_module_begin(); vlc_module_begin();
set_description( _("Video4Linux input") ); set_description( _("Video4Linux input") );
set_capability( "access", 80 ); add_category_hint( N_("v4l"), NULL, VLC_TRUE );
set_callbacks( V4lOpen, V4lClose ); add_integer( "v4l-caching", DEFAULT_PTS_DELAY / 1000, NULL,
CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
add_submodule();
add_shortcut( "v4l" );
set_capability( "access", 0 );
set_callbacks( AccessOpen, AccessClose );
add_submodule();
add_shortcut( "v4l" );
set_capability( "demux", 200 );
set_callbacks( DemuxOpen, DemuxClose );
vlc_module_end(); vlc_module_end();
static int i_fd;
/****************************************************************************
* I. Access Part
****************************************************************************/
struct access_sys_t
{
char *psz_video_device;
int fd;
vlc_fourcc_t i_codec; // if i_codec != i_chroma then we need a compressor
video_encoder_t *p_encoder;
picture_t pic;
int i_channel;
int i_audio;
int i_norm;
int i_tuner;
int i_frequency;
int i_chroma;
int i_width;
int i_height;
struct video_capability vid_cap;
struct video_mbuf vid_mbuf;
uint8_t *p_video_mmap;
int i_frame_pos;
struct video_mmap vid_mmap;
uint8_t *p_video_frame;
int i_video_frame_size;
int i_video_frame_size_allocated;
#ifdef _V4L_AUDIO_
char *psz_adev;
int fd_audio;
vlc_fourcc_t i_acodec_raw;
int i_sample_rate;
vlc_bool_t b_stereo;
uint8_t *p_audio_frame;
int i_audio_frame_size;
int i_audio_frame_size_allocated;
#endif
/* header */
int i_header_size;
int i_header_pos;
uint8_t *p_header; // at lest 8 bytes allocated
/* data */
int i_data_size;
int i_data_pos;
uint8_t *p_data; // never allocated
};
/*
* header:
* fcc ".v4l"
* u32 stream count
* fcc "auds"|"vids" 0
* fcc codec 4
* if vids
* u32 width 8
* u32 height 12
* u32 padding 16
* if auds
* u32 channels 12
* u32 samplerate 8
* u32 samplesize 16
*
* data:
* u32 stream number
* u32 data size
* u8 data
*/
static void SetDWBE( uint8_t *p, uint32_t dw )
{
p[0] = (dw >> 24)&0xff;
p[1] = (dw >> 16)&0xff;
p[2] = (dw >> 8)&0xff;
p[3] = (dw )&0xff;
}
static uint32_t GetDWBE( uint8_t *p_buff )
{
return( ( p_buff[0] << 24 ) + ( p_buff[1] << 16 ) +
( p_buff[2] << 8 ) + p_buff[3] );
}
/***************************************************************************** /*****************************************************************************
* V4lOpen: open device * Open: open device:
*****************************************************************************
*
* url: <video device>::::
*
*****************************************************************************/ *****************************************************************************/
static int V4lOpen( vlc_object_t *p_this ) static int AccessOpen( vlc_object_t *p_this )
{ {
input_thread_t * p_input = (input_thread_t *)p_this; input_thread_t *p_input = (input_thread_t *)p_this;
access_sys_t *p_sys;
char *psz_dup, *psz_parser;
struct video_channel vid_channel;
/* create access private data */
p_sys = malloc( sizeof( access_sys_t ) );
memset( p_sys, 0, sizeof( access_sys_t ) );
p_sys->psz_video_device = NULL;
p_sys->fd = -1;
p_sys->i_channel = -1;
p_sys->i_audio = -1;
p_sys->i_norm = VIDEO_MODE_AUTO; // auto
p_sys->i_tuner = -1;
p_sys->i_frequency = -1;
p_sys->i_width = 0;
p_sys->i_height = 0;
p_sys->i_frame_pos = 0;
p_sys->i_codec = VLC_FOURCC( 0, 0, 0, 0 );
p_sys->i_video_frame_size_allocated = 0;
#ifdef _V4L_AUDIO_
p_sys->psz_adev = NULL;
p_sys->fd_audio = -1;
p_sys->i_sample_rate = 44100;
p_sys->b_stereo = VLC_TRUE;
#endif
p_sys->i_data_size = 0;
p_sys->i_data_pos = 0;
p_sys->p_data = NULL;
/* parse url and open device(s) */
psz_dup = strdup( p_input->psz_name );
psz_parser = psz_dup;
while( *psz_parser && *psz_parser != ':' )
{
psz_parser++;
}
if( *psz_parser == ':' )
{
/* read options */
for( ;; )
{
*psz_parser++ = '\0';
if( !strncmp( psz_parser, "channel=", strlen( "channel=" ) ) )
{
p_sys->i_channel =
strtol( psz_parser + strlen( "channel=" ), &psz_parser, 0 );
}
else if( !strncmp( psz_parser, "norm=", strlen( "norm=" ) ) )
{
psz_parser += strlen( "norm=" );
if( !strncmp( psz_parser, "pal", strlen( "pal" ) ) )
{
p_sys->i_norm = VIDEO_MODE_PAL;
psz_parser += strlen( "pal" );
}
else if( !strncmp( psz_parser, "ntsc", strlen( "ntsc" ) ) )
{
p_sys->i_norm = VIDEO_MODE_NTSC;
psz_parser += strlen( "ntsc" );
}
else if( !strncmp( psz_parser, "secam", strlen( "secam" ) ) )
{
p_sys->i_norm = VIDEO_MODE_SECAM;
psz_parser += strlen( "secam" );
}
else if( !strncmp( psz_parser, "auto", strlen( "auto" ) ) )
{
p_sys->i_norm = VIDEO_MODE_AUTO;
psz_parser += strlen( "auto" );
}
else
{
p_sys->i_norm = strtol( psz_parser, &psz_parser, 0 );
}
}
else if( !strncmp( psz_parser, "frequency=", strlen( "frequency=" ) ) )
{
p_sys->i_frequency =
strtol( psz_parser + strlen( "frequency=" ), &psz_parser, 0 );
}
else if( !strncmp( psz_parser, "audio=", strlen( "audio=" ) ) )
{
p_sys->i_audio = strtol( psz_parser + strlen( "audio=" ), &psz_parser, 0 );
}
else if( !strncmp( psz_parser, "size=", strlen( "size=" ) ) )
{
psz_parser += strlen( "size=" );
if( !strncmp( psz_parser, "subqcif", strlen( "subqcif" ) ) )
{
p_sys->i_width = 128;
p_sys->i_height = 96;
}
else if( !strncmp( psz_parser, "qsif", strlen( "qsif" ) ) )
{
p_sys->i_width = 160;
p_sys->i_height = 120;
}
else if( !strncmp( psz_parser, "qcif", strlen( "qcif" ) ) )
{
p_sys->i_width = 176;
p_sys->i_height = 144;
}
else if( !strncmp( psz_parser, "sif", strlen( "sif" ) ) )
{
p_sys->i_width = 320;
p_sys->i_height = 244;
}
else if( !strncmp( psz_parser, "cif", strlen( "cif" ) ) )
{
p_sys->i_width = 352;
p_sys->i_height = 288;
}
else if( !strncmp( psz_parser, "vga", strlen( "vga" ) ) )
{
p_sys->i_width = 640;
p_sys->i_height = 480;
}
else
{
/* widthxheight */
p_sys->i_width = strtol( psz_parser, &psz_parser, 0 );
if( *psz_parser == 'x' || *psz_parser == 'X')
{
p_sys->i_height = strtol( psz_parser + 1, &psz_parser, 0 );
}
msg_Dbg( p_input, "WxH %dx%d", p_sys->i_width, p_sys->i_height );
}
}
else if( !strncmp( psz_parser, "tuner=", strlen( "tuner=" ) ) )
{
p_sys->i_tuner = strtol( psz_parser + strlen( "tuner=" ), &psz_parser, 0 );
}
else if( !strncmp( psz_parser, "codec=", strlen( "codec=" ) ) )
{
psz_parser += strlen( "codec=" );
if( !strncmp( psz_parser, "mpeg4", strlen( "mpeg4" ) ) )
{
p_sys->i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
}
else if( !strncmp( psz_parser, "mpeg1", strlen( "mpeg1" ) ) )
{
p_sys->i_codec = VLC_FOURCC( 'm', 'p', '1', 'v' );
}
else
{
msg_Warn( p_input, "unknow codec" );
}
}
#ifdef _V4L_AUDIO_
else if( !strncmp( psz_parser, "adev=", strlen( "adev=" ) ) )
{
int i_len;
psz_parser += strlen( "adev=" );
if( strchr( psz_parser, ':' ) )
{
i_len = strchr( psz_parser, ':' ) - psz_parser;
}
else
{
i_len = strlen( psz_parser );
}
p_sys->psz_adev = strndup( psz_parser, i_len );
psz_parser += i_len;
}
else if( !strncmp( psz_parser, "samplerate=", strlen( "samplerate=" ) ) )
{
p_sys->i_sample_rate = strtol( psz_parser + strlen( "samplerate=" ), &psz_parser, 0 );
}
else if( !strncmp( psz_parser, "stereo", strlen( "stereo" ) ) )
{
psz_parser += strlen( "stereo" );
p_sys->b_stereo = VLC_TRUE;
}
else if( !strncmp( psz_parser, "mono", strlen( "mono" ) ) )
{
psz_parser += strlen( "mono" );
p_sys->b_stereo = VLC_FALSE;
}
#endif
else
{
msg_Warn( p_input, "unknow option" );
}
while( *psz_parser && *psz_parser != ':' )
{
psz_parser++;
}
if( *psz_parser == '\0' )
{
break;
}
}
}
if( *psz_dup )
{
p_sys->psz_video_device = strdup( psz_dup );
}
else
{
p_sys->psz_video_device = strdup( "/dev/video" );
}
msg_Dbg( p_input, "video device=`%s'", p_sys->psz_video_device );
#ifdef _V4L_AUDIO_
if( p_sys->psz_adev && *p_sys->psz_adev == '\0' )
{
p_sys->psz_adev = strdup( "/dev/dsp" );
}
msg_Dbg( p_input, "audio device=`%s'", p_sys->psz_adev );
#endif
if( ( p_sys->fd = open( p_sys->psz_video_device, O_RDWR ) ) < 0 )
{
msg_Err( p_input, "cannot open device" );
goto failed;
}
if( ioctl( p_sys->fd, VIDIOCGCAP, &p_sys->vid_cap ) < 0 )
{
msg_Err( p_input, "cannot get capabilities" );
goto failed;
}
msg_Dbg( p_input,
"V4L device %s %d channels %d audios %d < w < %d %d < h < %d",
p_sys->vid_cap.name,
p_sys->vid_cap.channels,
p_sys->vid_cap.audios,
p_sys->vid_cap.minwidth, p_sys->vid_cap.maxwidth,
p_sys->vid_cap.minheight, p_sys->vid_cap.maxheight );
if( p_sys->i_channel < 0 || p_sys->i_channel >= p_sys->vid_cap.channels )
{
msg_Dbg( p_input, "invalid channel, falling back on channel 0" );
p_sys->i_channel = 0;
}
if( p_sys->i_audio >= p_sys->vid_cap.audios )
{
msg_Dbg( p_input, "invalid audio, falling back with no audio" );
p_sys->i_audio = -1;
}
if( p_sys->i_width < p_sys->vid_cap.minwidth ||
p_sys->i_width > p_sys->vid_cap.maxwidth )
{
msg_Dbg( p_input, "invalid width" );
p_sys->i_width = 0;
}
if( p_sys->i_height < p_sys->vid_cap.minheight ||
p_sys->i_height > p_sys->vid_cap.maxheight )
{
msg_Dbg( p_input, "invalid height" );
p_sys->i_height = 0;
}
if( !( p_sys->vid_cap.type&VID_TYPE_CAPTURE ) )
{
msg_Err( p_input, "cannot grab" );
goto failed;
}
vid_channel.channel = p_sys->i_channel;
if( ioctl( p_sys->fd, VIDIOCGCHAN, &vid_channel ) < 0 )
{
msg_Err( p_input, "cannot get channel infos" );
goto failed;
}
msg_Dbg( p_input,
"setting channel %s(%d) %d tuners flags=0x%x type=0x%x norm=0x%x",
vid_channel.name,
vid_channel.channel,
vid_channel.tuners,
vid_channel.flags,
vid_channel.type,
vid_channel.norm );
if( p_sys->i_tuner >= vid_channel.tuners )
{
msg_Dbg( p_input, "invalid tuner, falling back on tuner 0" );
p_sys->i_tuner = 0;
}
vid_channel.norm = p_sys->i_norm;
if( ioctl( p_sys->fd, VIDIOCSCHAN, &vid_channel ) < 0 )
{
msg_Err( p_input, "cannot set channel" );
goto failed;
}
if( vid_channel.flags & VIDEO_VC_TUNER )
{
/* set tuner */
#if 0
struct video_tuner vid_tuner;
if( p_sys->i_tuner >= 0 )
{
vid_tuner.tuner = p_sys->i_tuner;
if( ioctl( p_sys->fd, VIDIOCGTUNER, &vid_tuner ) < 0 )
{
msg_Err( p_input, "cannot get tuner" );
goto failed;
}
msg_Dbg( p_input,
"tuner %s low=%d high=%d, flags=0x%x mode=0x%x signal=0x%x",
vid_tuner.name,
vid_tuner.rangelow, vid_tuner.rangehigh,
vid_tuner.flags,
vid_tuner.mode,
vid_tuner.signal );
msg_Dbg( p_input,
"setting tuner %s (%d)",
vid_tuner.name, vid_tuner.tuner );
//vid_tuner.mode = p_sys->i_norm; /* FIXME FIXME to be checked FIXME FIXME */
if( ioctl( p_sys->fd, VIDIOCSTUNER, &vid_tuner ) < 0 )
{
msg_Err( p_input, "cannot set tuner" );
goto failed;
}
}
#endif
/* set frequency */
if( p_sys->i_frequency >= 0 )
{
if( ioctl( p_sys->fd, VIDIOCSFREQ, &p_sys->i_frequency ) < 0 )
{
msg_Err( p_input, "cannot set frequency" );
goto failed;
}
msg_Dbg( p_input, "frequency %d", p_sys->i_frequency );
}
}
/* set audio */
if( vid_channel.flags & VIDEO_VC_AUDIO )
{
struct video_audio vid_audio;
/* XXX TODO volume, balance, ... */
if( p_sys->i_audio >= 0 )
{
vid_audio.audio = p_sys->i_audio;
if( ioctl( p_sys->fd, VIDIOCGAUDIO, &vid_audio ) < 0 )
{
msg_Err( p_input, "cannot get audio" );
goto failed;
}
/* unmute audio */
vid_audio.flags &= ~VIDEO_AUDIO_MUTE;
if( ioctl( p_sys->fd, VIDIOCSAUDIO, &vid_audio ) < 0 )
{
msg_Err( p_input, "cannot set audio" );
goto failed;
}
#ifdef _V4L_AUDIO_
if( p_sys->psz_adev )
{
int i_format;
if( ( p_sys->fd_audio = open( p_sys->psz_adev, O_RDONLY ) ) < 0 )
{
msg_Err( p_input, "cannot open audio device" );
goto failed;
}
i_format = AFMT_S16_LE;
if( ioctl( p_sys->fd_audio, SNDCTL_DSP_SETFMT, &i_format ) < 0 ||
i_format != AFMT_S16_LE )
{
msg_Err( p_input, "cannot set audio format (16b little endian)" );
goto failed;
}
if( ioctl( p_sys->fd_audio, SNDCTL_DSP_STEREO, &p_sys->b_stereo ) < 0 )
{
msg_Err( p_input, "cannot set audio channels count" );
goto failed;
}
if( ioctl( p_sys->fd_audio, SNDCTL_DSP_SPEED, &p_sys->i_sample_rate ) < 0 )
{
msg_Err( p_input, "cannot set audio sample rate" );
goto failed;
}
msg_Dbg( p_input,
"adev=`%s' %s %dHz",
p_sys->psz_adev,
p_sys->b_stereo ? "stereo" : "mono",
p_sys->i_sample_rate );
p_sys->i_audio_frame_size = 0;
p_sys->i_audio_frame_size_allocated = 10*1024;
p_sys->p_audio_frame = malloc( p_sys->i_audio_frame_size_allocated );
}
#endif
}
}
/* fix width/heigh */
if( p_sys->i_width == 0 || p_sys->i_height == 0 )
{
struct video_window vid_win;
if( ioctl( p_sys->fd, VIDIOCGWIN, &vid_win ) < 0 )
{
msg_Err( p_input, "cannot get win" );
goto failed;
}
p_sys->i_width = vid_win.width;
p_sys->i_height = vid_win.height;
p_input->pf_read = V4lRead; msg_Dbg( p_input, "will use %dx%d", p_sys->i_width, p_sys->i_height );
}
if( ioctl( p_sys->fd, VIDIOCGMBUF, &p_sys->vid_mbuf ) < 0 )
{
msg_Err( p_input, "mmap unsupported" );
goto failed;
}
p_sys->p_video_mmap = mmap( 0, p_sys->vid_mbuf.size,
PROT_READ|PROT_WRITE,
MAP_SHARED,
p_sys->fd,
0 );
if( p_sys->p_video_mmap == MAP_FAILED )
{
/* FIXME -> normal read */
msg_Err( p_input, "mmap failed" );
goto failed;
}
p_sys->p_video_frame = NULL;
/* init grabbing */
p_sys->vid_mmap.frame = 0;
p_sys->vid_mmap.width = p_sys->i_width;
p_sys->vid_mmap.height = p_sys->i_height;
p_sys->vid_mmap.format = VIDEO_PALETTE_YUV420P;
p_sys->i_chroma = VLC_FOURCC( 'I', '4', '2', '0' );
if( ioctl( p_sys->fd, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )
{
msg_Warn( p_input, "%4.4s refused", (char*)&p_sys->i_chroma );
p_sys->vid_mmap.format = VIDEO_PALETTE_YUV422P;
p_sys->i_chroma = VLC_FOURCC( 'I', '4', '2', '2' );
if( ioctl( p_sys->fd, VIDIOCMCAPTURE, &p_sys->vid_mmap ) < 0 )
{
msg_Warn( p_input, "%4.4s refused", (char*)&p_sys->i_chroma );
msg_Err( p_input, "chroma selection failed" );
goto failed;
}
else
{
p_sys->i_video_frame_size = p_sys->i_width * p_sys->i_height * 2;
}
}
else
{
p_sys->i_video_frame_size = p_sys->i_width * p_sys->i_height * 3 / 2;
}
/* encoder part */
if( p_sys->i_codec != VLC_FOURCC( 0, 0, 0, 0 ) )
{
msg_Dbg( p_input,
"need a rencoder from %4.4s to %4.4s",
(char*)&p_sys->i_chroma,
(char*)&p_sys->i_codec );
#define p_enc p_sys->p_encoder
p_enc = vlc_object_create( p_input, sizeof( video_encoder_t ) );
p_enc->i_codec = p_sys->i_codec;
p_enc->i_chroma= p_sys->i_chroma;
p_enc->i_width = p_sys->i_width;
p_enc->i_height= p_sys->i_height;
p_enc->i_aspect= 0;
p_enc->p_module = module_Need( p_enc,
"video encoder",
"$video-encoder" );
if( !p_enc->p_module )
{
msg_Warn( p_input,
"no suitable encoder to %4.4s",
(char*)&p_enc->i_codec );
vlc_object_destroy( p_enc );
goto failed;
}
/* *** init the codec *** */
if( p_enc->pf_init( p_enc ) )
{
msg_Err( p_input, "failed to initialize video encoder plugin" );
vlc_object_destroy( p_enc );
goto failed;
}
/* *** alloacted buffer *** */
if( p_enc->i_buffer_size <= 0 )
{
p_enc->i_buffer_size = 10 * p_enc->i_width * p_enc->i_height;
}
p_sys->i_video_frame_size = p_enc->i_buffer_size;
p_sys->i_video_frame_size_allocated = p_enc->i_buffer_size;
if( !( p_sys->p_video_frame = malloc( p_enc->i_buffer_size ) ) )
{
msg_Err( p_input, "out of memory" );
goto failed;
}
switch( p_sys->i_chroma )
{
case VLC_FOURCC( 'I', '4', '2', '0' ):
p_sys->pic.i_planes = 3;
p_sys->pic.p[0].i_pitch = p_sys->i_width;
p_sys->pic.p[0].i_lines = p_sys->i_height;
p_sys->pic.p[0].i_pixel_pitch = 1;
p_sys->pic.p[0].i_visible_pitch = p_sys->i_width;
p_sys->pic.p[1].i_pitch = p_sys->i_width / 2;
p_sys->pic.p[1].i_lines = p_sys->i_height / 2;
p_sys->pic.p[1].i_pixel_pitch = 1;
p_sys->pic.p[1].i_visible_pitch = p_sys->i_width / 2;
p_sys->pic.p[2].i_pitch = p_sys->i_width / 2;
p_sys->pic.p[2].i_lines = p_sys->i_height / 2;
p_sys->pic.p[2].i_pixel_pitch = 1;
p_sys->pic.p[2].i_visible_pitch = p_sys->i_width / 2;
break;
default:
msg_Err( p_input, "unsuported chroma" );
vlc_object_destroy( p_enc );
goto failed;
}
#undef p_enc
}
else
{
p_sys->i_codec = p_sys->i_chroma;
p_sys->p_encoder = NULL;
}
p_input->pf_read = Read;
p_input->pf_seek = NULL; p_input->pf_seek = NULL;
p_input->pf_set_area = NULL; p_input->pf_set_area = NULL;
p_input->pf_set_program = NULL; p_input->pf_set_program = NULL;
p_input->p_access_data = p_sys;
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.b_pace_control = 0; p_input->stream.b_pace_control = 0;
p_input->stream.b_seekable = 0; p_input->stream.b_seekable = 0;
...@@ -69,66 +771,488 @@ static int V4lOpen( vlc_object_t *p_this ) ...@@ -69,66 +771,488 @@ static int V4lOpen( vlc_object_t *p_this )
p_input->stream.i_method = INPUT_METHOD_FILE; p_input->stream.i_method = INPUT_METHOD_FILE;
vlc_mutex_unlock( &p_input->stream.stream_lock ); vlc_mutex_unlock( &p_input->stream.stream_lock );
i_fd = open( "/dev/v4l/video0", O_RDWR ); /* Update default_pts to a suitable value for access */
p_input->i_pts_delay = config_GetInt( p_input, "v4l-caching" ) * 1000;
return 0; msg_Info( p_input, "v4l grabbing started" );
/* create header */
p_sys->i_header_size = 8 + 20;
p_sys->i_header_pos = 0;
p_sys->p_header = malloc( p_sys->i_header_size );
memcpy( &p_sys->p_header[0], ".v4l", 4 );
SetDWBE( &p_sys->p_header[4], 1 );
memcpy( &p_sys->p_header[ 8], "vids", 4 );
memcpy( &p_sys->p_header[12], &p_sys->i_codec, 4 );
SetDWBE( &p_sys->p_header[16], p_sys->i_width );
SetDWBE( &p_sys->p_header[20], p_sys->i_height );
SetDWBE( &p_sys->p_header[24], 0 );
#ifdef _V4L_AUDIO_
if( p_sys->fd_audio > 0 )
{
p_sys->i_header_size += 20;
p_sys->p_header = realloc( p_sys->p_header, p_sys->i_header_size );
SetDWBE( &p_sys->p_header[4], 2 );
memcpy( &p_sys->p_header[28], "auds", 4 );
memcpy( &p_sys->p_header[32], "araw", 4 );
SetDWBE( &p_sys->p_header[36], p_sys->b_stereo ? 2 : 1 );
SetDWBE( &p_sys->p_header[40], p_sys->i_sample_rate );
SetDWBE( &p_sys->p_header[44], 16 );
}
#endif
return VLC_SUCCESS;
failed:
free( p_sys->psz_video_device );
if( p_sys->fd >= 0 )
{
close( p_sys->fd );
}
free( p_sys );
return VLC_EGENERIC;
} }
/***************************************************************************** /*****************************************************************************
* V4lClose: close device * V4lClose: close device
*****************************************************************************/ *****************************************************************************/
static void V4lClose( vlc_object_t *p_this ) static void AccessClose( vlc_object_t *p_this )
{
input_thread_t *p_input = (input_thread_t *)p_this;
access_sys_t *p_sys = p_input->p_access_data;
msg_Info( p_input, "v4l grabbing stoped" );
free( p_sys->psz_video_device );
close( p_sys->fd );
if( p_sys->p_encoder )
{
p_sys->p_encoder->pf_end( p_sys->p_encoder );
module_Unneed( p_sys->p_encoder,
p_sys->p_encoder->p_module );
vlc_object_destroy( p_sys->p_encoder );
free( p_sys->p_video_frame );
}
free( p_sys );
}
#ifdef _V4L_AUDIO_
static int GrabAudio( input_thread_t * p_input,
uint8_t **pp_data,
int *pi_data )
{ {
input_thread_t * p_input = (input_thread_t *)p_this; access_sys_t *p_sys = p_input->p_access_data;
//thread_data_t *p_data = (thread_data_t *)p_input->p_access_data; fd_set fds;
struct timeval timeout;
int i_ret;
int i_read;
/* we first try to get an audio frame */
FD_ZERO( &fds );
FD_SET( p_sys->fd_audio, &fds );
timeout.tv_sec = 0;
timeout.tv_usec = 0;
i_ret = select( p_sys->fd_audio + 1, &fds, NULL, NULL, &timeout );
if( i_ret < 0 && errno != EINTR )
{
msg_Warn( p_input, "audio select failed" );
return VLC_EGENERIC;
}
if( !FD_ISSET( p_sys->fd_audio , &fds) )
{
return VLC_EGENERIC;
}
i_read = read( p_sys->fd_audio, p_sys->p_audio_frame, p_sys->i_audio_frame_size_allocated );
if( i_read <= 0 )
{
return VLC_EGENERIC;
}
p_sys->i_audio_frame_size = i_read;
*pp_data = p_sys->p_audio_frame;
*pi_data = p_sys->i_audio_frame_size;
return VLC_SUCCESS;
}
#endif
static int GrabVideo( input_thread_t * p_input,
uint8_t **pp_data,
int *pi_data )
{
access_sys_t *p_sys = p_input->p_access_data;
p_sys->vid_mmap.frame = ( p_sys->i_frame_pos + 1 ) % p_sys->vid_mbuf.frames;
for( ;; )
{
if( ioctl( p_sys->fd, VIDIOCMCAPTURE, &p_sys->vid_mmap ) >= 0 )
{
break;
}
if( errno != EAGAIN )
{
msg_Err( p_input, "failed while grabbing new frame" );
return( -1 );
}
msg_Dbg( p_input, "another try ?" );
}
//msg_Warn( p_input, "grab a new frame" );
while( ioctl(p_sys->fd, VIDIOCSYNC, &p_sys->i_frame_pos) < 0 &&
( errno == EAGAIN || errno == EINTR ) );
p_sys->i_frame_pos = p_sys->vid_mmap.frame;
if( p_sys->p_encoder )
{
p_sys->pic.p[0].p_pixels = p_sys->p_video_mmap + p_sys->vid_mbuf.offsets[p_sys->i_frame_pos];
p_sys->pic.p[1].p_pixels = p_sys->pic.p[0].p_pixels +
p_sys->pic.p[0].i_pitch * p_sys->pic.p[0].i_lines;
p_sys->pic.p[2].p_pixels = p_sys->pic.p[1].p_pixels +
p_sys->pic.p[1].i_pitch * p_sys->pic.p[1].i_lines;
p_sys->i_video_frame_size = p_sys->i_video_frame_size_allocated;
p_sys->p_encoder->pf_encode( p_sys->p_encoder,
&p_sys->pic,
p_sys->p_video_frame,
&p_sys->i_video_frame_size );
}
else
{
p_sys->p_video_frame = p_sys->p_video_mmap + p_sys->vid_mbuf.offsets[p_sys->i_frame_pos];
}
//close( p_data->i_handle ); *pp_data = p_sys->p_video_frame;
close( i_fd ); *pi_data = p_sys->i_video_frame_size;
//free( p_data ); return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* V4lRead: reads from the device into PES packets. * Read: reads from the device into PES packets.
***************************************************************************** *****************************************************************************
* Returns -1 in case of error, 0 in case of EOF, otherwise the number of * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
* bytes. * bytes.
*****************************************************************************/ *****************************************************************************/
#define WIDTH 640 static int Read( input_thread_t * p_input, byte_t * p_buffer,
#define HEIGHT 480
static int V4lRead( input_thread_t * p_input, byte_t * p_buffer,
size_t i_len ) size_t i_len )
{ {
struct video_capability vid_caps; access_sys_t *p_sys = p_input->p_access_data;
struct video_mbuf vid_buf; int i_data = 0;
struct video_mmap vid_mmap; int i_stream;
char *map = NULL; msg_Info( p_input, "access read" );
while( i_len > 0 )
{
//thread_data_t * p_data; /* First copy header if any */
int i_read = 0; if( i_len > 0 && p_sys->i_header_pos < p_sys->i_header_size )
{
int i_copy;
i_copy = __MIN( p_sys->i_header_size - p_sys->i_header_pos,
(int)i_len );
memcpy( p_buffer,
&p_sys->p_header[p_sys->i_header_pos],
i_copy );
p_sys->i_header_pos += i_copy;
p_buffer += i_copy;
i_len -= i_copy;
i_data += i_copy;
}
if( ioctl( i_fd, VIDIOCGCAP, &vid_caps ) == -1 ) /* then data */
if( i_len > 0 && p_sys->i_data_pos < p_sys->i_data_size )
{ {
printf("ioctl (VIDIOCGCAP) failed\n"); int i_copy;
return 0;
i_copy = __MIN( p_sys->i_data_size - p_sys->i_data_pos,
(int)i_len );
memcpy( p_buffer,
&p_sys->p_data[p_sys->i_data_pos],
i_copy );
p_sys->i_data_pos += i_copy;
p_buffer += i_copy;
i_len -= i_copy;
i_data += i_copy;
}
if( i_len <= 0 )
{
return( i_data );
} }
if( ioctl( i_fd, VIDIOCGMBUF, &vid_buf ) == -1 ) /* re fill data by grabbing audio/video */
p_sys->i_data_pos = 0;
/* try grabbing audio frames */
#ifdef _V4L_AUDIO_
i_stream = 1;
if( p_sys->fd_audio < 0 || GrabAudio( p_input, &p_sys->p_data, &p_sys->i_data_size ) )
{ {
// to do a normal read() /* and then get video frame if no audio */
map = malloc (WIDTH * HEIGHT * 3); i_stream = 0;
len = read (fd_webcam, map, WIDTH * HEIGHT * 3); if( GrabVideo( p_input, &p_sys->p_data, &p_sys->i_data_size ) )
if (len <= 0)
{ {
free (map); return -1;
return (NULL);
} }
*size = 0;
return (map);
} }
#else
/* and then get video frame if no audio */
i_stream = 0;
if( GrabVideo( p_input, &p_sys->p_data, &p_sys->i_data_size ) )
{
return -1;
}
#endif
//p_data = (thread_data_t *)p_input->p_access_data; /* create pseudo header */
return i_read; p_sys->i_header_size = 8;
p_sys->i_header_pos = 0;
SetDWBE( &p_sys->p_header[0], i_stream );
SetDWBE( &p_sys->p_header[4], p_sys->i_data_size );
}
return i_data;
} }
/****************************************************************************
* I. Demux Part
****************************************************************************/
#define MAX_PACKETS_IN_FIFO 3
static int DemuxOpen ( vlc_object_t *p_this )
{
input_thread_t *p_input = (input_thread_t *)p_this;
//demux_sys_t *p_sys;
uint8_t *p_peek;
int i_streams;
int i;
data_packet_t *p_pk;
/* Initialize access plug-in structures. */
if( p_input->i_mtu == 0 )
{
/* Improve speed. */
p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE ;
}
/* a little test to see if it's a v4l stream */
if( input_Peek( p_input, &p_peek, 8 ) < 8 )
{
msg_Warn( p_input, "v4l plugin discarded (cannot peek)" );
return( VLC_EGENERIC );
}
if( strncmp( p_peek, ".v4l", 4 ) || GetDWBE( &p_peek[4] ) <= 0 )
{
msg_Warn( p_input, "v4l plugin discarded (not a valid stream)" );
return VLC_EGENERIC;
}
/* create one program */
vlc_mutex_lock( &p_input->stream.stream_lock );
if( input_InitStream( p_input, 0 ) == -1)
{
vlc_mutex_unlock( &p_input->stream.stream_lock );
msg_Err( p_input, "cannot init stream" );
return( VLC_EGENERIC );
}
if( input_AddProgram( p_input, 0, 0) == NULL )
{
vlc_mutex_unlock( &p_input->stream.stream_lock );
msg_Err( p_input, "cannot add program" );
return( VLC_EGENERIC );
}
p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
p_input->stream.i_mux_rate = 0;
i_streams = GetDWBE( &p_peek[4] );
if( input_Peek( p_input, &p_peek, 8 + 20 * i_streams ) < 8 + 20 * i_streams )
{
msg_Err( p_input, "v4l plugin discarded (cannot peek)" );
return( VLC_EGENERIC );
}
p_peek += 8;
for( i = 0; i < i_streams; i++ )
{
es_descriptor_t *p_es;
p_es = input_AddES( p_input, p_input->stream.pp_programs[0], i + 1, 0 );
p_es->i_stream_id = i + 1;
if( !strncmp( p_peek, "auds", 4 ) )
{
#define wf ((WAVEFORMATEX*)p_es->p_waveformatex)
p_es->i_cat = AUDIO_ES;
p_es->i_fourcc = VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] );
p_es->p_waveformatex= malloc( sizeof( WAVEFORMATEX ) );
wf->wFormatTag = WAVE_FORMAT_UNKNOWN;
wf->nChannels = GetDWBE( &p_peek[8] );
wf->nSamplesPerSec = GetDWBE( &p_peek[12] );
wf->wBitsPerSample = GetDWBE( &p_peek[16] );
wf->nBlockAlign = wf->wBitsPerSample * wf->nChannels / 8;
wf->nAvgBytesPerSec = wf->nBlockAlign * wf->nSamplesPerSec;
wf->cbSize = 0;
msg_Dbg( p_input, "added new audio es %d channels %dHz",
wf->nChannels,
wf->nSamplesPerSec );
input_SelectES( p_input, p_es );
#undef wf
}
else if( !strncmp( p_peek, "vids", 4 ) )
{
#define bih ((BITMAPINFOHEADER*)p_es->p_bitmapinfoheader)
p_es->i_cat = VIDEO_ES;
p_es->i_fourcc = VLC_FOURCC( p_peek[4], p_peek[5], p_peek[6], p_peek[7] );
p_es->p_bitmapinfoheader = malloc( sizeof( BITMAPINFOHEADER ) );
bih->biSize = sizeof( BITMAPINFOHEADER );
bih->biWidth = GetDWBE( &p_peek[8] );
bih->biHeight = GetDWBE( &p_peek[12] );
bih->biPlanes = 0;
bih->biBitCount = 0;
bih->biCompression = 0;
bih->biSizeImage= 0;
bih->biXPelsPerMeter = 0;
bih->biYPelsPerMeter = 0;
bih->biClrUsed = 0;
bih->biClrImportant = 0;
msg_Dbg( p_input, "added new video es %4.4s %dx%d",
(char*)&p_es->i_fourcc,
bih->biWidth,
bih->biHeight );
input_SelectES( p_input, p_es );
#undef bih
}
p_peek += 20;
}
p_input->stream.p_selected_program->b_is_ok = 1;
vlc_mutex_unlock( &p_input->stream.stream_lock );
if( input_SplitBuffer( p_input, &p_pk, 8 + i_streams * 20 ) > 0 )
{
input_DeletePacket( p_input->p_method_data, p_pk );
}
p_input->pf_demux = Demux;
return VLC_SUCCESS;
}
static void DemuxClose ( vlc_object_t *p_this )
{
return;
}
static int Demux ( input_thread_t *p_input )
{
es_descriptor_t *p_es;
pes_packet_t *p_pes;
int i_stream;
int i_size;
uint8_t *p_peek;
if( input_Peek( p_input, &p_peek, 8 ) < 8 )
{
msg_Warn( p_input, "cannot peek (EOF ?)" );
return( 0 );
}
i_stream = GetDWBE( &p_peek[0] );
i_size = GetDWBE( &p_peek[4] );
msg_Dbg( p_input, "stream=%d size=%d", i_stream, i_size );
// p_es = input_FindES( p_input, i_stream );
p_es = p_input->stream.p_selected_program->pp_es[i_stream];
if( p_es == NULL || p_es->p_decoder_fifo == NULL )
{
msg_Err( p_input, "cannot find decoder" );
return 0;
}
p_pes = input_NewPES( p_input->p_method_data );
if( p_pes == NULL )
{
msg_Warn( p_input, "cannot allocate PES" );
msleep( 1000 );
return( 1 );
}
i_size += 8;
while( i_size > 0 )
{
data_packet_t *p_data;
int i_read;
if( (i_read = input_SplitBuffer( p_input,
&p_data,
__MIN( i_size, 10000 ) ) ) <= 0 )
{
input_DeletePES( p_input->p_method_data, p_pes );
return( 0 );
}
if( !p_pes->p_first )
{
p_pes->p_first = p_data;
p_pes->i_nb_data = 1;
p_pes->i_pes_size = i_read;
}
else
{
p_pes->p_last->p_next = p_data;
p_pes->i_nb_data++;
p_pes->i_pes_size += i_read;
}
p_pes->p_last = p_data;
i_size -= i_read;
}
// input_SplitBuffer( p_input, &p_pk, i_size + 8 );
p_pes->p_first->p_payload_start += 8;
vlc_mutex_lock( &p_es->p_decoder_fifo->data_lock );
if( p_es->p_decoder_fifo->i_depth >= MAX_PACKETS_IN_FIFO )
{
/* Wait for the decoder. */
vlc_cond_wait( &p_es->p_decoder_fifo->data_wait, &p_es->p_decoder_fifo->data_lock );
}
vlc_mutex_unlock( &p_es->p_decoder_fifo->data_lock );
p_pes->i_pts = mdate() + p_input->i_pts_delay;
input_DecodePES( p_es->p_decoder_fifo, p_pes );
return 1;
}
...@@ -12,3 +12,4 @@ SOURCES_xvid = modules/codec/xvid.c ...@@ -12,3 +12,4 @@ SOURCES_xvid = modules/codec/xvid.c
SOURCES_adpcm = modules/codec/adpcm.c SOURCES_adpcm = modules/codec/adpcm.c
SOURCES_mpeg_audio = modules/codec/mpeg_audio.c SOURCES_mpeg_audio = modules/codec/mpeg_audio.c
SOURCES_libmpeg2 = modules/codec/libmpeg2.c SOURCES_libmpeg2 = modules/codec/libmpeg2.c
SOURCES_rawvideo = modules/codec/rawvideo.c
/*****************************************************************************
* rawvideo.c: Pseudo audio decoder; for raw video data
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: rawvideo.c,v 1.1 2003/03/31 03:46:11 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* 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 <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/decoder.h>
#include <vlc/input.h>
#include <stdlib.h> /* malloc(), free() */
#include <string.h> /* strdup() */
#include "codecs.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
typedef struct
{
/* Input properties */
decoder_fifo_t *p_fifo;
int i_raw_size;
/* Output properties */
mtime_t pts;
vout_thread_t *p_vout;
} vdec_thread_t;
static int OpenDecoder ( vlc_object_t * );
static int RunDecoder ( decoder_fifo_t * );
static int InitThread ( vdec_thread_t * );
static void DecodeThread ( vdec_thread_t * );
static void EndThread ( vdec_thread_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("Pseudo Raw Video decoder") );
set_capability( "decoder", 50 );
set_callbacks( OpenDecoder, NULL );
vlc_module_end();
/*****************************************************************************
* OpenDecoder: probe the decoder and return score
*****************************************************************************
* Tries to launch a decoder and return score so that the interface is able
* to choose.
*****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this )
{
decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
switch( p_fifo->i_fourcc )
{
case VLC_FOURCC('I','4','2','0'):
case VLC_FOURCC('I','4','2','2'):
p_fifo->pf_run = RunDecoder;
return VLC_SUCCESS;
default:
return VLC_EGENERIC;
}
}
/*****************************************************************************
* RunDecoder: this function is called just after the thread is created
*****************************************************************************/
static int RunDecoder( decoder_fifo_t *p_fifo )
{
vdec_thread_t *p_vdec;
int b_error;
if( !( p_vdec = malloc( sizeof( vdec_thread_t ) ) ) )
{
msg_Err( p_fifo, "out of memory" );
DecoderError( p_fifo );
return( -1 );
}
memset( p_vdec, 0, sizeof( vdec_thread_t ) );
p_vdec->p_fifo = p_fifo;
if( InitThread( p_vdec ) != 0 )
{
DecoderError( p_fifo );
return( -1 );
}
while( ( !p_vdec->p_fifo->b_die )&&( !p_vdec->p_fifo->b_error ) )
{
DecodeThread( p_vdec );
}
if( ( b_error = p_vdec->p_fifo->b_error ) )
{
DecoderError( p_vdec->p_fifo );
}
EndThread( p_vdec );
if( b_error )
{
return( -1 );
}
return( 0 );
}
#define FREE( p ) if( p ) { free( p ); p = NULL; }
/*****************************************************************************
* InitThread: initialize data before entering main loop
*****************************************************************************/
static int InitThread( vdec_thread_t * p_vdec )
{
vlc_fourcc_t i_chroma;
#define bih ((BITMAPINFOHEADER*)p_vdec->p_fifo->p_bitmapinfoheader)
if( bih == NULL )
{
msg_Err( p_vdec->p_fifo,
"info missing, fatal" );
return( VLC_EGENERIC );
}
if( bih->biWidth <= 0 || bih->biHeight <= 0 )
{
msg_Err( p_vdec->p_fifo,
"invalid display size %dx%d",
bih->biWidth, bih->biHeight );
return( VLC_EGENERIC );
}
switch( p_vdec->p_fifo->i_fourcc )
{
case VLC_FOURCC( 'I', '4', '2', '0' ):
i_chroma = VLC_FOURCC( 'I', '4', '2', '0' );
p_vdec->i_raw_size = bih->biWidth * bih->biHeight * 3 / 2;
break;
default:
msg_Err( p_vdec->p_fifo, "invalid codec=%4.4s", (char*)&p_vdec->p_fifo->i_fourcc );
return( VLC_EGENERIC );
}
p_vdec->p_vout = vout_Request( p_vdec->p_fifo, NULL,
bih->biWidth, bih->biHeight,
i_chroma,
VOUT_ASPECT_FACTOR * bih->biWidth / bih->biHeight );
if( p_vdec->p_vout == NULL )
{
msg_Err( p_vdec->p_fifo, "failled created vout" );
return( VLC_EGENERIC );
}
return( VLC_SUCCESS );
#undef bih
}
static void FillPicture( pes_packet_t *p_pes, picture_t *p_pic )
{
int i_plane;
data_packet_t *p_data;
uint8_t *p_src;
int i_src;
p_data = p_pes->p_first;
p_src = p_data->p_payload_start;
i_src = p_data->p_payload_end - p_data->p_payload_start;
for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
{
uint8_t *p_dst;
int i_dst;
p_dst = p_pic->p[i_plane].p_pixels;
i_dst = p_pic->p[i_plane].i_pitch * p_pic->p[i_plane].i_lines;
while( i_dst > 0 )
{
int i_copy;
i_copy = __MIN( i_src, i_dst );
if( i_copy > 0 )
{
memcpy( p_dst, p_src, i_copy );
}
i_dst -= i_copy;
i_src -= i_copy;
if( i_src <= 0 )
{
do
{
p_data = p_data->p_next;
if( p_data == NULL )
{
return;
}
p_src = p_data->p_payload_start;
i_src = p_data->p_payload_end - p_data->p_payload_start;
} while( i_src <= 0 );
}
}
}
}
/*****************************************************************************
* DecodeThread: decodes a frame
*****************************************************************************/
static void DecodeThread( vdec_thread_t *p_vdec )
{
int i_size;
pes_packet_t *p_pes;
picture_t *p_pic;
/* **** get frame **** */
input_ExtractPES( p_vdec->p_fifo, &p_pes );
if( !p_pes )
{
p_vdec->p_fifo->b_error = 1;
return;
}
i_size = p_pes->i_pes_size;
if( i_size < p_vdec->i_raw_size )
{
msg_Warn( p_vdec->p_fifo, "invalid frame size (%d < %d)", i_size, p_vdec->i_raw_size );
input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
return;
}
/* **** get video picture **** */
while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
{
if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
{
return;
}
msleep( VOUT_OUTMEM_SLEEP );
}
/* **** fill p_pic **** */
FillPicture( p_pes, p_pic );
/* **** display p_pic **** */
vout_DatePicture( p_vdec->p_vout, p_pic, p_pes->i_pts);
vout_DisplayPicture( p_vdec->p_vout, p_pic );
input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
}
/*****************************************************************************
* EndThread : faad decoder thread destruction
*****************************************************************************/
static void EndThread (vdec_thread_t *p_vdec)
{
if( p_vdec->p_vout )
{
vout_Request( p_vdec->p_fifo, p_vdec->p_vout, 0, 0, 0, 0 );
}
msg_Dbg( p_vdec->p_fifo, "raw video decoder closed" );
free( p_vdec );
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* avi.c * avi.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: avi.c,v 1.10 2003/03/11 19:02:30 fenrir Exp $ * $Id: avi.c,v 1.11 2003/03/31 03:46:11 fenrir Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -106,6 +106,7 @@ typedef struct avi_stream_s ...@@ -106,6 +106,7 @@ typedef struct avi_stream_s
char fcc[4]; char fcc[4];
//mtime_t i_first_pts;
mtime_t i_duration; // in s mtime_t i_duration; // in s
int i_frames; // total frame count int i_frames; // total frame count
...@@ -138,6 +139,8 @@ typedef struct avi_idx1_s ...@@ -138,6 +139,8 @@ typedef struct avi_idx1_s
struct sout_mux_sys_t struct sout_mux_sys_t
{ {
vlc_bool_t b_write_header;
int i_streams; int i_streams;
int i_stream_video; int i_stream_video;
...@@ -156,7 +159,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -156,7 +159,7 @@ static int Open( vlc_object_t *p_this )
{ {
sout_mux_t *p_mux = (sout_mux_t*)p_this; sout_mux_t *p_mux = (sout_mux_t*)p_this;
sout_mux_sys_t *p_sys = p_mux->p_sys; sout_mux_sys_t *p_sys = p_mux->p_sys;
sout_buffer_t *p_hdr; //sout_buffer_t *p_hdr;
p_sys = malloc( sizeof( sout_mux_sys_t ) ); p_sys = malloc( sizeof( sout_mux_sys_t ) );
p_sys->i_streams = 0; p_sys->i_streams = 0;
...@@ -166,6 +169,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -166,6 +169,7 @@ static int Open( vlc_object_t *p_this )
p_sys->idx1.i_entry_count = 0; p_sys->idx1.i_entry_count = 0;
p_sys->idx1.i_entry_max = 10000; p_sys->idx1.i_entry_max = 10000;
p_sys->idx1.entry = calloc( p_sys->idx1.i_entry_max, sizeof( avi_idx1_entry_t ) ); p_sys->idx1.entry = calloc( p_sys->idx1.i_entry_max, sizeof( avi_idx1_entry_t ) );
p_sys->b_write_header = VLC_TRUE;
msg_Info( p_mux, "Open" ); msg_Info( p_mux, "Open" );
...@@ -176,10 +180,12 @@ static int Open( vlc_object_t *p_this ) ...@@ -176,10 +180,12 @@ static int Open( vlc_object_t *p_this )
p_mux->p_sys = p_sys; p_mux->p_sys = p_sys;
p_mux->i_preheader = 8; // (fourcc,length) header p_mux->i_preheader = 8; // (fourcc,length) header
#if 0
/* room to add header at the end */ /* room to add header at the end */
p_hdr = sout_BufferNew( p_mux->p_sout, HDR_SIZE ); p_hdr = sout_BufferNew( p_mux->p_sout, HDR_SIZE );
memset( p_hdr->p_buffer, 0, HDR_SIZE ); memset( p_hdr->p_buffer, 0, HDR_SIZE );
sout_AccessOutWrite( p_mux->p_access, p_hdr ); sout_AccessOutWrite( p_mux->p_access, p_hdr );
#endif
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -227,7 +233,8 @@ static void Close( vlc_object_t * p_this ) ...@@ -227,7 +233,8 @@ static void Close( vlc_object_t * p_this )
} }
msg_Err( p_mux, "stream[%d] duration:%lld totalsize:%lld frames:%d fps:%f kb/s:%d", msg_Err( p_mux, "stream[%d] duration:%lld totalsize:%lld frames:%d fps:%f kb/s:%d",
i_stream, i_stream,
p_stream->i_duration/1000000, p_stream->i_totalsize, (int64_t)p_stream->i_duration / (int64_t)1000000,
p_stream->i_totalsize,
p_stream->i_frames, p_stream->i_frames,
p_stream->f_fps, p_stream->i_bitrate/1024 ); p_stream->f_fps, p_stream->i_bitrate/1024 );
} }
...@@ -242,7 +249,7 @@ static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_ans ...@@ -242,7 +249,7 @@ static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_ans
switch( i_query ) switch( i_query )
{ {
case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME: case SOUT_MUX_CAP_GET_ADD_STREAM_ANY_TIME:
*(vlc_bool_t*)p_answer = VLC_TRUE; *(vlc_bool_t*)p_answer = VLC_FALSE;
return( SOUT_MUX_CAP_ERR_OK ); return( SOUT_MUX_CAP_ERR_OK );
default: default:
return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED ); return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
...@@ -318,6 +325,12 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input ) ...@@ -318,6 +325,12 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
p_stream->i_totalsize = 0; p_stream->i_totalsize = 0;
p_stream->i_frames = 0; p_stream->i_frames = 0;
p_stream->i_duration = 0; p_stream->i_duration = 0;
//p_stream->i_first_pts = 0;
/* fixed later */
p_stream->f_fps = 25;
p_stream->i_bitrate = 128 * 1024;
p_sys->i_streams++; p_sys->i_streams++;
return( 0 ); return( 0 );
...@@ -340,6 +353,18 @@ static int Mux ( sout_mux_t *p_mux ) ...@@ -340,6 +353,18 @@ static int Mux ( sout_mux_t *p_mux )
int i_stream; int i_stream;
int i; int i;
if( p_sys->b_write_header )
{
sout_buffer_t *p_hdr;
msg_Dbg( p_mux, "writing header" );
p_hdr = avi_HeaderCreateRIFF( p_mux );
sout_AccessOutWrite( p_mux->p_access, p_hdr );
p_sys->b_write_header = VLC_FALSE;
}
for( i = 0; i < p_mux->i_nb_inputs; i++ ) for( i = 0; i < p_mux->i_nb_inputs; i++ )
{ {
int i_count; int i_count;
...@@ -358,6 +383,11 @@ static int Mux ( sout_mux_t *p_mux ) ...@@ -358,6 +383,11 @@ static int Mux ( sout_mux_t *p_mux )
p_data = sout_FifoGet( p_fifo ); p_data = sout_FifoGet( p_fifo );
p_stream->i_frames++; p_stream->i_frames++;
if( p_data->i_length < 0 )
{
msg_Warn( p_mux, "argg length < 0 l" );
p_data->i_length = 0;
}
p_stream->i_duration += p_data->i_length; p_stream->i_duration += p_data->i_length;
p_stream->i_totalsize += p_data->i_size; p_stream->i_totalsize += p_data->i_size;
...@@ -527,7 +557,7 @@ static int avi_HeaderAdd_avih( sout_mux_t *p_mux, ...@@ -527,7 +557,7 @@ static int avi_HeaderAdd_avih( sout_mux_t *p_mux,
p_video = &p_sys->stream[p_sys->i_stream_video]; p_video = &p_sys->stream[p_sys->i_stream_video];
if( p_video->i_frames <= 0 ) if( p_video->i_frames <= 0 )
{ {
p_video = NULL; // p_video = NULL;
} }
} }
...@@ -540,14 +570,14 @@ static int avi_HeaderAdd_avih( sout_mux_t *p_mux, ...@@ -540,14 +570,14 @@ static int avi_HeaderAdd_avih( sout_mux_t *p_mux,
} }
else else
{ {
msg_Warn( p_mux, "avi file without audio video track isn't a good idea..." ); msg_Warn( p_mux, "avi file without video track isn't a good idea..." );
i_microsecperframe = 0; i_microsecperframe = 0;
i_totalframes = 0; i_totalframes = 0;
} }
for( i_stream = 0,i_maxbytespersec = 0; i_stream < p_sys->i_streams; i_stream++ ) for( i_stream = 0,i_maxbytespersec = 0; i_stream < p_sys->i_streams; i_stream++ )
{ {
if( p_sys->stream[p_sys->i_stream_video].i_duration > 0 ) if( p_sys->stream[i_stream].i_duration > 0 )
{ {
i_maxbytespersec += i_maxbytespersec +=
p_sys->stream[p_sys->i_stream_video].i_totalsize / p_sys->stream[p_sys->i_stream_video].i_totalsize /
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ogg.c * ogg.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: ogg.c,v 1.3 2003/03/11 19:02:30 fenrir Exp $ * $Id: ogg.c,v 1.4 2003/03/31 03:46:11 fenrir Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -126,6 +126,7 @@ struct sout_mux_sys_t ...@@ -126,6 +126,7 @@ struct sout_mux_sys_t
int b_write_header; int b_write_header;
int i_streams; int i_streams;
mtime_t i_start_dts;
}; };
#define SetWLE( p, v ) _SetWLE( (uint8_t*)p, v) #define SetWLE( p, v ) _SetWLE( (uint8_t*)p, v)
...@@ -326,6 +327,8 @@ static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input ) ...@@ -326,6 +327,8 @@ static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
/* flush all remaining data */ /* flush all remaining data */
if( p_input->p_sys )
{
p_og = OggStreamFlush( p_mux, &p_stream->os, 0 ); p_og = OggStreamFlush( p_mux, &p_stream->os, 0 );
if( p_og ) if( p_og )
{ {
...@@ -337,6 +340,7 @@ static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input ) ...@@ -337,6 +340,7 @@ static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
ogg_stream_clear( &p_stream->os ); ogg_stream_clear( &p_stream->os );
FREE( p_input->p_sys ); FREE( p_input->p_sys );
}
return( 0 ); return( 0 );
} }
...@@ -553,8 +557,12 @@ static int Mux ( sout_mux_t *p_mux ) ...@@ -553,8 +557,12 @@ static int Mux ( sout_mux_t *p_mux )
{ {
if( MuxGetStream( p_mux, &i_stream, &i_dts) < 0 ) if( MuxGetStream( p_mux, &i_stream, &i_dts) < 0 )
{ {
msg_Dbg( p_mux, "waiting data..." );
return( VLC_SUCCESS ); return( VLC_SUCCESS );
} }
p_sys->i_start_dts = i_dts;
msg_Dbg( p_mux, "writing header" );
sout_BufferChain( &p_og, OggCreateHeader( p_mux, i_dts ) ); sout_BufferChain( &p_og, OggCreateHeader( p_mux, i_dts ) );
p_sys->b_write_header = VLC_FALSE; p_sys->b_write_header = VLC_FALSE;
} }
...@@ -568,8 +576,10 @@ static int Mux ( sout_mux_t *p_mux ) ...@@ -568,8 +576,10 @@ static int Mux ( sout_mux_t *p_mux )
if( MuxGetStream( p_mux, &i_stream, &i_dts) < 0 ) if( MuxGetStream( p_mux, &i_stream, &i_dts) < 0 )
{ {
//msg_Dbg( p_mux, "waiting data..." );
return( VLC_SUCCESS ); return( VLC_SUCCESS );
} }
//msg_Dbg( p_mux, "doing job" );
p_input = p_mux->pp_inputs[i_stream]; p_input = p_mux->pp_inputs[i_stream];
p_stream = (ogg_stream_t*)p_input->p_sys; p_stream = (ogg_stream_t*)p_input->p_sys;
...@@ -586,11 +596,12 @@ static int Mux ( sout_mux_t *p_mux ) ...@@ -586,11 +596,12 @@ static int Mux ( sout_mux_t *p_mux )
if( p_stream->i_cat == AUDIO_ES ) if( p_stream->i_cat == AUDIO_ES )
{ {
/* number of sample from begining */ /* number of sample from begining */
op.granulepos = i_dts * p_stream->header.i_samples_per_unit / (int64_t)1000000; op.granulepos = ( i_dts - p_sys->i_start_dts ) *
p_stream->header.i_samples_per_unit / (int64_t)1000000;
} }
else if( p_stream->i_cat == VIDEO_ES ) else if( p_stream->i_cat == VIDEO_ES )
{ {
op.granulepos = i_dts/1000;//p_stream->i_packet_no; op.granulepos = ( i_dts - p_sys->i_start_dts ) / 1000;//p_stream->i_packet_no;
} }
op.packetno = p_stream->i_packet_no++; op.packetno = p_stream->i_packet_no++;
ogg_stream_packetin( &p_stream->os, &op ); ogg_stream_packetin( &p_stream->os, &op );
...@@ -598,13 +609,15 @@ static int Mux ( sout_mux_t *p_mux ) ...@@ -598,13 +609,15 @@ static int Mux ( sout_mux_t *p_mux )
sout_BufferChain( &p_og, sout_BufferChain( &p_og,
OggStreamPageOut( p_mux, OggStreamPageOut( p_mux,
&p_stream->os, &p_stream->os,
p_data->i_pts ) ); p_data->i_dts ) );
if( p_og ) if( p_og )
{ {
OggSetDate( p_og, p_stream->i_dts, p_stream->i_length ); OggSetDate( p_og, p_stream->i_dts, p_stream->i_length );
p_stream->i_dts = -1; p_stream->i_dts = -1;
p_stream->i_length = 0;; p_stream->i_length = 0;
msg_Dbg( p_mux, "writing data..." );
sout_AccessOutWrite( p_mux->p_access, p_og ); sout_AccessOutWrite( p_mux->p_access, p_og );
p_og = NULL; p_og = NULL;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* a52.c * a52.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: a52.c,v 1.2 2003/03/11 19:02:30 fenrir Exp $ * $Id: a52.c,v 1.3 2003/03/31 03:46:11 fenrir Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org> * Eric Petit <titer@videolan.org>
...@@ -49,6 +49,7 @@ typedef struct packetizer_s ...@@ -49,6 +49,7 @@ typedef struct packetizer_s
uint64_t i_samplescount; uint64_t i_samplescount;
mtime_t i_last_pts;
} packetizer_t; } packetizer_t;
static int Open ( vlc_object_t * ); static int Open ( vlc_object_t * );
...@@ -159,6 +160,7 @@ static int InitThread( packetizer_t *p_pack ) ...@@ -159,6 +160,7 @@ static int InitThread( packetizer_t *p_pack )
p_pack->p_sout_input = NULL; p_pack->p_sout_input = NULL;
p_pack->i_samplescount = 0; p_pack->i_samplescount = 0;
p_pack->i_last_pts = 0;
if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo, if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo,
NULL, NULL ) != VLC_SUCCESS ) NULL, NULL ) != VLC_SUCCESS )
...@@ -181,6 +183,7 @@ static void PacketizeThread( packetizer_t *p_pack ) ...@@ -181,6 +183,7 @@ static void PacketizeThread( packetizer_t *p_pack )
uint8_t p_header[7]; uint8_t p_header[7];
int i_channels, i_samplerate, i_bitrate; int i_channels, i_samplerate, i_bitrate;
int i_framelength; int i_framelength;
mtime_t i_pts;
/* search a valid start code */ /* search a valid start code */
for( ;; ) for( ;; )
...@@ -203,6 +206,9 @@ static void PacketizeThread( packetizer_t *p_pack ) ...@@ -203,6 +206,9 @@ static void PacketizeThread( packetizer_t *p_pack )
return; return;
} }
/* Set the Presentation Time Stamp */
NextPTS( &p_pack->bit_stream, &i_pts, NULL );
GetChunk( &p_pack->bit_stream, p_header, 7 ); GetChunk( &p_pack->bit_stream, p_header, 7 );
if( p_pack->p_fifo->b_die ) return; if( p_pack->p_fifo->b_die ) return;
...@@ -254,6 +260,22 @@ static void PacketizeThread( packetizer_t *p_pack ) ...@@ -254,6 +260,22 @@ static void PacketizeThread( packetizer_t *p_pack )
i_channels, i_samplerate, i_bitrate ); i_channels, i_samplerate, i_bitrate );
} }
if( i_pts <= 0 && p_pack->i_last_pts <= 0 )
{
msg_Dbg( p_pack->p_fifo, "need a starting pts" );
return;
}
/* fix pts */
if( i_pts <= 0 )
{
i_pts = p_pack->i_last_pts +
(uint64_t)1000000 *
(uint64_t)A52_FRAME_NB /
(uint64_t)i_samplerate;
}
p_pack->i_last_pts = i_pts;
p_sout_buffer = p_sout_buffer =
sout_BufferNew( p_pack->p_sout_input->p_sout, i_framelength ); sout_BufferNew( p_pack->p_sout_input->p_sout, i_framelength );
if( !p_sout_buffer ) if( !p_sout_buffer )
...@@ -265,10 +287,8 @@ static void PacketizeThread( packetizer_t *p_pack ) ...@@ -265,10 +287,8 @@ static void PacketizeThread( packetizer_t *p_pack )
p_sout_buffer->i_bitrate = i_bitrate; p_sout_buffer->i_bitrate = i_bitrate;
p_sout_buffer->i_pts = p_sout_buffer->i_pts =
p_sout_buffer->i_dts = p_sout_buffer->i_dts = i_pts;
(uint64_t)1000000 *
(uint64_t)p_pack->i_samplescount /
(uint64_t)i_samplerate;
p_sout_buffer->i_length = p_sout_buffer->i_length =
(uint64_t)1000000 * (uint64_t)1000000 *
(uint64_t)A52_FRAME_NB / (uint64_t)A52_FRAME_NB /
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* copy.c * copy.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: copy.c,v 1.5 2003/03/11 19:02:30 fenrir Exp $ * $Id: copy.c,v 1.6 2003/03/31 03:46:11 fenrir Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org> * Eric Petit <titer@videolan.org>
...@@ -47,7 +47,7 @@ typedef struct packetizer_thread_s ...@@ -47,7 +47,7 @@ typedef struct packetizer_thread_s
sout_packetizer_input_t *p_sout_input; sout_packetizer_input_t *p_sout_input;
sout_packet_format_t output_format; sout_packet_format_t output_format;
mtime_t i_pts_start; // mtime_t i_last_pts;
} packetizer_thread_t; } packetizer_thread_t;
...@@ -304,7 +304,7 @@ static int InitThread( packetizer_thread_t *p_pack ) ...@@ -304,7 +304,7 @@ static int InitThread( packetizer_thread_t *p_pack )
msg_Err( p_pack->p_fifo, "cannot add a new stream" ); msg_Err( p_pack->p_fifo, "cannot add a new stream" );
return( -1 ); return( -1 );
} }
p_pack->i_pts_start = -1; // p_pack->i_last_pts = 0;
return( 0 ); return( 0 );
} }
...@@ -316,6 +316,7 @@ static void PacketizeThread( packetizer_thread_t *p_pack ) ...@@ -316,6 +316,7 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
sout_buffer_t *p_sout_buffer; sout_buffer_t *p_sout_buffer;
pes_packet_t *p_pes; pes_packet_t *p_pes;
ssize_t i_size; ssize_t i_size;
mtime_t i_pts;
/* **** get samples count **** */ /* **** get samples count **** */
input_ExtractPES( p_pack->p_fifo, &p_pes ); input_ExtractPES( p_pack->p_fifo, &p_pes );
...@@ -324,11 +325,17 @@ static void PacketizeThread( packetizer_thread_t *p_pack ) ...@@ -324,11 +325,17 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
p_pack->p_fifo->b_error = 1; p_pack->p_fifo->b_error = 1;
return; return;
} }
if( p_pack->i_pts_start < 0 && p_pes->i_pts > 0 ) i_pts = p_pes->i_pts;
if( i_pts <= 0 ) //&& p_pack->i_last_pts <= 0 )
{ {
p_pack->i_pts_start = p_pes->i_pts; msg_Err( p_pack->p_fifo, "need pts != 0" );
input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
return;
} }
i_size = p_pes->i_pes_size; i_size = p_pes->i_pes_size;
// msg_Dbg( p_pack->p_fifo, "pes size:%d", i_size ); // msg_Dbg( p_pack->p_fifo, "pes size:%d", i_size );
if( i_size > 0 ) if( i_size > 0 )
{ {
...@@ -341,6 +348,7 @@ static void PacketizeThread( packetizer_thread_t *p_pack ) ...@@ -341,6 +348,7 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
if( !p_sout_buffer ) if( !p_sout_buffer )
{ {
p_pack->p_fifo->b_error = 1; p_pack->p_fifo->b_error = 1;
input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
return; return;
} }
/* TODO: memcpy of the pes packet */ /* TODO: memcpy of the pes packet */
...@@ -361,14 +369,14 @@ static void PacketizeThread( packetizer_thread_t *p_pack ) ...@@ -361,14 +369,14 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
i_buffer += i_copy; i_buffer += i_copy;
} }
p_sout_buffer->i_length = 0; p_sout_buffer->i_length = 0;
p_sout_buffer->i_dts = p_pes->i_pts - p_pack->i_pts_start; p_sout_buffer->i_dts = i_pts; //p_pes->i_pts - p_pack->i_pts_start;
p_sout_buffer->i_pts = p_pes->i_pts - p_pack->i_pts_start; p_sout_buffer->i_pts = i_pts; //p_pes->i_pts - p_pack->i_pts_start;
p_sout_buffer->i_bitrate = 0; p_sout_buffer->i_bitrate = 0;
input_ShowPES( p_pack->p_fifo, &p_pes_next ); input_ShowPES( p_pack->p_fifo, &p_pes_next );
if( p_pes_next ) if( p_pes_next )
{ {
p_sout_buffer->i_length = p_pes_next->i_pts - p_pes->i_pts; p_sout_buffer->i_length = p_pes_next->i_pts - i_pts;
} }
sout_InputSendBuffer( p_pack->p_sout_input, sout_InputSendBuffer( p_pack->p_sout_input,
p_sout_buffer ); p_sout_buffer );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpeg4audio.c * mpeg4audio.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: mpeg4audio.c,v 1.3 2003/03/11 19:02:31 fenrir Exp $ * $Id: mpeg4audio.c,v 1.4 2003/03/31 03:46:11 fenrir Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -62,8 +62,8 @@ typedef struct packetizer_thread_s ...@@ -62,8 +62,8 @@ typedef struct packetizer_thread_s
sout_packetizer_input_t *p_sout_input; sout_packetizer_input_t *p_sout_input;
sout_packet_format_t output_format; sout_packet_format_t output_format;
mtime_t i_pts_start; // mtime_t i_pts_start;
mtime_t i_pts; mtime_t i_last_pts;
WAVEFORMATEX *p_wf; WAVEFORMATEX *p_wf;
...@@ -244,8 +244,7 @@ static int InitThread( packetizer_thread_t *p_pack ) ...@@ -244,8 +244,7 @@ static int InitThread( packetizer_thread_t *p_pack )
return( -1 ); return( -1 );
} }
p_pack->i_pts_start = -1; p_pack->i_last_pts = 0;
p_pack->i_pts = 0;
return( 0 ); return( 0 );
} }
...@@ -257,6 +256,7 @@ static void PacketizeThreadMPEG4( packetizer_thread_t *p_pack ) ...@@ -257,6 +256,7 @@ static void PacketizeThreadMPEG4( packetizer_thread_t *p_pack )
sout_buffer_t *p_sout_buffer; sout_buffer_t *p_sout_buffer;
pes_packet_t *p_pes; pes_packet_t *p_pes;
ssize_t i_size; ssize_t i_size;
mtime_t i_pts;
/* **** get samples count **** */ /* **** get samples count **** */
input_ExtractPES( p_pack->p_fifo, &p_pes ); input_ExtractPES( p_pack->p_fifo, &p_pes );
...@@ -273,6 +273,14 @@ static void PacketizeThreadMPEG4( packetizer_thread_t *p_pack ) ...@@ -273,6 +273,14 @@ static void PacketizeThreadMPEG4( packetizer_thread_t *p_pack )
p_pack->i_pts = p_pes->i_pts - p_pack->i_pts_start; p_pack->i_pts = p_pes->i_pts - p_pack->i_pts_start;
#endif #endif
i_pts = p_pes->i_pts;
if( i_pts <= 0 && p_pack->i_last_pts <= 0 )
{
msg_Dbg( p_pack->p_fifo, "need a starting pts" );
input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
return;
}
i_size = p_pes->i_pes_size; i_size = p_pes->i_pes_size;
if( i_size > 0 ) if( i_size > 0 )
...@@ -285,6 +293,7 @@ static void PacketizeThreadMPEG4( packetizer_thread_t *p_pack ) ...@@ -285,6 +293,7 @@ static void PacketizeThreadMPEG4( packetizer_thread_t *p_pack )
if( !p_sout_buffer ) if( !p_sout_buffer )
{ {
p_pack->p_fifo->b_error = 1; p_pack->p_fifo->b_error = 1;
input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
return; return;
} }
/* TODO: memcpy of the pes packet */ /* TODO: memcpy of the pes packet */
...@@ -305,15 +314,24 @@ static void PacketizeThreadMPEG4( packetizer_thread_t *p_pack ) ...@@ -305,15 +314,24 @@ static void PacketizeThreadMPEG4( packetizer_thread_t *p_pack )
i_buffer += i_copy; i_buffer += i_copy;
} }
p_sout_buffer->i_length = (mtime_t)1000000 * (mtime_t)p_pack->i_frame_size / (mtime_t)p_pack->i_sample_rate; if( i_pts <= 0 )
{
i_pts = p_pack->i_last_pts +
(mtime_t)1000000 *
(mtime_t)p_pack->i_frame_size /
(mtime_t)p_pack->i_sample_rate;
}
p_pack->i_last_pts = i_pts;
p_sout_buffer->i_length = (mtime_t)1000000 *
(mtime_t)p_pack->i_frame_size /
(mtime_t)p_pack->i_sample_rate;
p_sout_buffer->i_bitrate = 0; p_sout_buffer->i_bitrate = 0;
p_sout_buffer->i_dts = p_pack->i_pts; p_sout_buffer->i_dts = i_pts;
p_sout_buffer->i_pts = p_pack->i_pts; p_sout_buffer->i_pts = i_pts;
sout_InputSendBuffer( p_pack->p_sout_input, sout_InputSendBuffer( p_pack->p_sout_input,
p_sout_buffer ); p_sout_buffer );
p_pack->i_pts += (mtime_t)1000000 * (mtime_t)p_pack->i_frame_size / (mtime_t)p_pack->i_sample_rate;
} }
input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes ); input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpeg4video.c * mpeg4video.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: mpeg4video.c,v 1.8 2003/03/11 19:02:31 fenrir Exp $ * $Id: mpeg4video.c,v 1.9 2003/03/31 03:46:11 fenrir Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org> * Eric Petit <titer@videolan.org>
...@@ -48,7 +48,7 @@ typedef struct packetizer_thread_s ...@@ -48,7 +48,7 @@ typedef struct packetizer_thread_s
sout_packetizer_input_t *p_sout_input; sout_packetizer_input_t *p_sout_input;
sout_packet_format_t output_format; sout_packet_format_t output_format;
mtime_t i_pts_start; mtime_t i_last_pts;
int i_vol; int i_vol;
uint8_t *p_vol; uint8_t *p_vol;
...@@ -224,8 +224,9 @@ static int InitThread( packetizer_thread_t *p_pack ) ...@@ -224,8 +224,9 @@ static int InitThread( packetizer_thread_t *p_pack )
msg_Err( p_pack->p_fifo, "cannot add a new stream" ); msg_Err( p_pack->p_fifo, "cannot add a new stream" );
return( -1 ); return( -1 );
} }
p_pack->i_pts_start = -1; p_pack->i_last_pts = 0;
return( 0 );
return VLC_SUCCESS;
} }
static int m4v_FindStartCode( uint8_t **pp_data, uint8_t *p_end ) static int m4v_FindStartCode( uint8_t **pp_data, uint8_t *p_end )
...@@ -248,6 +249,7 @@ static void PacketizeThread( packetizer_thread_t *p_pack ) ...@@ -248,6 +249,7 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
sout_buffer_t *p_sout_buffer; sout_buffer_t *p_sout_buffer;
pes_packet_t *p_pes; pes_packet_t *p_pes;
ssize_t i_size; ssize_t i_size;
mtime_t i_pts;
/* **** get samples count **** */ /* **** get samples count **** */
input_ExtractPES( p_pack->p_fifo, &p_pes ); input_ExtractPES( p_pack->p_fifo, &p_pes );
...@@ -256,9 +258,13 @@ static void PacketizeThread( packetizer_thread_t *p_pack ) ...@@ -256,9 +258,13 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
p_pack->p_fifo->b_error = 1; p_pack->p_fifo->b_error = 1;
return; return;
} }
if( p_pack->i_pts_start < 0 )
i_pts = p_pes->i_pts;
if( i_pts <= 0 && p_pack->i_last_pts <= 0 )
{ {
p_pack->i_pts_start = p_pes->i_pts; msg_Err( p_pack->p_fifo, "need a starting pts" );
input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
return;
} }
i_size = p_pes->i_pes_size; i_size = p_pes->i_pes_size;
...@@ -292,9 +298,21 @@ static void PacketizeThread( packetizer_thread_t *p_pack ) ...@@ -292,9 +298,21 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
} }
i_buffer += i_copy; i_buffer += i_copy;
} }
input_ShowPES( p_pack->p_fifo, &p_pes_next );
if( p_pes_next && p_pes_next->i_pts > 0 )
{
mtime_t i_gap;
i_gap = p_pes_next->i_pts - p_pes->i_pts;
p_sout_buffer->i_length = i_gap;
}
else
{
p_sout_buffer->i_length = 0; p_sout_buffer->i_length = 0;
p_sout_buffer->i_dts = p_pes->i_pts - p_pack->i_pts_start; }
p_sout_buffer->i_pts = p_pes->i_pts - p_pack->i_pts_start; p_sout_buffer->i_dts = i_pts;
p_sout_buffer->i_pts = i_pts;
p_sout_buffer->i_bitrate = 0; p_sout_buffer->i_bitrate = 0;
if( p_pack->p_vol == NULL ) if( p_pack->p_vol == NULL )
...@@ -392,37 +410,6 @@ static void PacketizeThread( packetizer_thread_t *p_pack ) ...@@ -392,37 +410,6 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
} }
} }
input_ShowPES( p_pack->p_fifo, &p_pes_next );
if( p_pes_next )
{
mtime_t i_gap;
i_gap = p_pes_next->i_pts - p_pes->i_pts;
#if 0
if( i_gap > 1000000 / 4 ) // too littl fps < 4 is no sense
{
i_gap = 1000000 / 25;
p_pack->i_pts_start =
- ( p_pes->i_pts - p_pack->i_pts_start ) + p_pes_next->i_pts - i_gap;
}
else if( i_gap < 0 )
{
p_pack->i_pts_start =
( p_pes->i_pts - p_pack->i_pts_start ) + p_pes_next->i_pts;
i_gap = 0;
}
if( i_gap < 0 )
{
msg_Dbg( p_pack->p_fifo, "pts:%lld next_pts:%lld", p_pes->i_pts, p_pes_next->i_pts );
/* work around for seek */
p_pack->i_pts_start -= i_gap;
}
// msg_Dbg( p_pack->p_fifo, "gap %lld date %lld next diff %lld", i_gap, p_pes->i_pts, p_pes_next->i_pts-p_pack->i_pts_start );
#endif
p_sout_buffer->i_length = i_gap;
}
sout_InputSendBuffer( p_pack->p_sout_input, sout_InputSendBuffer( p_pack->p_sout_input,
p_sout_buffer ); p_sout_buffer );
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpegaudio.c * mpegaudio.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: mpegaudio.c,v 1.4 2003/03/11 19:02:31 fenrir Exp $ * $Id: mpegaudio.c,v 1.5 2003/03/31 03:46:11 fenrir Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org> * Eric Petit <titer@videolan.org>
...@@ -50,6 +50,7 @@ typedef struct packetizer_s ...@@ -50,6 +50,7 @@ typedef struct packetizer_s
uint64_t i_samplescount; uint64_t i_samplescount;
uint32_t i_samplespersecond; uint32_t i_samplespersecond;
mtime_t i_last_pts;
} packetizer_t; } packetizer_t;
static int Open ( vlc_object_t * ); static int Open ( vlc_object_t * );
...@@ -186,6 +187,7 @@ static int InitThread( packetizer_t *p_pack ) ...@@ -186,6 +187,7 @@ static int InitThread( packetizer_t *p_pack )
p_pack->i_samplescount = 0; p_pack->i_samplescount = 0;
p_pack->i_samplespersecond = 0; p_pack->i_samplespersecond = 0;
p_pack->i_last_pts = 0;
if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo, if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo,
NULL, NULL ) != VLC_SUCCESS ) NULL, NULL ) != VLC_SUCCESS )
...@@ -204,6 +206,7 @@ static void PacketizeThread( packetizer_t *p_pack ) ...@@ -204,6 +206,7 @@ static void PacketizeThread( packetizer_t *p_pack )
{ {
sout_buffer_t *p_sout_buffer; sout_buffer_t *p_sout_buffer;
size_t i_size; size_t i_size;
mtime_t i_pts;
uint32_t i_sync, i_header; uint32_t i_sync, i_header;
int i_version, i_layer; int i_version, i_layer;
...@@ -233,6 +236,9 @@ static void PacketizeThread( packetizer_t *p_pack ) ...@@ -233,6 +236,9 @@ static void PacketizeThread( packetizer_t *p_pack )
return; return;
} }
/* Set the Presentation Time Stamp */
NextPTS( &p_pack->bit_stream, &i_pts, NULL );
i_sync = GetBits( &p_pack->bit_stream, 12 ); i_sync = GetBits( &p_pack->bit_stream, 12 );
i_header = ShowBits( &p_pack->bit_stream, 20 ); i_header = ShowBits( &p_pack->bit_stream, 20 );
...@@ -325,6 +331,20 @@ static void PacketizeThread( packetizer_t *p_pack ) ...@@ -325,6 +331,20 @@ static void PacketizeThread( packetizer_t *p_pack )
i_bitrate, i_framelength ); i_bitrate, i_framelength );
} }
if( i_pts <= 0 && p_pack->i_last_pts <= 0 )
{
msg_Dbg( p_pack->p_fifo, "need a starting pts" );
return;
}
if( i_pts <= 0 )
{
i_pts = p_pack->i_last_pts +
(uint64_t)1000000 *
(uint64_t)i_samplesperframe /
(uint64_t)i_samplerate;
}
p_pack->i_last_pts = i_pts;
i_size = __MAX( i_framelength, 4 ); i_size = __MAX( i_framelength, 4 );
// msg_Dbg( p_pack->p_fifo, "frame length %d b", i_size ); // msg_Dbg( p_pack->p_fifo, "frame length %d b", i_size );
p_sout_buffer = p_sout_buffer =
...@@ -341,11 +361,9 @@ static void PacketizeThread( packetizer_t *p_pack ) ...@@ -341,11 +361,9 @@ static void PacketizeThread( packetizer_t *p_pack )
p_sout_buffer->p_buffer[3] = ( i_header )&0xff; p_sout_buffer->p_buffer[3] = ( i_header )&0xff;
p_sout_buffer->i_bitrate = i_bitrate; p_sout_buffer->i_bitrate = i_bitrate;
p_sout_buffer->i_pts = p_sout_buffer->i_dts = i_pts;
p_sout_buffer->i_dts = p_sout_buffer->i_pts = i_pts;
(uint64_t)1000000 *
(uint64_t)p_pack->i_samplescount /
(uint64_t)i_samplerate;
p_sout_buffer->i_length = p_sout_buffer->i_length =
(uint64_t)1000000 * (uint64_t)1000000 *
(uint64_t)i_samplesperframe / (uint64_t)i_samplesperframe /
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpegvideo.c * mpegvideo.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN * Copyright (C) 2001, 2002 VideoLAN
* $Id: mpegvideo.c,v 1.10 2003/03/11 19:02:31 fenrir Exp $ * $Id: mpegvideo.c,v 1.11 2003/03/31 03:46:11 fenrir Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org> * Eric Petit <titer@videolan.org>
...@@ -214,6 +214,9 @@ static void PacketizeThread( packetizer_t *p_pack ) ...@@ -214,6 +214,9 @@ static void PacketizeThread( packetizer_t *p_pack )
int i_skipped; int i_skipped;
mtime_t i_duration; /* of the parsed picture */ mtime_t i_duration; /* of the parsed picture */
mtime_t i_pts;
mtime_t i_dts;
/* needed to calculate pts/dts */ /* needed to calculate pts/dts */
int i_temporal_ref = 0; int i_temporal_ref = 0;
int i_picture_structure = 0x03; /* frame picture */ int i_picture_structure = 0x03; /* frame picture */
...@@ -319,6 +322,7 @@ static void PacketizeThread( packetizer_t *p_pack ) ...@@ -319,6 +322,7 @@ static void PacketizeThread( packetizer_t *p_pack )
if( !p_pack->p_sout_input ) if( !p_pack->p_sout_input )
{ {
msg_Err( p_pack->p_fifo, "cannot add a new stream" ); msg_Err( p_pack->p_fifo, "cannot add a new stream" );
p_pack->p_fifo->b_error = VLC_TRUE;
return; return;
} }
...@@ -369,6 +373,8 @@ static void PacketizeThread( packetizer_t *p_pack ) ...@@ -369,6 +373,8 @@ static void PacketizeThread( packetizer_t *p_pack )
/* picture_start_code */ /* picture_start_code */
GetChunk( &p_pack->bit_stream, GetChunk( &p_pack->bit_stream,
p_sout_buffer->p_buffer + i_pos, 4 ); i_pos += 4; p_sout_buffer->p_buffer + i_pos, 4 ); i_pos += 4;
NextPTS( &p_pack->bit_stream, &i_pts, &i_dts );
i_temporal_ref = ShowBits( &p_pack->bit_stream, 10 ); i_temporal_ref = ShowBits( &p_pack->bit_stream, 10 );
CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos ); CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
...@@ -422,6 +428,26 @@ static void PacketizeThread( packetizer_t *p_pack ) ...@@ -422,6 +428,26 @@ static void PacketizeThread( packetizer_t *p_pack )
i_duration = (mtime_t)( 1000000 / p_pack->d_frame_rate / 2); i_duration = (mtime_t)( 1000000 / p_pack->d_frame_rate / 2);
} }
/* fix i_last_dts and i_last_ref_pts with i_dts and i_pts from stream */
if( i_dts <= 0 && p_pack->i_last_dts <= 0 )
{
msg_Dbg( p_pack->p_fifo, "need a starting pts" );
sout_BufferDelete( p_pack->p_sout_input->p_sout,
p_sout_buffer );
return;
}
if( i_dts > 0 )
{
p_pack->i_last_dts = i_dts;
}
if( i_pts > 0 )
{
p_pack->i_last_ref_pts =
i_pts - i_temporal_ref *
(mtime_t)( 1000000 / p_pack->d_frame_rate );
}
p_sout_buffer->i_dts = p_pack->i_last_dts; p_sout_buffer->i_dts = p_pack->i_last_dts;
p_sout_buffer->i_pts = p_pack->i_last_ref_pts + p_sout_buffer->i_pts = p_pack->i_last_ref_pts +
i_temporal_ref * (mtime_t)( 1000000 / p_pack->d_frame_rate ); i_temporal_ref * (mtime_t)( 1000000 / p_pack->d_frame_rate );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* stream_output.c : stream output module * stream_output.c : stream output module
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002 VideoLAN
* $Id: stream_output.c,v 1.22 2003/03/17 23:42:12 fenrir Exp $ * $Id: stream_output.c,v 1.23 2003/03/31 03:46:11 fenrir Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Laurent Aimar <fenrir@via.ecp.fr> * Laurent Aimar <fenrir@via.ecp.fr>
...@@ -681,9 +681,9 @@ static void MuxSendBuffer ( sout_mux_t *p_mux, ...@@ -681,9 +681,9 @@ static void MuxSendBuffer ( sout_mux_t *p_mux,
if( p_mux->b_waiting_stream ) if( p_mux->b_waiting_stream )
{ {
if( p_mux->i_add_stream_start > 0 && if( p_mux->i_add_stream_start > 0 &&
p_mux->i_add_stream_start + (mtime_t)1000000 < mdate() ) p_mux->i_add_stream_start + (mtime_t)1500000 < mdate() )
{ {
/* more than 1 second, start muxing */ /* more than 1.5 second, start muxing */
p_mux->b_waiting_stream = VLC_FALSE; p_mux->b_waiting_stream = VLC_FALSE;
} }
else else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment