Browse Source

packetizer: h264: gather and store SPSEXT

pull/126/head
Francois Cartegnie 5 years ago
committed by Jean-Baptiste Kempf
parent
commit
35251232e2
  1. 70
      modules/packetizer/h264.c

70
modules/packetizer/h264.c

@ -95,6 +95,10 @@ typedef struct
block_t *p_block;
h264_picture_parameter_set_t *p_pps;
} pps[H264_PPS_ID_MAX + 1];
struct
{
block_t *p_block;
} spsext[H264_SPSEXT_ID_MAX + 1];
const h264_sequence_parameter_set_t *p_active_sps;
const h264_picture_parameter_set_t *p_active_pps;
@ -151,6 +155,7 @@ static block_t *ParseNALBlock( decoder_t *, bool *pb_ts_used, block_t * );
static block_t *OutputPicture( decoder_t *p_dec );
static void PutSPS( decoder_t *p_dec, block_t *p_frag );
static void PutPPS( decoder_t *p_dec, block_t *p_frag );
static void PutSPSEXT( decoder_t *p_dec, block_t *p_frag );
static bool ParseSliceHeader( decoder_t *p_dec, const block_t *p_frag, h264_slice_t *p_slice );
static bool ParseSeiCallback( const hxxx_sei_data_t *, void * );
@ -187,6 +192,13 @@ static void StorePPS( decoder_sys_t *p_sys, uint8_t i_id,
p_sys->pps[i_id].p_pps = p_pps;
}
static void StoreSPSEXT( decoder_sys_t *p_sys, uint8_t i_id, block_t *p_block )
{
if( p_sys->spsext[i_id].p_block )
block_Release( p_sys->spsext[i_id].p_block );
p_sys->spsext[i_id].p_block = p_block;
}
static void ActivateSets( decoder_t *p_dec, const h264_sequence_parameter_set_t *p_sps,
const h264_picture_parameter_set_t *p_pps )
{
@ -241,18 +253,26 @@ static void ActivateSets( decoder_t *p_dec, const h264_sequence_parameter_set_t
{
const block_t *p_spsblock = p_sys->sps[p_sps->i_id].p_block;
const block_t *p_ppsblock = p_sys->pps[p_pps->i_id].p_block;
const block_t *p_spsextblock = p_sys->spsext[p_sps->i_id].p_block;
if( p_spsblock && p_ppsblock )
{
size_t i_alloc = p_ppsblock->i_buffer + p_spsblock->i_buffer;
if( p_spsextblock )
i_alloc += p_spsextblock->i_buffer;
p_dec->fmt_out.p_extra = malloc( i_alloc );
if( p_dec->fmt_out.p_extra )
{
uint8_t*p_buf = p_dec->fmt_out.p_extra;
p_dec->fmt_out.i_extra = i_alloc;
memcpy( &p_buf[0], p_spsblock->p_buffer, p_spsblock->i_buffer );
memcpy( &p_buf[p_spsblock->i_buffer], p_ppsblock->p_buffer,
p_ppsblock->i_buffer );
memcpy( p_buf, p_spsblock->p_buffer, p_spsblock->i_buffer );
p_buf += p_spsblock->i_buffer;
if( p_spsextblock )
{
memcpy( p_buf, p_spsextblock->p_buffer, p_spsextblock->i_buffer );
p_buf += p_spsextblock->i_buffer;
}
memcpy( p_buf, p_ppsblock->p_buffer, p_ppsblock->i_buffer );
}
}
}
@ -354,6 +374,8 @@ static int Open( vlc_object_t *p_this )
p_sys->pps[i].p_block = NULL;
}
p_sys->p_active_pps = NULL;
for( i = 0; i <= H264_SPSEXT_ID_MAX; i++ )
p_sys->spsext[i].p_block = NULL;
p_sys->i_recovery_frame_cnt = UINT_MAX;
h264_slice_init( &p_sys->slice );
@ -471,6 +493,8 @@ static void Close( vlc_object_t *p_this )
StoreSPS( p_sys, i, NULL, NULL );
for( i = 0; i <= H264_PPS_ID_MAX; i++ )
StorePPS( p_sys, i, NULL, NULL );
for( i = 0; i <= H264_SPSEXT_ID_MAX; i++ )
StoreSPSEXT( p_sys, i, NULL );
packetizer_Clean( &p_sys->packetizer );
@ -711,6 +735,11 @@ static block_t *ParseNALBlock( decoder_t *p_dec, bool *pb_ts_used, block_t *p_fr
break;
case H264_NAL_SPS_EXT:
PutSPSEXT( p_dec, p_frag );
if( p_sys->b_slice )
p_pic = OutputPicture( p_dec );
break;
case H264_NAL_PREFIX: /* first slice/VCL associated data */
case H264_NAL_SUBSET_SPS:
case H264_NAL_DEPTH_PS:
@ -855,6 +884,10 @@ static block_t *OutputPicture( decoder_t *p_dec )
{
if( p_sys->sps[i].p_block )
block_ChainLastAppend( &pp_xpsnal_tail, block_Duplicate( p_sys->sps[i].p_block ) );
/* 7.4.1.2.3, shall be the next NAL unit after a sequence parameter set NAL unit
* having the same value of seq_parameter_set_id */
if( p_sys->spsext[i].p_block )
block_ChainLastAppend( &pp_xpsnal_tail, block_Duplicate( p_sys->spsext[i].p_block ) );
}
for( int i = 0; i < H264_PPS_ID_MAX && (b_need_sps_pps || p_sys->b_new_pps); i++ )
{
@ -1112,6 +1145,37 @@ static void PutPPS( decoder_t *p_dec, block_t *p_frag )
StorePPS( p_sys, p_pps->i_id, p_frag, p_pps );
}
static void PutSPSEXT( decoder_t *p_dec, block_t *p_frag )
{
decoder_sys_t *p_sys = p_dec->p_sys;
const uint8_t *p_buffer = p_frag->p_buffer;
size_t i_buffer = p_frag->i_buffer;
if( !hxxx_strip_AnnexB_startcode( &p_buffer, &i_buffer ) )
{
block_Release( p_frag );
return;
}
h264_sequence_parameter_set_extension_t *p_spsext =
h264_decode_sps_extension( p_buffer, i_buffer, true );
if( !p_spsext )
{
msg_Warn( p_dec, "invalid SPSEXT" );
block_Release( p_frag );
return;
}
/* We have a new SPSEXT */
if( !p_sys->spsext[p_spsext->i_sps_id].p_block )
msg_Dbg( p_dec, "found NAL_SPSEXT (sps_id=%d)", p_spsext->i_sps_id );
StoreSPSEXT( p_sys, p_spsext->i_sps_id, p_frag );
/* we don't need a decoded one */
h264_release_sps_extension( p_spsext );
}
static void GetSPSPPS( uint8_t i_pps_id, void *priv,
const h264_sequence_parameter_set_t **pp_sps,
const h264_picture_parameter_set_t **pp_pps )

Loading…
Cancel
Save