+#define STD_PES_PAYLOAD 170
+static block_t *FixPES( sout_mux_t *p_mux, block_fifo_t *p_fifo )
+{
+ block_t *p_data;
+ size_t i_size;
+
+ p_data = block_FifoShow( p_fifo );
+ i_size = p_data->i_buffer;
+
+ if( i_size == STD_PES_PAYLOAD )
+ {
+ return block_FifoGet( p_fifo );
+ }
+ else if( i_size > STD_PES_PAYLOAD )
+ {
+ block_t *p_new = block_New( p_mux, STD_PES_PAYLOAD );
+ vlc_memcpy( p_new->p_buffer, p_data->p_buffer, STD_PES_PAYLOAD );
+ p_new->i_pts = p_data->i_pts;
+ p_new->i_dts = p_data->i_dts;
+ p_new->i_length = p_data->i_length * STD_PES_PAYLOAD
+ / p_data->i_buffer;
+ p_data->i_buffer -= STD_PES_PAYLOAD;
+ p_data->p_buffer += STD_PES_PAYLOAD;
+ p_data->i_pts += p_new->i_length;
+ p_data->i_dts += p_new->i_length;
+ p_data->i_length -= p_new->i_length;
+ p_data->i_flags |= BLOCK_FLAG_NO_KEYFRAME;
+ return p_new;
+ }
+ else
+ {
+ block_t *p_next;
+ int i_copy;
+
+ p_data = block_FifoGet( p_fifo );
+ p_data = block_Realloc( p_data, 0, STD_PES_PAYLOAD );
+ p_next = block_FifoShow( p_fifo );
+ if ( p_data->i_flags & BLOCK_FLAG_NO_KEYFRAME )
+ {
+ p_data->i_flags &= ~BLOCK_FLAG_NO_KEYFRAME;
+ p_data->i_pts = p_next->i_pts;
+ p_data->i_dts = p_next->i_dts;
+ }
+ i_copy = __MIN( STD_PES_PAYLOAD - i_size, p_next->i_buffer );
+
+ vlc_memcpy( &p_data->p_buffer[i_size], p_next->p_buffer, i_copy );
+ p_next->i_pts += p_next->i_length * i_copy / p_next->i_buffer;
+ p_next->i_dts += p_next->i_length * i_copy / p_next->i_buffer;
+ p_next->i_length -= p_next->i_length * i_copy / p_next->i_buffer;
+ p_next->i_buffer -= i_copy;
+ p_next->p_buffer += i_copy;
+ p_next->i_flags |= BLOCK_FLAG_NO_KEYFRAME;
+
+ if( !p_next->i_buffer )
+ {
+ p_next = block_FifoGet( p_fifo );
+ block_Release( p_next );
+ }
+ return p_data;
+ }
+}
+
+static block_t *Add_ADTS( block_t *p_data, es_format_t *p_fmt )
+{
+ uint8_t *p_extra = p_fmt->p_extra;
+
+ if( !p_data || p_fmt->i_extra < 2 || !p_extra )
+ return p_data; /* no data to construct the headers */
+
+ int i_index = ( (p_extra[0] << 1) | (p_extra[1] >> 7) ) & 0x0f;
+ int i_profile = (p_extra[0] >> 3) - 1; /* i_profile < 4 */
+
+ if( i_index == 0x0f && p_fmt->i_extra < 5 )
+ return p_data; /* not enough data */
+
+ int i_channels = (p_extra[i_index == 0x0f ? 4 : 1] >> 3) & 0x0f;
+
+#define ADTS_HEADER_SIZE 7 /* CRC needs 2 more bytes */
+
+
+ /* keep a copy in case block_Realloc() fails */
+ block_t *p_bak_block = block_Duplicate( p_data );
+ if( !p_bak_block ) /* OOM, block_Realloc() is likely to lose our block */
+ return p_data; /* the frame isn't correct but that's the best we have */
+
+ block_t *p_new_block = block_Realloc( p_data, ADTS_HEADER_SIZE,
+ p_data->i_buffer );
+ if( !p_new_block )
+ return p_bak_block; /* OOM, send the (incorrect) original frame */
+
+ block_Release( p_bak_block ); /* we don't need the copy anymore */
+
+
+ uint8_t *p_buffer = p_new_block->p_buffer;
+
+ /* fixed header */
+ p_buffer[0] = 0xff;
+ p_buffer[1] = 0xf1; /* 0xf0 | 0x00 | 0x00 | 0x01 */
+ p_buffer[2] = (i_profile << 6) | ((i_index & 0x0f) << 2) | ((i_channels >> 2) & 0x01) ;
+ p_buffer[3] = (i_channels << 6) | ((p_data->i_buffer >> 11) & 0x03);
+
+ /* variable header (starts at last 2 bits of 4th byte) */
+
+ int i_fullness = 0x7ff; /* 0x7ff means VBR */
+ /* XXX: We should check if it's CBR or VBR, but no known implementation
+ * do that, and it's a pain to calculate this field */
+
+ p_buffer[4] = p_data->i_buffer >> 3;
+ p_buffer[5] = ((p_data->i_buffer & 0x07) << 5) | ((i_fullness >> 6) & 0x1f);
+ p_buffer[6] = ((i_fullness & 0x3f) << 2) /* | 0xfc */;
+
+ return p_new_block;
+}
+