Commit 126902d3 authored by Laurent Aimar's avatar Laurent Aimar

Added support for multiple SPS and/or PPS.

parent 8c8db25b
...@@ -96,14 +96,14 @@ struct decoder_sys_t ...@@ -96,14 +96,14 @@ struct decoder_sys_t
bool b_slice; bool b_slice;
block_t *p_frame; block_t *p_frame;
bool b_header;
bool b_sps; bool b_sps;
bool b_pps; bool b_pps;
bool b_header; block_t *pp_sps[SPS_MAX];
block_t *pp_pps[PPS_MAX];
/* avcC data */ /* avcC data */
int i_avcC_length_size; int i_avcC_length_size;
block_t *p_sps;
block_t *p_pps;
/* Useful values of the Sequence Parameter Set */ /* Useful values of the Sequence Parameter Set */
int i_log2_max_frame_num; int i_log2_max_frame_num;
...@@ -168,6 +168,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -168,6 +168,7 @@ static int Open( vlc_object_t *p_this )
{ {
decoder_t *p_dec = (decoder_t*)p_this; decoder_t *p_dec = (decoder_t*)p_this;
decoder_sys_t *p_sys; decoder_sys_t *p_sys;
int i;
if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'h', '2', '6', '4') && if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'h', '2', '6', '4') &&
p_dec->fmt_in.i_codec != VLC_FOURCC( 'H', '2', '6', '4') && p_dec->fmt_in.i_codec != VLC_FOURCC( 'H', '2', '6', '4') &&
...@@ -194,11 +195,13 @@ static int Open( vlc_object_t *p_this ) ...@@ -194,11 +195,13 @@ static int Open( vlc_object_t *p_this )
p_sys->bytestream = block_BytestreamInit(); p_sys->bytestream = block_BytestreamInit();
p_sys->b_slice = false; p_sys->b_slice = false;
p_sys->p_frame = NULL; p_sys->p_frame = NULL;
p_sys->b_header= false;
p_sys->b_sps = false; p_sys->b_sps = false;
p_sys->b_pps = false; p_sys->b_pps = false;
p_sys->p_sps = 0; for( i = 0; i < SPS_MAX; i++ )
p_sys->p_pps = 0; p_sys->pp_sps[i] = NULL;
p_sys->b_header= false; for( i = 0; i < PPS_MAX; i++ )
p_sys->pp_pps[i] = NULL;
p_sys->slice.i_nal_type = -1; p_sys->slice.i_nal_type = -1;
p_sys->slice.i_nal_ref_idc = -1; p_sys->slice.i_nal_ref_idc = -1;
...@@ -263,26 +266,53 @@ static int Open( vlc_object_t *p_this ) ...@@ -263,26 +266,53 @@ static int Open( vlc_object_t *p_this )
msg_Dbg( p_dec, "avcC length size=%d, sps=%d, pps=%d", msg_Dbg( p_dec, "avcC length size=%d, sps=%d, pps=%d",
p_sys->i_avcC_length_size, i_sps, i_pps ); p_sys->i_avcC_length_size, i_sps, i_pps );
if( !p_sys->p_sps || p_sys->p_pps ) if( !p_sys->b_sps || !p_sys->b_pps )
return VLC_EGENERIC; return VLC_EGENERIC;
/* FIXME: FFMPEG isn't happy at all if you leave this */ /* FIXME: FFMPEG isn't happy at all if you leave this */
if( p_dec->fmt_out.i_extra > 0 ) free( p_dec->fmt_out.p_extra ); if( p_dec->fmt_out.i_extra > 0 )
free( p_dec->fmt_out.p_extra );
p_dec->fmt_out.i_extra = 0; p_dec->fmt_out.i_extra = 0;
p_dec->fmt_out.p_extra = NULL; p_dec->fmt_out.p_extra = NULL;
/* Set the new extradata */ /* Set the new extradata */
p_dec->fmt_out.i_extra = p_sys->p_pps->i_buffer + p_sys->p_sps->i_buffer; for( i = 0; i < SPS_MAX; i++ )
{
if( p_sys->pp_sps[i] )
p_dec->fmt_out.i_extra += p_sys->pp_sps[i]->i_buffer;
}
for( i = 0; i < PPS_MAX; i++ )
{
if( p_sys->pp_pps[i] )
p_dec->fmt_out.i_extra += p_sys->pp_pps[i]->i_buffer;
}
p_dec->fmt_out.p_extra = malloc( p_dec->fmt_out.i_extra ); p_dec->fmt_out.p_extra = malloc( p_dec->fmt_out.i_extra );
if( p_dec->fmt_out.p_extra ) if( p_dec->fmt_out.p_extra )
{ {
memcpy( (uint8_t*)p_dec->fmt_out.p_extra, uint8_t *p_dst = p_dec->fmt_out.p_extra;
p_sys->p_sps->p_buffer, p_sys->p_sps->i_buffer);
memcpy( (uint8_t*)p_dec->fmt_out.p_extra+p_sys->p_sps->i_buffer, for( i = 0; i < SPS_MAX; i++ )
p_sys->p_pps->p_buffer, p_sys->p_pps->i_buffer); {
if( p_sys->pp_sps[i] )
{
memcpy( p_dst, p_sys->pp_sps[i]->p_buffer, p_sys->pp_sps[i]->i_buffer );
p_dst += p_sys->pp_sps[i]->i_buffer;
}
}
for( i = 0; i < PPS_MAX; i++ )
{
if( p_sys->pp_pps[i] )
{
memcpy( p_dst, p_sys->pp_pps[i]->p_buffer, p_sys->pp_pps[i]->i_buffer );
p_dst += p_sys->pp_pps[i]->i_buffer;
}
}
p_sys->b_header = true; p_sys->b_header = true;
} }
else p_dec->fmt_out.i_extra = 0; else
{
p_dec->fmt_out.i_extra = 0;
}
/* Set callback */ /* Set callback */
p_dec->pf_packetize = PacketizeAVC1; p_dec->pf_packetize = PacketizeAVC1;
...@@ -323,10 +353,19 @@ static void Close( vlc_object_t *p_this ) ...@@ -323,10 +353,19 @@ static void Close( vlc_object_t *p_this )
{ {
decoder_t *p_dec = (decoder_t*)p_this; decoder_t *p_dec = (decoder_t*)p_this;
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
int i;
if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame ); if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame );
if( p_sys->p_sps ) block_Release( p_sys->p_sps ); for( i = 0; i < SPS_MAX; i++ )
if( p_sys->p_pps ) block_Release( p_sys->p_pps ); {
if( p_sys->pp_sps[i] )
block_Release( p_sys->pp_sps[i] );
}
for( i = 0; i < PPS_MAX; i++ )
{
if( p_sys->pp_pps[i] )
block_Release( p_sys->pp_pps[i] );
}
block_BytestreamRelease( &p_sys->bytestream ); block_BytestreamRelease( &p_sys->bytestream );
free( p_sys ); free( p_sys );
} }
...@@ -651,16 +690,29 @@ static block_t *OutputPicture( decoder_t *p_dec ) ...@@ -651,16 +690,29 @@ static block_t *OutputPicture( decoder_t *p_dec )
if( !p_sys->b_header && p_sys->slice.i_frame_type != BLOCK_FLAG_TYPE_I) if( !p_sys->b_header && p_sys->slice.i_frame_type != BLOCK_FLAG_TYPE_I)
return NULL; return NULL;
if( p_sys->slice.i_frame_type == BLOCK_FLAG_TYPE_I && p_sys->p_sps && p_sys->p_pps ) if( p_sys->slice.i_frame_type == BLOCK_FLAG_TYPE_I && p_sys->b_sps && p_sys->b_pps )
{ {
block_t *p_sps = block_Duplicate( p_sys->p_sps ); block_t *p_list = NULL;
block_t *p_pps = block_Duplicate( p_sys->p_pps ); int i;
p_sps->i_dts = p_sys->p_frame->i_dts;
p_sps->i_pts = p_sys->p_frame->i_pts; for( i = 0; i < SPS_MAX; i++ )
block_ChainAppend( &p_sps, p_pps ); {
block_ChainAppend( &p_sps, p_sys->p_frame ); if( p_sys->pp_sps[i] )
block_ChainAppend( &p_list, block_Duplicate( p_sys->pp_sps[i] ) );
}
for( i = 0; i < PPS_MAX; i++ )
{
if( p_sys->pp_pps[i] )
block_ChainAppend( &p_list, block_Duplicate( p_sys->pp_pps[i] ) );
}
if( p_list )
{
p_list->i_dts = p_sys->p_frame->i_dts;
p_list->i_pts = p_sys->p_frame->i_pts;
p_sys->b_header = true; p_sys->b_header = true;
p_pic = block_ChainGather( p_sps ); }
block_ChainAppend( &p_list, p_sys->p_frame );
p_pic = block_ChainGather( p_list );
} }
else else
{ {
...@@ -815,9 +867,9 @@ static void PutSPS( decoder_t *p_dec, block_t *p_frag ) ...@@ -815,9 +867,9 @@ static void PutSPS( decoder_t *p_dec, block_t *p_frag )
msg_Dbg( p_dec, "found NAL_SPS (sps_id=%d)", i_sps_id ); msg_Dbg( p_dec, "found NAL_SPS (sps_id=%d)", i_sps_id );
p_sys->b_sps = true; p_sys->b_sps = true;
if( p_sys->p_sps ) if( p_sys->pp_sps[i_sps_id] )
block_Release( p_sys->p_sps ); block_Release( p_sys->pp_sps[i_sps_id] );
p_sys->p_sps = p_frag; p_sys->pp_sps[i_sps_id] = p_frag;
} }
static void PutPPS( decoder_t *p_dec, block_t *p_frag ) static void PutPPS( decoder_t *p_dec, block_t *p_frag )
...@@ -845,9 +897,9 @@ static void PutPPS( decoder_t *p_dec, block_t *p_frag ) ...@@ -845,9 +897,9 @@ static void PutPPS( decoder_t *p_dec, block_t *p_frag )
msg_Dbg( p_dec, "found NAL_PPS (pps_id=%d sps_id=%d)", i_pps_id, i_sps_id ); msg_Dbg( p_dec, "found NAL_PPS (pps_id=%d sps_id=%d)", i_pps_id, i_sps_id );
p_sys->b_pps = true; p_sys->b_pps = true;
if( p_sys->p_pps ) if( p_sys->pp_pps[i_pps_id] )
block_Release( p_sys->p_pps ); block_Release( p_sys->pp_pps[i_pps_id] );
p_sys->p_pps = p_frag; p_sys->pp_pps[i_pps_id] = p_frag;
} }
static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice, static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice,
......
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