static int _parse_app_info(BITSTREAM *bs, INDX_APP_INFO *app_info) { uint32_t len; if (bs_seek_byte(bs, 40) < 0) { return 0; } len = bs_read(bs, 32); if (len != 34) { BD_DEBUG(DBG_NAV, "index.bdmv app_info length is %d, expected 34 !\n", len); } bs_skip(bs, 1); app_info->initial_output_mode_preference = bs_read(bs, 1); app_info->content_exist_flag = bs_read(bs, 1); bs_skip(bs, 5); app_info->video_format = bs_read(bs, 4); app_info->frame_rate = bs_read(bs, 4); bs_read_bytes(bs, app_info->user_data, 32); return 1; }
static int32_t getFPS( demux_t *p_demux, block_t * p_block ) { demux_sys_t *p_sys = p_demux->p_sys; bs_t bs; uint8_t * p_decoded_nal; int i_decoded_nal; if( p_block->i_buffer < 5 ) return -1; p_decoded_nal = CreateDecodedNAL(&i_decoded_nal, p_block->p_buffer+4, p_block->i_buffer-4); if( !p_decoded_nal ) return -1; bs_init( &bs, p_decoded_nal, i_decoded_nal ); bs_skip( &bs, 12 ); int32_t max_sub_layer_minus1 = bs_read( &bs, 3 ); bs_skip( &bs, 17 ); hevc_skip_profile_tiers_level( &bs, max_sub_layer_minus1 ); int32_t vps_sub_layer_ordering_info_present_flag = bs_read1( &bs ); int32_t i = vps_sub_layer_ordering_info_present_flag? 0 : max_sub_layer_minus1; for( ; i <= max_sub_layer_minus1; i++ ) { bs_read_ue( &bs ); bs_read_ue( &bs ); bs_read_ue( &bs ); } uint32_t vps_max_layer_id = bs_read( &bs, 6); uint32_t vps_num_layer_sets_minus1 = bs_read_ue( &bs ); bs_skip( &bs, vps_max_layer_id * vps_num_layer_sets_minus1 ); if( bs_read1( &bs )) { uint32_t num_units_in_tick = bs_read( &bs, 32 ); uint32_t time_scale = bs_read( &bs, 32 ); if( num_units_in_tick ) { p_sys->f_fps = ( (float) time_scale )/( (float) num_units_in_tick ); msg_Dbg(p_demux,"Using framerate %f fps from VPS", (double) p_sys->f_fps); } else { msg_Err( p_demux, "vps_num_units_in_tick null defaulting to 25 fps"); p_sys->f_fps = 25.0f; } } else { msg_Err( p_demux, "No timing info in VPS defaulting to 25 fps"); p_sys->f_fps = 25.0f; } free(p_decoded_nal); return 0; }
/* Parse WMV3 packet and extract frame type information */ static void ParseWMV3( decoder_t *p_dec, block_t *p_block ) { bs_t s; /* Parse Sequence header */ bs_init( &s, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); if( bs_read( &s, 2 ) == 3 ) return; bs_skip( &s, 22 ); const bool b_range_reduction = bs_read( &s, 1 ); const bool b_has_frames = bs_read( &s, 3 ) > 0; bs_skip( &s, 2 ); const bool b_frame_interpolation = bs_read( &s, 1 ); if( bs_eof( &s ) ) return; /* Parse frame type */ bs_init( &s, p_block->p_buffer, p_block->i_buffer ); bs_skip( &s, b_frame_interpolation + 2 + b_range_reduction ); p_block->i_flags &= ~BLOCK_FLAG_TYPE_MASK; if( bs_read( &s, 1 ) ) p_block->i_flags |= BLOCK_FLAG_TYPE_P; else if( !b_has_frames || bs_read( &s, 1 ) ) p_block->i_flags |= BLOCK_FLAG_TYPE_I; else p_block->i_flags |= BLOCK_FLAG_TYPE_B; }
void bd_mpls_mark_Parse( bd_mpls_mark_t *p_mark, bs_t *s ) { bs_skip( s, 8 ); p_mark->i_type = bs_read( s, 8 ); p_mark->i_play_item_id = bs_read( s, 16 ); p_mark->i_time = bs_read( s, 32 ); p_mark->i_entry_es_pid = bs_read( s, 16 ); bs_skip( s, 32 ); }
int bd_clpi_ep_map_Parse( bd_clpi_ep_map_t *p_ep_map, bs_t *s, const int i_ep_map_start ) { p_ep_map->i_pid = bs_read( s, 16 ); bs_skip( s, 10 ); p_ep_map->i_type = bs_read( s, 4 ); const int i_coarse = bs_read( s, 16 ); const int i_fine = bs_read( s, 18 ); const uint32_t i_coarse_start = bs_read( s, 32 ); p_ep_map->i_ep = i_fine; p_ep_map->p_ep = (bd_clpi_ep_t *)calloc( i_fine, sizeof(*p_ep_map->p_ep) ); // sunqueen modify if( !p_ep_map->p_ep ) return VLC_EGENERIC; bs_t cs = *s; bs_skip( &cs, 8*(i_ep_map_start + i_coarse_start) - bs_pos( s ) ); const uint32_t i_fine_start = bs_read( &cs, 32 ); for( int i = 0; i < i_coarse; i++ ) { const int i_fine_id = bs_read( &cs, 18 ); const int i_pts = bs_read( &cs, 14 ); const uint32_t i_packet = bs_read( &cs, 32 ); for( int j = i_fine_id; j < p_ep_map->i_ep; j++ ) { p_ep_map->p_ep[j].i_pts = (int64_t)(i_pts & ~1) << 19; p_ep_map->p_ep[j].i_packet = i_packet & ~( (1 << 17) - 1 ); } } bs_t fs = *s; bs_skip( &fs, 8*(i_ep_map_start + i_coarse_start + i_fine_start) - bs_pos( s ) ); for( int i = 0; i < i_fine; i++ ) { const bool b_angle_point = bs_read( &fs, 1 ); bs_skip( &fs, 3 ); /* I end position offset */ const int i_pts = bs_read( &fs, 11 ); const int i_packet = bs_read( &fs, 17 ); p_ep_map->p_ep[i].b_angle_point = b_angle_point; p_ep_map->p_ep[i].i_pts |= i_pts << 9; p_ep_map->p_ep[i].i_packet |= i_packet; } return VLC_SUCCESS; }
static int _parse_hdmv_obj(BITSTREAM *bs, INDX_HDMV_OBJ *hdmv) { hdmv->playback_type = bs_read(bs, 2); bs_skip(bs, 14); hdmv->id_ref = bs_read(bs, 16); bs_skip(bs, 32); if (hdmv->playback_type != indx_hdmv_playback_type_movie && hdmv->playback_type != indx_hdmv_playback_type_interactive) { BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv: invalid HDMV playback type %d\n", hdmv->playback_type); } return 1; }
static int _parse_bdj_obj(BITSTREAM *bs, INDX_BDJ_OBJ *bdj) { bdj->playback_type = bs_read(bs, 2); bs_skip(bs, 14); bs_read_string(bs, bdj->name, 5); bs_skip(bs, 8); if (bdj->playback_type != indx_bdj_playback_type_movie && bdj->playback_type != indx_bdj_playback_type_interactive) { BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv: invalid BD-J playback type %d\n", bdj->playback_type); } return 1; }
static void PutPPS( decoder_t *p_dec, block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; bs_t s; int i_pps_id; int i_sps_id; bs_init( &s, &p_frag->p_buffer[5], p_frag->i_buffer - 5 ); i_pps_id = bs_read_ue( &s ); // pps id i_sps_id = bs_read_ue( &s ); // sps id if( i_pps_id >= PPS_MAX || i_sps_id >= SPS_MAX ) { msg_Warn( p_dec, "invalid PPS (pps_id=%d sps_id=%d)", i_pps_id, i_sps_id ); block_Release( p_frag ); return; } bs_skip( &s, 1 ); // entropy coding mode flag p_sys->i_pic_order_present_flag = bs_read( &s, 1 ); /* TODO */ /* We have a new PPS */ if( !p_sys->b_pps ) msg_Dbg( p_dec, "found NAL_PPS (pps_id=%d sps_id=%d)", i_pps_id, i_sps_id ); p_sys->b_pps = true; if( p_sys->pp_pps[i_pps_id] ) block_Release( p_sys->pp_pps[i_pps_id] ); p_sys->pp_pps[i_pps_id] = p_frag; }
static int _mobj_parse_object(BITSTREAM *bs, MOBJ_OBJECT *obj) { int i; obj->resume_intention_flag = bs_read(bs, 1); obj->menu_call_mask = bs_read(bs, 1); obj->title_search_mask = bs_read(bs, 1); bs_skip(bs, 13); /* padding */ obj->num_cmds = bs_read(bs, 16); obj->cmds = calloc(obj->num_cmds, sizeof(MOBJ_CMD)); if (!obj->cmds) { BD_DEBUG(DBG_CRIT, "out of memory\n"); return 0; } for (i = 0; i < obj->num_cmds; i++) { uint8_t buf[12]; bs_read_bytes(bs, buf, 12); mobj_parse_cmd(buf, &obj->cmds[i]); } return 1; }
static int _parse_index(BITSTREAM *bs, INDX_ROOT *index) { uint32_t index_len, i; index_len = bs_read(bs, 32); /* TODO: check if goes to extension data area */ if ((bs_end(bs) - bs_pos(bs))/8 < (int64_t)index_len) { BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv: invalid index_len %d !\n", index_len); return 0; } if (!_parse_playback_obj(bs, &index->first_play) || !_parse_playback_obj(bs, &index->top_menu)) { return 0; } index->num_titles = bs_read(bs, 16); if (!index->num_titles) { BD_DEBUG(DBG_CRIT, "empty index\n"); return 0; } index->titles = calloc(index->num_titles, sizeof(INDX_TITLE)); if (!index->titles) { BD_DEBUG(DBG_CRIT, "out of memory\n"); return 0; } if (bs_avail(bs)/(12*8) < index->num_titles) { BD_DEBUG(DBG_HDMV|DBG_CRIT, "index.bdmv: unexpected EOF\n"); return 0; } for (i = 0; i < index->num_titles; i++) { index->titles[i].object_type = bs_read(bs, 2); index->titles[i].access_type = bs_read(bs, 2); bs_skip(bs, 28); switch (index->titles[i].object_type) { case indx_object_type_hdmv: if (!_parse_hdmv_obj(bs, &index->titles[i].hdmv)) return 0; break; case indx_object_type_bdj: if (!_parse_bdj_obj(bs, &index->titles[i].bdj)) return 0; break; default: BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv: unknown object type %d (#%d)\n", index->titles[i].object_type, i); return 0; } } return 1; }
/***************************************************************************** * parse_data_group ***************************************************************************** * ARIB STD-B24 VOLUME 1 Part 3 Chapter 9.2 Structure of data group *****************************************************************************/ static void parse_data_group( arib_parser_t *p_parser, bs_t *p_bs ) { uint8_t i_data_group_id = bs_read( p_bs, 6 ); bs_skip( p_bs, 2 ); /* i_data_group_version */ bs_skip( p_bs, 8 ); /* i_data_group_link_number */ bs_skip( p_bs, 8 ); /* i_last_data_group_link_number */ bs_skip( p_bs, 16 ); /* i_data_group_size */ if( i_data_group_id == 0x00 || i_data_group_id == 0x20 ) { parse_caption_management_data( p_parser, p_bs ); } else { parse_caption_statement_data( p_parser, p_bs ); } }
static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *p_block) { decoder_t *p_dec = p_private; decoder_sys_t *p_sys = p_dec->p_sys; block_t * p_nal = NULL; while (p_block->i_buffer > 5 && p_block->p_buffer[p_block->i_buffer-1] == 0x00 ) p_block->i_buffer--; bs_t bs; bs_init(&bs, p_block->p_buffer+3, p_block->i_buffer-3); /* Get NALU type */ uint32_t forbidden_zero_bit = bs_read1(&bs); if (forbidden_zero_bit) { msg_Err(p_dec,"Forbidden zero bit not null, corrupted NAL"); p_sys->p_frame = NULL; p_sys->b_vcl = false; return NULL; } uint32_t nalu_type = bs_read(&bs,6); bs_skip(&bs, 9); if (nalu_type < VPS) { /* NAL is a VCL NAL */ p_sys->b_vcl = true; uint32_t first_slice_in_pic = bs_read1(&bs); if (first_slice_in_pic && p_sys->p_frame) { p_nal = block_ChainGather(p_sys->p_frame); p_sys->p_frame = NULL; } block_ChainAppend(&p_sys->p_frame, p_block); } else { if (p_sys->b_vcl) { p_nal = block_ChainGather(p_sys->p_frame); p_nal->p_next = p_block; p_sys->p_frame = NULL; p_sys->b_vcl =false; } else p_nal = p_block; } *pb_ts_used = false; return p_nal; }
static MOBJ_OBJECTS *_mobj_parse(BD_FILE_H *fp) { BITSTREAM bs; MOBJ_OBJECTS *objects = NULL; uint16_t num_objects; uint32_t data_len; int extension_data_start, i; bs_init(&bs, fp); if (!_mobj_parse_header(&bs, &extension_data_start)) { BD_DEBUG(DBG_NAV | DBG_CRIT, "MovieObject.bdmv: invalid header\n"); goto error; } if (extension_data_start) { BD_DEBUG(DBG_NAV | DBG_CRIT, "MovieObject.bdmv: unknown extension data at %d\n", extension_data_start); } bs_seek_byte(&bs, 40); data_len = bs_read(&bs, 32); if ((bs_end(&bs) - bs_pos(&bs))/8 < (int64_t)data_len) { BD_DEBUG(DBG_NAV | DBG_CRIT, "MovieObject.bdmv: invalid data_len %d !\n", data_len); goto error; } objects = calloc(1, sizeof(MOBJ_OBJECTS)); if (!objects) { BD_DEBUG(DBG_CRIT, "out of memory\n"); goto error; } bs_skip(&bs, 32); /* reserved */ num_objects = bs_read(&bs, 16); objects->num_objects = num_objects; objects->objects = calloc(num_objects, sizeof(MOBJ_OBJECT)); if (!objects->objects) { BD_DEBUG(DBG_CRIT, "out of memory\n"); goto error; } for (i = 0; i < objects->num_objects; i++) { if (!_mobj_parse_object(&bs, &objects->objects[i])) { BD_DEBUG(DBG_NAV | DBG_CRIT, "MovieObject.bdmv: error parsing object %d\n", i); goto error; } } return objects; error: mobj_free(&objects); return NULL; }
static void parse_data_unit_others( arib_parser_t *p_parser, bs_t *p_bs, uint8_t i_data_unit_parameter, uint32_t i_data_unit_size ) { for( uint32_t i = 0; i < i_data_unit_size; i++ ) { bs_skip( p_bs, 8 ); p_parser->i_data_unit_size += 1; } }
static MOBJ_OBJECTS *_mobj_parse(const char *file_name) { BITSTREAM bs; BD_FILE_H *fp; MOBJ_OBJECTS *objects = NULL; uint16_t num_objects; uint32_t data_len; int extension_data_start, i; fp = file_open(file_name, "rb"); if (!fp) { BD_DEBUG(DBG_NAV | DBG_CRIT, "error opening %s\n", file_name); return NULL; } bs_init(&bs, fp); if (!_mobj_parse_header(&bs, &extension_data_start)) { BD_DEBUG(DBG_NAV | DBG_CRIT, "%s: invalid header\n", file_name); goto error; } bs_seek_byte(&bs, 40); data_len = bs_read(&bs, 32); if ((bs_end(&bs) - bs_pos(&bs))/8 < (off_t)data_len) { BD_DEBUG(DBG_NAV | DBG_CRIT, "%s: invalid data_len %d !\n", file_name, data_len); goto error; } bs_skip(&bs, 32); /* reserved */ num_objects = bs_read(&bs, 16); objects = calloc(1, sizeof(MOBJ_OBJECTS)); objects->num_objects = num_objects; objects->objects = calloc(num_objects, sizeof(MOBJ_OBJECT)); for (i = 0; i < objects->num_objects; i++) { if (!_mobj_parse_object(&bs, &objects->objects[i])) { BD_DEBUG(DBG_NAV | DBG_CRIT, "%s: error parsing object %d\n", file_name, i); goto error; } } file_close(fp); return objects; error: mobj_free(&objects); file_close(fp); return NULL; }
void bd_clpi_stream_Parse( bd_clpi_stream_t *p_stream, bs_t *s ) { p_stream->i_pid = bs_read( s, 16 ); const int i_length = bs_read( s, 8 ); p_stream->i_type = bs_read( s, 8 ); /* Ignore the rest */ if( i_length > 1 ) bs_skip( s, 8*i_length - 8 ); }
/***************************************************************************** * arib_parse_pes ***************************************************************************** * ARIB STD-B24 VOLUME3 Chapter 5 Independent PES transmission protocol *****************************************************************************/ void arib_parse_pes( arib_parser_t *p_parser, const void *p_data, size_t i_data ) { bs_t bs; bs_init( &bs, p_data, i_data ); uint8_t i_data_group_id = bs_read( &bs, 8 ); if( i_data_group_id != 0x80 && i_data_group_id != 0x81 ) { return; } uint8_t i_private_stream_id = bs_read( &bs, 8 ); if( i_private_stream_id != 0xFF ) { return; } bs_skip( &bs, 4 ); /* reserved */ uint8_t i_PES_data_packet_header_length= bs_read( &bs, 4 ); /* skip PES_data_private_data_byte */ bs_skip( &bs, i_PES_data_packet_header_length ); parse_data_group( p_parser, &bs ); }
static bool h264_parse_picture_parameter_set_rbsp( bs_t *p_bs, h264_picture_parameter_set_t *p_pps ) { p_pps->i_id = bs_read_ue( p_bs ); // pps id p_pps->i_sps_id = bs_read_ue( p_bs ); // sps id if( p_pps->i_id >= H264_PPS_MAX || p_pps->i_sps_id >= H264_SPS_MAX ) return false; bs_skip( p_bs, 1 ); // entropy coding mode flag p_pps->i_pic_order_present_flag = bs_read( p_bs, 1 ); /* TODO */ return true; }
void bd_mpls_sub_path_Parse( bd_mpls_sub_path_t *p_path, bs_t *s ) { const uint32_t i_length = bs_read( s, 32 ); const int i_start = bs_pos( s ) / 8; bs_skip( s, 8 ); p_path->i_type = bs_read( s, 8 ); bs_skip( s, 15 ); p_path->b_repeat = bs_read( s, 1 ); bs_skip( s, 8 ); p_path->i_item = bs_read( s, 8 ); for( int j = 0; j < p_path->i_item; j++ ) { const int i_length = bs_read( s, 16 ); const int i_start = bs_pos( s ) / 8; /* TODO */ bs_skip( s, 8 * ( i_start + i_length ) - bs_pos( s ) ); } bs_skip( s, 8 * ( i_start + i_length ) - bs_pos( s ) ); }
/***************************************************************************** * parse_caption_data ***************************************************************************** * ARIB STD-B24 VOLUME 1 Part 3 Chapter 9.3.2 Caption statement data *****************************************************************************/ static void parse_caption_statement_data( arib_parser_t *p_parser, bs_t *p_bs ) { uint8_t i_TMD = bs_read( p_bs, 2 ); bs_skip( p_bs, 6 ); /* Reserved */ if( i_TMD == 0x01 /* 01 */ || i_TMD == 0x02 /* 10 */ ) { bs_skip( p_bs, 32 ); /* STM << 4 */ bs_skip( p_bs, 4 ); /* STM & 15 */ bs_skip( p_bs, 4 ); /* Reserved */ } uint32_t i_data_unit_loop_length = bs_read( p_bs, 24 ); free( p_parser->psz_subtitle_data ); p_parser->i_subtitle_data_size = 0; p_parser->psz_subtitle_data = NULL; if( i_data_unit_loop_length > 0 ) { p_parser->psz_subtitle_data = (unsigned char*) calloc( i_data_unit_loop_length + 1, sizeof(unsigned char) ); } while( p_parser->i_data_unit_size < i_data_unit_loop_length ) { parse_data_unit( p_parser, p_bs ); } }
static int _parse_playback_obj(BITSTREAM *bs, INDX_PLAY_ITEM *obj) { obj->object_type = bs_read(bs, 2); bs_skip(bs, 30); switch (obj->object_type) { case indx_object_type_hdmv: return _parse_hdmv_obj(bs, &obj->hdmv); case indx_object_type_bdj: return _parse_bdj_obj(bs, &obj->bdj); } BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv: unknown object type %d\n", obj->object_type); return 0; }
int h264_parse_pps( const uint8_t *p_pps_buf, int i_pps_size, struct nal_pps *p_pps ) { bs_t s; if (i_pps_size < 5 || (p_pps_buf[4] & 0x1f) != NAL_PPS) return -1; memset( p_pps, 0, sizeof(struct nal_pps) ); bs_init( &s, &p_pps_buf[5], i_pps_size - 5 ); p_pps->i_id = bs_read_ue( &s ); // pps id p_pps->i_sps_id = bs_read_ue( &s ); // sps id if( p_pps->i_id >= PPS_MAX || p_pps->i_sps_id >= SPS_MAX ) { return -1; } bs_skip( &s, 1 ); // entropy coding mode flag p_pps->i_pic_order_present_flag = bs_read( &s, 1 ); /* TODO */ return 0; }
static bool h264_parse_sequence_parameter_set_rbsp( bs_t *p_bs, h264_sequence_parameter_set_t *p_sps ) { int i_tmp; int i_profile_idc = bs_read( p_bs, 8 ); p_sps->i_profile = i_profile_idc; p_sps->i_constraint_set_flags = bs_read( p_bs, 8 ); p_sps->i_level = bs_read( p_bs, 8 ); /* sps id */ uint32_t i_sps_id = bs_read_ue( p_bs ); if( i_sps_id > H264_SPS_ID_MAX ) return false; p_sps->i_id = i_sps_id; if( i_profile_idc == PROFILE_H264_HIGH || i_profile_idc == PROFILE_H264_HIGH_10 || i_profile_idc == PROFILE_H264_HIGH_422 || i_profile_idc == PROFILE_H264_HIGH_444 || /* Old one, no longer on spec */ i_profile_idc == PROFILE_H264_HIGH_444_PREDICTIVE || i_profile_idc == PROFILE_H264_CAVLC_INTRA || i_profile_idc == PROFILE_H264_SVC_BASELINE || i_profile_idc == PROFILE_H264_SVC_HIGH || i_profile_idc == PROFILE_H264_MVC_MULTIVIEW_HIGH || i_profile_idc == PROFILE_H264_MVC_STEREO_HIGH || i_profile_idc == PROFILE_H264_MVC_MULTIVIEW_DEPTH_HIGH || i_profile_idc == PROFILE_H264_MVC_ENHANCED_MULTIVIEW_DEPTH_HIGH || i_profile_idc == PROFILE_H264_MFC_HIGH ) { /* chroma_format_idc */ p_sps->i_chroma_idc = bs_read_ue( p_bs ); if( p_sps->i_chroma_idc == 3 ) bs_skip( p_bs, 1 ); /* separate_colour_plane_flag */ /* bit_depth_luma_minus8 */ p_sps->i_bit_depth_luma = bs_read_ue( p_bs ) + 8; /* bit_depth_chroma_minus8 */ p_sps->i_bit_depth_chroma = bs_read_ue( p_bs ) + 8; /* qpprime_y_zero_transform_bypass_flag */ bs_skip( p_bs, 1 ); /* seq_scaling_matrix_present_flag */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { for( int i = 0; i < ((3 != p_sps->i_chroma_idc) ? 8 : 12); i++ ) { /* seq_scaling_list_present_flag[i] */ i_tmp = bs_read( p_bs, 1 ); if( !i_tmp ) continue; const int i_size_of_scaling_list = (i < 6 ) ? 16 : 64; /* scaling_list (...) */ int i_lastscale = 8; int i_nextscale = 8; for( int j = 0; j < i_size_of_scaling_list; j++ ) { if( i_nextscale != 0 ) { /* delta_scale */ i_tmp = bs_read_se( p_bs ); i_nextscale = ( i_lastscale + i_tmp + 256 ) % 256; /* useDefaultScalingMatrixFlag = ... */ } /* scalinglist[j] */ i_lastscale = ( i_nextscale == 0 ) ? i_lastscale : i_nextscale; } } } } /* Skip i_log2_max_frame_num */ p_sps->i_log2_max_frame_num = bs_read_ue( p_bs ); if( p_sps->i_log2_max_frame_num > 12) p_sps->i_log2_max_frame_num = 12; /* Read poc_type */ p_sps->i_pic_order_cnt_type = bs_read_ue( p_bs ); if( p_sps->i_pic_order_cnt_type == 0 ) { /* skip i_log2_max_poc_lsb */ p_sps->i_log2_max_pic_order_cnt_lsb = bs_read_ue( p_bs ); if( p_sps->i_log2_max_pic_order_cnt_lsb > 12 ) p_sps->i_log2_max_pic_order_cnt_lsb = 12; } else if( p_sps->i_pic_order_cnt_type == 1 ) { int i_cycle; /* skip b_delta_pic_order_always_zero */ p_sps->i_delta_pic_order_always_zero_flag = bs_read( p_bs, 1 ); /* skip i_offset_for_non_ref_pic */ bs_read_se( p_bs ); /* skip i_offset_for_top_to_bottom_field */ bs_read_se( p_bs ); /* read i_num_ref_frames_in_poc_cycle */ i_cycle = bs_read_ue( p_bs ); if( i_cycle > 256 ) i_cycle = 256; while( i_cycle > 0 ) { /* skip i_offset_for_ref_frame */ bs_read_se(p_bs ); i_cycle--; } } /* i_num_ref_frames */ bs_read_ue( p_bs ); /* b_gaps_in_frame_num_value_allowed */ bs_skip( p_bs, 1 ); /* Read size */ p_sps->pic_width_in_mbs_minus1 = bs_read_ue( p_bs ); p_sps->pic_height_in_map_units_minus1 = bs_read_ue( p_bs ); /* b_frame_mbs_only */ p_sps->frame_mbs_only_flag = bs_read( p_bs, 1 ); if( !p_sps->frame_mbs_only_flag ) bs_skip( p_bs, 1 ); /* b_direct8x8_inference */ bs_skip( p_bs, 1 ); /* crop */ if( bs_read1( p_bs ) ) /* frame_cropping_flag */ { p_sps->frame_crop.left_offset = bs_read_ue( p_bs ); p_sps->frame_crop.right_offset = bs_read_ue( p_bs ); p_sps->frame_crop.right_offset = bs_read_ue( p_bs ); p_sps->frame_crop.bottom_offset = bs_read_ue( p_bs ); } /* vui */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { p_sps->vui.b_valid = true; /* read the aspect ratio part if any */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { static const struct { int w, h; } sar[17] = { { 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 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, }; int i_sar = bs_read( p_bs, 8 ); int w, h; if( i_sar < 17 ) { w = sar[i_sar].w; h = sar[i_sar].h; } else if( i_sar == 255 ) { w = bs_read( p_bs, 16 ); h = bs_read( p_bs, 16 ); } else { w = 0; h = 0; } if( w != 0 && h != 0 ) { p_sps->vui.i_sar_num = w; p_sps->vui.i_sar_den = h; } else { p_sps->vui.i_sar_num = 1; p_sps->vui.i_sar_den = 1; } } /* overscan */ i_tmp = bs_read( p_bs, 1 ); if ( i_tmp ) bs_read( p_bs, 1 ); /* video signal type */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { bs_read( p_bs, 3 ); p_sps->vui.colour.b_full_range = bs_read( p_bs, 1 ); /* colour desc */ i_tmp = bs_read( p_bs, 1 ); if ( i_tmp ) { p_sps->vui.colour.i_colour_primaries = bs_read( p_bs, 8 ); p_sps->vui.colour.i_transfer_characteristics = bs_read( p_bs, 8 ); p_sps->vui.colour.i_matrix_coefficients = bs_read( p_bs, 8 ); } else { p_sps->vui.colour.i_colour_primaries = HXXX_PRIMARIES_UNSPECIFIED; p_sps->vui.colour.i_transfer_characteristics = HXXX_TRANSFER_UNSPECIFIED; p_sps->vui.colour.i_matrix_coefficients = HXXX_MATRIX_UNSPECIFIED; } } /* chroma loc info */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { bs_read_ue( p_bs ); bs_read_ue( p_bs ); } /* timing info */ p_sps->vui.b_timing_info_present_flag = bs_read( p_bs, 1 ); if( p_sps->vui.b_timing_info_present_flag ) { p_sps->vui.i_num_units_in_tick = bs_read( p_bs, 32 ); p_sps->vui.i_time_scale = bs_read( p_bs, 32 ); p_sps->vui.b_fixed_frame_rate = bs_read( p_bs, 1 ); } /* Nal hrd & VC1 hrd parameters */ p_sps->vui.b_hrd_parameters_present_flag = false; for ( int i=0; i<2; i++ ) { i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { p_sps->vui.b_hrd_parameters_present_flag = true; uint32_t count = bs_read_ue( p_bs ) + 1; if( count > 31 ) return false; bs_read( p_bs, 4 ); bs_read( p_bs, 4 ); for( uint32_t i=0; i<count; i++ ) { if( bs_remain( p_bs ) < 23 ) return false; bs_read_ue( p_bs ); bs_read_ue( p_bs ); bs_read( p_bs, 1 ); } bs_read( p_bs, 5 ); p_sps->vui.i_cpb_removal_delay_length_minus1 = bs_read( p_bs, 5 ); p_sps->vui.i_dpb_output_delay_length_minus1 = bs_read( p_bs, 5 ); bs_read( p_bs, 5 ); } } if( p_sps->vui.b_hrd_parameters_present_flag ) bs_read( p_bs, 1 ); /* pic struct info */ p_sps->vui.b_pic_struct_present_flag = bs_read( p_bs, 1 ); /* + unparsed remains */ } return true; }
/* read in useful bits from sequence header */ static bool dirac_UnpackSeqHdr( struct seq_hdr_t *p_sh, block_t *p_block ) { bs_t bs; bs_init( &bs, p_block->p_buffer, p_block->i_buffer ); bs_skip( &bs, 13*8 ); /* parse_info_header */ dirac_uint( &bs ); /* major_version */ dirac_uint( &bs ); /* minor_version */ dirac_uint( &bs ); /* profile */ dirac_uint( &bs ); /* level */ uint32_t u_video_format = dirac_uint( &bs ); /* index */ if( u_video_format > 20 ) { /* don't know how to parse this header */ return false; } static const struct { uint32_t u_w, u_h; } dirac_size_tbl[] = { {640,480}, {176,120}, {176,144}, {352,240}, {352,288}, {704,480}, {704,576}, {720,480}, {720,576}, {1280,720}, {1280,720}, {1920,1080}, {1920,1080}, {1920,1080}, {1920,1080}, {2048,1080}, {4096,2160}, {3840,2160}, {3840,2160}, {7680,4320}, {7680,4320}, }; p_sh->u_width = dirac_size_tbl[u_video_format].u_w; p_sh->u_height = dirac_size_tbl[u_video_format].u_h; if( dirac_bool( &bs ) ) { p_sh->u_width = dirac_uint( &bs ); /* frame_width */ p_sh->u_height = dirac_uint( &bs ); /* frame_height */ } if( dirac_bool( &bs ) ) { dirac_uint( &bs ); /* chroma_format */ } if( dirac_bool( &bs ) ) { dirac_uint( &bs ); /* scan_format */ } static const struct { uint32_t u_n /* numerator */, u_d /* denominator */; } dirac_frate_tbl[] = { /* table 10.3 */ {1, 1}, /* this value is not used */ {24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1}, {50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2}, }; const unsigned dirac_frate_tbl_size = sizeof( dirac_frate_tbl ) / sizeof( *dirac_frate_tbl ); static const uint32_t dirac_vidfmt_frate[] = { /* table C.1 */ 1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6, }; p_sh->u_fps_num = dirac_frate_tbl[dirac_vidfmt_frate[u_video_format]].u_n; p_sh->u_fps_den = dirac_frate_tbl[dirac_vidfmt_frate[u_video_format]].u_d; if( dirac_bool( &bs ) ) { uint32_t frame_rate_index = dirac_uint( &bs ); if( frame_rate_index >= dirac_frate_tbl_size ) { /* invalid header */ return false; } p_sh->u_fps_num = dirac_frate_tbl[frame_rate_index].u_n; p_sh->u_fps_den = dirac_frate_tbl[frame_rate_index].u_d; if( frame_rate_index == 0 ) { p_sh->u_fps_num = dirac_uint( &bs ); /* frame_rate_numerator */ p_sh->u_fps_den = dirac_uint( &bs ); /* frame_rate_denominator */ } } /* must have a valid framerate */ if( !p_sh->u_fps_num || !p_sh->u_fps_den ) return false; if( dirac_bool( &bs ) ) { uint32_t par_index = dirac_uint( &bs ); if( !par_index ) { dirac_uint( &bs ); /* par_num */ dirac_uint( &bs ); /* par_den */ } } if( dirac_bool( &bs ) ) { dirac_uint( &bs ); /* clean_width */ dirac_uint( &bs ); /* clean_height */ dirac_uint( &bs ); /* clean_left_offset */ dirac_uint( &bs ); /* clean_top_offset */ } if( dirac_bool( &bs ) ) { uint32_t signal_range_index = dirac_uint( &bs ); if( !signal_range_index ) { dirac_uint( &bs ); /* luma_offset */ dirac_uint( &bs ); /* luma_excursion */ dirac_uint( &bs ); /* chroma_offset */ dirac_uint( &bs ); /* chroma_excursion */ } } if( dirac_bool( &bs ) ) { uint32_t colour_spec_index = dirac_uint( &bs ); if( !colour_spec_index ) { if( dirac_bool( &bs ) ) { dirac_uint( &bs ); /* colour_primaries_index */ } if( dirac_bool( &bs ) ) { dirac_uint( &bs ); /* colour_matrix_index */ } if( dirac_bool( &bs ) ) { dirac_uint( &bs ); /* transfer_function_index */ } } } p_sh->u_picture_coding_mode = dirac_uint( &bs ); return true; }
static void PutSPS( decoder_t *p_dec, block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; uint8_t *pb_dec = NULL; int i_dec = 0; bs_t s; int i_tmp; int i_sps_id; CreateDecodedNAL( &pb_dec, &i_dec, &p_frag->p_buffer[5], p_frag->i_buffer - 5 ); bs_init( &s, pb_dec, i_dec ); int i_profile_idc = bs_read( &s, 8 ); p_dec->fmt_out.i_profile = i_profile_idc; /* Skip constraint_set0123, reserved(4) */ bs_skip( &s, 1+1+1+1 + 4 ); p_dec->fmt_out.i_level = bs_read( &s, 8 ); /* sps id */ i_sps_id = bs_read_ue( &s ); if( i_sps_id >= SPS_MAX || i_sps_id < 0 ) { msg_Warn( p_dec, "invalid SPS (sps_id=%d)", i_sps_id ); free( pb_dec ); block_Release( p_frag ); return; } if( i_profile_idc == 100 || i_profile_idc == 110 || i_profile_idc == 122 || i_profile_idc == 244 || i_profile_idc == 44 || i_profile_idc == 83 || i_profile_idc == 86 ) { /* chroma_format_idc */ const int i_chroma_format_idc = bs_read_ue( &s ); if( i_chroma_format_idc == 3 ) bs_skip( &s, 1 ); /* separate_colour_plane_flag */ /* bit_depth_luma_minus8 */ bs_read_ue( &s ); /* bit_depth_chroma_minus8 */ bs_read_ue( &s ); /* qpprime_y_zero_transform_bypass_flag */ bs_skip( &s, 1 ); /* seq_scaling_matrix_present_flag */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { for( int i = 0; i < ((3 != i_chroma_format_idc) ? 8 : 12); i++ ) { /* seq_scaling_list_present_flag[i] */ i_tmp = bs_read( &s, 1 ); if( !i_tmp ) continue; const int i_size_of_scaling_list = (i < 6 ) ? 16 : 64; /* scaling_list (...) */ int i_lastscale = 8; int i_nextscale = 8; for( int j = 0; j < i_size_of_scaling_list; j++ ) { if( i_nextscale != 0 ) { /* delta_scale */ i_tmp = bs_read_se( &s ); i_nextscale = ( i_lastscale + i_tmp + 256 ) % 256; /* useDefaultScalingMatrixFlag = ... */ } /* scalinglist[j] */ i_lastscale = ( i_nextscale == 0 ) ? i_lastscale : i_nextscale; } } } } /* 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_cycle--; } } /* 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 ); p_dec->fmt_out.video.i_height *= ( 2 - p_sys->b_frame_mbs_only ); 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 */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { static const struct { int w, h; } sar[17] = { { 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 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, }; int i_sar = bs_read( &s, 8 ); int w, h; if( i_sar < 17 ) { w = sar[i_sar].w; h = sar[i_sar].h; } else if( i_sar == 255 ) { w = bs_read( &s, 16 ); h = bs_read( &s, 16 ); } else { w = 0; h = 0; } if( w != 0 && h != 0 ) { p_dec->fmt_out.video.i_sar_num = w; p_dec->fmt_out.video.i_sar_den = h; } else { p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; } } } free( pb_dec ); /* We have a new SPS */ if( !p_sys->b_sps ) msg_Dbg( p_dec, "found NAL_SPS (sps_id=%d)", i_sps_id ); p_sys->b_sps = true; if( p_sys->pp_sps[i_sps_id] ) block_Release( p_sys->pp_sps[i_sps_id] ); p_sys->pp_sps[i_sps_id] = p_frag; }
/***************************************************************************** * 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; }
/* ParseVOL: * TODO: * - support aspect ratio */ static int ParseVOL( decoder_t *p_dec, es_format_t *fmt, uint8_t *p_vol, int i_vol ) { decoder_sys_t *p_sys = p_dec->p_sys; int i_vo_type, i_vo_ver_id, i_ar, i_shape; bs_t s; for( ;; ) { if( p_vol[0] == 0x00 && p_vol[1] == 0x00 && p_vol[2] == 0x01 && p_vol[3] >= 0x20 && p_vol[3] <= 0x2f ) break; p_vol++; i_vol--; if( i_vol <= 4 ) return VLC_EGENERIC; } bs_init( &s, &p_vol[4], i_vol - 4 ); bs_skip( &s, 1 ); /* random access */ i_vo_type = bs_read( &s, 8 ); if( bs_read1( &s ) ) { i_vo_ver_id = bs_read( &s, 4 ); bs_skip( &s, 3 ); } else { i_vo_ver_id = 1; } i_ar = bs_read( &s, 4 ); if( i_ar == 0xf ) { int i_ar_width, i_ar_height; i_ar_width = bs_read( &s, 8 ); i_ar_height= bs_read( &s, 8 ); } if( bs_read1( &s ) ) { int i_chroma_format; int i_low_delay; /* vol control parameter */ i_chroma_format = bs_read( &s, 2 ); i_low_delay = bs_read1( &s ); if( bs_read1( &s ) ) /* vbv parameters */ { unsigned int i_bitrate, i_vbv_buffer_size, i_vbv_occupancy; i_bitrate = bs_read( &s, 15 ) << 15; bs_skip( &s, 1 ); i_bitrate += bs_read( &s, 15 ); bs_skip( &s, 1 ); i_vbv_buffer_size = bs_read( &s, 15 ) << 3; bs_skip( &s, 1 ); i_vbv_buffer_size += bs_read( &s, 3 ); i_vbv_occupancy = bs_read( &s, 11 ) << 15; bs_skip( &s, 1 ); i_vbv_occupancy += bs_read( &s, 15 ); bs_skip( &s, 1 ); p_dec->fmt_out.i_bitrate = i_bitrate * 400; p_dec->fmt_out.video.i_cpb_buffer = i_vbv_buffer_size * 16384; p_dec->p_sys->i_vbv_occupancy = i_vbv_occupancy * 64; } } /* shape 0->RECT, 1->BIN, 2->BIN_ONLY, 3->GRAY */ i_shape = bs_read( &s, 2 ); if( i_shape == 3 && i_vo_ver_id != 1 ) { bs_skip( &s, 4 ); } if( !bs_read1( &s ) ) return VLC_EGENERIC; /* Marker */ p_sys->i_fps_num = bs_read( &s, 16 ); /* Time increment resolution*/ if( !p_sys->i_fps_num ) p_sys->i_fps_num = 1; if( !bs_read1( &s ) ) return VLC_EGENERIC; /* Marker */ if( bs_read1( &s ) ) { int i_time_increment_bits = vlc_log2( p_sys->i_fps_num - 1 ) + 1; if( i_time_increment_bits < 1 ) i_time_increment_bits = 1; p_sys->i_fps_den = bs_read( &s, i_time_increment_bits ); } if( i_shape == 0 ) { bs_skip( &s, 1 ); fmt->video.i_width = bs_read( &s, 13 ); bs_skip( &s, 1 ); fmt->video.i_height= bs_read( &s, 13 ); bs_skip( &s, 1 ); } return VLC_SUCCESS; }
int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size, struct nal_sps *p_sps ) { uint8_t *pb_dec = NULL; int i_dec = 0; bs_t s; int i_tmp; if (i_sps_size < 5 || (p_sps_buf[4] & 0x1f) != NAL_SPS) return -1; memset( p_sps, 0, sizeof(struct nal_sps) ); CreateRbspFromNAL( &pb_dec, &i_dec, &p_sps_buf[5], i_sps_size - 5 ); bs_init( &s, pb_dec, i_dec ); int i_profile_idc = bs_read( &s, 8 ); p_sps->i_profile = i_profile_idc; p_sps->i_profile_compatibility = bs_read( &s, 8 ); p_sps->i_level = bs_read( &s, 8 ); /* sps id */ p_sps->i_id = bs_read_ue( &s ); if( p_sps->i_id >= SPS_MAX || p_sps->i_id < 0 ) { free( pb_dec ); return -1; } if( i_profile_idc == PROFILE_H264_HIGH || i_profile_idc == PROFILE_H264_HIGH_10 || i_profile_idc == PROFILE_H264_HIGH_422 || i_profile_idc == PROFILE_H264_HIGH_444_PREDICTIVE || i_profile_idc == PROFILE_H264_CAVLC_INTRA || i_profile_idc == PROFILE_H264_SVC_BASELINE || i_profile_idc == PROFILE_H264_SVC_HIGH ) { /* chroma_format_idc */ const int i_chroma_format_idc = bs_read_ue( &s ); if( i_chroma_format_idc == 3 ) bs_skip( &s, 1 ); /* separate_colour_plane_flag */ /* bit_depth_luma_minus8 */ bs_read_ue( &s ); /* bit_depth_chroma_minus8 */ bs_read_ue( &s ); /* qpprime_y_zero_transform_bypass_flag */ bs_skip( &s, 1 ); /* seq_scaling_matrix_present_flag */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { for( int i = 0; i < ((3 != i_chroma_format_idc) ? 8 : 12); i++ ) { /* seq_scaling_list_present_flag[i] */ i_tmp = bs_read( &s, 1 ); if( !i_tmp ) continue; const int i_size_of_scaling_list = (i < 6 ) ? 16 : 64; /* scaling_list (...) */ int i_lastscale = 8; int i_nextscale = 8; for( int j = 0; j < i_size_of_scaling_list; j++ ) { if( i_nextscale != 0 ) { /* delta_scale */ i_tmp = bs_read_se( &s ); i_nextscale = ( i_lastscale + i_tmp + 256 ) % 256; /* useDefaultScalingMatrixFlag = ... */ } /* scalinglist[j] */ i_lastscale = ( i_nextscale == 0 ) ? i_lastscale : i_nextscale; } } } } /* Skip i_log2_max_frame_num */ p_sps->i_log2_max_frame_num = bs_read_ue( &s ); if( p_sps->i_log2_max_frame_num > 12) p_sps->i_log2_max_frame_num = 12; /* Read poc_type */ p_sps->i_pic_order_cnt_type = bs_read_ue( &s ); if( p_sps->i_pic_order_cnt_type == 0 ) { /* skip i_log2_max_poc_lsb */ p_sps->i_log2_max_pic_order_cnt_lsb = bs_read_ue( &s ); if( p_sps->i_log2_max_pic_order_cnt_lsb > 12 ) p_sps->i_log2_max_pic_order_cnt_lsb = 12; } else if( p_sps->i_pic_order_cnt_type == 1 ) { int i_cycle; /* skip b_delta_pic_order_always_zero */ p_sps->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_cycle--; } } /* i_num_ref_frames */ bs_read_ue( &s ); /* b_gaps_in_frame_num_value_allowed */ bs_skip( &s, 1 ); /* Read size */ p_sps->i_width = 16 * ( bs_read_ue( &s ) + 1 ); p_sps->i_height = 16 * ( bs_read_ue( &s ) + 1 ); /* b_frame_mbs_only */ p_sps->b_frame_mbs_only = bs_read( &s, 1 ); p_sps->i_height *= ( 2 - p_sps->b_frame_mbs_only ); if( p_sps->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 ) { p_sps->vui.b_valid = true; /* read the aspect ratio part if any */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { static const struct { int w, h; } sar[17] = { { 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 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, }; int i_sar = bs_read( &s, 8 ); int w, h; if( i_sar < 17 ) { w = sar[i_sar].w; h = sar[i_sar].h; } else if( i_sar == 255 ) { w = bs_read( &s, 16 ); h = bs_read( &s, 16 ); } else { w = 0; h = 0; } if( w != 0 && h != 0 ) { p_sps->vui.i_sar_num = w; p_sps->vui.i_sar_den = h; } else { p_sps->vui.i_sar_num = 1; p_sps->vui.i_sar_den = 1; } } /* overscan */ i_tmp = bs_read( &s, 1 ); if ( i_tmp ) bs_read( &s, 1 ); /* video signal type */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { bs_read( &s, 4 ); /* colour desc */ bs_read( &s, 1 ); if ( i_tmp ) bs_read( &s, 24 ); } /* chroma loc info */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { bs_read_ue( &s ); bs_read_ue( &s ); } /* timing info */ p_sps->vui.b_timing_info_present_flag = bs_read( &s, 1 ); if( p_sps->vui.b_timing_info_present_flag ) { p_sps->vui.i_num_units_in_tick = bs_read( &s, 32 ); p_sps->vui.i_time_scale = bs_read( &s, 32 ); p_sps->vui.b_fixed_frame_rate = bs_read( &s, 1 ); } /* Nal hrd & VC1 hrd parameters */ p_sps->vui.b_cpb_dpb_delays_present_flag = false; for ( int i=0; i<2; i++ ) { i_tmp = bs_read( &s, 1 ); if( i_tmp ) { p_sps->vui.b_cpb_dpb_delays_present_flag = true; uint32_t count = bs_read_ue( &s ) + 1; bs_read( &s, 4 ); bs_read( &s, 4 ); for( uint32_t i=0; i<count; i++ ) { bs_read_ue( &s ); bs_read_ue( &s ); bs_read( &s, 1 ); } bs_read( &s, 5 ); p_sps->vui.i_cpb_removal_delay_length_minus1 = bs_read( &s, 5 ); p_sps->vui.i_dpb_output_delay_length_minus1 = bs_read( &s, 5 ); bs_read( &s, 5 ); } } if( p_sps->vui.b_cpb_dpb_delays_present_flag ) bs_read( &s, 1 ); /* pic struct info */ p_sps->vui.b_pic_struct_present_flag = bs_read( &s, 1 ); /* + unparsed remains */ } free( pb_dec ); return 0; }
int read_cdp( obe_user_data_t *user_data ) { uint8_t *start = NULL, calc_cs = 0; int cc_count = 0; bs_read_t s; bs_read_init( &s, user_data->data, user_data->len ); // cdp_header if( bs_read( &s, 16 ) != CDP_IDENTIFIER ) { syslog( LOG_ERR, "CDP identifier not found \n" ); return 1; } /* Verify Checksum */ for( int i = 0; i < user_data->len - 1; i++ ) calc_cs += user_data->data[i]; calc_cs = calc_cs ? 256 - calc_cs : 0; if( calc_cs != user_data->data[user_data->len - 1] ) { syslog( LOG_ERR, "Invalid checksum in Caption Distribution Packet \n" ); return 1; } bs_skip( &s, 8 ); // cdp_length bs_skip( &s, 4 ); // cdp_frame_rate bs_skip( &s, 4 ); // reserved bs_skip( &s, 1 ); // time_code_present bs_skip( &s, 1 ); // ccdata_present bs_skip( &s, 1 ); // svcinfo_present bs_skip( &s, 1 ); // svc_info_start bs_skip( &s, 1 ); // svc_info_change bs_skip( &s, 1 ); // svc_info_complete /* caption_service_active seemingly unreliable */ bs_skip( &s, 1 ); // caption_service_active bs_skip( &s, 1 ); // reserved bs_skip( &s, 16 ); // cdp_hdr_sequence_cntr while( !bs_read_eof( &s ) ) { uint8_t section_id = bs_read( &s, 8 ); if( section_id == CDP_TC_SECTION_ID ) { /* Is this timecode guaranteed to match VITC? */ bs_skip( &s, 2 ); // reserved bs_skip( &s, 2 ); // tc_10hrs bs_skip( &s, 4 ); // tc_1hrs bs_skip( &s, 1 ); // reserved bs_skip( &s, 3 ); // tc_10min bs_skip( &s, 4 ); // tc_1min bs_skip( &s, 1 ); // tc_field_flag bs_skip( &s, 3 ); // tc_10sec bs_skip( &s, 4 ); // tc_1sec bs_skip( &s, 1 ); // drop_frame_flag bs_skip( &s, 1 ); // zero bs_skip( &s, 2 ); // tc_10fr bs_skip( &s, 4 ); // tc_1fr } else if( section_id == CDP_CC_DATA_SECTION_ID ) { cc_count = bs_read( &s, 8 ) & 0x1f; start = &user_data->data[bs_read_pos( &s ) / 8]; for( int i = 0; i < cc_count; i++ ) { bs_skip( &s, 5 ); // marker_bits bs_skip( &s, 1 ); // cc_valid bs_skip( &s, 2 ); // cc_type bs_skip( &s, 8 ); // cc_data_1 bs_skip( &s, 8 ); // cc_data_2 } } else if( section_id == CDP_CC_SVC_INFO_SECTION_ID ) { /* TODO: pass this to muxer when user requests */ bs_skip( &s, 1 ); // reserved bs_skip( &s, 1 ); // svc_info_start bs_skip( &s, 1 ); // svc_info_change bs_skip( &s, 1 ); // svc_info_complete int svc_count = bs_read( &s, 4 ); for( int i = 0; i < svc_count; i++ ) { bs_skip( &s, 1 ); // reserved bs_skip( &s, 1 ); // csn_size bs_skip( &s, 6 ); // caption_service_number (note: csn_size branch in spec) bs_skip( &s, 8 ); // svc_data_byte_1 bs_skip( &s, 8 ); // svc_data_byte_2 bs_skip( &s, 8 ); // svc_data_byte_3 bs_skip( &s, 8 ); // svc_data_byte_4 bs_skip( &s, 8 ); // svc_data_byte_5 bs_skip( &s, 8 ); // svc_data_byte_6 } } else if( section_id == CDP_FOOTER_SECTION_ID ) { bs_skip( &s, 16 ); // cdp_ftr_sequence_cntr bs_skip( &s, 8 ); // packet_checksum break; } else // future_section { int future_len = bs_read( &s, 8 ); for( int i = 0; i < future_len; i++ ) bs_skip( &s, 8 ); } } if( !cc_count ) return 1; if( write_708_cc( user_data, start, cc_count ) < 0 ) return -1; return 0; }
void Parser::parse(int *pb_nal_start) { h264_t *h = &h264; bs_t s; *pb_nal_start = 0; if( nal.i_type == NAL_SPS || nal.i_type == NAL_PPS ) *pb_nal_start = 1; bs_init( &s, nal.p_payload, nal.i_payload ); if( nal.i_type == NAL_SPS ) { int i_tmp; i_tmp = bs_read( &s, 8 ); bs_skip( &s, 1+1+1 + 5 + 8 ); /* sps id */ bs_read_ue( &s ); if( i_tmp >= 100 ) { b_hiprofile = 1; bs_read_ue( &s ); // chroma_format_idc bs_read_ue( &s ); // bit_depth_luma_minus8 bs_read_ue( &s ); // bit_depth_chroma_minus8 bs_skip( &s, 1 ); // qpprime_y_zero_transform_bypass_flag if( bs_read( &s, 1 ) ) // seq_scaling_matrix_present_flag { int i, j; for( i = 0; i < 8; i++ ) { if( bs_read( &s, 1 ) ) // seq_scaling_list_present_flag[i] { uint8 i_tmp = 8; for( j = 0; j < (i<6?16:64); j++ ) { i_tmp += bs_read_se( &s ); if( i_tmp == 0 ) break; } } } } } /* Skip i_log2_max_frame_num */ h->i_log2_max_frame_num = bs_read_ue( &s ) + 4; /* Read poc_type */ h->i_poc_type = bs_read_ue( &s ); if( h->i_poc_type == 0 ) { h->i_log2_max_poc_lsb = bs_read_ue( &s ) + 4; } else if( h->i_poc_type == 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 */ h->i_width = 16 * ( bs_read_ue( &s ) + 1 ); h->i_height = 32 * ( bs_read_ue( &s ) + 1 ); /* b_frame_mbs_only */ i_tmp = bs_read( &s, 1 ); if( i_tmp == 1 ) { // fix: progressive, half height h->i_height /= 2; } else { // mb_adaptive_frame_field_flag bs_skip( &s, 1 ); } /* b_direct8x8_inference */ bs_skip( &s, 1 ); /* crop ? */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { // fix: no cropping /* left */ //h->i_width -= 2 * bs_read_ue( &s ); /* right */ //h->i_width -= 2 * bs_read_ue( &s ); /* top */ //h->i_height -= 2 * bs_read_ue( &s ); /* bottom */ //h->i_height -= 2 * bs_read_ue( &s ); } /* vui: ignored */ } else if( nal.i_type >= NAL_SLICE && nal.i_type <= NAL_SLICE_IDR ) { int i_tmp; /* i_first_mb */ bs_read_ue( &s ); /* picture type */ switch( bs_read_ue( &s ) ) { case 0: case 5: /* P */ case 1: case 6: /* B */ case 3: case 8: /* SP */ h->b_key = 0; break; case 2: case 7: /* I */ case 4: case 9: /* SI */ // fix: key flags in high profile h->b_key = (nal.i_type == NAL_SLICE_IDR || (b_hiprofile && nal.i_type == NAL_SLICE)); break; } /* pps id */ bs_read_ue( &s ); /* frame num */ i_tmp = bs_read( &s, h->i_log2_max_frame_num ); if( i_tmp != h->i_frame_num ) *pb_nal_start = 1; h->i_frame_num = i_tmp; if( nal.i_type == NAL_SLICE_IDR ) { i_tmp = bs_read_ue( &s ); if( h->i_nal_type == NAL_SLICE_IDR && h->i_idr_pic_id != i_tmp ) *pb_nal_start = 1; h->i_idr_pic_id = i_tmp; } if( h->i_poc_type == 0 ) { i_tmp = bs_read( &s, h->i_log2_max_poc_lsb ); if( i_tmp != h->i_poc ) *pb_nal_start = 1; h->i_poc = i_tmp; } } h->i_nal_type = nal.i_type; h->i_ref_idc = nal.i_ref_idc; }