Commit 9589dcb7 authored by Christophe Massiot's avatar Christophe Massiot

* Use of ptrdiff_t whenever necessary (IA-64 port) ;

* Changed behaviour of preparsing code, faster startup ;
* Fixed DecodePSM(), cannot test ;
* Cleaned up ParsePES(), fixed a bug which could reject very small but
  valid PES packets ;
* Fixed cosmetic bugs in vpar_synchro frame_rate display.
parent 19324a98
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Collection of useful common types and macros definitions * Collection of useful common types and macros definitions
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: common.h,v 1.19 2000/12/26 19:14:46 massiot Exp $
* *
* Authors: Samuel Hocevar <sam@via.ecp.fr> * Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr> * Vincent Seguin <seguin@via.ecp.fr>
...@@ -39,10 +40,23 @@ typedef u8 byte_t; ...@@ -39,10 +40,23 @@ typedef u8 byte_t;
#ifndef SYS_SOLARIS #ifndef SYS_SOLARIS
typedef int boolean_t; typedef int boolean_t;
#else #else
#include <sys/types.h> # include <sys/types.h>
#endif #endif
#ifdef SYS_GNU #ifdef SYS_GNU
#define _MACH_I386_BOOLEAN_H_ # define _MACH_I386_BOOLEAN_H_
#endif
/* ptrdiff_t definition */
#ifdef _HAVE_STDDEF_H
# include <stddef.h>
#else
# include <malloc.h>
#endif
#ifndef _PTRDIFF_T
# define _PTRDIFF_T
/* Not portable in a 64-bit environment. */
typedef int ptrdiff_t;
#endif #endif
/* Counter for statistics and profiling */ /* Counter for statistics and profiling */
...@@ -126,7 +140,7 @@ typedef struct video_parser_s * p_video_parser_t; ...@@ -126,7 +140,7 @@ typedef struct video_parser_s * p_video_parser_t;
#define MIN(a, b) ( ((a) < (b)) ? (a) : (b) ) #define MIN(a, b) ( ((a) < (b)) ? (a) : (b) )
#endif #endif
/* MSB (big endian)/LSB (little endian) convertions - network order is always /* MSB (big endian)/LSB (little endian) conversions - network order is always
* MSB, and should be used for both network communications and files. Note that * MSB, and should be used for both network communications and files. Note that
* byte orders other than little and big endians are not supported, but only * byte orders other than little and big endians are not supported, but only
* the VAX seems to have such exotic properties - note that these 'functions' * the VAX seems to have such exotic properties - note that these 'functions'
...@@ -151,6 +165,6 @@ typedef struct video_parser_s * p_video_parser_t; ...@@ -151,6 +165,6 @@ typedef struct video_parser_s * p_video_parser_t;
/* XXX??: cause a compilation error */ /* XXX??: cause a compilation error */
#endif #endif
/* Macros used by input to access the TS buffer */ /* Macros with automatic casts */
#define U32_AT(p) ( ntohl ( *( (u32 *)(p) ) ) ) #define U32_AT(p) ( ntohl ( *( (u32 *)(p) ) ) )
#define U16_AT(p) ( ntohs ( *( (u16 *)(p) ) ) ) #define U16_AT(p) ( ntohs ( *( (u16 *)(p) ) ) )
...@@ -171,8 +171,8 @@ ...@@ -171,8 +171,8 @@
/* Maximum size of a data packet (128 kB) */ /* Maximum size of a data packet (128 kB) */
#define INPUT_MAX_PACKET_SIZE 131072 #define INPUT_MAX_PACKET_SIZE 131072
/* Maximum length of a pre-parsed chunk (32 MB) */ /* Maximum length of a pre-parsed chunk (4 MB) */
#define INPUT_PREPARSE_LENGTH 33554432 #define INPUT_PREPARSE_LENGTH 4194304
/* Maximum length of a hostname or source name */ /* Maximum length of a hostname or source name */
#define INPUT_MAX_SOURCE_LENGTH 100 #define INPUT_MAX_SOURCE_LENGTH 100
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ext-dec.h: structures exported to the VideoLAN decoders * input_ext-dec.h: structures exported to the VideoLAN decoders
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-dec.h,v 1.5 2000/12/22 17:53:30 massiot Exp $ * $Id: input_ext-dec.h,v 1.6 2000/12/26 19:14:46 massiot Exp $
* *
* Authors: * Authors:
* *
...@@ -400,7 +400,7 @@ static __inline__ void RealignBits( bit_stream_t * p_bit_stream ) ...@@ -400,7 +400,7 @@ static __inline__ void RealignBits( bit_stream_t * p_bit_stream )
static __inline__ void GetChunk( bit_stream_t * p_bit_stream, static __inline__ void GetChunk( bit_stream_t * p_bit_stream,
byte_t * p_buffer, size_t i_buf_len ) byte_t * p_buffer, size_t i_buf_len )
{ {
int i_available; ptrdiff_t i_available;
if( (i_available = p_bit_stream->p_end - p_bit_stream->p_byte) if( (i_available = p_bit_stream->p_end - p_bit_stream->p_byte)
>= i_buf_len ) >= i_buf_len )
......
...@@ -69,8 +69,7 @@ void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo ) ...@@ -69,8 +69,7 @@ void InitBitstream( bit_stream_t * p_bit_stream, decoder_fifo_t * p_fifo )
void NextDataPacket( bit_stream_t * p_bit_stream ) void NextDataPacket( bit_stream_t * p_bit_stream )
{ {
WORD_TYPE buffer_left; WORD_TYPE buffer_left;
/* FIXME : not portable in a 64bit environment */ ptrdiff_t i_bytes_left;
int i_bytes_left;
decoder_fifo_t * p_fifo = p_bit_stream->p_decoder_fifo; decoder_fifo_t * p_fifo = p_bit_stream->p_decoder_fifo;
/* Buffer used at the end of a decoder thread, to give it zero /* Buffer used at the end of a decoder thread, to give it zero
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_ps.c: PS demux and packet management * input_ps.c: PS demux and packet management
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input_ps.c,v 1.12 2000/12/22 13:04:45 sam Exp $ * $Id: input_ps.c,v 1.13 2000/12/26 19:14:47 massiot Exp $
* *
* Authors: * Authors:
* *
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <malloc.h>
#include "config.h" #include "config.h"
#include "common.h" #include "common.h"
...@@ -38,6 +39,8 @@ ...@@ -38,6 +39,8 @@
#include "intf_msg.h" #include "intf_msg.h"
#include "main.h"
#include "stream_control.h" #include "stream_control.h"
#include "input_ext-intf.h" #include "input_ext-intf.h"
#include "input_ext-dec.h" #include "input_ext-dec.h"
...@@ -106,16 +109,28 @@ static void PSInit( input_thread_t * p_input ) ...@@ -106,16 +109,28 @@ static void PSInit( input_thread_t * p_input )
if( p_input->stream.b_seekable ) if( p_input->stream.b_seekable )
{ {
stream_ps_data_t * p_demux_data =
(stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data;
/* Pre-parse the stream to gather stream_descriptor_t. */ /* Pre-parse the stream to gather stream_descriptor_t. */
p_input->stream.pp_programs[0]->b_is_ok = 0; p_input->stream.pp_programs[0]->b_is_ok = 0;
/* FIXME: don't read all stream (it can be long !) */ p_demux_data->i_PSM_version = EMPTY_PSM_VERSION;
while( !p_input->b_die && !p_input->b_error )
while( !p_input->b_die && !p_input->b_error
&& !p_demux_data->b_has_PSM )
{ {
int i_result, i; int i_result, i;
data_packet_t * pp_packets[INPUT_READ_ONCE]; data_packet_t * pp_packets[INPUT_READ_ONCE];
i_result = PSRead( p_input, pp_packets ); i_result = PSRead( p_input, pp_packets );
if( i_result == 1 ) break; if( i_result == 1 )
{
/* EOF */
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.pp_programs[0]->b_is_ok = 1;
vlc_mutex_unlock( &p_input->stream.stream_lock );
break;
}
if( i_result == -1 ) if( i_result == -1 )
{ {
p_input->b_error = 1; p_input->b_error = 1;
...@@ -137,8 +152,66 @@ static void PSInit( input_thread_t * p_input ) ...@@ -137,8 +152,66 @@ static void PSInit( input_thread_t * p_input )
} }
fseek( p_method->stream, 0, SEEK_SET ); fseek( p_method->stream, 0, SEEK_SET );
vlc_mutex_lock( &p_input->stream.stream_lock ); vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.pp_programs[0]->b_is_ok = 1;
p_input->stream.i_tell = 0; p_input->stream.i_tell = 0;
if( p_demux_data->b_has_PSM )
{
/* (The PSM decoder will care about spawning the decoders) */
p_input->stream.pp_programs[0]->b_is_ok = 1;
}
#ifdef AUTO_SPAWN
else
{
/* (We have to do it ourselves) */
int i_es;
/* FIXME: we should do multiple passes in case an audio type
* is not present */
for( i_es = 0;
i_es < p_input->stream.pp_programs[0]->i_es_number;
i_es++ )
{
#define p_es p_input->stream.pp_programs[0]->pp_es[i_es]
switch( p_es->i_type )
{
case MPEG1_VIDEO_ES:
case MPEG2_VIDEO_ES:
input_SelectES( p_input, p_es );
break;
case MPEG1_AUDIO_ES:
case MPEG2_AUDIO_ES:
if( main_GetIntVariable( INPUT_DVD_AUDIO_VAR, 0 )
== REQUESTED_MPEG
&& main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 )
== (p_es->i_id & 0x1F) )
{
input_SelectES( p_input, p_es );
}
break;
case AC3_AUDIO_ES:
if( main_GetIntVariable( INPUT_DVD_AUDIO_VAR, 0 )
== REQUESTED_AC3
&& main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 )
== ((p_es->i_id & 0xF00) >> 8) )
{
input_SelectES( p_input, p_es );
}
case DVD_SPU_ES:
if( main_GetIntVariable( INPUT_DVD_SUBTITLE_VAR, 0 )
== ((p_es->i_id & 0x1F00) >> 8) )
{
input_SelectES( p_input, p_es );
}
case LPCM_AUDIO_ES:
/* FIXME ! */
}
}
}
#endif
#ifdef STATS #ifdef STATS
input_DumpStream( p_input ); input_DumpStream( p_input );
#endif #endif
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mpeg_system.c: TS, PS and PES management * mpeg_system.c: TS, PS and PES management
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: mpeg_system.c,v 1.18 2000/12/22 17:53:30 massiot Exp $ * $Id: mpeg_system.c,v 1.19 2000/12/26 19:14:47 massiot Exp $
* *
* Authors: * Authors:
* *
...@@ -55,17 +55,71 @@ ...@@ -55,17 +55,71 @@
* PES Packet management * PES Packet management
*/ */
/*****************************************************************************
* MoveChunk
*****************************************************************************
* Small utility function used to parse discontinuous headers safely. Copies
* i_buf_len bytes of data to a buffer and returns the size copied.
* This is a variation on the theme of input_ext-dec.h:GetChunk().
*****************************************************************************/
static __inline__ size_t MoveChunk( byte_t * p_dest,
data_packet_t ** pp_data_src,
byte_t ** pp_src,
size_t i_buf_len )
{
ptrdiff_t i_available;
if( (i_available = (*pp_data_src)->p_payload_end - *pp_src)
>= i_buf_len )
{
if( p_dest != NULL )
memcpy( p_dest, *pp_src, i_buf_len );
*pp_src += i_buf_len;
return( i_buf_len );
}
else
{
size_t i_init_len = i_buf_len;
do
{
if( p_dest != NULL )
memcpy( p_dest, *pp_src, i_available );
*pp_data_src = (*pp_data_src)->p_next;
i_buf_len -= i_available;
p_dest += i_available;
if( *pp_data_src == NULL )
{
*pp_src = NULL;
return( i_init_len - i_buf_len );
}
*pp_src = (*pp_data_src)->p_payload_start;
}
while( (i_available = (*pp_data_src)->p_payload_end - *pp_src)
<= i_buf_len );
if( i_buf_len )
{
if( p_dest != NULL )
memcpy( p_dest, *pp_src, i_buf_len );
*pp_src += i_buf_len;
}
return( i_init_len );
}
}
/***************************************************************************** /*****************************************************************************
* input_ParsePES * input_ParsePES
***************************************************************************** *****************************************************************************
* Parse a finished PES packet and analyze its header. * Parse a finished PES packet and analyze its header.
*****************************************************************************/ *****************************************************************************/
#define PES_HEADER_SIZE 14 #define PES_HEADER_SIZE 7
void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es ) void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
{ {
data_packet_t * p_header_data; data_packet_t * p_data;
byte_t * p_byte;
byte_t p_header[PES_HEADER_SIZE]; byte_t p_header[PES_HEADER_SIZE];
int i_done, i_todo; int i_done;
#define p_pes (p_es->p_pes) #define p_pes (p_es->p_pes)
...@@ -74,31 +128,12 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -74,31 +128,12 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
/* Parse the header. The header has a variable length, but in order /* Parse the header. The header has a variable length, but in order
* to improve the algorithm, we will read the 14 bytes we may be * to improve the algorithm, we will read the 14 bytes we may be
* interested in */ * interested in */
p_header_data = p_pes->p_first; p_data = p_pes->p_first;
p_byte = p_data->p_payload_start;
i_done = 0; i_done = 0;
for( ; ; ) if( MoveChunk( p_header, &p_data, &p_byte, PES_HEADER_SIZE )
{ != PES_HEADER_SIZE )
i_todo = p_header_data->p_payload_end
- p_header_data->p_payload_start;
if( i_todo > PES_HEADER_SIZE - i_done )
i_todo = PES_HEADER_SIZE - i_done;
memcpy( p_header + i_done, p_header_data->p_payload_start,
i_todo );
i_done += i_todo;
if( i_done < PES_HEADER_SIZE && p_header_data->p_next != NULL )
{
p_header_data = p_header_data->p_next;
}
else
{
break;
}
}
if( i_done != PES_HEADER_SIZE )
{ {
intf_WarnMsg( 3, "PES packet too short to have a header" ); intf_WarnMsg( 3, "PES packet too short to have a header" );
p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes ); p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
...@@ -150,46 +185,65 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -150,46 +185,65 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
if( (p_header[6] & 0xC0) == 0x80 ) if( (p_header[6] & 0xC0) == 0x80 )
{ {
/* MPEG-2 : the PES header contains at least 3 more bytes. */ /* MPEG-2 : the PES header contains at least 3 more bytes. */
size_t i_max_len;
p_pes->b_data_alignment = p_header[6] & 0x04; p_pes->b_data_alignment = p_header[6] & 0x04;
p_pes->b_has_pts = p_header[7] & 0x80;
i_pes_header_size = p_header[8] + 9;
/* Now parse the optional header extensions (in the limit of /* Re-use p_header buffer now that we don't need it. */
* the 14 bytes). */ i_max_len = MoveChunk( p_header, &p_data, &p_byte, 7 );
if( i_max_len < 2 )
{
intf_WarnMsg( 3,
"PES packet too short to have a MPEG-2 header" );
p_input->p_plugin->pf_delete_pes( p_input->p_method_data,
p_pes );
p_pes = NULL;
return;
}
p_pes->b_has_pts = p_header[0] & 0x80;
i_pes_header_size = p_header[1] + 9;
/* Now parse the optional header extensions */
if( p_pes->b_has_pts ) if( p_pes->b_has_pts )
{ {
if( i_max_len < 7 )
{
intf_WarnMsg( 3,
"PES packet too short to have a MPEG-2 header" );
p_input->p_plugin->pf_delete_pes(
p_input->p_method_data,
p_pes );
p_pes = NULL;
return;
}
p_pes->i_pts = p_pes->i_pts =
( ((mtime_t)(p_header[9] & 0x0E) << 29) | ( ((mtime_t)(p_header[2] & 0x0E) << 29) |
(((mtime_t)U16_AT(p_header + 10) << 14) - (1 << 14)) | (((mtime_t)U16_AT(p_header + 3) << 14) - (1 << 14)) |
((mtime_t)U16_AT(p_header + 12) >> 1) ) * 300; ((mtime_t)U16_AT(p_header + 5) >> 1) ) * 300;
p_pes->i_pts /= 27; p_pes->i_pts /= 27;
} }
} }
else else
{ {
/* Probably MPEG-1 */ /* Probably MPEG-1 */
byte_t * p_byte;
data_packet_t * p_data;
i_pes_header_size = 6; i_pes_header_size = 6;
p_data = p_pes->p_first; p_data = p_pes->p_first;
p_byte = p_data->p_buffer + 6; p_byte = p_data->p_payload_start;
/* Cannot fail because the previous one succeeded. */
MoveChunk( NULL, &p_data, &p_byte, 6 );
while( *p_byte == 0xFF && i_pes_header_size < 22 ) while( *p_byte == 0xFF && i_pes_header_size < 22 )
{ {
i_pes_header_size++; i_pes_header_size++;
p_byte++; if( MoveChunk( NULL, &p_data, &p_byte, 1 ) != 1 )
if( p_byte >= p_data->p_payload_end )
{ {
p_data = p_data->p_next; intf_WarnMsg( 3,
if( p_data == NULL ) "PES packet too short to have a MPEG-1 header" );
{
intf_ErrMsg( "MPEG-1 packet too short for header" );
p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes ); p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
p_pes = NULL; p_pes = NULL;
return; return;
} }
p_byte = p_data->p_payload_start;
}
} }
if( i_pes_header_size == 22 ) if( i_pes_header_size == 22 )
{ {
...@@ -203,57 +257,42 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -203,57 +257,42 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
{ {
/* Don't ask why... --Meuuh */ /* Don't ask why... --Meuuh */
/* Erm... why ? --Sam */ /* Erm... why ? --Sam */
p_byte += 2; /* Well... According to the recommendation, it is for
* STD_buffer_scale and STD_buffer_size. --Meuuh */
i_pes_header_size += 2; i_pes_header_size += 2;
if( p_byte >= p_data->p_payload_end ) if( MoveChunk( NULL, &p_data, &p_byte, 2 ) != 2 )
{ {
int i_plus = p_byte - p_data->p_payload_end; intf_WarnMsg( 3,
p_data = p_data->p_next; "PES packet too short to have a MPEG-1 header" );
if( p_data == NULL )
{
intf_ErrMsg( "MPEG-1 packet too short for header" );
p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes ); p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
p_pes = NULL; p_pes = NULL;
return; return;
} }
p_byte = p_data->p_payload_start + i_plus;
}
} }
i_pes_header_size++; i_pes_header_size++;
p_pes->b_has_pts = *p_byte & 0x20;
if( *p_byte & 0x10 ) if( *p_byte & 0x10 )
{ {
/* DTS */ /* DTS */
i_pes_header_size += 5; i_pes_header_size += 5;
} }
if( *p_byte & 0x20 ) if( (p_pes->b_has_pts = (*p_byte & 0x20)) )
{ {
/* PTS */ /* PTS */
byte_t p_pts[5]; byte_t p_pts[5];
int i;
i_pes_header_size += 4; i_pes_header_size += 4;
p_pts[0] = *p_byte; if( MoveChunk( p_pts, &p_data, &p_byte, 5 ) != 5 )
for( i = 1; i < 5; i++ )
{ {
p_byte++; intf_WarnMsg( 3,
if( p_byte >= p_data->p_payload_end ) "PES packet too short to have a MPEG-1 header" );
{ p_input->p_plugin->pf_delete_pes(
p_data = p_data->p_next; p_input->p_method_data, p_pes );
if( p_data == NULL )
{
intf_ErrMsg( "MPEG-1 packet too short for header" );
p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_pes );
p_pes = NULL; p_pes = NULL;
return; return;
} }
p_byte = p_data->p_payload_start;
}
p_pts[i] = *p_byte;
}
p_pes->i_pts = p_pes->i_pts =
( ((mtime_t)(p_pts[0] & 0x0E) << 29) | ( ((mtime_t)(p_pts[0] & 0x0E) << 29) |
(((mtime_t)U16_AT(p_pts + 1) << 14) - (1 << 14)) | (((mtime_t)U16_AT(p_pts + 1) << 14) - (1 << 14)) |
...@@ -299,16 +338,16 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -299,16 +338,16 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
* specific data packets where the PES payload begins (renumber * specific data packets where the PES payload begins (renumber
* p_payload_start), so that the decoders can find the beginning * p_payload_start), so that the decoders can find the beginning
* of their data right out of the box. */ * of their data right out of the box. */
p_header_data = p_pes->p_first; p_data = p_pes->p_first;
i_payload_size = p_header_data->p_payload_end i_payload_size = p_data->p_payload_end
- p_header_data->p_payload_start; - p_data->p_payload_start;
while( i_pes_header_size > i_payload_size ) while( i_pes_header_size > i_payload_size )
{ {
/* These packets are entirely filled by the PES header. */ /* These packets are entirely filled by the PES header. */
i_pes_header_size -= i_payload_size; i_pes_header_size -= i_payload_size;
p_header_data->p_payload_start = p_header_data->p_payload_end; p_data->p_payload_start = p_data->p_payload_end;
/* Go to the next data packet. */ /* Go to the next data packet. */
if( (p_header_data = p_header_data->p_next) == NULL ) if( (p_data = p_data->p_next) == NULL )
{ {
intf_ErrMsg( "PES header bigger than payload" ); intf_ErrMsg( "PES header bigger than payload" );
p_input->p_plugin->pf_delete_pes( p_input->p_method_data, p_input->p_plugin->pf_delete_pes( p_input->p_method_data,
...@@ -316,8 +355,8 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -316,8 +355,8 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
p_pes = NULL; p_pes = NULL;
return; return;
} }
i_payload_size = p_header_data->p_payload_end i_payload_size = p_data->p_payload_end
- p_header_data->p_payload_start; - p_data->p_payload_start;
} }
/* This last packet is partly header, partly payload. */ /* This last packet is partly header, partly payload. */
if( i_payload_size < i_pes_header_size ) if( i_payload_size < i_pes_header_size )
...@@ -327,7 +366,7 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es ) ...@@ -327,7 +366,7 @@ void input_ParsePES( input_thread_t * p_input, es_descriptor_t * p_es )
p_pes = NULL; p_pes = NULL;
return; return;
} }
p_header_data->p_payload_start += i_pes_header_size; p_data->p_payload_start += i_pes_header_size;
/* Now we can eventually put the PES packet in the decoder's /* Now we can eventually put the PES packet in the decoder's
* PES fifo */ * PES fifo */
...@@ -623,27 +662,35 @@ static u16 GetID( data_packet_t * p_data ) ...@@ -623,27 +662,35 @@ static u16 GetID( data_packet_t * p_data )
/***************************************************************************** /*****************************************************************************
* DecodePSM: Decode the Program Stream Map information * DecodePSM: Decode the Program Stream Map information
*****************************************************************************/ *****************************************************************************/
/* FIXME : deprecated code ! */
static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data ) static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
{ {
stream_ps_data_t * p_demux = stream_ps_data_t * p_demux =
(stream_ps_data_t *)p_input->stream.p_demux_data; (stream_ps_data_t *)p_input->stream.p_demux_data;
byte_t * p_byte;
byte_t * p_end;
int i;
int i_new_es_number = 0;
intf_Msg("input info: Your stream contains Program Stream Map information"); intf_Msg("input info: Your stream contains Program Stream Map information");
intf_Msg("input info: Please send a mail to <massiot@via.ecp.fr>"); intf_Msg("input info: Please send a mail to <massiot@via.ecp.fr>");
#if 0 p_demux->b_has_PSM = 1;
if( !p_demux->b_is_PSM_complete )
{
byte_t * p_byte;
byte_t * p_end;
intf_DbgMsg( "Building PSM" );
if( p_data->p_payload_start + 10 > p_data->p_payload_end ) if( p_data->p_payload_start + 10 > p_data->p_payload_end )
{ {
intf_ErrMsg( "PSM too short : packet corrupt" ); intf_ErrMsg( "PSM too short : packet corrupt" );
return; return;
} }
if( p_demux->i_PSM_version == (p_data->p_buffer[6] & 0x1F) )
{
/* Already got that one. */
return;
}
intf_DbgMsg( "Building PSM" );
p_demux->i_PSM_version = p_data->p_buffer[6] & 0x1F;
/* Go to elementary_stream_map_length, jumping over /* Go to elementary_stream_map_length, jumping over
* program_stream_info. */ * program_stream_info. */
p_byte = p_data->p_payload_start + 10 p_byte = p_data->p_payload_start + 10
...@@ -669,25 +716,67 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data ) ...@@ -669,25 +716,67 @@ static void DecodePSM( input_thread_t * p_input, data_packet_t * p_data )
/* 4 == minimum useful size of a section */ /* 4 == minimum useful size of a section */
while( p_byte + 4 <= p_end ) while( p_byte + 4 <= p_end )
{ {
es_descriptor_t * p_es; es_descriptor_t * p_es = NULL;
u8 i_stream_id = p_byte[1];
/* FIXME: there will be a problem with private streams... (same
* stream_id) */
/* Look for the ES in the ES table */
for( i = i_new_es_number;
i < p_input->stream.pp_programs[0]->i_es_number;
i++ )
{
if( p_input->stream.pp_programs[0]->pp_es[i]->i_stream_id
== i_stream_id )
{
p_es = p_input->stream.pp_programs[0]->pp_es[i];
if( p_es->i_type != p_byte[0] )
{
input_DelES( p_input, p_es );
p_es = NULL;
}
else
{
/* Move the ES to the beginning. */
i_new_es_number++;
p_input->stream.pp_programs[0]->pp_es[i]
= p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ];
p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ]
= p_es;
}
break;
}
}
/* The goal is to have all the ES we have just read in the
* beginning of the pp_es table, and all the others at the end,
* so that we can close them more easily at the end. */
if( p_es == NULL )
{
p_es = input_AddES( p_input, p_input->stream.pp_programs[0], p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
p_byte[1], 0 ); i_stream_id, 0 );
p_es->i_type = p_byte[0]; p_es->i_type = p_byte[0];
i_new_es_number++;
/* input_AddES has inserted the new element at the end. */
p_input->stream.pp_programs[0]->pp_es[
p_input->stream.pp_programs[0]->i_es_number ]
= p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ];
p_input->stream.pp_programs[0]->pp_es[ i_new_es_number ] = p_es;
}
p_byte += 4 + U16_AT(&p_byte[2]); p_byte += 4 + U16_AT(&p_byte[2]);
} }
vlc_mutex_unlock( &p_input->stream.stream_lock ); /* Un-select the streams that are no longer parts of the program. */
p_demux->i_PSM_version = p_data->p_buffer[6] & 0x1F; for( i = i_new_es_number;
p_demux->b_is_PSM_complete = 1; i < p_input->stream.pp_programs[0]->i_es_number;
} i++ )
else if( p_demux->i_PSM_version != (p_data->p_buffer[6] & 0x1F) )
{ {
/* FIXME */ input_DelES( p_input,
intf_ErrMsg( "PSM changed, this is not supported yet !" ); p_input->stream.pp_programs[0]->pp_es[i_new_es_number] );
p_demux->i_PSM_version = p_data->p_buffer[6] & 0x1F; /* Yes, I wrote *i_new_es_number* */
} }
#endif vlc_mutex_unlock( &p_input->stream.stream_lock );
} }
/***************************************************************************** /*****************************************************************************
...@@ -725,10 +814,13 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input, ...@@ -725,10 +814,13 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
} }
else else
{ {
stream_ps_data_t * p_demux =
(stream_ps_data_t *)p_input->stream.pp_programs[0]->p_demux_data;
/* Search all ES ; if not found -> AddES */ /* Search all ES ; if not found -> AddES */
p_es = input_FindES( p_input, i_id ); p_es = input_FindES( p_input, i_id );
if( p_es == NULL ) if( p_es == NULL && !p_demux->b_has_PSM )
{ {
p_es = input_AddES( p_input, p_input->stream.pp_programs[0], p_es = input_AddES( p_input, p_input->stream.pp_programs[0],
i_id, 0 ); i_id, 0 );
...@@ -742,6 +834,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input, ...@@ -742,6 +834,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
/* MPEG video */ /* MPEG video */
p_es->i_type = MPEG2_VIDEO_ES; p_es->i_type = MPEG2_VIDEO_ES;
#ifdef AUTO_SPAWN #ifdef AUTO_SPAWN
if( !p_input->stream.b_seekable )
input_SelectES( p_input, p_es ); input_SelectES( p_input, p_es );
#endif #endif
} }
...@@ -755,6 +848,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input, ...@@ -755,6 +848,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
&& main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 ) && main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 )
== (p_es->i_id & 0x1F) ) == (p_es->i_id & 0x1F) )
{ {
if( !p_input->stream.b_seekable )
input_SelectES( p_input, p_es ); input_SelectES( p_input, p_es );
} }
#endif #endif
...@@ -769,6 +863,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input, ...@@ -769,6 +863,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
&& main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 ) && main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 )
== ((p_es->i_id & 0xF00) >> 8) ) == ((p_es->i_id & 0xF00) >> 8) )
{ {
if( !p_input->stream.b_seekable )
input_SelectES( p_input, p_es ); input_SelectES( p_input, p_es );
} }
#endif #endif
...@@ -781,6 +876,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input, ...@@ -781,6 +876,7 @@ es_descriptor_t * input_ParsePS( input_thread_t * p_input,
if( main_GetIntVariable( INPUT_DVD_SUBTITLE_VAR, 0 ) if( main_GetIntVariable( INPUT_DVD_SUBTITLE_VAR, 0 )
== ((p_es->i_id & 0x1F00) >> 8) ) == ((p_es->i_id & 0x1F00) >> 8) )
{ {
if( !p_input->stream.b_seekable )
input_SelectES( p_input, p_es ); input_SelectES( p_input, p_es );
} }
#endif #endif
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* and TS system layers * and TS system layers
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: mpeg_system.h,v 1.3 2000/12/22 10:58:27 massiot Exp $ * $Id: mpeg_system.h,v 1.4 2000/12/26 19:14:47 massiot Exp $
* *
* Authors: * Authors:
* *
...@@ -103,10 +103,14 @@ typedef struct stream_ts_data_s ...@@ -103,10 +103,14 @@ typedef struct stream_ts_data_s
*****************************************************************************/ *****************************************************************************/
typedef struct stream_ps_data_s typedef struct stream_ps_data_s
{ {
boolean_t b_has_PSM; /* very rare, in fact */
u8 i_PSM_version; u8 i_PSM_version;
boolean_t b_is_PSM_complete;
} stream_ps_data_t; } stream_ps_data_t;
/* PSM version is 5 bits, so -1 is not a valid value */
#define EMPTY_PSM_VERSION -1
/***************************************************************************** /*****************************************************************************
* Prototypes * Prototypes
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vpar_synchro.h : video parser blocks management * vpar_synchro.h : video parser blocks management
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: vpar_synchro.h,v 1.1 2000/12/21 17:19:52 massiot Exp $ * $Id: vpar_synchro.h,v 1.2 2000/12/26 19:14:47 massiot Exp $
* *
* Author: Christophe Massiot <massiot@via.ecp.fr> * Author: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -66,7 +66,7 @@ typedef struct video_synchro_s ...@@ -66,7 +66,7 @@ typedef struct video_synchro_s
mtime_t backward_pts, current_pts; mtime_t backward_pts, current_pts;
#ifdef STATS #ifdef STATS
unsigned int i_trashed_pic; unsigned int i_trashed_pic, i_pic;
#endif #endif
} video_synchro_t; } video_synchro_t;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* vpar_synchro.c : frame dropping routines * vpar_synchro.c : frame dropping routines
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000 VideoLAN
* $Id: vpar_synchro.c,v 1.63 2000/12/22 13:04:45 sam Exp $ * $Id: vpar_synchro.c,v 1.64 2000/12/26 19:14:47 massiot Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr> * Samuel Hocevar <sam@via.ecp.fr>
...@@ -271,7 +271,7 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type, ...@@ -271,7 +271,7 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type,
if( S.i_eta_b ) if( S.i_eta_b )
S.i_n_b = S.i_eta_b; S.i_n_b = S.i_eta_b;
if( S.i_eta_p + 1 > S.i_n_p ) if( S.i_eta_p + 1 > S.i_n_p )
S.i_n_p++; S.i_n_p = S.i_eta_p + 1;
if( S.backward_pts ) if( S.backward_pts )
{ {
...@@ -310,7 +310,7 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type, ...@@ -310,7 +310,7 @@ boolean_t vpar_SynchroChoose( vpar_thread_t * p_vpar, int i_coding_type,
case B_CODING_TYPE: case B_CODING_TYPE:
/* Stream structure changes */ /* Stream structure changes */
if( S.i_eta_b + 1 > S.i_n_b ) if( S.i_eta_b + 1 > S.i_n_b )
S.i_n_b++; S.i_n_b = S.i_eta_b + 1;
pts = S.current_pts + period; pts = S.current_pts + period;
...@@ -495,6 +495,8 @@ static void SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type ) ...@@ -495,6 +495,8 @@ static void SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type )
{ {
case I_CODING_TYPE: case I_CODING_TYPE:
p_vpar->synchro.i_eta_p = p_vpar->synchro.i_eta_b = 0; p_vpar->synchro.i_eta_p = p_vpar->synchro.i_eta_b = 0;
if( p_vpar->synchro.i_eta_p )
p_vpar->synchro.i_n_p = p_vpar->synchro.i_eta_p;
#ifdef STATS #ifdef STATS
if( p_vpar->synchro.i_type == VPAR_SYNCHRO_DEFAULT ) if( p_vpar->synchro.i_type == VPAR_SYNCHRO_DEFAULT )
{ {
...@@ -505,16 +507,19 @@ static void SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type ) ...@@ -505,16 +507,19 @@ static void SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type )
p_vpar->synchro.p_tau[B_CODING_TYPE], p_vpar->synchro.p_tau[B_CODING_TYPE],
p_vpar->synchro.i_n_b, p_vpar->synchro.i_n_b,
p_vpar->p_vout->render_time, p_vpar->p_vout->render_time,
1 + p_vpar->synchro.i_n_p * (1 + p_vpar->synchro.i_n_b) - p_vpar->synchro.i_pic -
p_vpar->synchro.i_trashed_pic, p_vpar->synchro.i_trashed_pic,
1 + p_vpar->synchro.i_n_p * (1 + p_vpar->synchro.i_n_b) ); p_vpar->synchro.i_pic );
p_vpar->synchro.i_trashed_pic = 0; p_vpar->synchro.i_trashed_pic = 0;
p_vpar->synchro.i_pic = 0;
} }
#endif #endif
break; break;
case P_CODING_TYPE: case P_CODING_TYPE:
p_vpar->synchro.i_eta_b = 0;
p_vpar->synchro.i_eta_p++; p_vpar->synchro.i_eta_p++;
if( p_vpar->synchro.i_eta_b )
p_vpar->synchro.i_n_b = p_vpar->synchro.i_eta_b;
p_vpar->synchro.i_eta_b = 0;
break; break;
case B_CODING_TYPE: case B_CODING_TYPE:
p_vpar->synchro.i_eta_b++; p_vpar->synchro.i_eta_b++;
...@@ -537,14 +542,16 @@ static void SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type ) ...@@ -537,14 +542,16 @@ static void SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type )
} }
else else
{ {
p_vpar->synchro.current_pts += 1000000 / (p_vpar->sequence.i_frame_rate) * 1001; p_vpar->synchro.current_pts += 1000000
/ (p_vpar->sequence.i_frame_rate) * 1001;
} }
} }
else else
{ {
if( p_vpar->synchro.backward_pts == 0 ) if( p_vpar->synchro.backward_pts == 0 )
{ {
p_vpar->synchro.current_pts += 1000000 / (p_vpar->sequence.i_frame_rate) * 1001; p_vpar->synchro.current_pts += 1000000
/ (p_vpar->sequence.i_frame_rate) * 1001;
} }
else else
{ {
...@@ -564,4 +571,8 @@ static void SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type ) ...@@ -564,4 +571,8 @@ static void SynchroNewPicture( vpar_thread_t * p_vpar, int i_coding_type )
p_pes->b_has_pts = 0; p_pes->b_has_pts = 0;
} }
} }
#ifdef STATS
p_vpar->synchro.i_pic++;
#endif
} }
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