GF_Err gf_m4a_write_config_bs(GF_BitStream *bs, GF_M4ADecSpecInfo *cfg)
{
	if (!cfg->base_sr_index) {
		if (!cfg->base_sr) return GF_BAD_PARAM;
		while (GF_M4ASampleRates[cfg->base_sr_index]) {
			if (GF_M4ASampleRates[cfg->base_sr_index]==cfg->base_sr)
				break;
			cfg->base_sr_index++;
		}
	}
	if (cfg->sbr_sr && !cfg->sbr_sr_index) {
		while (GF_M4ASampleRates[cfg->sbr_sr_index]) {
			if (GF_M4ASampleRates[cfg->sbr_sr_index]==cfg->sbr_sr)
				break;
			cfg->sbr_sr_index++;
		}
	}
	/*extended object type*/
	if (cfg->base_object_type>=32) {
		gf_bs_write_int(bs, 31, 5);
		gf_bs_write_int(bs, cfg->base_object_type-32, 6);
	} else {
		gf_bs_write_int(bs, cfg->base_object_type, 5);
	}
	gf_bs_write_int(bs, cfg->base_sr_index, 4);
	if (cfg->base_sr_index == 0x0F) {
		gf_bs_write_int(bs, cfg->base_sr, 24);
	}

	if (cfg->program_config_element_present) {
		gf_bs_write_int(bs, 0, 4);
	} else {
		gf_bs_write_int(bs, gf_m4a_get_channel_cfg( cfg->nb_chan) , 4);
	}

	if (cfg->base_object_type==5 || cfg->base_object_type==29) {
		if (cfg->base_object_type == 29) {
			cfg->has_ps = 1;
			cfg->nb_chan = 1;
		}
		cfg->has_sbr = 1;
		gf_bs_write_int(bs, cfg->sbr_sr_index, 4);
		if (cfg->sbr_sr_index == 0x0F) {
			gf_bs_write_int(bs, cfg->sbr_sr, 24);
		}
		gf_bs_write_int(bs, cfg->sbr_object_type, 5);
	}

	/*object cfg*/
	switch (cfg->base_object_type) {
	case 1:
	case 2:
	case 3:
	case 4:
	case 6:
	case 7:
	case 17:
	case 19:
	case 20:
	case 21:
	case 22:
	case 23:
	{
		/*frame length flag*/
		gf_bs_write_int(bs, 0, 1);
		/*depends on core coder*/
		gf_bs_write_int(bs, 0, 1);
		/*ext flag*/
		gf_bs_write_int(bs, 0, 1);

		if (cfg->program_config_element_present) {
			u32 i;
			gf_bs_write_int(bs, cfg->element_instance_tag, 4);
			gf_bs_write_int(bs, cfg->object_type, 2);
			gf_bs_write_int(bs, cfg->sampling_frequency_index, 4);
			gf_bs_write_int(bs, cfg->num_front_channel_elements, 4);
			gf_bs_write_int(bs, cfg->num_side_channel_elements, 4);
			gf_bs_write_int(bs, cfg->num_back_channel_elements, 4);
			gf_bs_write_int(bs, cfg->num_lfe_channel_elements, 2);
			gf_bs_write_int(bs, cfg->num_assoc_data_elements, 3);
			gf_bs_write_int(bs, cfg->num_valid_cc_elements, 4);
			gf_bs_write_int(bs, cfg-> mono_mixdown_present, 1);
			if (cfg->mono_mixdown_present) {
				gf_bs_write_int(bs, cfg->mono_mixdown_element_number, 4);
			}
			gf_bs_write_int(bs, cfg->stereo_mixdown_present, 1);
			if (cfg->stereo_mixdown_present) {
				gf_bs_write_int(bs, cfg->stereo_mixdown_element_number, 4);
			}
			gf_bs_write_int(bs, cfg->matrix_mixdown_idx_present, 1);
			if (cfg->matrix_mixdown_idx_present) {
				gf_bs_write_int(bs, cfg->matrix_mixdown_idx, 2);
				gf_bs_write_int(bs, cfg->pseudo_surround_enable, 1);
			}
			for (i = 0; i < cfg->num_front_channel_elements; i++) {
				gf_bs_write_int(bs, cfg->front_element_is_cpe[i], 1);
				gf_bs_write_int(bs, cfg->front_element_tag_select[i], 4);
			}
			for (i = 0; i < cfg->num_side_channel_elements; i++) {
				gf_bs_write_int(bs, cfg->side_element_is_cpe[i], 1);
				gf_bs_write_int(bs, cfg->side_element_tag_select[i], 4);
			}
			for (i = 0; i < cfg->num_back_channel_elements; i++) {
				gf_bs_write_int(bs, cfg->back_element_is_cpe[i], 1);
				gf_bs_write_int(bs, cfg->back_element_tag_select[i], 4);
			}
			for (i = 0; i < cfg->num_lfe_channel_elements; i++) {
				gf_bs_write_int(bs, cfg->lfe_element_tag_select[i], 4);
			}
			for ( i = 0; i < cfg->num_assoc_data_elements; i++) {
				gf_bs_write_int(bs, cfg->assoc_data_element_tag_select[i], 4);
			}

			for (i = 0; i < cfg->num_valid_cc_elements; i++) {
				gf_bs_write_int(bs, cfg->cc_element_is_ind_sw[i], 1);
				gf_bs_write_int(bs, cfg->valid_cc_element_tag_select[i], 4);
			}
			gf_bs_align(bs);
			gf_bs_write_int(bs, cfg->comment_field_bytes, 8);
			gf_bs_write_data(bs, (char *) cfg->comments, cfg->comment_field_bytes);
		}

		if ((cfg->base_object_type == 6) || (cfg->base_object_type == 20)) {
			gf_bs_write_int(bs, 0, 3);
		}
	}
	break;
	}
	/*ER cfg - not supported*/

	/*implicit sbr - not used yet*/
	if (0 && (cfg->base_object_type != 5) && (cfg->base_object_type != 29) ) {
		gf_bs_write_int(bs, 0x2b7, 11);
		cfg->sbr_object_type = gf_bs_read_int(bs, 5);
		cfg->has_sbr = gf_bs_read_int(bs, 1);
		if (cfg->has_sbr) {
			cfg->sbr_sr_index = gf_bs_read_int(bs, 4);
			if (cfg->sbr_sr_index == 0x0F) {
				cfg->sbr_sr = gf_bs_read_int(bs, 24);
			} else {
				cfg->sbr_sr = GF_M4ASampleRates[cfg->sbr_sr_index];
			}
		}
	}
	return GF_OK;
}
GF_Err gf_m4a_write_config_bs(GF_BitStream *bs, GF_M4ADecSpecInfo *cfg)
{
	if (!cfg->base_sr_index) {
		if (!cfg->base_sr) return GF_BAD_PARAM;
		while (GF_M4ASampleRates[cfg->base_sr_index]) {
			if (GF_M4ASampleRates[cfg->base_sr_index]==cfg->base_sr)
				break;
			cfg->base_sr_index++;
		}
	}
	if (cfg->sbr_sr && !cfg->sbr_sr_index) {
		while (GF_M4ASampleRates[cfg->sbr_sr_index]) {
			if (GF_M4ASampleRates[cfg->sbr_sr_index]==cfg->sbr_sr)
				break;
			cfg->sbr_sr_index++;
		}
	}
	 
	if (cfg->base_object_type>=32) {
		gf_bs_write_int(bs, 31, 5);
		gf_bs_write_int(bs, cfg->base_object_type-32, 6);
	} else {
		gf_bs_write_int(bs, cfg->base_object_type, 5);
	}
	gf_bs_write_int(bs, cfg->base_sr_index, 4);
	if (cfg->base_sr_index == 0x0F) {
		gf_bs_write_int(bs, cfg->base_sr, 24);
	}

	if (cfg->program_config_element_present) {
		gf_bs_write_int(bs, 0, 4);
	} else {
		gf_bs_write_int(bs, gf_m4a_get_channel_cfg( cfg->nb_chan) , 4);
	}

	if (cfg->base_object_type==5 || cfg->base_object_type==29) {
		if (cfg->base_object_type == 29) {
			cfg->has_ps = 1;
			cfg->nb_chan = 1;
		}
		cfg->has_sbr = 1;
		gf_bs_write_int(bs, cfg->sbr_sr_index, 4);
		if (cfg->sbr_sr_index == 0x0F) {
			gf_bs_write_int(bs, cfg->sbr_sr, 24);
		}
		gf_bs_write_int(bs, cfg->sbr_object_type, 5);
	}

	 
	switch (cfg->base_object_type) {
	case 1:
	case 2:
	case 3:
	case 4:
	case 6:
	case 7:
	case 17:
	case 19:
	case 20:
	case 21:
	case 22:
	case 23:
	{
		 
		gf_bs_write_int(bs, 0, 1);
		 
		gf_bs_write_int(bs, 0, 1);
		 
		gf_bs_write_int(bs, 0, 1);

		if (cfg->program_config_element_present) {
			u32 i;
			gf_bs_write_int(bs, cfg->element_instance_tag, 4);
			gf_bs_write_int(bs, cfg->object_type, 2);
			gf_bs_write_int(bs, cfg->sampling_frequency_index, 4);
			gf_bs_write_int(bs, cfg->num_front_channel_elements, 4);
			gf_bs_write_int(bs, cfg->num_side_channel_elements, 4);
			gf_bs_write_int(bs, cfg->num_back_channel_elements, 4);
			gf_bs_write_int(bs, cfg->num_lfe_channel_elements, 2);
			gf_bs_write_int(bs, cfg->num_assoc_data_elements, 3);
			gf_bs_write_int(bs, cfg->num_valid_cc_elements, 4);
			gf_bs_write_int(bs, cfg-> mono_mixdown_present, 1);
			if (cfg->mono_mixdown_present) {
				gf_bs_write_int(bs, cfg->mono_mixdown_element_number, 4);
			}
			gf_bs_write_int(bs, cfg->stereo_mixdown_present, 1);
			if (cfg->stereo_mixdown_present) {
				gf_bs_write_int(bs, cfg->stereo_mixdown_element_number, 4);
			}
			gf_bs_write_int(bs, cfg->matrix_mixdown_idx_present, 1);
			if (cfg->matrix_mixdown_idx_present) {
				gf_bs_write_int(bs, cfg->matrix_mixdown_idx, 2);
				gf_bs_write_int(bs, cfg->pseudo_surround_enable, 1);
			}
			for (i = 0; i < cfg->num_front_channel_elements; i++) {
				gf_bs_write_int(bs, cfg->front_element_is_cpe[i], 1);
				gf_bs_write_int(bs, cfg->front_element_tag_select[i], 4);
			}
			for (i = 0; i < cfg->num_side_channel_elements; i++) {
				gf_bs_write_int(bs, cfg->side_element_is_cpe[i], 1);
				gf_bs_write_int(bs, cfg->side_element_tag_select[i], 4);
			}
			for (i = 0; i < cfg->num_back_channel_elements; i++) {
				gf_bs_write_int(bs, cfg->back_element_is_cpe[i], 1);
				gf_bs_write_int(bs, cfg->back_element_tag_select[i], 4);
			}
			for (i = 0; i < cfg->num_lfe_channel_elements; i++) {
				gf_bs_write_int(bs, cfg->lfe_element_tag_select[i], 4);
			}
			for ( i = 0; i < cfg->num_assoc_data_elements; i++) {
				gf_bs_write_int(bs, cfg->assoc_data_element_tag_select[i], 4);
			}

			for (i = 0; i < cfg->num_valid_cc_elements; i++) {
				gf_bs_write_int(bs, cfg->cc_element_is_ind_sw[i], 1);
				gf_bs_write_int(bs, cfg->valid_cc_element_tag_select[i], 4);
			}
			gf_bs_align(bs);
			gf_bs_write_int(bs, cfg->comment_field_bytes, 8);
			gf_bs_write_data(bs, (char *) cfg->comments, cfg->comment_field_bytes);
		}

		if ((cfg->base_object_type == 6) || (cfg->base_object_type == 20)) {
			gf_bs_write_int(bs, 0, 3);
		}
	}
	break;
	}
	 

	 
	if (0 && (cfg->base_object_type != 5) && (cfg->base_object_type != 29) ) {
		gf_bs_write_int(bs, 0x2b7, 11);
		cfg->sbr_object_type = gf_bs_read_int(bs, 5);
		cfg->has_sbr = gf_bs_read_int(bs, 1);
		if (cfg->has_sbr) {
			cfg->sbr_sr_index = gf_bs_read_int(bs, 4);
			if (cfg->sbr_sr_index == 0x0F) {
				cfg->sbr_sr = gf_bs_read_int(bs, 24);
			} else {
				cfg->sbr_sr = GF_M4ASampleRates[cfg->sbr_sr_index];
			}
		}
	}
	return GF_OK;
}