decoder_fifo.h 11.7 KB
Newer Older
Michel Kaempf's avatar
Michel Kaempf committed
1 2 3 4 5 6 7
/******************************************************************************
 * decoder_fifo.h: interface for decoders PES fifo
 * (c)1999 VideoLAN
 ******************************************************************************
 * Required headers:
 * - "config.h"
 * - "common.h"
8
 * - "vlc_thread.h"
Michel Kaempf's avatar
Michel Kaempf committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 * - "input.h"
 ******************************************************************************/

/******************************************************************************
 * 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 ) \
                                          & 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) \
                                                         & FIFO_SIZE )

/******************************************************************************
 * decoder_fifo_t
 ******************************************************************************
 * This rotative FIFO contains PES packets that are to be decoded...
 ******************************************************************************/
typedef struct
{
34 35
    vlc_mutex_t         data_lock;                          /* fifo data lock */
    vlc_cond_t          data_wait;          /* fifo data conditional variable */
Michel Kaempf's avatar
Michel Kaempf committed
36 37 38 39 40 41 42

    /* buffer is an array of PES packets pointers */
    pes_packet_t *      buffer[FIFO_SIZE + 1];
    int                 i_start;
    int                 i_end;

} decoder_fifo_t;
43

Michel Kaempf's avatar
Michel Kaempf committed
44 45 46 47
/******************************************************************************
 * bit_fifo_t : bit fifo descriptor
 ******************************************************************************
 * This type describes a bit fifo used to store bits while working with the
48 49 50 51 52 53 54 55 56 57 58 59 60 61
 * input stream at the bit level.
 ******************************************************************************/
typedef struct bit_fifo_s
{
    /* 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;

    /* Number of bits available in the bit buffer */
    int                 i_available;

} bit_fifo_t;

Michel Kaempf's avatar
Michel Kaempf committed
62 63 64 65
/******************************************************************************
 * bit_stream_t : bit stream descriptor
 ******************************************************************************
 * This type, based on a PES stream, includes all the structures needed to
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
 * handle the input stream like a bit stream.
 ******************************************************************************/
typedef struct bit_stream_s
{
    /*
     * Input structures
     */
    /* The input thread feeds the stream with fresh PES packets */
    input_thread_t *    p_input;
    /* The decoder fifo contains the data of the PES stream */
    decoder_fifo_t *    p_decoder_fifo;

    /*
     * Byte structures
     */
    /* Current TS packet (in the current PES packet of the PES stream) */
    ts_packet_t *       p_ts;
    /* Index of the next byte that is to be read (in the current TS packet) */
    unsigned int        i_byte;

    /*
     * Bit structures
     */
    bit_fifo_t          fifo;

} bit_stream_t;


/*****************************************************************************
 * GetByte : reads the next byte in the input stream
 *****************************************************************************/
static __inline__ byte_t GetByte( bit_stream_t * p_bit_stream )
{
    /* Are there some bytes left in the current TS packet ? */
    if ( p_bit_stream->i_byte < p_bit_stream->p_ts->i_payload_end )
    {
        return( p_bit_stream->p_ts->buffer[ p_bit_stream->i_byte++ ] );
    }
    else
    {
        /* 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 )
            {
Michel Kaempf's avatar
Michel Kaempf committed
114 115 116 117 118
                /* 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 );

119 120 121
                /* Is the input thread dying ? */
                if ( p_bit_stream->p_input->b_die )
                {
Michel Kaempf's avatar
Michel Kaempf committed
122
                    vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
123 124
                    return( 0 );
                }
Michel Kaempf's avatar
Michel Kaempf committed
125

126 127 128 129 130 131 132 133 134 135
                /* 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) )
                {
Michel Kaempf's avatar
Michel Kaempf committed
136
                    vlc_cond_wait( &p_bit_stream->p_decoder_fifo->data_wait, &p_bit_stream->p_decoder_fifo->data_lock );
Michel Kaempf's avatar
Michel Kaempf committed
137 138
                    if ( p_bit_stream->p_input->b_die )
                    {
139
                        vlc_mutex_unlock( &(p_bit_stream->p_decoder_fifo->data_lock) );
Michel Kaempf's avatar
Michel Kaempf committed
140 141
                        return( 0 );
                    }
142 143 144 145 146 147
                }

                /* 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 */
148
                vlc_mutex_unlock( &p_bit_stream->p_decoder_fifo->data_lock );
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
            }
            /* 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... As we
         * return the payload's first byte, we set i_byte to the following
         * one */
        p_bit_stream->i_byte = p_bit_stream->p_ts->i_payload_start;
        return( p_bit_stream->p_ts->buffer[ p_bit_stream->i_byte++ ] );
    }
}

Michel Kaempf's avatar
Michel Kaempf committed
166 167
/******************************************************************************
 * NeedBits : reads i_bits new bits in the bit stream and stores them in the
Jean-Marc Dressler's avatar
 
Jean-Marc Dressler committed
168
 *            bit buffer
Michel Kaempf's avatar
Michel Kaempf committed
169 170
 ******************************************************************************
 * - i_bits must be less or equal 32 !
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
 * - There is something important to notice with that function : if the number
 * of bits available in the bit buffer when calling NeedBits() is greater than
 * 24 (i_available > 24) but less than the number of needed bits
 * (i_available < i_bits), the byte returned by GetByte() will be shifted with
 * a negative value and the number of bits available in the bit buffer will be
 * set to more than 32 !
 ******************************************************************************/
static __inline__ void NeedBits( bit_stream_t * p_bit_stream, int i_bits )
{
    while ( p_bit_stream->fifo.i_available < i_bits )
    {
        p_bit_stream->fifo.buffer |= ((u32)GetByte( p_bit_stream )) << (24 - p_bit_stream->fifo.i_available);
        p_bit_stream->fifo.i_available += 8;
    }
}

Michel Kaempf's avatar
Michel Kaempf committed
187 188 189 190
/******************************************************************************
 * DumpBits : removes i_bits bits from the bit buffer
 ******************************************************************************
 * - i_bits <= i_available
191 192 193 194 195 196 197
 * - i_bits < 32 (because (u32 << 32) <=> (u32 = u32))
 ******************************************************************************/
static __inline__ void DumpBits( bit_stream_t * p_bit_stream, int i_bits )
{
    p_bit_stream->fifo.buffer <<= i_bits;
    p_bit_stream->fifo.i_available -= i_bits;
}
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217

/******************************************************************************
 * 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.
 ******************************************************************************/
static __inline__ void DumpBits32( bit_stream_t * p_bit_stream )
{
    p_bit_stream->fifo.buffer = 0;
    p_bit_stream->fifo.i_available = 0;
}

/*
 * For the following functions, please read VERY CAREFULLY the warning in
 * NeedBits(). If i_bits > 24, the stream parser must be already aligned
 * on an 8-bit boundary, or you will get curious results (that is, you
 * need to call RealignBits() before).
 */

Jean-Marc Dressler's avatar
 
Jean-Marc Dressler committed
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
/******************************************************************************
 * 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 );
}

/******************************************************************************
 * RemoveBits32 : removes 32 bits from the bit buffer
 ******************************************************************************/
static __inline__ void RemoveBits32( bit_stream_t * p_bit_stream )
{
    NeedBits( p_bit_stream, 32 );
    DumpBits32( p_bit_stream );
}

236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
/******************************************************************************
 * ShowBits : return i_bits bits from the bit stream
 ******************************************************************************/
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) );
}

/******************************************************************************
 * GetBits : returns i_bits bits from the bit stream and removes them
 ******************************************************************************/
static __inline__ u32 GetBits( bit_stream_t * p_bit_stream, int i_bits )
{
    u32 i_buffer;

    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 );
}

/******************************************************************************
 * GetBits32 : returns 32 bits from the bit stream and removes them
 ******************************************************************************/
static __inline__ u32 GetBits32( bit_stream_t * p_bit_stream )
{
    u32 i_buffer;

    NeedBits( p_bit_stream, 32 );
    i_buffer = p_bit_stream->fifo.buffer;
    DumpBits32( p_bit_stream );
    return( i_buffer );
}

/******************************************************************************
 * RealignBits : realigns the bit buffer on an 8-bit boundary
 ******************************************************************************/
static __inline__ void RealignBits( bit_stream_t * p_bit_stream )
{
    DumpBits( p_bit_stream, p_bit_stream->fifo.i_available & 7 );
}