static s32 gf_media_hevc_read_sps_bs(GF_BitStream *bs, HEVCState *hevc, u8 layer_id, u32 *vui_flag_pos)
{
	s32 vps_id, sps_id = -1;
	u8 max_sub_layers_minus1, flag;
	Bool scaling_list_enable_flag;
	u32 i, nb_CTUs, depth;
	u32 log2_diff_max_min_luma_coding_block_size;
	u32 log2_min_transform_block_size, log2_min_luma_coding_block_size;
	Bool sps_sub_layer_ordering_info_present_flag;
	HEVC_SPS *sps;
	HEVC_VPS *vps;
	HEVC_ProfileTierLevel ptl;
	u32 sps_ext_or_max_sub_layers_minus1;
	Bool multiLayerExtSpsFlag;

	if (vui_flag_pos) *vui_flag_pos = 0;

	//nalu header already parsed
	vps_id = gf_bs_read_int(bs, 4);
	if (vps_id>=16) {
		return -1;
	}
	memset(&ptl, 0, sizeof(ptl));
	max_sub_layers_minus1 = 0;
	sps_ext_or_max_sub_layers_minus1 = 0;
	if (layer_id == 0)
		max_sub_layers_minus1 = gf_bs_read_int(bs, 3);
	else
		sps_ext_or_max_sub_layers_minus1 = gf_bs_read_int(bs, 3);
	multiLayerExtSpsFlag = (layer_id != 0) && (sps_ext_or_max_sub_layers_minus1 == 7);
	if (!multiLayerExtSpsFlag) {		
		/*temporal_id_nesting_flag = */gf_bs_read_int(bs, 1);
		profile_tier_level(bs, 1, max_sub_layers_minus1, &ptl);
	}

	sps_id = bs_get_ue(bs);
	if ((sps_id<0) ||(sps_id>=16)) {
		return -1;
	}

	sps = &hevc->sps[sps_id];
	if (!sps->state) {
		sps->state = 1;
		sps->id = sps_id;
		sps->vps_id = vps_id;
	}
	sps->ptl = ptl;
	vps = &hevc->vps[vps_id];

	//sps_rep_format_idx = 0;
	if (multiLayerExtSpsFlag) {
		u8 update_rep_format_flag = gf_bs_read_int(bs, 1);
		if (update_rep_format_flag) {
			sps->rep_format_idx = gf_bs_read_int(bs, 8);
		} else {
			sps->rep_format_idx = vps->rep_format_idx[layer_id];
		}
		sps->width = vps->rep_formats[sps->rep_format_idx].pic_width_luma_samples;
		sps->height = vps->rep_formats[sps->rep_format_idx].pic_height_luma_samples;
		sps->chroma_format_idc = vps->rep_formats[sps->rep_format_idx].chroma_format_idc;
		sps->bit_depth_luma = vps->rep_formats[sps->rep_format_idx].bit_depth_luma;
		sps->bit_depth_chroma = vps->rep_formats[sps->rep_format_idx].bit_depth_chroma;
		sps->separate_colour_plane_flag = vps->rep_formats[sps->rep_format_idx].separate_colour_plane_flag;

		//TODO this is crude ...
		sps->ptl = vps->ext_ptl[0];
	} else {
		sps->chroma_format_idc = bs_get_ue(bs);
		if (sps->chroma_format_idc==3)
			sps->separate_colour_plane_flag = gf_bs_read_int(bs, 1);
		sps->width = bs_get_ue(bs);
		sps->height = bs_get_ue(bs);
		if (/*conformance_window_flag*/gf_bs_read_int(bs, 1)) {
			u32 SubWidthC, SubHeightC;

			if (sps->chroma_format_idc==1) {
				SubWidthC = SubHeightC = 2;
			}
			else if (sps->chroma_format_idc==2) {
				SubWidthC = 2;
				SubHeightC = 1;
			} else {
				SubWidthC = SubHeightC = 1;
			}

			sps->cw_left = bs_get_ue(bs);
			sps->cw_right = bs_get_ue(bs);
			sps->cw_top = bs_get_ue(bs);
			sps->cw_bottom = bs_get_ue(bs);

			sps->width -= SubWidthC * (sps->cw_left + sps->cw_right);
			sps->height -= SubHeightC * (sps->cw_top + sps->cw_bottom);
		}
		sps->bit_depth_luma = 8 + bs_get_ue(bs);
		sps->bit_depth_chroma = 8 + bs_get_ue(bs);
	}

	sps->log2_max_pic_order_cnt_lsb = 4 + bs_get_ue(bs);

	if (!multiLayerExtSpsFlag) {
		sps_sub_layer_ordering_info_present_flag = gf_bs_read_int(bs, 1);
		for(i=sps_sub_layer_ordering_info_present_flag ? 0 : max_sub_layers_minus1; i<=max_sub_layers_minus1; i++) {
			/*max_dec_pic_buffering = */ bs_get_ue(bs);
			/*num_reorder_pics = */ bs_get_ue(bs);
			/*max_latency_increase = */ bs_get_ue(bs);
		}
	}

	log2_min_luma_coding_block_size = 3 + bs_get_ue(bs);
	log2_diff_max_min_luma_coding_block_size = bs_get_ue(bs);
	sps->max_CU_width = ( 1<<(log2_min_luma_coding_block_size + log2_diff_max_min_luma_coding_block_size) );
	sps->max_CU_height = ( 1<<(log2_min_luma_coding_block_size + log2_diff_max_min_luma_coding_block_size) );

	log2_min_transform_block_size = 2 + bs_get_ue(bs);
	/*log2_max_transform_block_size = log2_min_transform_block_size  + */bs_get_ue(bs);

	depth = 0;
	/*u32 max_transform_hierarchy_depth_inter = */bs_get_ue(bs);
	/*u32 max_transform_hierarchy_depth_intra = */bs_get_ue(bs);
	while( (u32) ( sps->max_CU_width >> log2_diff_max_min_luma_coding_block_size ) > (u32) ( 1 << ( log2_min_transform_block_size + depth )  ) )
	{
		depth++;
	}
	sps->max_CU_depth = log2_diff_max_min_luma_coding_block_size + depth;

	nb_CTUs = ((sps->width + sps->max_CU_width -1) / sps->max_CU_width) * ((sps->height + sps->max_CU_height-1) / sps->max_CU_height);
	sps->bitsSliceSegmentAddress = 0;
	while (nb_CTUs > (u32) (1 << sps->bitsSliceSegmentAddress)) {
		sps->bitsSliceSegmentAddress++;
	}

	scaling_list_enable_flag = gf_bs_read_int(bs, 1);
	if (scaling_list_enable_flag) {
		Bool sps_infer_scaling_list_flag = 0;
		/*u8 sps_scaling_list_ref_layer_id = 0;*/
		if (multiLayerExtSpsFlag) {
			sps_infer_scaling_list_flag = gf_bs_read_int(bs, 1);
		}

		if (sps_infer_scaling_list_flag) {
			/*sps_scaling_list_ref_layer_id = */gf_bs_read_int(bs, 6);
		} else {
			if (/*sps_scaling_list_data_present_flag=*/gf_bs_read_int(bs, 1) ) {
				hevc_scaling_list_data(bs);
			}
		}
	}
	/*asymmetric_motion_partitions_enabled_flag= */ gf_bs_read_int(bs, 1);
	sps->sample_adaptive_offset_enabled_flag = gf_bs_read_int(bs, 1);
	if (/*pcm_enabled_flag= */ gf_bs_read_int(bs, 1) ) {
		/*pcm_sample_bit_depth_luma_minus1=*/gf_bs_read_int(bs, 4);
		/*pcm_sample_bit_depth_chroma_minus1=*/gf_bs_read_int(bs, 4);
		/*log2_min_pcm_luma_coding_block_size_minus3= */ bs_get_ue(bs);
		/*log2_diff_max_min_pcm_luma_coding_block_size = */ bs_get_ue(bs);
		/*pcm_loop_filter_disable_flag=*/gf_bs_read_int(bs, 1);
	}
	sps->num_short_term_ref_pic_sets = bs_get_ue(bs);
	if (sps->num_short_term_ref_pic_sets>64) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[HEVC] Invalid number of short term reference picture sets %d\n", sps->num_short_term_ref_pic_sets));
		return -1;
	}
	
	for (i=0; i<sps->num_short_term_ref_pic_sets; i++) {
		Bool ret = parse_short_term_ref_pic_set(bs, sps, i);
		/*cannot parse short_term_ref_pic_set, skip VUI parsing*/
		if (!ret) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[HEVC] Invalid short_term_ref_pic_set\n"));
			return -1;
		}
	}
	sps->long_term_ref_pics_present_flag = gf_bs_read_int(bs, 1);
	if (sps->long_term_ref_pics_present_flag) {
		sps->num_long_term_ref_pic_sps = bs_get_ue(bs);
		for (i=0; i<sps->num_long_term_ref_pic_sps; i++) {
			/*lt_ref_pic_poc_lsb_sps=*/gf_bs_read_int(bs, sps->log2_max_pic_order_cnt_lsb);
			/*used_by_curr_pic_lt_sps_flag*/gf_bs_read_int(bs, 1);
		}
	}
	sps->temporal_mvp_enable_flag = gf_bs_read_int(bs, 1);
	/*strong_intra_smoothing_enable_flag*/gf_bs_read_int(bs, 1);

	if (vui_flag_pos)
		*vui_flag_pos = (u32) gf_bs_get_bit_offset(bs);

	if (/*vui_parameters_present_flag*/gf_bs_read_int(bs, 1)) {

		sps->aspect_ratio_info_present_flag = gf_bs_read_int(bs, 1);
		if (sps->aspect_ratio_info_present_flag) {
			sps->sar_idc = gf_bs_read_int(bs, 8);
			if (sps->sar_idc == 255) {
				sps->sar_width = gf_bs_read_int(bs, 16);
				sps->sar_height = gf_bs_read_int(bs, 16);
			} else if (sps->sar_idc<17) {
				sps->sar_width = hevc_sar[sps->sar_idc].w;
				sps->sar_height = hevc_sar[sps->sar_idc].h;
			}
		}

		if (/*overscan_info_present = */ gf_bs_read_int(bs, 1))
			/*overscan_appropriate = */ gf_bs_read_int(bs, 1);

		/*video_signal_type_present_flag = */flag = gf_bs_read_int(bs, 1);
		if (flag) {
			/*video_format = */gf_bs_read_int(bs, 3);
			/*video_full_range_flag = */gf_bs_read_int(bs, 1);
			if (/*colour_description_present_flag = */gf_bs_read_int(bs, 1)) {
				/*colour_primaries = */ gf_bs_read_int(bs, 8);
				/* transfer_characteristic = */ gf_bs_read_int(bs, 8);
				/* matrix_coeffs = */ gf_bs_read_int(bs, 8);
			}
		}

		if (/*chroma_loc_info_present_flag = */ gf_bs_read_int(bs, 1)) {
			/*chroma_sample_loc_type_top_field = */ bs_get_ue(bs);
			/*chroma_sample_loc_type_bottom_field = */bs_get_ue(bs);
		}

		/*neutra_chroma_indication_flag = */gf_bs_read_int(bs, 1);
		/*field_seq_flag = */gf_bs_read_int(bs, 1);
		/*frame_field_info_present_flag = */gf_bs_read_int(bs, 1);

		if (/*default_display_window_flag=*/gf_bs_read_int(bs, 1)) {
			/*left_offset = */bs_get_ue(bs);
			/*right_offset = */bs_get_ue(bs);
			/*top_offset = */bs_get_ue(bs);
			/*bottom_offset = */bs_get_ue(bs);
		}

		sps->has_timing_info = gf_bs_read_int(bs, 1);
		if (sps->has_timing_info ) {
			sps->num_units_in_tick = gf_bs_read_int(bs, 32);
			sps->time_scale = gf_bs_read_int(bs, 32);
			sps->poc_proportional_to_timing_flag = gf_bs_read_int(bs, 1);
			if (sps->poc_proportional_to_timing_flag)
				sps->num_ticks_poc_diff_one_minus1 = bs_get_ue(bs);
			if (/*hrd_parameters_present_flag=*/gf_bs_read_int(bs, 1) ) {
//				GF_LOG(GF_LOG_INFO, GF_LOG_CODING, ("[HEVC] HRD param parsing not implemented\n"));
				return sps_id;
			}
		}

		if (/*bitstream_restriction_flag=*/gf_bs_read_int(bs, 1)) {
			/*tiles_fixed_structure_flag = */gf_bs_read_int(bs, 1);
			/*motion_vectors_over_pic_boundaries_flag = */gf_bs_read_int(bs, 1);
			/*restricted_ref_pic_lists_flag = */gf_bs_read_int(bs, 1);
			/*min_spatial_segmentation_idc = */bs_get_ue(bs);
			/*max_bytes_per_pic_denom = */bs_get_ue(bs);
			/*max_bits_per_min_cu_denom = */bs_get_ue(bs);
			/*log2_max_mv_length_horizontal = */bs_get_ue(bs);
			/*log2_max_mv_length_vertical = */bs_get_ue(bs);
		}
	}

	if (/*sps_extension_flag*/gf_bs_read_int(bs, 1)) {
		while (gf_bs_available(bs)) {
			/*sps_extension_data_flag */ gf_bs_read_int(bs, 1);
		}
	}

	return sps_id;
}
static s32 gf_media_hevc_read_sps_bs(GF_BitStream *bs, HEVCState *hevc, u8 layer_id, u32 *vui_flag_pos)
{
	s32 vps_id, sps_id = -1;
	u8 max_sub_layers_minus1, flag;
	Bool scaling_list_enable_flag;
	u32 i, nb_CTUs, depth;
	u32 log2_diff_max_min_luma_coding_block_size;
	u32 log2_min_transform_block_size, log2_min_luma_coding_block_size;
	Bool sps_sub_layer_ordering_info_present_flag;
	HEVC_SPS *sps;
	HEVC_VPS *vps;
	HEVC_ProfileTierLevel ptl;
	u32 sps_ext_or_max_sub_layers_minus1;
	Bool multiLayerExtSpsFlag;

	if (vui_flag_pos) *vui_flag_pos = 0;

	 
	vps_id = gf_bs_read_int(bs, 4);
	if (vps_id>=16) {
		return -1;
	}
	memset(&ptl, 0, sizeof(ptl));
	max_sub_layers_minus1 = 0;
	sps_ext_or_max_sub_layers_minus1 = 0;
	if (layer_id == 0)
		max_sub_layers_minus1 = gf_bs_read_int(bs, 3);
	else
		sps_ext_or_max_sub_layers_minus1 = gf_bs_read_int(bs, 3);
	multiLayerExtSpsFlag = (layer_id != 0) && (sps_ext_or_max_sub_layers_minus1 == 7);
	if (!multiLayerExtSpsFlag) {		
		 gf_bs_read_int(bs, 1);
		profile_tier_level(bs, 1, max_sub_layers_minus1, &ptl);
	}

	sps_id = bs_get_ue(bs);
	if ((sps_id<0) ||(sps_id>=16)) {
		return -1;
	}

	sps = &hevc->sps[sps_id];
	if (!sps->state) {
		sps->state = 1;
		sps->id = sps_id;
		sps->vps_id = vps_id;
	}
	sps->ptl = ptl;
	vps = &hevc->vps[vps_id];

	 
	if (multiLayerExtSpsFlag) {
		u8 update_rep_format_flag = gf_bs_read_int(bs, 1);
		if (update_rep_format_flag) {
			sps->rep_format_idx = gf_bs_read_int(bs, 8);
		} else {
			sps->rep_format_idx = vps->rep_format_idx[layer_id];
		}
		sps->width = vps->rep_formats[sps->rep_format_idx].pic_width_luma_samples;
		sps->height = vps->rep_formats[sps->rep_format_idx].pic_height_luma_samples;
		sps->chroma_format_idc = vps->rep_formats[sps->rep_format_idx].chroma_format_idc;
		sps->bit_depth_luma = vps->rep_formats[sps->rep_format_idx].bit_depth_luma;
		sps->bit_depth_chroma = vps->rep_formats[sps->rep_format_idx].bit_depth_chroma;
		sps->separate_colour_plane_flag = vps->rep_formats[sps->rep_format_idx].separate_colour_plane_flag;

		 
		sps->ptl = vps->ext_ptl[0];
	} else {
		sps->chroma_format_idc = bs_get_ue(bs);
		if (sps->chroma_format_idc==3)
			sps->separate_colour_plane_flag = gf_bs_read_int(bs, 1);
		sps->width = bs_get_ue(bs);
		sps->height = bs_get_ue(bs);
		if ( gf_bs_read_int(bs, 1)) {
			u32 SubWidthC, SubHeightC;

			if (sps->chroma_format_idc==1) {
				SubWidthC = SubHeightC = 2;
			}
			else if (sps->chroma_format_idc==2) {
				SubWidthC = 2;
				SubHeightC = 1;
			} else {
				SubWidthC = SubHeightC = 1;
			}

			sps->cw_left = bs_get_ue(bs);
			sps->cw_right = bs_get_ue(bs);
			sps->cw_top = bs_get_ue(bs);
			sps->cw_bottom = bs_get_ue(bs);

			sps->width -= SubWidthC * (sps->cw_left + sps->cw_right);
			sps->height -= SubHeightC * (sps->cw_top + sps->cw_bottom);
		}
		sps->bit_depth_luma = 8 + bs_get_ue(bs);
		sps->bit_depth_chroma = 8 + bs_get_ue(bs);
	}

	sps->log2_max_pic_order_cnt_lsb = 4 + bs_get_ue(bs);

	if (!multiLayerExtSpsFlag) {
		sps_sub_layer_ordering_info_present_flag = gf_bs_read_int(bs, 1);
		for(i=sps_sub_layer_ordering_info_present_flag ? 0 : max_sub_layers_minus1; i<=max_sub_layers_minus1; i++) {
			  bs_get_ue(bs);
			  bs_get_ue(bs);
			  bs_get_ue(bs);
		}
	}

	log2_min_luma_coding_block_size = 3 + bs_get_ue(bs);
	log2_diff_max_min_luma_coding_block_size = bs_get_ue(bs);
	sps->max_CU_width = ( 1<<(log2_min_luma_coding_block_size + log2_diff_max_min_luma_coding_block_size) );
	sps->max_CU_height = ( 1<<(log2_min_luma_coding_block_size + log2_diff_max_min_luma_coding_block_size) );

	log2_min_transform_block_size = 2 + bs_get_ue(bs);
	 bs_get_ue(bs);

	depth = 0;
	 bs_get_ue(bs);
	 bs_get_ue(bs);
	while( (u32) ( sps->max_CU_width >> log2_diff_max_min_luma_coding_block_size ) > (u32) ( 1 << ( log2_min_transform_block_size + depth )  ) )
	{
		depth++;
	}
	sps->max_CU_depth = log2_diff_max_min_luma_coding_block_size + depth;

	nb_CTUs = ((sps->width + sps->max_CU_width -1) / sps->max_CU_width) * ((sps->height + sps->max_CU_height-1) / sps->max_CU_height);
	sps->bitsSliceSegmentAddress = 0;
	while (nb_CTUs > (u32) (1 << sps->bitsSliceSegmentAddress)) {
		sps->bitsSliceSegmentAddress++;
	}

	scaling_list_enable_flag = gf_bs_read_int(bs, 1);
	if (scaling_list_enable_flag) {
		Bool sps_infer_scaling_list_flag = 0;
		 
		if (multiLayerExtSpsFlag) {
			sps_infer_scaling_list_flag = gf_bs_read_int(bs, 1);
		}

		if (sps_infer_scaling_list_flag) {
			 gf_bs_read_int(bs, 6);
		} else {
			if ( gf_bs_read_int(bs, 1) ) {
				hevc_scaling_list_data(bs);
			}
		}
	}
	  gf_bs_read_int(bs, 1);
	sps->sample_adaptive_offset_enabled_flag = gf_bs_read_int(bs, 1);
	if (  gf_bs_read_int(bs, 1) ) {
		 gf_bs_read_int(bs, 4);
		 gf_bs_read_int(bs, 4);
		  bs_get_ue(bs);
		  bs_get_ue(bs);
		 gf_bs_read_int(bs, 1);
	}
	sps->num_short_term_ref_pic_sets = bs_get_ue(bs);
	if (sps->num_short_term_ref_pic_sets>64) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[HEVC] Invalid number of short term reference picture sets %d\n", sps->num_short_term_ref_pic_sets));
		return -1;
	}
	
	for (i=0; i<sps->num_short_term_ref_pic_sets; i++) {
		Bool ret = parse_short_term_ref_pic_set(bs, sps, i);
		 
		if (!ret) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[HEVC] Invalid short_term_ref_pic_set\n"));
			return -1;
		}
	}
	sps->long_term_ref_pics_present_flag = gf_bs_read_int(bs, 1);
	if (sps->long_term_ref_pics_present_flag) {
		sps->num_long_term_ref_pic_sps = bs_get_ue(bs);
		for (i=0; i<sps->num_long_term_ref_pic_sps; i++) {
			 gf_bs_read_int(bs, sps->log2_max_pic_order_cnt_lsb);
			 gf_bs_read_int(bs, 1);
		}
	}
	sps->temporal_mvp_enable_flag = gf_bs_read_int(bs, 1);
	 gf_bs_read_int(bs, 1);

	if (vui_flag_pos)
		*vui_flag_pos = (u32) gf_bs_get_bit_offset(bs);

	if ( gf_bs_read_int(bs, 1)) {

		sps->aspect_ratio_info_present_flag = gf_bs_read_int(bs, 1);
		if (sps->aspect_ratio_info_present_flag) {
			sps->sar_idc = gf_bs_read_int(bs, 8);
			if (sps->sar_idc == 255) {
				sps->sar_width = gf_bs_read_int(bs, 16);
				sps->sar_height = gf_bs_read_int(bs, 16);
			} else if (sps->sar_idc<17) {
				sps->sar_width = hevc_sar[sps->sar_idc].w;
				sps->sar_height = hevc_sar[sps->sar_idc].h;
			}
		}

		if (  gf_bs_read_int(bs, 1))
			  gf_bs_read_int(bs, 1);

		 flag = gf_bs_read_int(bs, 1);
		if (flag) {
			 gf_bs_read_int(bs, 3);
			 gf_bs_read_int(bs, 1);
			if ( gf_bs_read_int(bs, 1)) {
				  gf_bs_read_int(bs, 8);
				  gf_bs_read_int(bs, 8);
				  gf_bs_read_int(bs, 8);
			}
		}

		if (  gf_bs_read_int(bs, 1)) {
			  bs_get_ue(bs);
			 bs_get_ue(bs);
		}

		 gf_bs_read_int(bs, 1);
		 gf_bs_read_int(bs, 1);
		 gf_bs_read_int(bs, 1);

		if ( gf_bs_read_int(bs, 1)) {
			 bs_get_ue(bs);
			 bs_get_ue(bs);
			 bs_get_ue(bs);
			 bs_get_ue(bs);
		}

		sps->has_timing_info = gf_bs_read_int(bs, 1);
		if (sps->has_timing_info ) {
			sps->num_units_in_tick = gf_bs_read_int(bs, 32);
			sps->time_scale = gf_bs_read_int(bs, 32);
			sps->poc_proportional_to_timing_flag = gf_bs_read_int(bs, 1);
			if (sps->poc_proportional_to_timing_flag)
				sps->num_ticks_poc_diff_one_minus1 = bs_get_ue(bs);
			if ( gf_bs_read_int(bs, 1) ) {
 
				return sps_id;
			}
		}

		if ( gf_bs_read_int(bs, 1)) {
			 gf_bs_read_int(bs, 1);
			 gf_bs_read_int(bs, 1);
			 gf_bs_read_int(bs, 1);
			 bs_get_ue(bs);
			 bs_get_ue(bs);
			 bs_get_ue(bs);
			 bs_get_ue(bs);
			 bs_get_ue(bs);
		}
	}

	if ( gf_bs_read_int(bs, 1)) {
		while (gf_bs_available(bs)) {
			  gf_bs_read_int(bs, 1);
		}
	}

	return sps_id;
}