/*****************************************************************************
* decoder_fifo.h: interface for decoders PES fifo
- * (c)1999 VideoLAN
*****************************************************************************
+ * Copyright (C) 1999, 2000 VideoLAN
+ *
+ * Authors:
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
* Required headers:
* - "config.h"
* - "common.h"
- * - "vlc_thread.h"
+ * - "threads.h"
* - "input.h"
*****************************************************************************/
+#define WORD_TYPE u32
+#define WORD_BYTE_LENGTH 4
+#define WORD_LENGTH 32
+
/*****************************************************************************
* Macros
*****************************************************************************/
-/* ?? move to inline functions */
-#define DECODER_FIFO_ISEMPTY( fifo ) ( (fifo).i_start == (fifo).i_end )
-#define DECODER_FIFO_ISFULL( fifo ) ( ( ( (fifo).i_end + 1 - (fifo).i_start ) \
+/* FIXME: move to inline functions ??*/
+#define DECODER_FIFO_ISEMPTY( fifo ) ( (fifo).i_start == (fifo).i_end )
+#define DECODER_FIFO_ISFULL( fifo ) ( ( ((fifo).i_end + 1 - (fifo).i_start)\
& FIFO_SIZE ) == 0 )
-#define DECODER_FIFO_START( fifo ) ( (fifo).buffer[ (fifo).i_start ] )
-#define DECODER_FIFO_INCSTART( fifo ) ( (fifo).i_start = ((fifo).i_start + 1)\
- & FIFO_SIZE )
-#define DECODER_FIFO_END( fifo ) ( (fifo).buffer[ (fifo).i_end ] )
-#define DECODER_FIFO_INCEND( fifo ) ( (fifo).i_end = ((fifo).i_end + 1) \
+#define DECODER_FIFO_START( fifo ) ( (fifo).buffer[ (fifo).i_start ] )
+#define DECODER_FIFO_INCSTART( fifo ) ( (fifo).i_start = ((fifo).i_start + 1)\
& FIFO_SIZE )
+#define DECODER_FIFO_END( fifo ) ( (fifo).buffer[ (fifo).i_end ] )
+#define DECODER_FIFO_INCEND( fifo ) ( (fifo).i_end = ((fifo).i_end + 1) \
+ & FIFO_SIZE )
/*****************************************************************************
* decoder_fifo_t
/* This unsigned integer allows us to work at the bit level. This buffer
* can contain 32 bits, and the used space can be found on the MSb's side
* and the available space on the LSb's side. */
- u32 buffer;
+ WORD_TYPE buffer;
/* Number of bits available in the bit buffer */
int i_available;
*/
/* Current TS packet (in the current PES packet of the PES stream) */
ts_packet_t * p_ts;
- /* Pointer to the next byte that is to be read (in the current TS packet) */
+ /* Pointer to the next byte that is to be read (in the current TS packet) */
byte_t * p_byte;
/* Pointer to the last byte that is to be read (in the current TS packet */
byte_t * p_end;
/* could change this test to have a if (! (bytes--)) instead */
if ( p_bit_stream->p_byte >= p_bit_stream->p_end )
{
- /* no, switch to next TS packet */
- decoder_fifo_next( p_bit_stream );
+ /* no, switch to next TS packet */
+ decoder_fifo_next( p_bit_stream );
}
return( *(p_bit_stream->p_byte++));
* DumpBits32 : removes 32 bits from the bit buffer
*****************************************************************************
* This function actually believes that you have already put 32 bits in the
- * bit buffer, so you can't you use it anytime.
+ * bit buffer, so you can't use it anytime.
*****************************************************************************/
static __inline__ void DumpBits32( bit_stream_t * p_bit_stream )
{
* need to call RealignBits() before).
*/
+void PeekNextPacket( bit_stream_t * p_bit_stream );
+
+//(stolen from the kernel)
+// XXX: The macro swab32 for little endian machine does
+// not seem to work correctly
+
+#if defined(SYS_BEOS)
+# define swab32(x) B_BENDIAN_TO_HOST_INT32(x)
+#else
+# if __BYTE_ORDER == __BIG_ENDIAN
+# define swab32(x) (x)
+# else
+# if defined (__i386__)
+# define swab32(x) __i386_swab32(x)
+static inline const u32 __i386_swab32(u32 x)
+{
+ __asm__("bswap %0" : "=r" (x) : "0" (x));
+ return x;
+}
+# else
+# define swab32(x)\
+ ( ( (u32)(((u8*)&x)[0]) << 24 ) | ( (u32)(((u8*)&x)[1]) << 16 ) | \
+ ( (u32)(((u8*)&x)[2]) << 8 ) | ( (u32)(((u8*)&x)[3])) )
+# endif
+# endif
+#endif
+
+
+static __inline__ WORD_TYPE GetWord( bit_stream_t * p_bit_stream )
+{
+ if( p_bit_stream->p_byte <= p_bit_stream->p_end - WORD_BYTE_LENGTH )
+ {
+ return( swab32( *(((WORD_TYPE *)p_bit_stream->p_byte)++) ) );
+ }
+ else
+ {
+ PeekNextPacket( p_bit_stream );
+ return( swab32( *(((WORD_TYPE *)p_bit_stream->p_byte)++) ) );
+ }
+}
+
/*****************************************************************************
* RemoveBits : removes i_bits bits from the bit buffer
*****************************************************************************/
static __inline__ void RemoveBits( bit_stream_t * p_bit_stream, int i_bits )
{
- NeedBits( p_bit_stream, i_bits );
- DumpBits( p_bit_stream, i_bits );
+ p_bit_stream->fifo.i_available -= i_bits;
+
+ if( p_bit_stream->fifo.i_available >= 0 )
+ {
+ p_bit_stream->fifo.buffer <<= i_bits;
+ return;
+ }
+ p_bit_stream->fifo.buffer = GetWord( p_bit_stream )
+ << ( -p_bit_stream->fifo.i_available );
+ p_bit_stream->fifo.i_available += WORD_LENGTH;
}
/*****************************************************************************
- * RemoveBits32 : removes 32 bits from the bit buffer
+ * RemoveBits32 : removes 32 bits from the bit buffer (and as a side effect,
+ * refill it)
*****************************************************************************/
static __inline__ void RemoveBits32( bit_stream_t * p_bit_stream )
{
- NeedBits( p_bit_stream, 32 );
- DumpBits32( p_bit_stream );
+ p_bit_stream->fifo.buffer = GetWord( p_bit_stream )
+ << (32 - p_bit_stream->fifo.i_available);
}
/*****************************************************************************
* ShowBits : return i_bits bits from the bit stream
*****************************************************************************/
+static __inline__ WORD_TYPE ShowWord( bit_stream_t * p_bit_stream )
+{
+ if( p_bit_stream->p_byte <= p_bit_stream->p_end - WORD_BYTE_LENGTH )
+ {
+ return( swab32( *((WORD_TYPE *)p_bit_stream->p_byte) ) );
+ }
+
+ PeekNextPacket( p_bit_stream );
+ return( swab32( *((WORD_TYPE *)p_bit_stream->p_byte) ) );
+}
+
static __inline__ u32 ShowBits( bit_stream_t * p_bit_stream, int i_bits )
{
- NeedBits( p_bit_stream, i_bits );
- return( p_bit_stream->fifo.buffer >> (32 - i_bits) );
+ if( p_bit_stream->fifo.i_available >= i_bits )
+ {
+ return( p_bit_stream->fifo.buffer >> (32 - i_bits) );
+ }
+
+ return( (p_bit_stream->fifo.buffer |
+ (ShowWord( p_bit_stream ) >> p_bit_stream->fifo.i_available))
+ >> (32 - i_bits) );
}
/*****************************************************************************
*****************************************************************************/
static __inline__ u32 GetBits( bit_stream_t * p_bit_stream, int i_bits )
{
- u32 i_buffer;
+ u32 i_result;
- NeedBits( p_bit_stream, i_bits );
- i_buffer = p_bit_stream->fifo.buffer >> (32 - i_bits);
- DumpBits( p_bit_stream, i_bits );
- return( i_buffer );
+ p_bit_stream->fifo.i_available -= i_bits;
+ if( p_bit_stream->fifo.i_available >= 0 )
+ {
+ i_result = p_bit_stream->fifo.buffer >> (32 - i_bits);
+ p_bit_stream->fifo.buffer <<= i_bits;
+ return( i_result );
+ }
+
+ i_result = p_bit_stream->fifo.buffer >> (32 - i_bits);
+ p_bit_stream->fifo.buffer = GetWord( p_bit_stream );
+ i_result |= p_bit_stream->fifo.buffer
+ >> (32 + p_bit_stream->fifo.i_available);
+ p_bit_stream->fifo.buffer <<= ( -p_bit_stream->fifo.i_available );
+ p_bit_stream->fifo.i_available += WORD_LENGTH;
+
+ return( i_result );
}
/*****************************************************************************
*****************************************************************************/
static __inline__ u32 GetBits32( bit_stream_t * p_bit_stream )
{
- u32 i_buffer;
+ u32 i_result;
- NeedBits( p_bit_stream, 32 );
- i_buffer = p_bit_stream->fifo.buffer;
- DumpBits32( p_bit_stream );
- return( i_buffer );
+ i_result = p_bit_stream->fifo.buffer;
+ p_bit_stream->fifo.buffer = GetWord( p_bit_stream );
+ i_result |= p_bit_stream->fifo.buffer
+ >> (p_bit_stream->fifo.i_available);
+ p_bit_stream->fifo.buffer <<= (32 - p_bit_stream->fifo.i_available);
+
+ return( i_result );
}
/*****************************************************************************
*****************************************************************************/
static __inline__ void RealignBits( bit_stream_t * p_bit_stream )
{
- DumpBits( p_bit_stream, p_bit_stream->fifo.i_available & 7 );
+ p_bit_stream->fifo.buffer <<= (p_bit_stream->fifo.i_available & 0x7);
+ p_bit_stream->fifo.i_available &= ~0x7;
}
+