/*****************************************************************************
* stream.c
*****************************************************************************
- * Copyright (C) 1999-2001 VideoLAN
- * $Id: stream.c,v 1.2 2003/08/14 11:25:56 sigmunau Exp $
+ * Copyright (C) 1999-2004 VideoLAN
+ * $Id: stream.c,v 1.11 2004/01/16 11:12:16 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
#include "ninput.h"
+#define MAX_LINE 1024
/****************************************************************************
* stream_* :
* XXX for now it's just a wrapper
/**
* Create a "stream_t *" from an "input_thread_t *".
*/
-stream_t *stream_OpenInput( input_thread_t *p_input )
+stream_t *stream_OpenInput( input_thread_t *p_input )
{
stream_t *s;
/**
* Destroy a previously created "stream_t *" instance.
*/
-void stream_Release( stream_t *s )
+void stream_Release( stream_t *s )
{
vlc_object_destroy( s );
}
/**
- * Similar to #stream_Control(), but takes a va_list and not variable arguments.
+ * Similar to #stream_Control(), but takes a va_list and not variable
+ * arguments.
*/
-int stream_vaControl( stream_t *s, int i_query, va_list args )
+int stream_vaControl( stream_t *s, int i_query, va_list args )
{
vlc_bool_t *p_b;
int64_t *p_i64, i64;
+ int *p_int;
switch( i_query )
{
p_b = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
vlc_mutex_lock( &s->p_input->stream.stream_lock );
- *p_b = s->p_input->stream.b_seekable && s->p_input->stream.i_method == INPUT_METHOD_FILE;
+ *p_b = s->p_input->stream.b_seekable &&
+ s->p_input->stream.i_method == INPUT_METHOD_FILE;
vlc_mutex_unlock( &s->p_input->stream.stream_lock );
return VLC_SUCCESS;
s->p_input->stream.p_selected_area->i_size < i64 ) )
{
vlc_mutex_unlock( &s->p_input->stream.stream_lock );
- msg_Err( s, "seek out of bound" );
+ msg_Warn( s, "seek out of bound" );
return VLC_EGENERIC;
}
vlc_mutex_unlock( &s->p_input->stream.stream_lock );
if( s->p_input->stream.b_seekable &&
( s->p_input->stream.i_method == INPUT_METHOD_FILE ||
i64 - s->p_input->stream.p_selected_area->i_tell < 0 ||
- i64 - s->p_input->stream.p_selected_area->i_tell > 1024 ) )
+ i64 - s->p_input->stream.p_selected_area->i_tell > 4096 ) )
{
input_AccessReinit( s->p_input );
s->p_input->pf_seek( s->p_input, i64 );
if( i64 - s->p_input->stream.p_selected_area->i_tell > 0 )
{
- data_packet_t *p_data;
- int i_skip = i64 - s->p_input->stream.p_selected_area->i_tell;
+ data_packet_t *p_data;
+ int i_skip = i64 - s->p_input->stream.p_selected_area->i_tell;
- msg_Warn( s, "will skip %d bytes, slow", i_skip );
+ if( i_skip > 1000 )
+ {
+ msg_Warn( s, "will skip %d bytes, slow", i_skip );
+ }
while (i_skip > 0 )
{
int i_read;
- i_read = input_SplitBuffer( s->p_input, &p_data, __MIN( 4096, i_skip ) );
+ i_read = input_SplitBuffer( s->p_input, &p_data,
+ __MIN( (int)s->p_input->i_bufsize, i_skip ) );
if( i_read < 0 )
{
return VLC_EGENERIC;
}
}
}
+ return VLC_SUCCESS;
+ case STREAM_GET_MTU:
+ p_int = (int*) va_arg( args, int * );
+ *p_int = s->p_input->i_mtu;
return VLC_SUCCESS;
default:
* possible "i_query" value and format arguments. Return VLC_SUCCESS
* if ... succeed ;) and VLC_EGENERIC if failed or unimplemented
*/
-int stream_Control( stream_t *s, int i_query, ... )
+int stream_Control( stream_t *s, int i_query, ... )
{
va_list args;
int i_result;
* value is the real numbers of bytes read/skip. If this value is less
* than i_read that means that it's the end of the stream.
*/
-int stream_Read( stream_t *s, void *p_data, int i_data )
+int stream_Read( stream_t *s, void *p_data, int i_data )
{
uint8_t *p = (uint8_t*)p_data;
data_packet_t *p_packet;
{
int i_count;
- i_count = input_SplitBuffer( s->p_input, &p_packet, __MIN( i_data, 4096 ) );
+ i_count = input_SplitBuffer( s->p_input, &p_packet,
+ __MIN( i_data, (int)s->p_input->i_bufsize ) );
+
if( i_count <= 0 )
{
+ if( i_count == 0 )
+ input_DeletePacket( s->p_input->p_method_data, p_packet );
+
return i_read;
}
/**
* Store in pp_peek a pointer to the next "i_peek" bytes in the stream
- * The return value is the real numbers of valid bytes, if it's less
- * or equal to 0, *pp_peek is invalid. XXX: it's a pointer to
- * internal buffer and it will be invalid as soons as other stream_*
- * functions are called. be 0 (then *pp_peek isn't valid). XXX: due
- * to input limitation, it could be less than i_peek without meaning
+ * \return The real numbers of valid bytes, if it's less
+ * or equal to 0, *pp_peek is invalid.
+ * \note pp_peek is a pointer to internal buffer and it will be invalid as
+ * soons as other stream_* functions are called.
+ * \note Due to input limitation, it could be less than i_peek without meaning
* the end of the stream (but only when you have i_peek >=
* p_input->i_bufsize)
*/
-int stream_Peek( stream_t *s, uint8_t **pp_peek, int i_data )
+int stream_Peek( stream_t *s, uint8_t **pp_peek, int i_peek )
+{
+ return input_Peek( s->p_input, pp_peek, i_peek );
+}
+
+/**
+ * Read "i_size" bytes and store them in a block_t. If less than "i_size"
+ * bytes are available then return what is left and if nothing is availble,
+ * return NULL.
+ */
+block_t *stream_Block( stream_t *s, int i_size )
+{
+ block_t *p_block;
+
+ if( i_size <= 0 ) return NULL;
+ if( !(p_block = block_New( s->p_input, i_size ) ) ) return NULL;
+
+ p_block->i_buffer = stream_Read( s, p_block->p_buffer, i_size );
+ if( !p_block->i_buffer )
+ {
+ block_Release( p_block );
+ p_block = NULL;
+ }
+
+ return p_block;
+}
+
+/**
+ * Read from the stream untill first newline.
+ * \param s Stream handle to read from
+ * \return A null-terminated string. This must be freed,
+ */
+char *stream_ReadLine( stream_t *s )
{
- return input_Peek( s->p_input, pp_peek, i_data );
+ uint8_t *p_data;
+ char *p_line;
+ int i_data;
+ int i = 0;
+ i_data = stream_Peek( s, &p_data, MAX_LINE );
+ msg_Dbg( s->p_input, "i_data %d", i_data );
+ while( i < i_data && p_data[i] != '\n' )
+ {
+ i++;
+ }
+ if( i_data <= 0 )
+ {
+ return NULL;
+ }
+ else
+ {
+ p_line = malloc( i + 1 );
+ if( p_line == NULL )
+ {
+ msg_Err( s->p_input, "Out of memory" );
+ return NULL;
+ }
+ i = stream_Read( s, p_line, i + 1 );
+ p_line[ i - 1 ] = '\0';
+ msg_Dbg( s->p_input, "found %d chars long line", i );
+ return p_line;
+ }
}
/**
* you need to fill i_dts, i_pts, ... ) If only less than "i_size"
* bytes are available NULL is returned.
*/
-pes_packet_t *stream_PesPacket( stream_t *s, int i_data )
+pes_packet_t *stream_PesPacket( stream_t *s, int i_data )
{
pes_packet_t *p_pes;
data_packet_t *p_packet;
if( i_data <= 0 )
{
p_pes->p_first =
- p_pes->p_last =
- input_NewPacket( s->p_input->p_method_data, 0 );
+ p_pes->p_last = input_NewPacket( s->p_input->p_method_data, 0 );
p_pes->i_nb_data = 1;
return p_pes;
}
{
int i_read;
- i_read = input_SplitBuffer( s->p_input, &p_packet, __MIN( i_data, 4096 ) );
+ i_read = input_SplitBuffer( s->p_input, &p_packet,
+ __MIN( i_data, (int)s->p_input->i_bufsize ) );
if( i_read <= 0 )
{
/* should occur only with EOF and max allocation reached
p_pes->p_last = p_packet;
p_pes->i_nb_data++;
p_pes->i_pes_size += i_read;
- i_data -= i_read;
+ i_data -= i_read;
}
return p_pes;
}
+/**
+ * Read i_size into a data_packet_t. If b_force is not set, fewer bytes can
+ * be returned. You should always set b_force, unless you know what you are
+ * doing.
+ */
+data_packet_t *stream_DataPacket( stream_t *s, int i_size, vlc_bool_t b_force )
+{
+ data_packet_t *p_pk;
+ int i_read;
+
+ if( i_size <= 0 )
+ {
+ p_pk = input_NewPacket( s->p_input->p_method_data, 0 );
+ if( p_pk )
+ {
+ p_pk->p_payload_end = p_pk->p_payload_start;
+ }
+ return p_pk;
+ }
+
+ i_read = input_SplitBuffer( s->p_input, &p_pk, i_size );
+ if( i_read <= 0 )
+ {
+ return NULL;
+ }
+ /* Should be really rare, near 0 */
+ if( i_read < i_size && b_force )
+ {
+ data_packet_t *p_old = p_pk;
+ int i_missing = i_size - i_read;
+ p_pk = input_NewPacket( s->p_input->p_method_data, i_size );
+ if( p_pk == NULL )
+ {
+ input_DeletePacket( s->p_input->p_method_data, p_old );
+ return NULL;
+ }
+ p_pk->p_payload_end = p_pk->p_payload_start + i_size;
+ memcpy( p_pk->p_payload_start, p_old->p_payload_start, i_read );
+ input_DeletePacket( s->p_input->p_method_data, p_old );
+ if( stream_Read( s, &p_pk->p_payload_start[i_read], i_missing )
+ < i_missing )
+ {
+ input_DeletePacket( s->p_input->p_method_data, p_pk );
+ return NULL;
+ }
+ }
+ return p_pk;
+}