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"
#PLUGINS="${PLUGINS} scope"
PLUGINS="${PLUGINS} i420_rgb i420_yuy2 i422_yuy2 i420_ymga"
PLUGINS="${PLUGINS} id3 m3u"
PLUGINS="${PLUGINS} rawvideo"
PLUGINS="${PLUGINS} wav araw demuxdump demuxsub adpcm a52sys au"
PLUGINS="${PLUGINS} access_file access_udp access_http ipv4 access_mms"
PLUGINS="${PLUGINS} access_ftp access_directory sap httpd"
......
This diff is collapsed.
......@@ -12,3 +12,4 @@ SOURCES_xvid = modules/codec/xvid.c
SOURCES_adpcm = modules/codec/adpcm.c
SOURCES_mpeg_audio = modules/codec/mpeg_audio.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 @@
* avi.c
*****************************************************************************
* 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>
*
......@@ -106,6 +106,7 @@ typedef struct avi_stream_s
char fcc[4];
//mtime_t i_first_pts;
mtime_t i_duration; // in s
int i_frames; // total frame count
......@@ -138,6 +139,8 @@ typedef struct avi_idx1_s
struct sout_mux_sys_t
{
vlc_bool_t b_write_header;
int i_streams;
int i_stream_video;
......@@ -156,7 +159,7 @@ static int Open( vlc_object_t *p_this )
{
sout_mux_t *p_mux = (sout_mux_t*)p_this;
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->i_streams = 0;
......@@ -166,6 +169,7 @@ static int Open( vlc_object_t *p_this )
p_sys->idx1.i_entry_count = 0;
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->b_write_header = VLC_TRUE;
msg_Info( p_mux, "Open" );
......@@ -176,10 +180,12 @@ static int Open( vlc_object_t *p_this )
p_mux->p_sys = p_sys;
p_mux->i_preheader = 8; // (fourcc,length) header
#if 0
/* room to add header at the end */
p_hdr = sout_BufferNew( p_mux->p_sout, HDR_SIZE );
memset( p_hdr->p_buffer, 0, HDR_SIZE );
sout_AccessOutWrite( p_mux->p_access, p_hdr );
#endif
return VLC_SUCCESS;
}
......@@ -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",
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->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
switch( i_query )
{
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 );
default:
return( SOUT_MUX_CAP_ERR_UNIMPLEMENTED );
......@@ -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_frames = 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++;
return( 0 );
......@@ -340,6 +353,18 @@ static int Mux ( sout_mux_t *p_mux )
int i_stream;
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++ )
{
int i_count;
......@@ -358,6 +383,11 @@ static int Mux ( sout_mux_t *p_mux )
p_data = sout_FifoGet( p_fifo );
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_totalsize += p_data->i_size;
......@@ -527,7 +557,7 @@ static int avi_HeaderAdd_avih( sout_mux_t *p_mux,
p_video = &p_sys->stream[p_sys->i_stream_video];
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,
}
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_totalframes = 0;
}
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 +=
p_sys->stream[p_sys->i_stream_video].i_totalsize /
......
......@@ -2,7 +2,7 @@
* ogg.c
*****************************************************************************
* 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>
*
......@@ -126,6 +126,7 @@ struct sout_mux_sys_t
int b_write_header;
int i_streams;
mtime_t i_start_dts;
};
#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 )
/* flush all remaining data */
if( p_input->p_sys )
{
p_og = OggStreamFlush( p_mux, &p_stream->os, 0 );
if( p_og )
{
......@@ -337,6 +340,7 @@ static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
ogg_stream_clear( &p_stream->os );
FREE( p_input->p_sys );
}
return( 0 );
}
......@@ -553,8 +557,12 @@ static int Mux ( sout_mux_t *p_mux )
{
if( MuxGetStream( p_mux, &i_stream, &i_dts) < 0 )
{
msg_Dbg( p_mux, "waiting data..." );
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 ) );
p_sys->b_write_header = VLC_FALSE;
}
......@@ -568,8 +576,10 @@ static int Mux ( sout_mux_t *p_mux )
if( MuxGetStream( p_mux, &i_stream, &i_dts) < 0 )
{
//msg_Dbg( p_mux, "waiting data..." );
return( VLC_SUCCESS );
}
//msg_Dbg( p_mux, "doing job" );
p_input = p_mux->pp_inputs[i_stream];
p_stream = (ogg_stream_t*)p_input->p_sys;
......@@ -586,11 +596,12 @@ static int Mux ( sout_mux_t *p_mux )
if( p_stream->i_cat == AUDIO_ES )
{
/* 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 )
{
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++;
ogg_stream_packetin( &p_stream->os, &op );
......@@ -598,13 +609,15 @@ static int Mux ( sout_mux_t *p_mux )
sout_BufferChain( &p_og,
OggStreamPageOut( p_mux,
&p_stream->os,
p_data->i_pts ) );
p_data->i_dts ) );
if( p_og )
{
OggSetDate( p_og, p_stream->i_dts, p_stream->i_length );
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 );
p_og = NULL;
......
......@@ -2,7 +2,7 @@
* a52.c
*****************************************************************************
* 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>
* Eric Petit <titer@videolan.org>
......@@ -49,6 +49,7 @@ typedef struct packetizer_s
uint64_t i_samplescount;
mtime_t i_last_pts;
} packetizer_t;
static int Open ( vlc_object_t * );
......@@ -159,6 +160,7 @@ static int InitThread( packetizer_t *p_pack )
p_pack->p_sout_input = NULL;
p_pack->i_samplescount = 0;
p_pack->i_last_pts = 0;
if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo,
NULL, NULL ) != VLC_SUCCESS )
......@@ -181,6 +183,7 @@ static void PacketizeThread( packetizer_t *p_pack )
uint8_t p_header[7];
int i_channels, i_samplerate, i_bitrate;
int i_framelength;
mtime_t i_pts;
/* search a valid start code */
for( ;; )
......@@ -203,6 +206,9 @@ static void PacketizeThread( packetizer_t *p_pack )
return;
}
/* Set the Presentation Time Stamp */
NextPTS( &p_pack->bit_stream, &i_pts, NULL );
GetChunk( &p_pack->bit_stream, p_header, 7 );
if( p_pack->p_fifo->b_die ) return;
......@@ -254,6 +260,22 @@ static void PacketizeThread( packetizer_t *p_pack )
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 =
sout_BufferNew( p_pack->p_sout_input->p_sout, i_framelength );
if( !p_sout_buffer )
......@@ -265,10 +287,8 @@ static void PacketizeThread( packetizer_t *p_pack )
p_sout_buffer->i_bitrate = i_bitrate;
p_sout_buffer->i_pts =
p_sout_buffer->i_dts =
(uint64_t)1000000 *
(uint64_t)p_pack->i_samplescount /
(uint64_t)i_samplerate;
p_sout_buffer->i_dts = i_pts;
p_sout_buffer->i_length =
(uint64_t)1000000 *
(uint64_t)A52_FRAME_NB /
......
......@@ -2,7 +2,7 @@
* copy.c
*****************************************************************************
* 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>
* Eric Petit <titer@videolan.org>
......@@ -47,7 +47,7 @@ typedef struct packetizer_thread_s
sout_packetizer_input_t *p_sout_input;
sout_packet_format_t output_format;
mtime_t i_pts_start;
// mtime_t i_last_pts;
} packetizer_thread_t;
......@@ -304,7 +304,7 @@ static int InitThread( packetizer_thread_t *p_pack )
msg_Err( p_pack->p_fifo, "cannot add a new stream" );
return( -1 );
}
p_pack->i_pts_start = -1;
// p_pack->i_last_pts = 0;
return( 0 );
}
......@@ -316,6 +316,7 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
sout_buffer_t *p_sout_buffer;
pes_packet_t *p_pes;
ssize_t i_size;
mtime_t i_pts;
/* **** get samples count **** */
input_ExtractPES( p_pack->p_fifo, &p_pes );
......@@ -324,11 +325,17 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
p_pack->p_fifo->b_error = 1;
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;
// msg_Dbg( p_pack->p_fifo, "pes size:%d", i_size );
if( i_size > 0 )
{
......@@ -341,6 +348,7 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
if( !p_sout_buffer )
{
p_pack->p_fifo->b_error = 1;
input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
return;
}
/* TODO: memcpy of the pes packet */
......@@ -361,14 +369,14 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
i_buffer += i_copy;
}
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_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;
input_ShowPES( p_pack->p_fifo, &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,
p_sout_buffer );
......
......@@ -2,7 +2,7 @@
* mpeg4audio.c
*****************************************************************************
* 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>
*
......@@ -62,8 +62,8 @@ typedef struct packetizer_thread_s
sout_packetizer_input_t *p_sout_input;
sout_packet_format_t output_format;
mtime_t i_pts_start;
mtime_t i_pts;
// mtime_t i_pts_start;
mtime_t i_last_pts;
WAVEFORMATEX *p_wf;
......@@ -244,8 +244,7 @@ static int InitThread( packetizer_thread_t *p_pack )
return( -1 );
}
p_pack->i_pts_start = -1;
p_pack->i_pts = 0;
p_pack->i_last_pts = 0;
return( 0 );
}
......@@ -257,6 +256,7 @@ static void PacketizeThreadMPEG4( packetizer_thread_t *p_pack )
sout_buffer_t *p_sout_buffer;
pes_packet_t *p_pes;
ssize_t i_size;
mtime_t i_pts;
/* **** get samples count **** */
input_ExtractPES( p_pack->p_fifo, &p_pes );
......@@ -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;
#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;
if( i_size > 0 )
......@@ -285,6 +293,7 @@ static void PacketizeThreadMPEG4( packetizer_thread_t *p_pack )
if( !p_sout_buffer )
{
p_pack->p_fifo->b_error = 1;
input_DeletePES( p_pack->p_fifo->p_packets_mgt, p_pes );
return;
}
/* TODO: memcpy of the pes packet */
......@@ -305,15 +314,24 @@ static void PacketizeThreadMPEG4( packetizer_thread_t *p_pack )
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_dts = p_pack->i_pts;
p_sout_buffer->i_pts = p_pack->i_pts;
p_sout_buffer->i_dts = i_pts;
p_sout_buffer->i_pts = i_pts;
sout_InputSendBuffer( p_pack->p_sout_input,
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 );
......
......@@ -2,7 +2,7 @@
* mpeg4video.c
*****************************************************************************
* 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>
* Eric Petit <titer@videolan.org>
......@@ -48,7 +48,7 @@ typedef struct packetizer_thread_s
sout_packetizer_input_t *p_sout_input;
sout_packet_format_t output_format;
mtime_t i_pts_start;
mtime_t i_last_pts;
int i_vol;
uint8_t *p_vol;
......@@ -224,8 +224,9 @@ static int InitThread( packetizer_thread_t *p_pack )
msg_Err( p_pack->p_fifo, "cannot add a new stream" );
return( -1 );
}
p_pack->i_pts_start = -1;
return( 0 );
p_pack->i_last_pts = 0;
return VLC_SUCCESS;
}
static int m4v_FindStartCode( uint8_t **pp_data, uint8_t *p_end )
......@@ -248,6 +249,7 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
sout_buffer_t *p_sout_buffer;
pes_packet_t *p_pes;
ssize_t i_size;
mtime_t i_pts;
/* **** get samples count **** */
input_ExtractPES( p_pack->p_fifo, &p_pes );
......@@ -256,9 +258,13 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
p_pack->p_fifo->b_error = 1;
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;
......@@ -292,9 +298,21 @@ static void PacketizeThread( packetizer_thread_t *p_pack )
}
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_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;
if( p_pack->p_vol == NULL )
......@@ -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,
p_sout_buffer );
}
......
......@@ -2,7 +2,7 @@
* mpegaudio.c
*****************************************************************************
* 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>
* Eric Petit <titer@videolan.org>
......@@ -50,6 +50,7 @@ typedef struct packetizer_s
uint64_t i_samplescount;
uint32_t i_samplespersecond;
mtime_t i_last_pts;
} packetizer_t;
static int Open ( vlc_object_t * );
......@@ -186,6 +187,7 @@ static int InitThread( packetizer_t *p_pack )
p_pack->i_samplescount = 0;
p_pack->i_samplespersecond = 0;
p_pack->i_last_pts = 0;
if( InitBitstream( &p_pack->bit_stream, p_pack->p_fifo,
NULL, NULL ) != VLC_SUCCESS )
......@@ -204,6 +206,7 @@ static void PacketizeThread( packetizer_t *p_pack )
{
sout_buffer_t *p_sout_buffer;
size_t i_size;
mtime_t i_pts;
uint32_t i_sync, i_header;
int i_version, i_layer;
......@@ -233,6 +236,9 @@ static void PacketizeThread( packetizer_t *p_pack )
return;
}
/* Set the Presentation Time Stamp */
NextPTS( &p_pack->bit_stream, &i_pts, NULL );
i_sync = GetBits( &p_pack->bit_stream, 12 );
i_header = ShowBits( &p_pack->bit_stream, 20 );
......@@ -325,6 +331,20 @@ static void PacketizeThread( packetizer_t *p_pack )
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 );
// msg_Dbg( p_pack->p_fifo, "frame length %d b", i_size );
p_sout_buffer =
......@@ -341,11 +361,9 @@ static void PacketizeThread( packetizer_t *p_pack )
p_sout_buffer->p_buffer[3] = ( i_header )&0xff;
p_sout_buffer->i_bitrate = i_bitrate;
p_sout_buffer->i_pts =
p_sout_buffer->i_dts =
(uint64_t)1000000 *
(uint64_t)p_pack->i_samplescount /
(uint64_t)i_samplerate;
p_sout_buffer->i_dts = i_pts;
p_sout_buffer->i_pts = i_pts;
p_sout_buffer->i_length =
(uint64_t)1000000 *
(uint64_t)i_samplesperframe /
......
......@@ -2,7 +2,7 @@
* mpegvideo.c
*****************************************************************************
* 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>
* Eric Petit <titer@videolan.org>
......@@ -214,6 +214,9 @@ static void PacketizeThread( packetizer_t *p_pack )
int i_skipped;
mtime_t i_duration; /* of the parsed picture */
mtime_t i_pts;
mtime_t i_dts;
/* needed to calculate pts/dts */
int i_temporal_ref = 0;
int i_picture_structure = 0x03; /* frame picture */
......@@ -319,6 +322,7 @@ static void PacketizeThread( packetizer_t *p_pack )
if( !p_pack->p_sout_input )
{
msg_Err( p_pack->p_fifo, "cannot add a new stream" );
p_pack->p_fifo->b_error = VLC_TRUE;
return;
}
......@@ -369,6 +373,8 @@ static void PacketizeThread( packetizer_t *p_pack )
/* picture_start_code */
GetChunk( &p_pack->bit_stream,
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 );
CopyUntilNextStartCode( p_pack, p_sout_buffer, &i_pos );
......@@ -422,6 +428,26 @@ static void PacketizeThread( packetizer_t *p_pack )
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_pts = p_pack->i_last_ref_pts +
i_temporal_ref * (mtime_t)( 1000000 / p_pack->d_frame_rate );
......
......@@ -2,7 +2,7 @@
* stream_output.c : stream output module
*****************************************************************************
* 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>
* Laurent Aimar <fenrir@via.ecp.fr>
......@@ -681,9 +681,9 @@ static void MuxSendBuffer ( sout_mux_t *p_mux,
if( p_mux->b_waiting_stream )
{
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;
}
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