Commit a6d8c190 authored by Laurent Aimar's avatar Laurent Aimar

Split up ParseNALBlock into smaller functions.

Fix the output order on new slice.
parent dc7fd052
......@@ -150,6 +150,13 @@ static block_t *ParseNALBlock( decoder_t *, block_t * );
static block_t *nal_get_annexeb( decoder_t *, uint8_t *p, int );
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 ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice,
int i_nal_ref_idc, int i_nal_type, const block_t *p_frag );
/*****************************************************************************
* Open: probe the packetizer and return score
* When opening after demux, the packetizer is only loaded AFTER the decoder
......@@ -555,39 +562,6 @@ static inline int bs_read_se( bs_t *s )
* ParseNALBlock: parses annexB type NALs
* All p_frag blocks are required to start with 0 0 0 1 4-byte startcode
*****************************************************************************/
static block_t *OutputPicture( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
block_t *p_pic;
if( !p_sys->b_header && p_sys->slice.i_frame_type != BLOCK_FLAG_TYPE_I)
return NULL;
if( p_sys->slice.i_frame_type == BLOCK_FLAG_TYPE_I && p_sys->p_sps && p_sys->p_pps )
{
block_t *p_sps = block_Duplicate( p_sys->p_sps );
block_t *p_pps = block_Duplicate( p_sys->p_pps );
p_sps->i_dts = p_sys->p_frame->i_dts;
p_sps->i_pts = p_sys->p_frame->i_pts;
block_ChainAppend( &p_sps, p_pps );
block_ChainAppend( &p_sps, p_sys->p_frame );
p_sys->b_header = true;
p_pic = block_ChainGather( p_sps );
}
else
{
p_pic = block_ChainGather( p_sys->p_frame );
}
p_pic->i_length = 0; /* FIXME */
p_pic->i_flags |= p_sys->slice.i_frame_type;
p_sys->slice.i_frame_type = 0;
p_sys->p_frame = NULL;
p_sys->b_slice = false;
return p_pic;
}
static block_t *ParseNALBlock( decoder_t *p_dec, block_t *p_frag )
{
decoder_sys_t *p_sys = p_dec->p_sys;
......@@ -615,127 +589,97 @@ static block_t *ParseNALBlock( decoder_t *p_dec, block_t *p_frag )
}
else if( i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR )
{
uint8_t *dec = NULL;
int i_dec = 0, i_first_mb, i_slice_type;
slice_t slice;
bool b_pic;
bs_t s;
/* do not convert the whole frame */
nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[5],
__MIN( p_frag->i_buffer - 5, 60 ) );
bs_init( &s, dec, i_dec );
bool b_new_picture;
/* first_mb_in_slice */
i_first_mb = bs_read_ue( &s );
ParseSlice( p_dec, &b_new_picture, &slice, i_nal_ref_idc, i_nal_type, p_frag );
/* slice_type */
switch( (i_slice_type = bs_read_ue( &s )) )
{
case 0: case 5:
slice.i_frame_type = BLOCK_FLAG_TYPE_P;
break;
case 1: case 6:
slice.i_frame_type = BLOCK_FLAG_TYPE_B;
break;
case 2: case 7:
slice.i_frame_type = BLOCK_FLAG_TYPE_I;
break;
case 3: case 8: /* SP */
slice.i_frame_type = BLOCK_FLAG_TYPE_P;
break;
case 4: case 9:
slice.i_frame_type = BLOCK_FLAG_TYPE_I;
break;
default:
slice.i_frame_type = 0;
break;
}
/* */
if( b_new_picture && p_sys->b_slice )
p_pic = OutputPicture( p_dec );
/* */
slice.i_nal_type = i_nal_type;
slice.i_nal_ref_idc = i_nal_ref_idc;
p_sys->slice = slice;
p_sys->b_slice = true;
}
else if( i_nal_type == NAL_SPS )
{
if( p_sys->b_slice )
p_pic = OutputPicture( p_dec );
slice.i_pic_parameter_set_id = bs_read_ue( &s );
slice.i_frame_num = bs_read( &s, p_sys->i_log2_max_frame_num + 4 );
PutSPS( p_dec, p_frag );
slice.i_field_pic_flag = 0;
slice.i_bottom_field_flag = -1;
if( !p_sys->b_frame_mbs_only )
{
/* field_pic_flag */
slice.i_field_pic_flag = bs_read( &s, 1 );
if( slice.i_field_pic_flag )
slice.i_bottom_field_flag = bs_read( &s, 1 );
/* Do not append the SPS because we will insert it on keyframes */
return p_pic;
}
else if( i_nal_type == NAL_PPS )
{
if( p_sys->b_slice )
p_pic = OutputPicture( p_dec );
slice.i_idr_pic_id = p_sys->slice.i_idr_pic_id;
if( slice.i_nal_type == NAL_SLICE_IDR )
slice.i_idr_pic_id = bs_read_ue( &s );
PutPPS( p_dec, p_frag );
slice.i_pic_order_cnt_lsb = -1;
slice.i_delta_pic_order_cnt_bottom = -1;
slice.i_delta_pic_order_cnt0 = 0;
slice.i_delta_pic_order_cnt1 = 0;
if( p_sys->i_pic_order_cnt_type == 0 )
{
slice.i_pic_order_cnt_lsb = bs_read( &s, p_sys->i_log2_max_pic_order_cnt_lsb + 4 );
if( p_sys->i_pic_order_present_flag && !slice.i_field_pic_flag )
slice.i_delta_pic_order_cnt_bottom = bs_read_se( &s );
/* Do not append the PPS because we will insert it on keyframes */
return p_pic;
}
else if( (p_sys->i_pic_order_cnt_type == 1) &&
(!p_sys->i_delta_pic_order_always_zero_flag) )
else if( i_nal_type == NAL_AU_DELIMITER ||
i_nal_type == NAL_SEI ||
( i_nal_type >= 13 && i_nal_type <= 18 ) )
{
slice.i_delta_pic_order_cnt0 = bs_read_se( &s );
if( p_sys->i_pic_order_present_flag && !slice.i_field_pic_flag )
slice.i_delta_pic_order_cnt1 = bs_read_se( &s );
if( p_sys->b_slice )
p_pic = OutputPicture( p_dec );
}
/* Detection of the first VCL NAL unit of a primary coded picture
* (cf. 7.4.1.2.4) */
b_pic = false;
if( slice.i_frame_num != p_sys->slice.i_frame_num ||
slice.i_pic_parameter_set_id != p_sys->slice.i_pic_parameter_set_id ||
slice.i_field_pic_flag != p_sys->slice.i_field_pic_flag ||
slice.i_nal_ref_idc != p_sys->slice.i_nal_ref_idc )
b_pic = true;
if( (slice.i_bottom_field_flag != -1) &&
(p_sys->slice.i_bottom_field_flag != -1) &&
(slice.i_bottom_field_flag != p_sys->slice.i_bottom_field_flag) )
b_pic = true;
if( p_sys->i_pic_order_cnt_type == 0 &&
( slice.i_pic_order_cnt_lsb != p_sys->slice.i_pic_order_cnt_lsb ||
slice.i_delta_pic_order_cnt_bottom != p_sys->slice.i_delta_pic_order_cnt_bottom ) )
b_pic = true;
else if( p_sys->i_pic_order_cnt_type == 1 &&
( slice.i_delta_pic_order_cnt0 != p_sys->slice.i_delta_pic_order_cnt0 ||
slice.i_delta_pic_order_cnt1 != p_sys->slice.i_delta_pic_order_cnt1 ) )
b_pic = true;
if( ( slice.i_nal_type == NAL_SLICE_IDR || p_sys->slice.i_nal_type == NAL_SLICE_IDR ) &&
( slice.i_nal_type != p_sys->slice.i_nal_type || slice.i_idr_pic_id != p_sys->slice.i_idr_pic_id ) )
b_pic = true;
/* Append the block */
block_ChainAppend( &p_sys->p_frame, p_frag );
/* */
p_sys->slice = slice;
return p_pic;
}
if( b_pic && p_sys->b_slice )
p_pic = OutputPicture( p_dec );
static block_t *OutputPicture( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
block_t *p_pic;
p_sys->b_slice = true;
if( !p_sys->b_header && p_sys->slice.i_frame_type != BLOCK_FLAG_TYPE_I)
return NULL;
free( dec );
if( p_sys->slice.i_frame_type == BLOCK_FLAG_TYPE_I && p_sys->p_sps && p_sys->p_pps )
{
block_t *p_sps = block_Duplicate( p_sys->p_sps );
block_t *p_pps = block_Duplicate( p_sys->p_pps );
p_sps->i_dts = p_sys->p_frame->i_dts;
p_sps->i_pts = p_sys->p_frame->i_pts;
block_ChainAppend( &p_sps, p_pps );
block_ChainAppend( &p_sps, p_sys->p_frame );
p_sys->b_header = true;
p_pic = block_ChainGather( p_sps );
}
else if( i_nal_type == NAL_SPS )
else
{
p_pic = block_ChainGather( p_sys->p_frame );
}
p_pic->i_length = 0; /* FIXME */
p_pic->i_flags |= p_sys->slice.i_frame_type;
p_sys->slice.i_frame_type = 0;
p_sys->p_frame = NULL;
p_sys->b_slice = false;
return p_pic;
}
static void PutSPS( decoder_t *p_dec, block_t *p_frag )
{
decoder_sys_t *p_sys = p_dec->p_sys;
uint8_t *dec = NULL;
int i_dec = 0;
bs_t s;
int i_tmp;
if( p_sys->b_slice )
p_pic = OutputPicture( p_dec );
if( !p_sys->b_sps ) msg_Dbg( p_dec, "found NAL_SPS" );
if( !p_sys->b_sps )
msg_Dbg( p_dec, "found NAL_SPS" );
p_sys->b_sps = true;
......@@ -850,47 +794,142 @@ static block_t *ParseNALBlock( decoder_t *p_dec, block_t *p_frag )
free( dec );
/* We have a new SPS */
if( p_sys->p_sps ) block_Release( p_sys->p_sps );
if( p_sys->p_sps )
block_Release( p_sys->p_sps );
p_sys->p_sps = p_frag;
}
/* Do not append the SPS because we will insert it on keyframes */
return p_pic;
}
else if( i_nal_type == NAL_PPS )
{
static void PutPPS( decoder_t *p_dec, block_t *p_frag )
{
decoder_sys_t *p_sys = p_dec->p_sys;
bs_t s;
if( p_sys->b_slice )
p_pic = OutputPicture( p_dec );
bs_init( &s, &p_frag->p_buffer[5], p_frag->i_buffer - 5 );
bs_read_ue( &s ); // pps id
bs_read_ue( &s ); // sps id
bs_skip( &s, 1 ); // entropy coding mode flag
p_sys->i_pic_order_present_flag = bs_read( &s, 1 );
if( !p_sys->b_pps ) msg_Dbg( p_dec, "found NAL_PPS" );
if( !p_sys->b_pps )
msg_Dbg( p_dec, "found NAL_PPS" );
p_sys->b_pps = true;
/* TODO */
/* We have a new PPS */
if( p_sys->p_pps ) block_Release( p_sys->p_pps );
if( p_sys->p_pps )
block_Release( p_sys->p_pps );
p_sys->p_pps = p_frag;
}
/* Do not append the PPS because we will insert it on keyframes */
return p_pic;
static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice,
int i_nal_ref_idc, int i_nal_type, const block_t *p_frag )
{
decoder_sys_t *p_sys = p_dec->p_sys;
uint8_t *pb_dec;
int i_dec;
int i_first_mb, i_slice_type;
slice_t slice;
bs_t s;
/* do not convert the whole frame */
nal_get_decoded( &pb_dec, &i_dec, &p_frag->p_buffer[5],
__MIN( p_frag->i_buffer - 5, 60 ) );
bs_init( &s, pb_dec, i_dec );
/* first_mb_in_slice */
i_first_mb = bs_read_ue( &s );
/* slice_type */
switch( (i_slice_type = bs_read_ue( &s )) )
{
case 0: case 5:
slice.i_frame_type = BLOCK_FLAG_TYPE_P;
break;
case 1: case 6:
slice.i_frame_type = BLOCK_FLAG_TYPE_B;
break;
case 2: case 7:
slice.i_frame_type = BLOCK_FLAG_TYPE_I;
break;
case 3: case 8: /* SP */
slice.i_frame_type = BLOCK_FLAG_TYPE_P;
break;
case 4: case 9:
slice.i_frame_type = BLOCK_FLAG_TYPE_I;
break;
default:
slice.i_frame_type = 0;
break;
}
else if( i_nal_type == NAL_AU_DELIMITER ||
i_nal_type == NAL_SEI ||
( i_nal_type >= 13 && i_nal_type <= 18 ) )
/* */
slice.i_nal_type = i_nal_type;
slice.i_nal_ref_idc = i_nal_ref_idc;
slice.i_pic_parameter_set_id = bs_read_ue( &s );
slice.i_frame_num = bs_read( &s, p_sys->i_log2_max_frame_num + 4 );
slice.i_field_pic_flag = 0;
slice.i_bottom_field_flag = -1;
if( !p_sys->b_frame_mbs_only )
{
if( p_sys->b_slice )
p_pic = OutputPicture( p_dec );
/* field_pic_flag */
slice.i_field_pic_flag = bs_read( &s, 1 );
if( slice.i_field_pic_flag )
slice.i_bottom_field_flag = bs_read( &s, 1 );
}
/* Append the block */
block_ChainAppend( &p_sys->p_frame, p_frag );
slice.i_idr_pic_id = p_sys->slice.i_idr_pic_id;
if( slice.i_nal_type == NAL_SLICE_IDR )
slice.i_idr_pic_id = bs_read_ue( &s );
return p_pic;
slice.i_pic_order_cnt_lsb = -1;
slice.i_delta_pic_order_cnt_bottom = -1;
slice.i_delta_pic_order_cnt0 = 0;
slice.i_delta_pic_order_cnt1 = 0;
if( p_sys->i_pic_order_cnt_type == 0 )
{
slice.i_pic_order_cnt_lsb = bs_read( &s, p_sys->i_log2_max_pic_order_cnt_lsb + 4 );
if( p_sys->i_pic_order_present_flag && !slice.i_field_pic_flag )
slice.i_delta_pic_order_cnt_bottom = bs_read_se( &s );
}
else if( (p_sys->i_pic_order_cnt_type == 1) &&
(!p_sys->i_delta_pic_order_always_zero_flag) )
{
slice.i_delta_pic_order_cnt0 = bs_read_se( &s );
if( p_sys->i_pic_order_present_flag && !slice.i_field_pic_flag )
slice.i_delta_pic_order_cnt1 = bs_read_se( &s );
}
free( pb_dec );
/* Detection of the first VCL NAL unit of a primary coded picture
* (cf. 7.4.1.2.4) */
bool b_pic = false;
if( slice.i_frame_num != p_sys->slice.i_frame_num ||
slice.i_pic_parameter_set_id != p_sys->slice.i_pic_parameter_set_id ||
slice.i_field_pic_flag != p_sys->slice.i_field_pic_flag ||
slice.i_nal_ref_idc != p_sys->slice.i_nal_ref_idc )
b_pic = true;
if( (slice.i_bottom_field_flag != -1) &&
(p_sys->slice.i_bottom_field_flag != -1) &&
(slice.i_bottom_field_flag != p_sys->slice.i_bottom_field_flag) )
b_pic = true;
if( p_sys->i_pic_order_cnt_type == 0 &&
( slice.i_pic_order_cnt_lsb != p_sys->slice.i_pic_order_cnt_lsb ||
slice.i_delta_pic_order_cnt_bottom != p_sys->slice.i_delta_pic_order_cnt_bottom ) )
b_pic = true;
else if( p_sys->i_pic_order_cnt_type == 1 &&
( slice.i_delta_pic_order_cnt0 != p_sys->slice.i_delta_pic_order_cnt0 ||
slice.i_delta_pic_order_cnt1 != p_sys->slice.i_delta_pic_order_cnt1 ) )
b_pic = true;
if( ( slice.i_nal_type == NAL_SLICE_IDR || p_sys->slice.i_nal_type == NAL_SLICE_IDR ) &&
( slice.i_nal_type != p_sys->slice.i_nal_type || slice.i_idr_pic_id != p_sys->slice.i_idr_pic_id ) )
b_pic = true;
/* */
*pb_new_picture = b_pic;
*p_slice = 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