Commit 3f576688 authored by Thomas Guillem's avatar Thomas Guillem Committed by Felix Paul Kühne

h264_nal: add convert_annexb_to_h264

This function converts Annex B to avcC format.
Signed-off-by: default avatarFelix Paul Kühne <fkuehne@videolan.org>
parent 3c0f6102
......@@ -147,6 +147,167 @@ void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
}
}
static block_t *h264_increase_startcode_size( block_t *p_block,
size_t i_start_ofs )
{
block_t *p_new;
uint32_t i_buf = p_block->i_buffer - i_start_ofs;
uint8_t *p_buf = p_block->p_buffer;
uint8_t *p_new_buf;
size_t i_ofs = i_start_ofs;
size_t i_grow = 0;
size_t i_new_ofs;
/* Search all startcode of size 3 */
while( i_buf > 0 )
{
if( i_buf > 3 && memcmp( &p_buf[i_ofs], annexb_startcode, 3 ) == 0 )
{
if( i_ofs == 0 || p_buf[i_ofs - 1] != 0 )
i_grow++;
i_buf -= 3;
i_ofs += 3;
}
else
{
i_buf--;
i_ofs++;
}
}
if( i_grow == 0 )
return p_block;
/* Alloc a bigger buffer */
p_new = block_Alloc( p_block->i_buffer + i_grow );
if( !p_new )
return NULL;
i_buf = p_block->i_buffer - i_start_ofs;
p_new_buf = p_new->p_buffer;
i_new_ofs = i_ofs = i_start_ofs;
/* Copy the beginning of the buffer (same data) */
if( i_start_ofs )
memcpy( p_new_buf, p_buf, i_start_ofs );
/* Copy the rest of the buffer and append a 0 before each 000001 */
while( i_buf > 0 )
{
if( i_buf > 3 && memcmp( &p_buf[i_ofs], annexb_startcode, 3 ) == 0 )
{
if( i_ofs == 0 || p_buf[i_ofs - 1] != 0 )
p_new_buf[i_new_ofs++] = 0;
for( int i = 0; i < 3; ++i )
p_new_buf[i_new_ofs++] = p_buf[i_ofs++];
i_buf -= 3;
} else
{
p_new_buf[i_new_ofs++] = p_buf[i_ofs++];
i_buf--;
}
}
block_Release( p_block );
return p_new;
}
static int h264_replace_startcode( uint8_t *p_buf,
size_t i_nal_length_size,
size_t i_startcode_ofs,
size_t i_nal_size )
{
if( i_nal_size < (unsigned) 1 << ( 8 * i_nal_length_size) )
{
/* NAL is too big to fit in i_nal_length_size */
return -1;
}
p_buf[i_startcode_ofs++] = i_nal_size >> (--i_nal_length_size * 8);
if( !i_nal_length_size )
return 0;
p_buf[i_startcode_ofs++] = i_nal_size >> (--i_nal_length_size * 8);
if( !i_nal_length_size )
return 0;
p_buf[i_startcode_ofs++] = i_nal_size >> (--i_nal_length_size * 8);
p_buf[i_startcode_ofs] = i_nal_size;
return 0;
}
block_t *convert_annexb_to_h264( block_t *p_block, size_t i_nal_length_size )
{
size_t i_startcode_ofs = 0;
size_t i_startcode_size = 0;
uint32_t i_buf = p_block->i_buffer;
uint8_t *p_buf = p_block->p_buffer;
size_t i_ofs = 0;
/* The length of the NAL size is encoded using 1, 2 or 4 bytes */
if( i_nal_length_size != 1 && i_nal_length_size != 2
&& i_nal_length_size != 4 )
goto error;
/* Replace the Annex B start code with the size of the NAL. */
while( i_buf > 0 )
{
if( i_buf > 3 && memcmp( &p_buf[i_ofs], annexb_startcode, 3 ) == 0 )
{
if( i_startcode_size )
{
size_t i_nal_size = i_ofs - i_startcode_ofs - i_startcode_size;
if( i_ofs > 0 && p_buf[i_ofs - 1] == 0 )
i_nal_size--;
if( h264_replace_startcode( p_buf, i_nal_length_size,
i_startcode_ofs,
i_nal_size ) )
goto error;
}
if( i_ofs > 0 && p_buf[i_ofs - 1] == 0 )
{
/* startcode of size 3 */
i_startcode_ofs = i_ofs - 1;
i_startcode_size = 4;
}
else
{
i_startcode_ofs = i_ofs;
i_startcode_size = 3;
}
if( i_startcode_size < i_nal_length_size )
{
/* i_nal_length_size can't fit in i_startcode_size. Therefore,
* reallocate a buffer in order to increase all startcode that
* are smaller than i_nal_length_size. This is not efficient but
* it's a corner case that won't happen often */
p_block = h264_increase_startcode_size( p_block, i_startcode_ofs );
if( !p_block )
return NULL;
p_buf = p_block->p_buffer;
i_startcode_size++;
}
i_buf -= 3;
i_ofs += 3;
}
else
{
i_buf--;
i_ofs++;
}
}
if( i_startcode_size
&& h264_replace_startcode( p_buf, i_nal_length_size, i_startcode_ofs,
i_ofs - i_startcode_ofs - i_startcode_size) )
return NULL;
else
return p_block;
error:
block_Release( p_block );
return NULL;
}
int h264_get_spspps( uint8_t *p_buf, size_t i_buf,
uint8_t **pp_sps, size_t *p_sps_size,
uint8_t **pp_pps, size_t *p_pps_size )
......
......@@ -120,9 +120,16 @@ int convert_sps_pps( decoder_t *p_dec, const uint8_t *p_buf,
uint32_t i_out_buf_size, uint32_t *p_sps_pps_size,
uint32_t *p_nal_length_size);
/* Convert avcC format to Annex B in-place */
void convert_h264_to_annexb( uint8_t *p_buf, uint32_t i_len,
size_t i_nal_length_size );
/* Convert Annex B to avcC format in-place
* Returns the same p_block or a new p_block if there is not enough room to put
* the NAL size. In case of error, NULL is returned and p_block is released.
* */
block_t *convert_annexb_to_h264( block_t *p_block, size_t i_nal_length_size );
/* Get the SPS/PPS pointers from an Annex B buffer
* Returns 0 if a SPS and/or a PPS is found */
int h264_get_spspps( uint8_t *p_buf, size_t i_buf,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment