s32 gf_media_hevc_parse_nalu(char *data, u32 size, HEVCState *hevc, u8 *nal_unit_type, u8 *temporal_id, u8 *layer_id)
{
	GF_BitStream *bs=NULL;
	char *data_without_emulation_bytes = NULL;
	u32 data_without_emulation_bytes_size = 0;
	Bool is_slice = GF_FALSE;
	s32 ret = -1;
	HEVCSliceInfo n_state;

	memcpy(&n_state, &hevc->s_info, sizeof(HEVCSliceInfo));

	hevc->last_parsed_vps_id = hevc->last_parsed_sps_id = hevc->last_parsed_pps_id = -1;
	hevc->s_info.entry_point_start_bits = -1;
	hevc->s_info.payload_start_offset = -1;

	data_without_emulation_bytes_size = avc_emulation_bytes_remove_count(data, size);
	if (!data_without_emulation_bytes_size) {
		bs = gf_bs_new(data, size, GF_BITSTREAM_READ);
	} else {
		/*still contains emulation bytes*/
		data_without_emulation_bytes = gf_malloc(size*sizeof(char));
		data_without_emulation_bytes_size = avc_remove_emulation_bytes(data, data_without_emulation_bytes, size);
		bs = gf_bs_new(data_without_emulation_bytes, data_without_emulation_bytes_size, GF_BITSTREAM_READ);
	}
	if (!bs) goto exit;

	if (! hevc_parse_nal_header(bs, nal_unit_type, temporal_id, layer_id)) goto exit;
	n_state.nal_unit_type = *nal_unit_type;

	switch (n_state.nal_unit_type) {
	case GF_HEVC_NALU_ACCESS_UNIT:
	case GF_HEVC_NALU_END_OF_SEQ:
	case GF_HEVC_NALU_END_OF_STREAM:
		ret = 1;
		break;

	/*slice_segment_layer_rbsp*/
	case GF_HEVC_NALU_SLICE_TRAIL_N:
	case GF_HEVC_NALU_SLICE_TRAIL_R:
	case GF_HEVC_NALU_SLICE_TSA_N:
	case GF_HEVC_NALU_SLICE_TSA_R:
	case GF_HEVC_NALU_SLICE_STSA_N:
	case GF_HEVC_NALU_SLICE_STSA_R:
	case GF_HEVC_NALU_SLICE_BLA_W_LP:
	case GF_HEVC_NALU_SLICE_BLA_W_DLP:
	case GF_HEVC_NALU_SLICE_BLA_N_LP:
	case GF_HEVC_NALU_SLICE_IDR_W_DLP:
	case GF_HEVC_NALU_SLICE_IDR_N_LP:
	case GF_HEVC_NALU_SLICE_CRA:
	case GF_HEVC_NALU_SLICE_RADL_N:
	case GF_HEVC_NALU_SLICE_RADL_R:
	case GF_HEVC_NALU_SLICE_RASL_N:
	case GF_HEVC_NALU_SLICE_RASL_R:
		is_slice = GF_TRUE;
		/* slice - read the info and compare.*/
		ret = hevc_parse_slice_segment(bs, hevc, &n_state);
		if (ret<0) goto exit;

		hevc_compute_poc(&n_state);

		ret = 0;

		if (hevc->s_info.poc != n_state.poc) {
			ret=1;
			break;
		}
		if (n_state.first_slice_segment_in_pic_flag) {
			if (!(*layer_id) || (n_state.prev_layer_id_plus1 && ((*layer_id) <= n_state.prev_layer_id_plus1 - 1)) ) {
				ret = 1;
				break;
			}
		}
		break;
	case GF_HEVC_NALU_SEQ_PARAM:
		hevc->last_parsed_sps_id = gf_media_hevc_read_sps_bs(bs, hevc, *layer_id, NULL);
		ret = 0;
		break;
	case GF_HEVC_NALU_PIC_PARAM:
		hevc->last_parsed_pps_id = gf_media_hevc_read_pps_bs(bs, hevc);
		ret = 0;
		break;
	case GF_HEVC_NALU_VID_PARAM:
		hevc->last_parsed_vps_id = gf_media_hevc_read_vps_bs(bs, hevc, GF_FALSE);
		ret = 0;
		break;
	default:
		ret = 0;
		break;
	}

	/* save _prev values */
	if (ret && hevc->s_info.sps) {
		n_state.frame_num_offset_prev = hevc->s_info.frame_num_offset;
		n_state.frame_num_prev = hevc->s_info.frame_num;

		n_state.poc_lsb_prev = hevc->s_info.poc_lsb;
		n_state.poc_msb_prev = hevc->s_info.poc_msb;
		n_state.prev_layer_id_plus1 = *layer_id + 1;
	}
	if (is_slice) hevc_compute_poc(&n_state);
	memcpy(&hevc->s_info, &n_state, sizeof(HEVCSliceInfo));

exit:
	if (bs) gf_bs_del(bs);
	if (data_without_emulation_bytes) gf_free(data_without_emulation_bytes);
	return ret;
}