/***************************************************************************** * ParseNALBlock: parses annexB type NALs * All p_frag blocks are required to start with 0 0 0 1 4-byte startcode *****************************************************************************/ static block_t *ParseNALBlock( decoder_t *p_dec, block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_pic = NULL; const int i_nal_ref_idc = (p_frag->p_buffer[4] >> 5)&0x03; const int i_nal_type = p_frag->p_buffer[4]&0x1f; #define OUTPUT \ do { \ if( !p_sys->b_header && p_sys->slice.i_frame_type != BLOCK_FLAG_TYPE_I) \ break; \ \ if( p_sys->slice.i_frame_type == BLOCK_FLAG_TYPE_I && p_sys->p_sps && p_sys->p_pps && !p_sys->b_header ) \ { \ 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 = VLC_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 = VLC_FALSE; \ } while(0) if( p_sys->b_slice && ( !p_sys->b_sps || !p_sys->b_pps ) ) { block_ChainRelease( p_sys->p_frame ); msg_Warn( p_dec, "waiting for SPS/PPS" ); /* Reset context */ p_sys->slice.i_frame_type = 0; p_sys->p_frame = NULL; p_sys->b_slice = VLC_FALSE; } if( ( !p_sys->b_sps || !p_sys->b_pps ) && i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR ) { p_sys->b_slice = VLC_TRUE; /* Fragment will be discarded later on */ } else if( i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR ) { uint8_t *dec; int i_dec, i_first_mb, i_slice_type; slice_t slice; vlc_bool_t 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 ); /* 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; } /* */ 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 ) { /* 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 ); } 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 ); 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 ); } /* Detection of the first VCL NAL unit of a primary coded picture * (cf. 7.4.1.2.4) */ b_pic = VLC_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 = VLC_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 = VLC_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 = VLC_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 = VLC_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 = VLC_TRUE; /* */ p_sys->slice = slice; if( b_pic && p_sys->b_slice ) OUTPUT; p_sys->b_slice = VLC_TRUE; free( dec ); } else if( i_nal_type == NAL_SPS ) { uint8_t *dec; int i_dec; bs_t s; int i_tmp; if( !p_sys->b_sps ) msg_Dbg( p_dec, "found NAL_SPS" ); p_sys->b_sps = VLC_TRUE; nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[5], p_frag->i_buffer - 5 ); bs_init( &s, dec, i_dec ); /* Skip profile(8), constraint_set012, reserver(5), level(8) */ bs_skip( &s, 8 + 1+1+1 + 5 + 8 ); /* sps id */ bs_read_ue( &s ); /* Skip i_log2_max_frame_num */ p_sys->i_log2_max_frame_num = bs_read_ue( &s ); if( p_sys->i_log2_max_frame_num > 12) p_sys->i_log2_max_frame_num = 12; /* Read poc_type */ p_sys->i_pic_order_cnt_type = bs_read_ue( &s ); if( p_sys->i_pic_order_cnt_type == 0 ) { /* skip i_log2_max_poc_lsb */ p_sys->i_log2_max_pic_order_cnt_lsb = bs_read_ue( &s ); if( p_sys->i_log2_max_pic_order_cnt_lsb > 12 ) p_sys->i_log2_max_pic_order_cnt_lsb = 12; } else if( p_sys->i_pic_order_cnt_type == 1 ) { int i_cycle; /* skip b_delta_pic_order_always_zero */ p_sys->i_delta_pic_order_always_zero_flag = bs_read( &s, 1 ); /* skip i_offset_for_non_ref_pic */ bs_read_se( &s ); /* skip i_offset_for_top_to_bottom_field */ bs_read_se( &s ); /* read i_num_ref_frames_in_poc_cycle */ i_cycle = bs_read_ue( &s ); if( i_cycle > 256 ) i_cycle = 256; while( i_cycle > 0 ) { /* skip i_offset_for_ref_frame */ bs_read_se(&s ); } } /* i_num_ref_frames */ bs_read_ue( &s ); /* b_gaps_in_frame_num_value_allowed */ bs_skip( &s, 1 ); /* Read size */ p_dec->fmt_out.video.i_width = 16 * ( bs_read_ue( &s ) + 1 ); p_dec->fmt_out.video.i_height = 16 * ( bs_read_ue( &s ) + 1 ); /* b_frame_mbs_only */ p_sys->b_frame_mbs_only = bs_read( &s, 1 ); if( p_sys->b_frame_mbs_only == 0 ) { bs_skip( &s, 1 ); } /* b_direct8x8_inference */ bs_skip( &s, 1 ); /* crop */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { /* left */ bs_read_ue( &s ); /* right */ bs_read_ue( &s ); /* top */ bs_read_ue( &s ); /* bottom */ bs_read_ue( &s ); } /* vui */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { /* read the aspect ratio part if any FIXME check it */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { static const struct { int w, h; } sar[14] = { { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, { 160,99 }, }; int i_sar = bs_read( &s, 8 ); int w, h; if( i_sar < 14 ) { w = sar[i_sar].w; h = sar[i_sar].h; } else { w = bs_read( &s, 16 ); h = bs_read( &s, 16 ); } if( h != 0 ) p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * w / h * p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height; else p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR; } } free( dec ); if( p_sys->b_slice ) OUTPUT; /* We have a new 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 ) { bs_t s; 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" ); p_sys->b_pps = VLC_TRUE; /* TODO */ if( p_sys->b_slice ) OUTPUT; /* We have a new 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; } else if( i_nal_type == NAL_AU_DELIMITER || i_nal_type == NAL_SEI || ( i_nal_type >= 13 && i_nal_type <= 18 ) ) { if( p_sys->b_slice ) OUTPUT; } #undef OUTPUT /* Append the block */ block_ChainAppend( &p_sys->p_frame, p_frag ); return p_pic; }
static block_t *ParseNALBlock( decoder_t *p_dec, block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_pic = NULL; const int i_nal_ref_idc = (p_frag->p_buffer[3] >> 5)&0x03; const int i_nal_type = p_frag->p_buffer[3]&0x1f; if( p_sys->b_slice && !p_sys->b_sps ) { block_ChainRelease( p_sys->p_frame ); msg_Warn( p_dec, "waiting for SPS" ); /* Reset context */ p_sys->p_frame = NULL; p_sys->b_slice = VLC_FALSE; } if( !p_sys->b_sps && i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR ) { p_sys->b_slice = VLC_TRUE; /* Fragment will be discarded later on */ } else if( i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR ) { uint8_t *dec; int i_dec, i_first_mb, i_slice_type, i_frame_num, i_pic_flags = 0; vlc_bool_t b_pic = VLC_FALSE; bs_t s; /* do not convert the whole frame */ nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[4], __MIN( p_frag->i_buffer - 4, 60 ) ); bs_init( &s, 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: i_pic_flags = BLOCK_FLAG_TYPE_P; break; case 1: case 6: i_pic_flags = BLOCK_FLAG_TYPE_B; break; case 2: case 7: i_pic_flags = BLOCK_FLAG_TYPE_I; break; case 3: case 8: /* SP */ i_pic_flags = BLOCK_FLAG_TYPE_P; break; case 4: case 9: i_pic_flags = BLOCK_FLAG_TYPE_I; break; } /* pic_parameter_set_id */ bs_read_ue( &s ); /* frame_num */ i_frame_num = bs_read( &s, p_sys->i_log2_max_frame_num + 4 ); /* Detection of the first VCL NAL unit of a primary coded picture * (cf. 7.4.1.2.4) */ if( i_frame_num != p_sys->i_frame_num || ( (i_nal_ref_idc != p_sys->i_nal_ref_idc) && (!i_nal_ref_idc || !p_sys->i_nal_ref_idc) ) ) { b_pic = VLC_TRUE; } p_sys->i_frame_num = i_frame_num; p_sys->i_nal_ref_idc = i_nal_ref_idc; if( !p_sys->b_frame_mbs_only ) { /* field_pic_flag */ if( bs_read( &s, 1 ) ) { /* bottom_field_flag */ bs_read( &s, 1 ); } } if( i_nal_type == NAL_SLICE_IDR ) { /* id_pic_id */ int i_idr_pic_id = bs_read_ue( &s ); if( p_sys->i_nal_type != i_nal_type ) b_pic = VLC_TRUE; if( p_sys->i_idr_pic_id != i_idr_pic_id ) b_pic = VLC_TRUE; p_sys->i_idr_pic_id = i_idr_pic_id; } p_sys->i_nal_type = i_nal_type; if( b_pic && p_sys->b_slice ) { p_pic = block_ChainGather( p_sys->p_frame ); p_pic->i_dts = p_sys->i_dts; p_pic->i_pts = p_sys->i_pts; p_pic->i_length = 0; /* FIXME */ p_pic->i_flags = p_sys->i_flags; /* Reset context */ p_sys->p_frame = NULL; p_sys->b_slice = VLC_FALSE; } p_sys->b_slice = VLC_TRUE; p_sys->i_flags = i_pic_flags; p_sys->i_dts = p_frag->i_dts; p_sys->i_pts = p_frag->i_pts; free( dec ); } else if( i_nal_type == NAL_SPS ) { uint8_t *dec; int i_dec; bs_t s; int i_tmp; msg_Dbg( p_dec, "found NAL_SPS" ); p_sys->b_sps = VLC_TRUE; nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[4], p_frag->i_buffer - 4 ); bs_init( &s, dec, i_dec ); /* Skip profile(8), constraint_set012, reserver(5), level(8) */ bs_skip( &s, 8 + 1+1+1 + 5 + 8 ); /* sps id */ bs_read_ue( &s ); /* Skip i_log2_max_frame_num */ p_sys->i_log2_max_frame_num = bs_read_ue( &s ); /* Read poc_type */ i_tmp = bs_read_ue( &s ); if( i_tmp == 0 ) { /* skip i_log2_max_poc_lsb */ bs_read_ue( &s ); } else if( i_tmp == 1 ) { int i_cycle; /* skip b_delta_pic_order_always_zero */ bs_skip( &s, 1 ); /* skip i_offset_for_non_ref_pic */ bs_read_se( &s ); /* skip i_offset_for_top_to_bottom_field */ bs_read_se( &s ); /* read i_num_ref_frames_in_poc_cycle */ i_cycle = bs_read_ue( &s ); if( i_cycle > 256 ) i_cycle = 256; while( i_cycle > 0 ) { /* skip i_offset_for_ref_frame */ bs_read_se(&s ); } } /* i_num_ref_frames */ bs_read_ue( &s ); /* b_gaps_in_frame_num_value_allowed */ bs_skip( &s, 1 ); /* Read size */ p_dec->fmt_out.video.i_width = 16 * ( bs_read_ue( &s ) + 1 ); p_dec->fmt_out.video.i_height = 16 * ( bs_read_ue( &s ) + 1 ); /* b_frame_mbs_only */ p_sys->b_frame_mbs_only = bs_read( &s, 1 ); if( p_sys->b_frame_mbs_only == 0 ) { bs_skip( &s, 1 ); } /* b_direct8x8_inference */ bs_skip( &s, 1 ); /* crop */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { /* left */ bs_read_ue( &s ); /* right */ bs_read_ue( &s ); /* top */ bs_read_ue( &s ); /* bottom */ bs_read_ue( &s ); } /* vui */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { /* read the aspect ratio part if any FIXME check it */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { static const struct { int w, h; } sar[14] = { { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, { 160,99 }, }; int i_sar = bs_read( &s, 8 ); int w, h; if( i_sar < 14 ) { w = sar[i_sar].w; h = sar[i_sar].h; } else { w = bs_read( &s, 16 ); h = bs_read( &s, 16 ); } p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * w / h * p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height; } } free( dec ); } else if( i_nal_type == NAL_PPS ) { bs_t s; bs_init( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4 ); /* TODO */ msg_Dbg( p_dec, "found NAL_PPS" ); } /* Append the block */ block_ChainAppend( &p_sys->p_frame, p_frag ); return p_pic; }