+static inline void block_ChainRelease( block_t *p_block )
+{
+ while( p_block )
+ {
+ block_t *p_next = p_block->p_next;
+ block_Release( p_block );
+ p_block = p_next;
+ }
+}
+
+static size_t block_ChainExtract( block_t *p_list, void *p_data, size_t i_max )
+{
+ size_t i_total = 0;
+ uint8_t *p = (uint8_t*)p_data;
+
+ while( p_list && i_max )
+ {
+ size_t i_copy = __MIN( i_max, p_list->i_buffer );
+ memcpy( p, p_list->p_buffer, i_copy );
+ i_max -= i_copy;
+ i_total += i_copy;
+ p += i_copy;
+
+ p_list = p_list->p_next;
+ }
+ return i_total;
+}
+
+static inline void block_ChainProperties( block_t *p_list, int *pi_count, size_t *pi_size, mtime_t *pi_length )
+{
+ size_t i_size = 0;
+ mtime_t i_length = 0;
+ int i_count = 0;
+
+ while( p_list )
+ {
+ i_size += p_list->i_buffer;
+ i_length += p_list->i_length;
+ i_count++;
+
+ p_list = p_list->p_next;
+ }
+
+ if( pi_size )
+ *pi_size = i_size;
+ if( pi_length )
+ *pi_length = i_length;
+ if( pi_count )
+ *pi_count = i_count;
+}
+
+static inline block_t *block_ChainGather( block_t *p_list )
+{
+ size_t i_total = 0;
+ mtime_t i_length = 0;
+ block_t *g;
+
+ if( p_list->p_next == NULL )
+ return p_list; /* Already gathered */
+
+ block_ChainProperties( p_list, NULL, &i_total, &i_length );
+
+ g = block_Alloc( i_total );
+ block_ChainExtract( p_list, g->p_buffer, g->i_buffer );
+
+ g->i_flags = p_list->i_flags;
+ g->i_pts = p_list->i_pts;
+ g->i_dts = p_list->i_dts;
+ g->i_length = i_length;
+
+ /* free p_list */
+ block_ChainRelease( p_list );
+ return g;
+}
+
+/****************************************************************************
+ * Fifos of blocks.
+ ****************************************************************************
+ * - block_FifoNew : create and init a new fifo
+ * - block_FifoRelease : destroy a fifo and free all blocks in it.
+ * - block_FifoPace : wait for a fifo to drain to a specified number of packets or total data size
+ * - block_FifoEmpty : free all blocks in a fifo
+ * - block_FifoPut : put a block
+ * - block_FifoGet : get a packet from the fifo (and wait if it is empty)
+ * - block_FifoShow : show the first packet of the fifo (and wait if
+ * needed), be carefull, you can use it ONLY if you are sure to be the
+ * only one getting data from the fifo.
+ * - block_FifoCount : how many packets are waiting in the fifo
+ * - block_FifoWake : wake ups a thread with block_FifoGet() = NULL
+ * (this is used to wakeup a thread when there is no data to queue)
+ *
+ * block_FifoGet and block_FifoShow are cancellation points.
+ ****************************************************************************/