* - "input.h"
*****************************************************************************/
+#define WORD_TYPE u32
+#define WORD_BYTE_LENGTH 4
+#define WORD_LENGTH 32
+
/*****************************************************************************
* Macros
*****************************************************************************/
/* 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;
* 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)
+#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)\
+ ((((u8*)&x)[0] << 24) | (((u8*)&x)[1] << 16) | \
+ (((u8*)&x)[2] << 8) | (((u8*)&x)[3]))
+# 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;
+
+ 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;
- 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 );
+ 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 & 0x7 );
+ p_bit_stream->fifo.buffer <<= (p_bit_stream->fifo.i_available & 0x7);
+ p_bit_stream->fifo.i_available &= ~0x7;
}
p_bit_stream->p_byte = p_bit_stream->p_ts->buffer + p_bit_stream->p_ts->i_payload_start;
p_bit_stream->p_end = p_bit_stream->p_ts->buffer + p_bit_stream->p_ts->i_payload_end;
}
+
+void PeekNextPacket( bit_stream_t * p_bit_stream )
+{
+ WORD_TYPE buffer_left;
+ int i_bytes_left; /* FIXME : not portable in a 64bit environment */
+
+ /* Put the remaining bytes (not aligned on a word boundary) in a
+ * temporary buffer. */
+ i_bytes_left = p_bit_stream->p_end - p_bit_stream->p_byte;
+ buffer_left = *((WORD_TYPE *)p_bit_stream->p_end - 1);
+
+ /* We are looking for the next TS packet that contains real data,
+ * and not just a PES header */
+ do
+ {
+ /* We were reading the last TS packet of this PES packet... It's
+ * time to jump to the next PES packet */
+ if ( p_bit_stream->p_ts->p_next_ts == NULL )
+ {
+ /* We are going to read/write the start and end indexes of the
+ * decoder fifo and to use the fifo's conditional variable,
+ * that's why we need to take the lock before */
+ vlc_mutex_lock( &p_bit_stream->p_decoder_fifo->data_lock );
+
+ /* Is the input thread dying ? */
+ if ( p_bit_stream->p_input->b_die )
+ {
+ vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
+ return;
+ }
+
+ /* We should increase the start index of the decoder fifo, but
+ * if we do this now, the input thread could overwrite the
+ * pointer to the current PES packet, and we weren't able to
+ * give it back to the netlist. That's why we free the PES
+ * packet first. */
+ input_NetlistFreePES( p_bit_stream->p_input, DECODER_FIFO_START(*p_bit_stream->p_decoder_fifo) );
+ DECODER_FIFO_INCSTART( *p_bit_stream->p_decoder_fifo );
+
+ while ( DECODER_FIFO_ISEMPTY(*p_bit_stream->p_decoder_fifo) )
+ {
+ vlc_cond_wait( &p_bit_stream->p_decoder_fifo->data_wait, &p_bit_stream->p_decoder_fifo->data_lock );
+ if ( p_bit_stream->p_input->b_die )
+ {
+ vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
+ return;
+ }
+ }
+
+ /* The next byte could be found in the next PES packet */
+ p_bit_stream->p_ts = DECODER_FIFO_START( *p_bit_stream->p_decoder_fifo )->p_first_ts;
+
+ /* We can release the fifo's data lock */
+ vlc_mutex_unlock( &p_bit_stream->p_decoder_fifo->data_lock );
+ }
+ /* Perhaps the next TS packet of the current PES packet contains
+ * real data (ie its payload's size is greater than 0) */
+ else
+ {
+ p_bit_stream->p_ts = p_bit_stream->p_ts->p_next_ts;
+ }
+ } while ( p_bit_stream->p_ts->i_payload_start == p_bit_stream->p_ts->i_payload_end );
+
+ /* We've found a TS packet which contains interesting data... */
+ p_bit_stream->p_byte = p_bit_stream->p_ts->buffer + p_bit_stream->p_ts->i_payload_start;
+ p_bit_stream->p_end = p_bit_stream->p_ts->buffer + p_bit_stream->p_ts->i_payload_end;
+
+ /* Copy remaining bits of the previous packet */
+ *((WORD_TYPE *)p_bit_stream->p_byte - 1) = buffer_left;
+ p_bit_stream->p_byte -= i_bytes_left;
+}