GF_Err udta_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem)
{
	GF_Err e;
	u32 box_type;
	GF_UserDataMap *map;
	GF_UserDataBox *ptr = (GF_UserDataBox *)s;
	if (!ptr) return GF_BAD_PARAM;
	if (!a) return GF_OK;

	//detach from parent list if any
	gf_list_del_item(ptr->child_boxes, a);

	/* for unknown udta boxes, we reference them by their original box type */
	box_type = a->type;
	if (box_type == GF_ISOM_BOX_TYPE_UNKNOWN) {
		GF_UnknownBox* unkn = (GF_UnknownBox *)a;
		box_type = unkn->original_4cc;
	}

	map = udta_getEntry(ptr, box_type, (a->type==GF_ISOM_BOX_TYPE_UUID) ? & ((GF_UUIDBox *)a)->uuid : NULL);
	if (map == NULL) {
		if (is_rem) return GF_OK;

		map = (GF_UserDataMap *) gf_malloc(sizeof(GF_UserDataMap));
		if (map == NULL) return GF_OUT_OF_MEM;
		memset(map, 0, sizeof(GF_UserDataMap));

		map->boxType = box_type;
		if (a->type == GF_ISOM_BOX_TYPE_UUID)
			memcpy(map->uuid, ((GF_UUIDBox *)a)->uuid, 16);
		map->boxes = gf_list_new();
		if (!map->boxes) {
			gf_free(map);
			return GF_OUT_OF_MEM;
		}
		e = gf_list_add(ptr->recordList, map);
		if (e) return e;
	}
	if (is_rem) {
		gf_list_del_item(map->boxes, a);
		return GF_OK;
	}
	return gf_list_add(map->boxes, a);
}

fixed #2255


GF_Box *saio_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_SampleAuxiliaryInfoOffsetBox, GF_ISOM_BOX_TYPE_SAIO);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err fecr_box_size(GF_Box *s)
{
	FECReservoirBox *ptr = (FECReservoirBox *)s;
	ptr->size += (ptr->version ? 4 : 2) +  ptr->nb_entries * (ptr->version ? 8 : 6);
	return GF_OK;
}

fixed #2255


void trgr_box_del(GF_Box *s)
{
	GF_TrackGroupBox *ptr = (GF_TrackGroupBox *)s;
	if (ptr == NULL) return;
	gf_list_del(ptr->groups);
	gf_free(ptr);
}

fixed #2255


GF_Err tref_box_size(GF_Box *s)
{
	return GF_OK;
}

fixed #2255


GF_Err saiz_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_SampleAuxiliaryInfoSizeBox*ptr = (GF_SampleAuxiliaryInfoSizeBox*) s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	if (ptr->flags & 1) {
		gf_bs_write_u32(bs, ptr->aux_info_type);
		gf_bs_write_u32(bs, ptr->aux_info_type_parameter);
	}
	gf_bs_write_u8(bs, ptr->default_sample_info_size);
	gf_bs_write_u32(bs, ptr->sample_count);
	if (!ptr->default_sample_info_size) {
		if (!ptr->sample_info_size)
			gf_bs_write_u8(bs, 0);
		else
			gf_bs_write_data(bs, (char *) ptr->sample_info_size, ptr->sample_count);
	}
	return GF_OK;
}

fixed #2255


GF_Err audio_sample_entry_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_MPEGAudioSampleEntryBox *ptr;
	char *data;
	u8 a, b, c, d;
	u32 i, size, v, nb_alnum;
	GF_Err e;
	u64 pos, start;

	ptr = (GF_MPEGAudioSampleEntryBox *)s;

	start = gf_bs_get_position(bs);
	gf_bs_seek(bs, start + 8);
	v = gf_bs_read_u16(bs);
	if (v)
		ptr->qtff_mode = GF_ISOM_AUDIO_QTFF_ON_NOEXT;

	//try to disambiguate QTFF v1 and MP4 v1 audio sample entries ...
	if (v==1) {
		//go to end of ISOM audio sample entry, skip 4 byte (box size field), read 4 bytes (box type) and check if this looks like a box
		gf_bs_seek(bs, start + 8 + 20  + 4);
		a = gf_bs_read_u8(bs);
		b = gf_bs_read_u8(bs);
		c = gf_bs_read_u8(bs);
		d = gf_bs_read_u8(bs);
		nb_alnum = 0;
		if (isalnum(a)) nb_alnum++;
		if (isalnum(b)) nb_alnum++;
		if (isalnum(c)) nb_alnum++;
		if (isalnum(d)) nb_alnum++;
		if (nb_alnum>2) ptr->qtff_mode = GF_ISOM_AUDIO_QTFF_NONE;
	}

	gf_bs_seek(bs, start);
	e = gf_isom_audio_sample_entry_read((GF_AudioSampleEntryBox*)s, bs);
	if (e) return e;
	pos = gf_bs_get_position(bs);
	size = (u32) s->size;

	//when cookie is set on bs, always convert qtff-style mp4a to isobmff-style
	//since the conversion is done in addBox and we don't have the bitstream there (arg...), flag the box
 	if (gf_bs_get_cookie(bs) & GF_ISOM_BS_COOKIE_QT_CONV) {
 		ptr->qtff_mode |= GF_ISOM_AUDIO_QTFF_CONVERT_FLAG;
 	}

	e = gf_isom_box_array_read(s, bs);
	if (!e) {
		if (s->type==GF_ISOM_BOX_TYPE_ENCA) {
			GF_ProtectionSchemeInfoBox *sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(s->child_boxes, GF_ISOM_BOX_TYPE_SINF);

			if (sinf && sinf->original_format) {
				u32 type = sinf->original_format->data_format;
				switch (type) {
				case GF_ISOM_SUBTYPE_3GP_AMR:
				case GF_ISOM_SUBTYPE_3GP_AMR_WB:
				case GF_ISOM_SUBTYPE_3GP_EVRC:
				case GF_ISOM_SUBTYPE_3GP_QCELP:
				case GF_ISOM_SUBTYPE_3GP_SMV:
					if (ptr->cfg_3gpp) ptr->cfg_3gpp->cfg.type = type;
					break;
				}
			}
		}
		return GF_OK;
	}
	if (size<8) return GF_ISOM_INVALID_FILE;

	/*hack for some weird files (possibly recorded with live.com tools, needs further investigations)*/
	gf_bs_seek(bs, pos);
	data = (char*)gf_malloc(sizeof(char) * size);
	if (!data) return GF_OUT_OF_MEM;

	gf_bs_read_data(bs, data, size);
	for (i=0; i<size-8; i++) {
		if (GF_4CC((u32)data[i+4], (u8)data[i+5], (u8)data[i+6], (u8)data[i+7]) == GF_ISOM_BOX_TYPE_ESDS) {
			GF_BitStream *mybs = gf_bs_new(data + i, size - i, GF_BITSTREAM_READ);
			gf_bs_set_cookie(mybs, GF_ISOM_BS_COOKIE_NO_LOGS);
			if (ptr->esd) gf_isom_box_del_parent(&ptr->child_boxes, (GF_Box *)ptr->esd);
			ptr->esd = NULL;
			e = gf_isom_box_parse((GF_Box **)&ptr->esd, mybs);
			gf_bs_del(mybs);

			if ((e==GF_OK) && ptr->esd && (ptr->esd->type == GF_ISOM_BOX_TYPE_ESDS)) {
				if (!ptr->child_boxes) ptr->child_boxes = gf_list_new();
				gf_list_add(ptr->child_boxes, ptr->esd);
			} else if (ptr->esd) {
				gf_isom_box_del((GF_Box *)ptr->esd);
				ptr->esd = NULL;
			}
			e = GF_OK;
			break;
		}
	}
	gf_free(data);
	return e;
}

fixed #2255


GF_Err lsrc_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_LASERConfigurationBox *ptr = (GF_LASERConfigurationBox *)s;
	ptr->hdr_size = (u32) ptr->size;
	ptr->hdr = gf_malloc(sizeof(char)*ptr->hdr_size);
	if (!ptr->hdr) return GF_OUT_OF_MEM;
	gf_bs_read_data(bs, ptr->hdr, ptr->hdr_size);
	return GF_OK;
}

fixed #2255


GF_Err lsr1_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_LASeRSampleEntryBox *ptr = (GF_LASeRSampleEntryBox *)s;
	e = gf_isom_box_write_header(s, bs);
	if (e) return e;

	gf_bs_write_data(bs, ptr->reserved, 6);
	gf_bs_write_u16(bs, ptr->dataReferenceIndex);
	return GF_OK;
}

fixed #2255


GF_Box *prhd_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_ProjectionHeaderBox, GF_ISOM_BOX_TYPE_PRHD);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err txtc_box_size(GF_Box *s)
{
	GF_TextConfigBox *ptr = (GF_TextConfigBox *)s;
	if (ptr->config)
		ptr->size += strlen(ptr->config);
	ptr->size++;
	return GF_OK;
}

fixed #2255


GF_Err trik_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u32 i;
	GF_TrickPlayBox *ptr = (GF_TrickPlayBox *) s;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	for (i=0; i < ptr->entry_count; i++ ) {
		gf_bs_write_int(bs, ptr->entries[i].pic_type, 2);
		gf_bs_write_int(bs, ptr->entries[i].dependency_level, 6);
	}
	return GF_OK;
}

fixed #2255


GF_Err gitn_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u32 i;
	GroupIdToNameBox *ptr = (GroupIdToNameBox *) s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	gf_bs_write_u16(bs, ptr->nb_entries);
	for (i=0; i<ptr->nb_entries; i++) {
		gf_bs_write_u32(bs, ptr->entries[i].group_id);
		if (ptr->entries[i].name) gf_bs_write_data(bs, ptr->entries[i].name, (u32)strlen(ptr->entries[i].name) );
		gf_bs_write_u8(bs, 0);
	}
	return GF_OK;
}

fixed #2255


GF_Box *stri_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_SubTrackInformationBox, GF_ISOM_BOX_TYPE_STRI);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err vmhd_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_VideoMediaHeaderBox *ptr = (GF_VideoMediaHeaderBox *)s;

	ISOM_DECREASE_SIZE(ptr, 8);
	ptr->reserved = gf_bs_read_u64(bs);
	return GF_OK;
}

fixed #2255


GF_Box *segr_box_new()
{
	ISOM_DECL_BOX_ALLOC(FDSessionGroupBox, GF_ISOM_BOX_TYPE_SEGR);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *txtc_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_TextConfigBox, GF_ISOM_BOX_TYPE_TXTC);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err st3d_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_Stereo3DBox *ptr = (GF_Stereo3DBox *)s;
	ISOM_DECREASE_SIZE(ptr, 1)
	ptr->stereo_type = gf_bs_read_u8(bs);
	return GF_OK;
}

fixed #2255


static GF_Err ctrn_box_size(GF_TrackFragmentRunBox *ctrn)
{
	Bool use_ctso_multi = GF_TRUE;
	u32 i, count;
	GF_TrunEntry *ent;

	ctrn->ctrn_flags = 0;
	ctrn->ctrn_first_dur = ctrn->ctrn_first_size = ctrn->ctrn_first_sample_flags = ctrn->ctrn_first_ctts = 0;
	ctrn->ctrn_dur = ctrn->ctrn_size = ctrn->ctrn_sample_flags = ctrn->ctrn_ctts = 0;

	ctrn->size += 2; //16 bits for sample count
	if (ctrn->flags & GF_ISOM_TRUN_DATA_OFFSET) {
		ctrn->ctrn_flags |= GF_ISOM_TRUN_DATA_OFFSET;
		if (ABS(ctrn->data_offset) < 32767) {
			ctrn->size += 2;
			ctrn->ctrn_flags |= GF_ISOM_CTRN_DATAOFFSET_16;
		} else
			ctrn->size += 4;
	}

	count = gf_list_count(ctrn->entries);
	if (ctrn->ctso_multiplier && (ctrn->flags & GF_ISOM_TRUN_CTS_OFFSET) && (ctrn->ctso_multiplier<=0xFFFF) ) {
		for (i=0; i<count; i++) {
			GF_TrunEntry *a_ent = gf_list_get(ctrn->entries, i);
			if (a_ent->CTS_Offset % ctrn->ctso_multiplier) {
				use_ctso_multi = GF_FALSE;
				break;
			}
		}
	} else {
		use_ctso_multi = GF_FALSE;
	}
	if (ctrn->use_inherit) {
		use_ctso_multi = GF_FALSE;
		ctrn->ctrn_flags |= 0xB0; //duration=1,size=0,flags=1,cts=1 << 4
	}

	if (use_ctso_multi) {
		ctrn->size += 2;
		ctrn->ctrn_flags |= GF_ISOM_CTRN_CTSO_MULTIPLIER;
	} else {
		ctrn->ctso_multiplier = 0;
	}

	/*we always write first sample using first flags*/
	ent = gf_list_get(ctrn->entries, 0);
	ctrn->ctrn_flags |= GF_ISOM_CTRN_FIRST_SAMPLE;

	if (!ctrn->use_inherit && (ctrn->flags & GF_ISOM_TRUN_DURATION)) {
		ctrn->ctrn_first_dur = ctrn_u32_to_index(ent->Duration);
		if (ctrn->ctrn_first_dur) {
			ctrn->size += ctrn_field_size(ctrn->ctrn_first_dur);
			ctrn->ctrn_flags |= ctrn->ctrn_first_dur<<22;
		}
	}

	if (ctrn->flags & GF_ISOM_TRUN_SIZE) {
		ctrn->ctrn_first_size = ctrn_u32_to_index(ent->size);
		if (ctrn->ctrn_first_size) {
			ctrn->size += ctrn_field_size(ctrn->ctrn_first_size);
			ctrn->ctrn_flags |= ctrn->ctrn_first_size<<20;
		}
	}

	if (!ctrn->use_inherit && (ctrn->flags & GF_ISOM_TRUN_FLAGS)) {
		ctrn->ctrn_first_sample_flags = ctrn_sample_flags_to_index(ent->flags);
		if (ctrn->ctrn_first_sample_flags) {
			ctrn->size += ctrn_field_size(ctrn->ctrn_first_sample_flags);
			ctrn->ctrn_flags |= ctrn->ctrn_first_sample_flags<<18;
		}
	}
	if (!ctrn->use_inherit && (ctrn->flags & GF_ISOM_TRUN_CTS_OFFSET)) {
		ctrn->ctrn_first_ctts = ctrn_ctts_to_index(ctrn, ent->CTS_Offset);
		if (ctrn->ctrn_first_ctts) {
			ctrn->size += ctrn_field_size(ctrn->ctrn_first_ctts);
			ctrn->ctrn_flags |= ctrn->ctrn_first_ctts<<16;
		}
	}

	for (i=1; i<count; i++) {
		u8 field_idx;
		GF_TrunEntry *a_ent = gf_list_get(ctrn->entries, i);

		if (!ctrn->use_inherit && (ctrn->flags & GF_ISOM_TRUN_DURATION)) {
			field_idx = ctrn_u32_to_index(a_ent->Duration);
			if (ctrn->ctrn_dur < field_idx)
				ctrn->ctrn_dur = field_idx;
		}
		if (ctrn->flags & GF_ISOM_TRUN_SIZE) {
			field_idx = ctrn_u32_to_index(a_ent->size);
			if (ctrn->ctrn_size < field_idx)
				ctrn->ctrn_size = field_idx;
		}
		if (!ctrn->use_inherit && (ctrn->flags & GF_ISOM_TRUN_FLAGS)) {
			field_idx = ctrn_sample_flags_to_index(a_ent->flags);
			if (ctrn->ctrn_sample_flags < field_idx)
				ctrn->ctrn_sample_flags = field_idx;
		}
		if (!ctrn->use_inherit) {
			field_idx = ctrn_ctts_to_index(ctrn, a_ent->CTS_Offset);
			if (ctrn->ctrn_ctts < field_idx)
				ctrn->ctrn_ctts = field_idx;
		}
	}
	count-=1;
	if (ctrn->ctrn_dur) {
		ctrn->size += count * ctrn_field_size(ctrn->ctrn_dur);
		ctrn->ctrn_flags |= ctrn->ctrn_dur<<14;
	}
	if (ctrn->ctrn_size) {
		ctrn->size += count * ctrn_field_size(ctrn->ctrn_size);
		ctrn->ctrn_flags |= ctrn->ctrn_size<<12;
	}
	if (ctrn->ctrn_sample_flags) {
		ctrn->size += count * ctrn_field_size(ctrn->ctrn_sample_flags);
		ctrn->ctrn_flags |= ctrn->ctrn_sample_flags<<10;
	}
	if (ctrn->ctrn_ctts) {
		ctrn->size += count * ctrn_field_size(ctrn->ctrn_ctts);
		ctrn->ctrn_flags |= ctrn->ctrn_ctts<<8;
	}
	return GF_OK;
}

fixed #2255


void vmhd_box_del(GF_Box *s)
{
	GF_VideoMediaHeaderBox *ptr = (GF_VideoMediaHeaderBox *)s;
	if (ptr == NULL) return;
	gf_free(ptr);
}

fixed #2255


GF_Err dfla_box_size(GF_Box *s)
{
	GF_FLACConfigBox *ptr = (GF_FLACConfigBox *) s;
	ptr->size += ptr->dataSize;
	return GF_OK;
}

fixed #2255


GF_Err fecr_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u32 i;
	FECReservoirBox *ptr = (FECReservoirBox *) s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	gf_bs_write_int(bs, ptr->nb_entries, ptr->version ? 32 : 16);
	for (i=0; i<ptr->nb_entries; i++) {
		gf_bs_write_int(bs, ptr->entries[i].item_id, ptr->version ? 32 : 16);
		gf_bs_write_u32(bs, ptr->entries[i].symbol_count);
	}
	return GF_OK;
}

fixed #2255


GF_Box *trgt_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_TrackGroupTypeBox, GF_ISOM_BOX_TYPE_TRGT);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err trak_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u32 i;
	GF_TrackBox *ptr = (GF_TrackBox *)s;
	e = gf_isom_box_array_read(s, bs);
	if (e) return e;
	e = gf_isom_check_sample_desc(ptr);
	if (e) return e;

	if (!ptr->Header) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Missing TrackHeaderBox\n"));
		return GF_ISOM_INVALID_FILE;
	}
	if (!ptr->Media) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Missing MediaBox\n"));
		return GF_ISOM_INVALID_FILE;
	}
	if (!ptr->Media->information || !ptr->Media->information->sampleTable) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid MediaBox\n"));
		return GF_ISOM_INVALID_FILE;
	}
	if (!ptr->Media->information->sampleTable->SampleSize || (ptr->Media->information->sampleTable->SampleSize->sampleCount==0)) {
		if (ptr->Header->initial_duration) {
			GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Track with no samples but duration defined, ignoring duration\n"));
			ptr->Header->initial_duration = 0;
		}
	}

	for (i=0; i<gf_list_count(ptr->Media->information->sampleTable->child_boxes); i++) {
		GF_Box *a = gf_list_get(ptr->Media->information->sampleTable->child_boxes, i);
		if ((a->type ==GF_ISOM_BOX_TYPE_UUID) && (((GF_UUIDBox *)a)->internal_4cc == GF_ISOM_BOX_UUID_PSEC)) {
			ptr->sample_encryption = (struct __sample_encryption_box *) a;
			break;
		}
		else if (a->type == GF_ISOM_BOX_TYPE_SENC) {
			ptr->sample_encryption = (struct __sample_encryption_box *)a;
			break;
		}
	}
	return e;
}

fixed #2255


GF_Box *leva_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_LevelAssignmentBox, GF_ISOM_BOX_TYPE_LEVA);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *subs_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_SubSampleInformationBox, GF_ISOM_BOX_TYPE_SUBS);
	tmp->Samples = gf_list_new();
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err rvcc_box_size(GF_Box *s)
{
	GF_RVCConfigurationBox *ptr = (GF_RVCConfigurationBox *)s;
	ptr->size += 2;
	if (! ptr->predefined_rvc_config) ptr->size += 2;
	return GF_OK;
}

fixed #2255


GF_Err pcmC_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_PCMConfigBox *ptr = (GF_PCMConfigBox *) s;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;
	gf_bs_write_u8(bs, ptr->format_flags);
	gf_bs_write_u8(bs, ptr->PCM_sample_size);
	return GF_OK;
}

fixed #2255


GF_Err trex_box_size(GF_Box *s)
{
	GF_TrackExtendsBox *ptr = (GF_TrackExtendsBox *)s;
	ptr->size += 20;
	return GF_OK;
}

fixed #2255


void jp2h_box_del(GF_Box *s)
{
	gf_free(s);
}

fixed #2255


GF_Err fiin_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	FDItemInformationBox *ptr = (FDItemInformationBox *) s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	gf_bs_write_u16(bs, gf_list_count(ptr->partition_entries) );
	return GF_OK;
}

fixed #2255


GF_Box *fiin_box_new()
{
	ISOM_DECL_BOX_ALLOC(FDItemInformationBox, GF_ISOM_BOX_TYPE_FIIN);
	return (GF_Box *)tmp;
}

fixed #2255


void ssix_box_del(GF_Box *s)
{
	u32 i;
	GF_SubsegmentIndexBox *ptr = (GF_SubsegmentIndexBox *)s;
	if (ptr == NULL) return;
	if (ptr->subsegments) {
		for (i = 0; i < ptr->subsegment_alloc; i++) {
			GF_SubsegmentInfo *subsegment = &ptr->subsegments[i];
			if (subsegment->ranges) gf_free(subsegment->ranges);
		}
		gf_free(ptr->subsegments);
	}
	gf_free(ptr);
}

fixed #2255


GF_Err fdsa_box_read(GF_Box *s, GF_BitStream *bs)
{
	return gf_isom_box_array_read(s, bs);
}

fixed #2255


GF_Err csgp_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 i, bits, gidx_mask;
	Bool index_msb_indicates_fragment_local_description, grouping_type_parameter_present;
	u32 pattern_size, scount_size, index_size;
	GF_CompactSampleGroupBox *ptr = (GF_CompactSampleGroupBox *)s;

	ISOM_DECREASE_SIZE(ptr, 8);
	ptr->version = gf_bs_read_u8(bs);
	ptr->flags = gf_bs_read_u24(bs);

	index_msb_indicates_fragment_local_description = (ptr->flags & (1<<7)) ? GF_TRUE : GF_FALSE;
	grouping_type_parameter_present = (ptr->flags & (1<<6)) ? GF_TRUE : GF_FALSE;

	pattern_size = get_size_by_code( ((ptr->flags>>4) & 0x3) );
	scount_size = get_size_by_code( ((ptr->flags>>2) & 0x3) );
	index_size = get_size_by_code( (ptr->flags & 0x3) );

	if (((pattern_size==4) && (scount_size!=4)) || ((pattern_size!=4) && (scount_size==4))) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] compact sample gorup pattern_size and sample_count_size mare not both 4 bits\n"));
		return GF_ISOM_INVALID_FILE;
	}

	ptr->grouping_type = gf_bs_read_u32(bs);
	if (grouping_type_parameter_present) {
		ISOM_DECREASE_SIZE(ptr, 4);
		ptr->grouping_type_parameter = gf_bs_read_u32(bs);
	}
	ISOM_DECREASE_SIZE(ptr, 4);
	ptr->pattern_count = gf_bs_read_u32(bs);

	if ( (ptr->size / ( (pattern_size + scount_size) / 8 ) < ptr->pattern_count) || (u64)ptr->pattern_count > (u64)SIZE_MAX/sizeof(GF_CompactSampleGroupPattern) ) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] compact sample gorup pattern_count value (%lu) invalid\n", ptr->pattern_count));
		return GF_ISOM_INVALID_FILE;
	}

	ptr->patterns = gf_malloc(sizeof(GF_CompactSampleGroupPattern) * ptr->pattern_count);
	if (!ptr->patterns) return GF_OUT_OF_MEM;
	memset(ptr->patterns, 0, sizeof(GF_CompactSampleGroupPattern) * ptr->pattern_count);

	u64 patterns_sizes=0;
	bits = 0;
	for (i=0; i<ptr->pattern_count; i++) {
		ptr->patterns[i].length = gf_bs_read_int(bs, pattern_size);
		ptr->patterns[i].sample_count = gf_bs_read_int(bs, scount_size);
		bits += pattern_size + scount_size;
		if (! (bits % 8)) {
			bits/=8;
			ISOM_DECREASE_SIZE(ptr, bits);
			bits=0;
		}
		patterns_sizes+=ptr->patterns[i].length;
		if (patterns_sizes * index_size > ptr->size*8) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] compact sample gorup pattern cumulated sizes "LLU" larger than box size "LLU"\n", patterns_sizes, ptr->size));
			ptr->patterns[i].sample_group_description_indices = NULL;
			return GF_ISOM_INVALID_FILE;
		}

		if ( (u64)ptr->patterns[i].length > (u64)SIZE_MAX/sizeof(u32) ) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] compact sample gorup pattern #%d value (%lu) invalid\n", i, ptr->patterns[i].length));
			ptr->patterns[i].sample_group_description_indices = NULL;
			return GF_ISOM_INVALID_FILE;
		}
		ptr->patterns[i].sample_group_description_indices = gf_malloc(sizeof(u32) * ptr->patterns[i].length);
		if (!ptr->patterns[i].sample_group_description_indices) return GF_OUT_OF_MEM;
	}
	bits = 0;
	gidx_mask = ((u32)1) << (index_size-1);
	for (i=0; i<ptr->pattern_count; i++) {
		u32 j;
		for (j=0; j<ptr->patterns[i].length; j++) {
			u32 idx = gf_bs_read_int(bs, index_size);
			if (index_msb_indicates_fragment_local_description) {
				//MSB set, this is a index of a group described in the fragment
				if (idx & gidx_mask) {
					idx += 0x10000;
					idx &= ~gidx_mask;
				}
			}
			ptr->patterns[i].sample_group_description_indices[j] = idx;
			bits += index_size;

			if (! (bits % 8)) {
				bits/=8;
				ISOM_DECREASE_SIZE(ptr, bits);
				bits=0;
			}
		}
	}
	if (bits)
		gf_bs_align(bs);
	return GF_OK;
}

fixed #2255


GF_Err leva_box_size(GF_Box *s)
{
	u32 i;
	GF_LevelAssignmentBox *ptr = (GF_LevelAssignmentBox*)s;

	ptr->size += 1;
	for (i = 0; i < ptr->level_count; i++) {
		ptr->size += 5;
		if (ptr->levels[i].type == 0 || ptr->levels[i].type == 4) {
			ptr->size += 4;
		}
		else if (ptr->levels[i].type == 1) {
			ptr->size += 8;
		}
	}
	return GF_OK;
}

fixed #2255


GF_Err mhac_box_read(GF_Box *s,GF_BitStream *bs)
{
	GF_MHAConfigBox *ptr = (GF_MHAConfigBox *) s;

	ISOM_DECREASE_SIZE(s, 5)
	ptr->configuration_version = gf_bs_read_u8(bs);
	ptr->mha_pl_indication = gf_bs_read_u8(bs);
	ptr->reference_channel_layout = gf_bs_read_u8(bs);
	ptr->mha_config_size = gf_bs_read_u16(bs);
	if (ptr->mha_config_size) {
		ISOM_DECREASE_SIZE(s, ptr->mha_config_size)

		ptr->mha_config = gf_malloc(sizeof(char)*ptr->mha_config_size);
		if (!ptr->mha_config) return GF_OUT_OF_MEM;

		gf_bs_read_data(bs, ptr->mha_config, ptr->mha_config_size);
	}
	return GF_OK;
}

fixed #2255


GF_Box *trep_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_TrackExtensionPropertiesBox, GF_ISOM_BOX_TYPE_TREP);
	tmp->child_boxes = gf_list_new();
	return (GF_Box *)tmp;
}

fixed #2255


void xtra_box_del(GF_Box *s)
{
	GF_XtraBox *ptr = (GF_XtraBox *)s;
	while (gf_list_count(ptr->tags)) {
		GF_XtraTag *tag = gf_list_pop_back(ptr->tags);
		if (tag->name) gf_free(tag->name);
		if (tag->prop_value) gf_free(tag->prop_value);
		gf_free(tag);
	}
	gf_list_del(ptr->tags);
	gf_free(s);
}

fixed #2255


GF_Err dvcC_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 i;
	GF_DOVIConfigurationBox *ptr = (GF_DOVIConfigurationBox *)s;

	//GF_DOVIDecoderConfigurationRecord
	ISOM_DECREASE_SIZE(ptr, 24)
	ptr->DOVIConfig.dv_version_major = gf_bs_read_u8(bs);
	ptr->DOVIConfig.dv_version_minor = gf_bs_read_u8(bs);
	ptr->DOVIConfig.dv_profile = gf_bs_read_int(bs, 7);
	ptr->DOVIConfig.dv_level = gf_bs_read_int(bs, 6);
	ptr->DOVIConfig.rpu_present_flag = gf_bs_read_int(bs, 1);
	ptr->DOVIConfig.el_present_flag = gf_bs_read_int(bs, 1);
	ptr->DOVIConfig.bl_present_flag = gf_bs_read_int(bs, 1);
	ptr->DOVIConfig.dv_bl_signal_compatibility_id = gf_bs_read_int(bs, 4);
	if (gf_bs_read_int(bs, 28) != 0)
		GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] dvcC reserved bits are not zero\n"));

	for (i = 0; i < 4; i++) {
		if (gf_bs_read_u32(bs) != 0) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] dvcC reserved bits are not zero\n"));
		}
	}
	if (ptr->DOVIConfig.dv_profile==8) {
		if (!ptr->DOVIConfig.dv_bl_signal_compatibility_id || (ptr->DOVIConfig.dv_bl_signal_compatibility_id>2) ) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] dvcC profile 8 but compatibility ID %d is not 1 or 2, patching to 2\n", ptr->DOVIConfig.dv_bl_signal_compatibility_id));
			ptr->DOVIConfig.dv_bl_signal_compatibility_id = 2;
		}
	}
	return GF_OK;
}

fixed #2255


GF_Box *prft_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_ProducerReferenceTimeBox, GF_ISOM_BOX_TYPE_PRFT);
	return (GF_Box *)tmp;
}

fixed #2255


void tsro_box_del(GF_Box *s)
{
	GF_TimeOffHintEntryBox *tsro = (GF_TimeOffHintEntryBox *)s;
	gf_free(tsro);
}

fixed #2255


GF_Err extr_box_size(GF_Box *s)
{
	GF_ExtraDataBox *ptr = (GF_ExtraDataBox *) s;
	ptr->size += ptr->data_length;
	if (ptr->feci) {
		GF_Err e = gf_isom_box_size((GF_Box*)ptr->feci);
		if (e) return e;
		ptr->size += ptr->feci->size;
	}
	return GF_OK;
}

fixed #2255


GF_Box *dvcC_box_new()
{
	GF_DOVIConfigurationBox *tmp = (GF_DOVIConfigurationBox *)gf_malloc(sizeof(GF_DOVIConfigurationBox));
	if (tmp == NULL) return NULL;
	memset(tmp, 0, sizeof(GF_DOVIConfigurationBox));
	tmp->type = GF_ISOM_BOX_TYPE_DVCC;
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *clap_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_CleanApertureBox, GF_ISOM_BOX_TYPE_CLAP);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *xtra_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_XtraBox, GF_ISOM_BOX_TYPE_XTRA);
	tmp->tags = gf_list_new();
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err mhac_box_size(GF_Box *s)
{
	GF_MHAConfigBox *ptr = (GF_MHAConfigBox *) s;
	s->size += 5;
	if (ptr->mha_config_size && ptr->mha_config) s->size += ptr->mha_config_size;
	return GF_OK;
}

fixed #2255


GF_Err saiz_box_size(GF_Box *s)
{
	GF_SampleAuxiliaryInfoSizeBox *ptr = (GF_SampleAuxiliaryInfoSizeBox*)s;

	if (ptr->aux_info_type || ptr->aux_info_type_parameter) {
		ptr->flags |= 1;
	}
	if (ptr->flags & 1) ptr->size += 8;
	ptr->size += 5;
	if (ptr->default_sample_info_size==0)  ptr->size += ptr->sample_count;
	return GF_OK;
}

fixed #2255


GF_Err stvi_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_StereoVideoBox *ptr = (GF_StereoVideoBox *) s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	gf_bs_write_int(bs, 0, 30);
	gf_bs_write_int(bs, ptr->single_view_allowed, 2);
	gf_bs_write_u32(bs, ptr->stereo_scheme);
	gf_bs_write_u32(bs, ptr->sit_len);
	gf_bs_write_data(bs, ptr->stereo_indication_type, ptr->sit_len);

	return GF_OK;
}

fixed #2255


static GF_Err gf_isom_check_sample_desc(GF_TrackBox *trak)
{
	GF_BitStream *bs;
	GF_UnknownBox *a;
	u32 i;
	GF_Err e;
	GF_SampleTableBox *stbl;

	if (!trak->Media || !trak->Media->information) {
		GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Track with no media box !\n" ));
		return GF_OK;
	}
	if (!trak->Media->information->sampleTable) {
		GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Track with no sample table !\n" ));
		trak->Media->information->sampleTable = (GF_SampleTableBox *) gf_isom_box_new_parent(&trak->Media->information->child_boxes, GF_ISOM_BOX_TYPE_STBL);
	}
	stbl = trak->Media->information->sampleTable;

	if (!stbl->SampleDescription) {
		GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Track with no sample description box !\n" ));
		stbl->SampleDescription = (GF_SampleDescriptionBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STSD);
		return GF_OK;
	}

	i=0;
	while ((a = (GF_UnknownBox*)gf_list_enum(stbl->SampleDescription->child_boxes, &i))) {
		GF_ProtectionSchemeInfoBox *sinf;
		u32 base_ent_type = 0;
		u32 type = a->type;
		switch (a->type) {
		case GF_ISOM_BOX_TYPE_ENCS:
		case GF_ISOM_BOX_TYPE_ENCA:
		case GF_ISOM_BOX_TYPE_ENCV:
		case GF_ISOM_BOX_TYPE_RESV:
		case GF_ISOM_BOX_TYPE_ENCT:
			sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(a->child_boxes, GF_ISOM_BOX_TYPE_SINF);
			if (!sinf || !sinf->original_format) return GF_ISOM_INVALID_FILE;
			type = sinf->original_format->data_format;
			base_ent_type = ((GF_SampleEntryBox *)a)->internal_type;
			break;
		}

		switch (type) {
		case GF_ISOM_BOX_TYPE_MP4S:
			if (base_ent_type && (base_ent_type != GF_ISOM_SAMPLE_ENTRY_MP4S)) {
				GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Protected sample entry %s uses incompatible sample description %s\n", gf_4cc_to_str(a->type), gf_4cc_to_str(type) ));

				return GF_ISOM_INVALID_FILE;
			}
			continue;

		case GF_ISOM_SUBTYPE_3GP_AMR:
		case GF_ISOM_SUBTYPE_3GP_AMR_WB:
		case GF_ISOM_SUBTYPE_3GP_EVRC:
		case GF_ISOM_SUBTYPE_3GP_QCELP:
		case GF_ISOM_SUBTYPE_3GP_SMV:
		case GF_ISOM_BOX_TYPE_MP4A:
		case GF_ISOM_BOX_TYPE_MP3:
		case GF_ISOM_BOX_TYPE_MHA1:
		case GF_ISOM_BOX_TYPE_MHA2:
		case GF_ISOM_BOX_TYPE_MHM1:
		case GF_ISOM_BOX_TYPE_MHM2:
		case GF_ISOM_BOX_TYPE_OPUS:
		case GF_ISOM_BOX_TYPE_AC3:
		case GF_ISOM_BOX_TYPE_EC3:
		case GF_QT_SUBTYPE_RAW_AUD:
		case GF_QT_SUBTYPE_TWOS:
		case GF_QT_SUBTYPE_SOWT:
		case GF_QT_SUBTYPE_FL32:
		case GF_QT_SUBTYPE_FL64:
		case GF_QT_SUBTYPE_IN24:
		case GF_QT_SUBTYPE_IN32:
		case GF_QT_SUBTYPE_ULAW:
		case GF_QT_SUBTYPE_ALAW:
		case GF_QT_SUBTYPE_ADPCM:
		case GF_QT_SUBTYPE_IMA_ADPCM:
		case GF_QT_SUBTYPE_DVCA:
		case GF_QT_SUBTYPE_QDMC:
		case GF_QT_SUBTYPE_QDMC2:
		case GF_QT_SUBTYPE_QCELP:
		case GF_QT_SUBTYPE_kMP3:
		case GF_ISOM_BOX_TYPE_IPCM:
		case GF_ISOM_BOX_TYPE_FPCM:
			if (base_ent_type && (base_ent_type != GF_ISOM_SAMPLE_ENTRY_AUDIO))
				return GF_ISOM_INVALID_FILE;
			continue;

		case GF_ISOM_BOX_TYPE_MP4V:
		case GF_ISOM_SUBTYPE_3GP_H263:
		case GF_ISOM_BOX_TYPE_AVC1:
		case GF_ISOM_BOX_TYPE_AVC2:
		case GF_ISOM_BOX_TYPE_AVC3:
		case GF_ISOM_BOX_TYPE_AVC4:
		case GF_ISOM_BOX_TYPE_SVC1:
		case GF_ISOM_BOX_TYPE_MVC1:
		case GF_ISOM_BOX_TYPE_HVC1:
		case GF_ISOM_BOX_TYPE_HEV1:
		case GF_ISOM_BOX_TYPE_HVC2:
		case GF_ISOM_BOX_TYPE_HEV2:
		case GF_ISOM_BOX_TYPE_HVT1:
		case GF_ISOM_BOX_TYPE_LHV1:
		case GF_ISOM_BOX_TYPE_LHE1:
		case GF_ISOM_BOX_TYPE_AV01:
		case GF_ISOM_BOX_TYPE_VP08:
		case GF_ISOM_BOX_TYPE_VP09:
		case GF_ISOM_BOX_TYPE_AV1C:
		case GF_ISOM_BOX_TYPE_JPEG:
		case GF_ISOM_BOX_TYPE_PNG:
		case GF_ISOM_BOX_TYPE_JP2K:
		case GF_ISOM_BOX_TYPE_MJP2:
		case GF_QT_SUBTYPE_APCH:
		case GF_QT_SUBTYPE_APCO:
		case GF_QT_SUBTYPE_APCN:
		case GF_QT_SUBTYPE_APCS:
		case GF_QT_SUBTYPE_AP4X:
		case GF_QT_SUBTYPE_AP4H:
		case GF_ISOM_BOX_TYPE_VVC1:
		case GF_ISOM_BOX_TYPE_VVI1:
		case GF_QT_SUBTYPE_RAW_VID:
		case GF_QT_SUBTYPE_YUYV:
		case GF_QT_SUBTYPE_UYVY:
		case GF_QT_SUBTYPE_YUV444:
		case GF_QT_SUBTYPE_YUVA444:
		case GF_QT_SUBTYPE_YUV422_10:
		case GF_QT_SUBTYPE_YUV444_10:
		case GF_QT_SUBTYPE_YUV422_16:
		case GF_QT_SUBTYPE_YUV420:
		case GF_QT_SUBTYPE_I420:
		case GF_QT_SUBTYPE_IYUV:
		case GF_QT_SUBTYPE_YV12:
		case GF_QT_SUBTYPE_YVYU:
		case GF_QT_SUBTYPE_RGBA:
		case GF_QT_SUBTYPE_ABGR:
		case GF_ISOM_BOX_TYPE_DVHE:
		case GF_ISOM_BOX_TYPE_DVH1:
		case GF_ISOM_BOX_TYPE_DVA1:
		case GF_ISOM_BOX_TYPE_DVAV:
		case GF_ISOM_BOX_TYPE_DAV1:
			if (base_ent_type && (base_ent_type != GF_ISOM_SAMPLE_ENTRY_VIDEO))
				return GF_ISOM_INVALID_FILE;
			continue;

		case GF_ISOM_BOX_TYPE_METX:
		case GF_ISOM_BOX_TYPE_METT:
		case GF_ISOM_BOX_TYPE_STXT:
		case GF_ISOM_BOX_TYPE_TX3G:
		case GF_ISOM_BOX_TYPE_TEXT:
		case GF_ISOM_BOX_TYPE_GHNT:
		case GF_ISOM_BOX_TYPE_RTP_STSD:
		case GF_ISOM_BOX_TYPE_SRTP_STSD:
		case GF_ISOM_BOX_TYPE_FDP_STSD:
		case GF_ISOM_BOX_TYPE_RRTP_STSD:
		case GF_ISOM_BOX_TYPE_RTCP_STSD:
		case GF_ISOM_BOX_TYPE_DIMS:
		case GF_ISOM_BOX_TYPE_LSR1:
		case GF_ISOM_BOX_TYPE_WVTT:
		case GF_ISOM_BOX_TYPE_STPP:
		case GF_ISOM_BOX_TYPE_SBTT:
			if (base_ent_type && (base_ent_type != GF_ISOM_SAMPLE_ENTRY_GENERIC))
				return GF_ISOM_INVALID_FILE;
			continue;

		case GF_ISOM_BOX_TYPE_UNKNOWN:
			break;
		default:
			if (gf_box_valid_in_parent((GF_Box *) a, "stsd")) {
				continue;
			}
			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Unexpected box %s in stsd!\n", gf_4cc_to_str(a->type)));
			continue;
		}
		//we are sure to have an unknown box here
		assert(a->type==GF_ISOM_BOX_TYPE_UNKNOWN);

		if (!a->data || (a->dataSize<8) ) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Sample description %s does not have at least 8 bytes!\n", gf_4cc_to_str(a->original_4cc) ));
			continue;
		}
		else if (a->dataSize > a->size) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Sample description %s has wrong data size %d!\n", gf_4cc_to_str(a->original_4cc), a->dataSize));
			continue;
		}

		/*only process visual or audio
		note: no need for new_box_parent here since we always store sample descriptions in child_boxes*/
		switch (trak->Media->handler->handlerType) {
        case GF_ISOM_MEDIA_VISUAL:
		case GF_ISOM_MEDIA_AUXV:
		case GF_ISOM_MEDIA_PICT:
		{
			GF_GenericVisualSampleEntryBox *genv = (GF_GenericVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_GNRV);
			bs = gf_bs_new(a->data, a->dataSize, GF_BITSTREAM_READ);
			genv->size = a->size-8;
			gf_isom_video_sample_entry_read((GF_VisualSampleEntryBox *) genv, bs);

			stsd_switch_box(bs, (GF_Box *) genv, a, &genv->data, &genv->data_size, &genv->EntryType, trak->Media->information->sampleTable->SampleDescription, i-1);
		}
		break;
		case GF_ISOM_MEDIA_AUDIO:
		{
			GF_GenericAudioSampleEntryBox *gena = (GF_GenericAudioSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_GNRA);
			gena->size = a->size-8;
			bs = gf_bs_new(a->data, a->dataSize, GF_BITSTREAM_READ);
			gf_isom_audio_sample_entry_read((GF_AudioSampleEntryBox *) gena, bs);

			stsd_switch_box(bs, (GF_Box *) gena, a, &gena->data, &gena->data_size, &gena->EntryType, trak->Media->information->sampleTable->SampleDescription, i-1);
		}
		break;

		default:
		{
			GF_GenericSampleEntryBox *genm = (GF_GenericSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_GNRM);
			genm->size = a->size-8;
			bs = gf_bs_new(a->data, a->dataSize, GF_BITSTREAM_READ);

			e = gf_isom_base_sample_entry_read((GF_SampleEntryBox *)genm, bs);
			if (e) return e;

			stsd_switch_box(bs, (GF_Box *) genm, a, &genm->data, &genm->data_size, &genm->EntryType, trak->Media->information->sampleTable->SampleDescription, i-1);
		}
		break;
		}
	}
	return GF_OK;
}

fixed #2255


GF_Err txtc_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_TextConfigBox *ptr = (GF_TextConfigBox*)s;
	if ((u32)ptr->size >= (u32)0xFFFFFFFF) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid size %llu in txtc box\n", ptr->size));
		return GF_ISOM_INVALID_FILE;
	}
	ptr->config = (char *)gf_malloc(sizeof(char)*((u32) ptr->size+1));
	if (!ptr->config) return GF_OUT_OF_MEM;
	gf_bs_read_data(bs, ptr->config, (u32) ptr->size);
	ptr->config[ptr->size] = 0;
	return GF_OK;
}

fixed #2255


GF_Err fdpa_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 i;
	GF_FDpacketBox *ptr = (GF_FDpacketBox *)s;

	ISOM_DECREASE_SIZE(ptr, 3);
	ptr->info.sender_current_time_present = gf_bs_read_int(bs, 1);
	ptr->info.expected_residual_time_present = gf_bs_read_int(bs, 1);
	ptr->info.session_close_bit = gf_bs_read_int(bs, 1);
	ptr->info.object_close_bit = gf_bs_read_int(bs, 1);
	gf_bs_read_int(bs, 4);
	ptr->info.transport_object_identifier = gf_bs_read_u16(bs);
	ISOM_DECREASE_SIZE(ptr, 2);
	ptr->header_ext_count = gf_bs_read_u16(bs);
	if (ptr->size / 2 < ptr->header_ext_count) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of entries %d in fdpa\n", ptr->header_ext_count));
		return GF_ISOM_INVALID_FILE;
	}

	GF_SAFE_ALLOC_N(ptr->headers, ptr->header_ext_count, GF_LCTheaderExtension);
	if (!ptr->headers) return GF_OUT_OF_MEM;

	for (i=0; i<ptr->header_ext_count; i++) {
		ptr->headers[i].header_extension_type = gf_bs_read_u8(bs);
		ISOM_DECREASE_SIZE(ptr, 1);

		if (ptr->headers[i].header_extension_type > 127) {
			ISOM_DECREASE_SIZE(ptr, 3);
			gf_bs_read_data(bs, (char *) ptr->headers[i].content, 3);
		} else {
			ISOM_DECREASE_SIZE(ptr, 1);
			ptr->headers[i].data_length = gf_bs_read_u8(bs);
			if (ptr->headers[i].data_length) {
				ptr->headers[i].data_length = 4*ptr->headers[i].data_length - 2;
				if (ptr->size < sizeof(char) * ptr->headers[i].data_length)
				    return GF_ISOM_INVALID_FILE;
				ptr->headers[i].data = gf_malloc(sizeof(char) * ptr->headers[i].data_length);
				if (!ptr->headers[i].data) return GF_OUT_OF_MEM;

				ISOM_DECREASE_SIZE(ptr, ptr->headers[i].data_length);
				gf_bs_read_data(bs, ptr->headers[i].data, ptr->headers[i].data_length);
			}
		}
	}
	return GF_OK;
}

fixed #2255


GF_Err trik_box_size(GF_Box *s)
{
	GF_TrickPlayBox *ptr = (GF_TrickPlayBox *) s;
	ptr->size += 8 * ptr->entry_count;
	return GF_OK;
}

fixed #2255


GF_Err bloc_box_read(GF_Box *s,GF_BitStream *bs)
{
	GF_BaseLocationBox *ptr = (GF_BaseLocationBox *) s;

	ISOM_DECREASE_SIZE(s, 256)
	gf_bs_read_data(bs, (char *) ptr->baseLocation, 256);
	ptr->baseLocation[256]=0;
	ISOM_DECREASE_SIZE(s, 256)
	gf_bs_read_data(bs, (char *) ptr->basePurlLocation, 256);
	ISOM_DECREASE_SIZE(s, 512)
	ptr->basePurlLocation[256]=0;
	gf_bs_skip_bytes(bs, 512);
	return GF_OK;
}

fixed #2255


GF_Box *dmlp_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_TrueHDConfigBox, GF_ISOM_BOX_TYPE_DMLP);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err saio_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_SampleAuxiliaryInfoOffsetBox *ptr = (GF_SampleAuxiliaryInfoOffsetBox *)s;

	if (ptr->flags & 1) {
		ISOM_DECREASE_SIZE(ptr, 8);
		ptr->aux_info_type = gf_bs_read_u32(bs);
		ptr->aux_info_type_parameter = gf_bs_read_u32(bs);
	}
	ISOM_DECREASE_SIZE(ptr, 4);
	ptr->entry_count = gf_bs_read_u32(bs);

	if (ptr->entry_count) {
		u32 i;
		if (ptr->size / (ptr->version == 0 ? 4 : 8) < ptr->entry_count || (u64)ptr->entry_count > (u64)SIZE_MAX/sizeof(u64))
			return GF_ISOM_INVALID_FILE;
		ptr->offsets = gf_malloc(sizeof(u64)*ptr->entry_count);
		if (!ptr->offsets)
			return GF_OUT_OF_MEM;
		ptr->entry_alloc = ptr->entry_count;
		if (ptr->version==0) {
			ISOM_DECREASE_SIZE(ptr, 4*ptr->entry_count);
			for (i=0; i<ptr->entry_count; i++)
				ptr->offsets[i] = gf_bs_read_u32(bs);
		} else {
			ISOM_DECREASE_SIZE(ptr, 8*ptr->entry_count);
			for (i=0; i<ptr->entry_count; i++)
				ptr->offsets[i] = gf_bs_read_u64(bs);
		}
	}
	return GF_OK;
}

fixed #2255


GF_Box *dOps_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_OpusSpecificBox, GF_ISOM_BOX_TYPE_DOPS);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err dmlp_box_size(GF_Box *s)
{
	s->size += 10;
	return GF_OK;
}

fixed #2255


GF_Err fpar_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 i;
	GF_Err e;
	FilePartitionBox *ptr = (FilePartitionBox *)s;

	ISOM_DECREASE_SIZE(ptr, ((ptr->version ? 4 : 2) + 12) );
	ptr->itemID = gf_bs_read_int(bs, ptr->version ? 32 : 16);
	ptr->packet_payload_size = gf_bs_read_u16(bs);
	gf_bs_read_u8(bs);
	ptr->FEC_encoding_ID = gf_bs_read_u8(bs);
	ptr->FEC_instance_ID = gf_bs_read_u16(bs);
	ptr->max_source_block_length = gf_bs_read_u16(bs);
	ptr->encoding_symbol_length = gf_bs_read_u16(bs);
	ptr->max_number_of_encoding_symbols = gf_bs_read_u16(bs);

	e = gf_isom_read_null_terminated_string(s, bs, ptr->size, &ptr->scheme_specific_info);
	if (e) return e;

	ISOM_DECREASE_SIZE(ptr, (ptr->version ? 4 : 2) );
	ptr->nb_entries = gf_bs_read_int(bs, ptr->version ? 32 : 16);
	if (ptr->nb_entries > ptr->size / 6 || (u64)ptr->nb_entries > (u64)SIZE_MAX/sizeof(FilePartitionEntry))
		return GF_ISOM_INVALID_FILE;

	ISOM_DECREASE_SIZE(ptr, ptr->nb_entries * 6 );
	GF_SAFE_ALLOC_N(ptr->entries, ptr->nb_entries, FilePartitionEntry);
	if (!ptr->entries) return GF_OUT_OF_MEM;

	for (i=0;i < ptr->nb_entries; i++) {
		ptr->entries[i].block_count = gf_bs_read_u16(bs);
		ptr->entries[i].block_size = gf_bs_read_u32(bs);
	}
	return GF_OK;
}

fixed #2255


GF_Err reftype_box_size(GF_Box *s)
{
	GF_TrackReferenceTypeBox *ptr = (GF_TrackReferenceTypeBox *)s;
	if (ptr->trackIDCount)
		ptr->size += (ptr->trackIDCount * sizeof(u32));
	return GF_OK;
}

fixed #2255


GF_Err udta_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e = gf_isom_box_array_read(s, bs);
	if (e) return e;
	if (s->size==4) {
		u32 val = gf_bs_read_u32(bs);
		s->size = 0;
		if (val) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] udta has 4 remaining bytes set to %08X but they should be 0\n", val));
		}
	}
	return GF_OK;
}

fixed #2255


void proj_type_box_del(GF_Box *s)
{
	gf_free(s);
}

fixed #2255


GF_Err dvvC_box_write(GF_Box *s, GF_BitStream *bs)
{
	return dvcC_box_write(s, bs);
}

fixed #2255


GF_Err pasp_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_PixelAspectRatioBox *ptr = (GF_PixelAspectRatioBox *)s;
	GF_Err e = gf_isom_box_write_header(s, bs);
	if (e) return e;
	gf_bs_write_u32(bs, ptr->hSpacing);
	gf_bs_write_u32(bs, ptr->vSpacing);
	return GF_OK;
}

fixed #2255


void mvcg_box_del(GF_Box *s)
{
	GF_MultiviewGroupBox *ptr = (GF_MultiviewGroupBox *) s;
	if (ptr->entries) gf_free(ptr->entries);
	gf_free(ptr);
}

fixed #2255


static void *sgpd_parse_entry(u32 grouping_type, GF_BitStream *bs, s32 bytes_in_box, u32 entry_size, u32 *total_bytes)
{
	Bool null_size_ok = GF_FALSE;
	GF_DefaultSampleGroupDescriptionEntry *def_ptr;

	switch (grouping_type) {
	case GF_ISOM_SAMPLE_GROUP_ROLL:
	case GF_ISOM_SAMPLE_GROUP_PROL:
	{
		GF_RollRecoveryEntry *ptr;
		GF_SAFEALLOC(ptr, GF_RollRecoveryEntry);
		if (!ptr) return NULL;
		ptr->roll_distance = gf_bs_read_int(bs, 16);
		*total_bytes = 2;
		return ptr;
	}
	case GF_ISOM_SAMPLE_GROUP_RAP:
	{
		GF_VisualRandomAccessEntry *ptr;
		GF_SAFEALLOC(ptr, GF_VisualRandomAccessEntry);
		if (!ptr) return NULL;
		ptr->num_leading_samples_known = gf_bs_read_int(bs, 1);
		ptr->num_leading_samples = gf_bs_read_int(bs, 7);
		*total_bytes = 1;
		return ptr;
	}
	case GF_ISOM_SAMPLE_GROUP_SAP:
	{
		GF_SAPEntry *ptr;
		GF_SAFEALLOC(ptr, GF_SAPEntry);
		if (!ptr) return NULL;
		ptr->dependent_flag = gf_bs_read_int(bs, 1);
		gf_bs_read_int(bs, 3);
		ptr->SAP_type = gf_bs_read_int(bs, 4);
		*total_bytes = 1;
		return ptr;
	}
	case GF_ISOM_SAMPLE_GROUP_SYNC:
	{
		GF_SYNCEntry *ptr;
		GF_SAFEALLOC(ptr, GF_SYNCEntry);
		if (!ptr) return NULL;
		gf_bs_read_int(bs, 2);
		ptr->NALU_type = gf_bs_read_int(bs, 6);
		*total_bytes = 1;
		return ptr;
	}
	case GF_ISOM_SAMPLE_GROUP_TELE:
	{
		GF_TemporalLevelEntry *ptr;
		GF_SAFEALLOC(ptr, GF_TemporalLevelEntry);
		if (!ptr) return NULL;
		ptr->level_independently_decodable = gf_bs_read_int(bs, 1);
		gf_bs_read_int(bs, 7);
		*total_bytes = 1;
		return ptr;
	}
	case GF_ISOM_SAMPLE_GROUP_SEIG:
	{
		GF_CENCSampleEncryptionGroupEntry *ptr;
		if (bytes_in_box<3) return NULL;
		GF_SAFEALLOC(ptr, GF_CENCSampleEncryptionGroupEntry);
		if (!ptr) return NULL;
		Bool use_mkey = gf_bs_read_int(bs, 1);
		gf_bs_read_int(bs, 7); //reserved
		ptr->crypt_byte_block = gf_bs_read_int(bs, 4);
		ptr->skip_byte_block = gf_bs_read_int(bs, 4);
		ptr->IsProtected = gf_bs_read_u8(bs);
		bytes_in_box -= 3;
		if (use_mkey) {
			u64 pos = gf_bs_get_position(bs);
			u32 i, count = gf_bs_read_u16(bs);
			bytes_in_box -= 2;
			if (bytes_in_box<0) {
				gf_free(ptr);
				return NULL;
			}
			for (i=0; i<count; i++) {
				u8 ivsize = gf_bs_read_u8(bs);
				gf_bs_skip_bytes(bs, 16);
				bytes_in_box -= 17;
				if (!ivsize) {
					//const IV
					ivsize = gf_bs_read_u8(bs);
					gf_bs_skip_bytes(bs, ivsize);
					bytes_in_box -= 1 + ivsize;
				}
				if (bytes_in_box<0) {
					gf_free(ptr);
					return NULL;
				}
			}
			ptr->key_info_size = 1 + (u32) (gf_bs_get_position(bs) - pos);
			ptr->key_info = gf_malloc(sizeof(u8) * ptr->key_info_size);
			if (!ptr->key_info) {
				gf_free(ptr);
				return NULL;
			}
			gf_bs_seek(bs, pos);
			ptr->key_info[0] = 1;
			gf_bs_read_data(bs, ptr->key_info + 1, ptr->key_info_size - 1);
			*total_bytes = 3 + ptr->key_info_size - 1;

			if (!gf_cenc_validate_key_info(ptr->key_info, ptr->key_info_size)) {
				gf_free(ptr->key_info);
				gf_free(ptr);
				return NULL;
			}
		} else {
			bin128 kid;
			u8 const_iv_size = 0;
			u8 iv_size = gf_bs_read_u8(bs);
			gf_bs_read_data(bs, kid, 16);
			bytes_in_box -= 17;
			if (bytes_in_box<0) {
				gf_free(ptr);
				return NULL;
			}

			*total_bytes = 20;
			if ((ptr->IsProtected == 1) && !iv_size) {
				const_iv_size = gf_bs_read_u8(bs);
				if ((const_iv_size != 8) && (const_iv_size != 16)) {
					GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] seig sample group have invalid constant_IV size\n"));
					gf_free(ptr);
					return NULL;
				}
			}
			ptr->key_info_size = 20;
			if (!iv_size && ptr->IsProtected) {
				ptr->key_info_size += 1 + const_iv_size;
			}
			ptr->key_info = gf_malloc(sizeof(u8) * ptr->key_info_size);
			if (!ptr->key_info) {
				gf_free(ptr);
				return NULL;
			}
			ptr->key_info[0] = 0;
			ptr->key_info[1] = 0;
			ptr->key_info[2] = 0;
			ptr->key_info[3] = iv_size;
			memcpy(ptr->key_info+4, kid, 16);
			if (!iv_size && ptr->IsProtected) {
				ptr->key_info[20] = const_iv_size;
				gf_bs_read_data(bs, (char *)ptr->key_info+21, const_iv_size);
				*total_bytes += 1 + const_iv_size;
			}
		}

		if (!entry_size) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] seig sample group does not indicate entry size, deprecated in spec\n"));
		}
		return ptr;
	}
	case GF_ISOM_SAMPLE_GROUP_OINF:
	{
		GF_OperatingPointsInformation *ptr = gf_isom_oinf_new_entry();
		u32 s = (u32) gf_bs_get_position(bs);
		gf_isom_oinf_read_entry(ptr, bs);
		*total_bytes = (u32) gf_bs_get_position(bs) - s;
		if (!entry_size) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] oinf sample group does not indicate entry size, deprecated in spec\n"));
		}
		return ptr;
	}
	case GF_ISOM_SAMPLE_GROUP_LINF:
	{
		GF_LHVCLayerInformation *ptr = gf_isom_linf_new_entry();
		u32 s = (u32) gf_bs_get_position(bs);
		gf_isom_linf_read_entry(ptr, bs);
		*total_bytes = (u32) gf_bs_get_position(bs) - s;
		if (!entry_size) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] linf sample group does not indicate entry size, deprecated in spec\n"));
		}
		return ptr;
	}

	case GF_ISOM_SAMPLE_GROUP_TRIF:
		if (! entry_size) {
			u32 flags = gf_bs_peek_bits(bs, 24, 0);
			if (flags & 0x10000) entry_size=3;
			else {
				if (flags & 0x80000) entry_size=7;
				else entry_size=11;
				//have dependency list
				if (flags & 0x200000) {
					u32 nb_entries = gf_bs_peek_bits(bs, 16, entry_size);
					entry_size += 2 + 2*nb_entries;
				}
			}
			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] trif sample group does not indicate entry size, deprecated in spec\n"));
		}
		break;
	case GF_ISOM_SAMPLE_GROUP_NALM:
		if (! entry_size) {
			u64 start = gf_bs_get_position(bs);
			Bool rle, large_size;
			u32 entry_count;
			gf_bs_read_int(bs, 6);
			large_size = gf_bs_read_int(bs, 1);
			rle = gf_bs_read_int(bs, 1);
			entry_count = gf_bs_read_int(bs, large_size ? 16 : 8);
			gf_bs_seek(bs, start);
			entry_size = 1 + (large_size ? 2 : 1);
			entry_size += entry_count * 2;
			if (rle) entry_size += entry_count * (large_size ? 2 : 1);
			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] nalm sample group does not indicate entry size, deprecated in spec\n"));
		}
		break;

	case GF_ISOM_SAMPLE_GROUP_TSAS:
	case GF_ISOM_SAMPLE_GROUP_STSA:
		null_size_ok = GF_TRUE;
		break;
	//TODO, add support for these ones ?
	case GF_ISOM_SAMPLE_GROUP_TSCL:
		entry_size = 20;
		break;
	case GF_ISOM_SAMPLE_GROUP_LBLI:
		entry_size = 2;
		break;
	case GF_ISOM_SAMPLE_GROUP_SPOR:
	{
		u32 i;
		GF_SubpictureOrderEntry *ptr;
		GF_SAFEALLOC(ptr, GF_SubpictureOrderEntry);
		if (!ptr) return NULL;
		ptr->subpic_id_info_flag = gf_bs_read_int(bs, 1);
		ptr->num_subpic_ref_idx = gf_bs_read_int(bs, 15);
		*total_bytes = 2;
		ptr->subp_track_ref_idx = gf_malloc(sizeof(u16) * ptr->num_subpic_ref_idx);
		if (!ptr->subp_track_ref_idx) {
			gf_free(ptr);
			return NULL;
		}
		for (i=0; i<ptr->num_subpic_ref_idx; i++) {
			ptr->subp_track_ref_idx[i] = gf_bs_read_u16(bs);
			*total_bytes += 2;
		}
		if (ptr->subpic_id_info_flag) {
			ptr->spinfo.subpic_id_len_minus1 = gf_bs_read_int(bs, 4);
			ptr->spinfo.subpic_id_bit_pos = gf_bs_read_int(bs, 12);
			ptr->spinfo.start_code_emul_flag = gf_bs_read_int(bs, 1);
			ptr->spinfo.pps_sps_subpic_id_flag = gf_bs_read_int(bs, 1);
			if (ptr->spinfo.pps_sps_subpic_id_flag) {
				ptr->spinfo.xps_id = gf_bs_read_int(bs, 6);
			} else {
				ptr->spinfo.xps_id = gf_bs_read_int(bs, 4);
				gf_bs_read_int(bs, 2);
			}
			*total_bytes += 3;
		}
		return ptr;
	}
	case GF_ISOM_SAMPLE_GROUP_SULM:
	{
		u32 i;
		GF_SubpictureLayoutMapEntry *ptr;
		GF_SAFEALLOC(ptr, GF_SubpictureLayoutMapEntry);
		if (!ptr) return NULL;
		ptr->groupID_info_4cc = gf_bs_read_u32(bs);
		ptr->nb_entries = 1 + gf_bs_read_u16(bs);
		*total_bytes = 6;
		ptr->groupIDs = gf_malloc(sizeof(u16) * ptr->nb_entries);
		if (!ptr->groupIDs) {
			gf_free(ptr);
			return NULL;
		}
		for (i=0; i<ptr->nb_entries; i++) {
			ptr->groupIDs[i] = gf_bs_read_u16(bs);
			*total_bytes += 2;
		}
		return ptr;
	}
	default:
		break;
	}

	if (!entry_size && !null_size_ok) {
		GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] %s sample group does not indicate entry size and is not implemented, cannot parse!\n", gf_4cc_to_str( grouping_type) ));
		return NULL;
	}
	GF_SAFEALLOC(def_ptr, GF_DefaultSampleGroupDescriptionEntry);
	if (!def_ptr) return NULL;
	if (entry_size) {
		def_ptr->length = entry_size;
		def_ptr->data = (u8 *) gf_malloc(sizeof(u8)*def_ptr->length);
		if (!def_ptr->data) {
			gf_free(def_ptr);
			return NULL;
		}
		gf_bs_read_data(bs, (char *) def_ptr->data, def_ptr->length);
		*total_bytes = entry_size;
	}
	return def_ptr;
}

fixed #2255


void trun_box_del(GF_Box *s)
{
	GF_TrackFragmentRunBox *ptr = (GF_TrackFragmentRunBox *)s;
	if (ptr == NULL) return;

	if (ptr->samples) gf_free(ptr->samples);
	if (ptr->cache) gf_bs_del(ptr->cache);
	if (ptr->sample_order) gf_free(ptr->sample_order);
	gf_free(ptr);
}

fixed #2255


GF_Box *lsr1_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_LASeRSampleEntryBox, GF_ISOM_BOX_TYPE_LSR1);
	gf_isom_sample_entry_init((GF_SampleEntryBox*)tmp);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *ainf_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_AssetInformationBox, GF_ISOM_BOX_TYPE_AINF);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err proj_type_box_size(GF_Box *s)
{
	GF_ProjectionTypeBox *ptr = (GF_ProjectionTypeBox *)s;
	if (ptr->type==GF_ISOM_BOX_TYPE_CBMP)
		s->size += 8;
	else if (ptr->type==GF_ISOM_BOX_TYPE_EQUI)
		s->size += 16;
	else
		s->size += 8;

	return GF_OK;
}

fixed #2255


GF_Box *dfla_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_FLACConfigBox, GF_ISOM_BOX_TYPE_DFLA);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err trak_box_write(GF_Box *s, GF_BitStream *bs)
{
	return gf_isom_box_write_header(s, bs);
}

fixed #2255


void leva_box_del(GF_Box *s)
{
	GF_LevelAssignmentBox *ptr = (GF_LevelAssignmentBox *)s;
	if (ptr == NULL) return;
	if (ptr->levels) gf_free(ptr->levels);
	gf_free(ptr);
}

fixed #2255


GF_Box *reftype_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_TrackReferenceTypeBox, GF_ISOM_BOX_TYPE_REFT);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err paen_box_read(GF_Box *s, GF_BitStream *bs)
{
	return gf_isom_box_array_read(s, bs);
}

fixed #2255


static u32 ctrn_field_size(u32 field_idx)
{
	if (field_idx==3) return 4;
	return field_idx;
}

fixed #2255


GF_Box *sidx_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_SegmentIndexBox, GF_ISOM_BOX_TYPE_SIDX);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *udta_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_UserDataBox, GF_ISOM_BOX_TYPE_UDTA);
	tmp->recordList = gf_list_new();
	if (!tmp->recordList) {
		gf_free(tmp);
		return NULL;
	}
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err saio_box_size(GF_Box *s)
{
	GF_SampleAuxiliaryInfoOffsetBox *ptr = (GF_SampleAuxiliaryInfoOffsetBox*)s;

	if (ptr->aux_info_type || ptr->aux_info_type_parameter) {
		ptr->flags |= 1;
	}

	if (ptr->flags & 1) ptr->size += 8;
	ptr->size += 4;
	//a little optim here: in cenc, the saio always points to a single data block, only one entry is needed
	switch (ptr->aux_info_type) {
	case GF_ISOM_CENC_SCHEME:
	case GF_ISOM_CBC_SCHEME:
	case GF_ISOM_CENS_SCHEME:
	case GF_ISOM_CBCS_SCHEME:
		if (ptr->offsets) gf_free(ptr->offsets);
		ptr->offsets = NULL;
		ptr->entry_alloc = 0;
		ptr->entry_count = 1;
		break;
	}

	ptr->size += ((ptr->version==1) ? 8 : 4) * ptr->entry_count;
	return GF_OK;
}

fixed #2255


GF_Err chnl_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_ChannelLayoutBox *ptr = (GF_ChannelLayoutBox *) s;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	gf_bs_write_u8(bs, ptr->layout.stream_structure);
	if (ptr->layout.stream_structure & 1) {
		gf_bs_write_u8(bs, ptr->layout.definedLayout);
		if (ptr->layout.definedLayout==0) {
			u32 i;
			for (i=0; i<ptr->layout.channels_count; i++) {
				gf_bs_write_u8(bs, ptr->layout.layouts[i].position);
				if (ptr->layout.layouts[i].position==126) {
					gf_bs_write_int(bs, ptr->layout.layouts[i].azimuth, 16);
					gf_bs_write_int(bs, ptr->layout.layouts[i].elevation, 8);
				}
			}
		} else {
			gf_bs_write_u64(bs, ptr->layout.omittedChannelsMap);
		}
	}
	if (ptr->layout.stream_structure & 2) {
		gf_bs_write_u8(bs, ptr->layout.object_count);
	}
	return GF_OK;
}

fixed #2255


GF_Err prft_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_ProducerReferenceTimeBox *ptr = (GF_ProducerReferenceTimeBox *) s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	gf_bs_write_u32(bs, ptr->refTrackID);
	gf_bs_write_u64(bs, ptr->ntp);
	if (ptr->version==0) {
		gf_bs_write_u32(bs, (u32) ptr->timestamp);
	} else {
		gf_bs_write_u64(bs, ptr->timestamp);
	}

	return GF_OK;
}

fixed #2255


GF_Err subs_box_size(GF_Box *s)
{
	GF_SubSampleInformationBox *ptr = (GF_SubSampleInformationBox *) s;
	u32 entry_count, i;
	u16 subsample_count;

	// add 4 byte for entry_count
	ptr->size += 4;
	entry_count = gf_list_count(ptr->Samples);
	for (i=0; i<entry_count; i++) {
		GF_SubSampleInfoEntry *pSamp = (GF_SubSampleInfoEntry*) gf_list_get(ptr->Samples, i);
		subsample_count = gf_list_count(pSamp->SubSamples);
		// 4 byte for sample_delta, 2 byte for subsample_count
		// and 6 + (4 or 2) bytes for each subsample
		ptr->size += 4 + 2 + subsample_count * (6 + (ptr->version==1 ? 4 : 2));
	}
	return GF_OK;
}

fixed #2255


GF_Box *stvi_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_StereoVideoBox, GF_ISOM_BOX_TYPE_STVI);
	return (GF_Box *)tmp;
}

fixed #2255


void fdsa_box_del(GF_Box *s)
{
	GF_HintSample *ptr = (GF_HintSample *)s;
	gf_list_del(ptr->packetTable);
	gf_free(ptr);
}

fixed #2255


static GF_Err ctrn_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 i, count, flags, first_idx=0;
	Bool inherit_dur, inherit_size, inherit_flags, inherit_ctso;
	GF_TrunEntry *ent;
	GF_TrackFragmentRunBox *ptr = (GF_TrackFragmentRunBox *)s;
	flags = ptr->flags;
	ptr->ctrn_flags = flags;
	ptr->flags = 0;

	ptr->sample_count = gf_bs_read_u16(bs);
	ISOM_DECREASE_SIZE(ptr, 2);

	if (flags & GF_ISOM_TRUN_DATA_OFFSET) {
		if (flags & GF_ISOM_CTRN_DATAOFFSET_16) {
			ptr->data_offset = gf_bs_read_u16(bs);
			ISOM_DECREASE_SIZE(ptr, 2);
		} else {
			ptr->data_offset = gf_bs_read_u32(bs);
			ISOM_DECREASE_SIZE(ptr, 4);
		}
		ptr->flags |= GF_ISOM_TRUN_DATA_OFFSET;
	}
	if (flags & GF_ISOM_CTRN_CTSO_MULTIPLIER) {
		ptr->ctso_multiplier = gf_bs_read_u16(bs);
		ISOM_DECREASE_SIZE(ptr, 2);
	}
	/*no sample dur/sample_flag/size/ctso for first or following, create a pack sample */
	if (! (flags & 0x00FFFF00)) {
		GF_SAFEALLOC(ent, GF_TrunEntry);
		if (!ent) return GF_OUT_OF_MEM;
		ent->nb_pack = ptr->sample_count;
		gf_list_add(ptr->entries, ent);
		return GF_OK;
	}
	/*allocate all entries*/
	for (i=0; i<ptr->sample_count; i++) {
		GF_SAFEALLOC(ent, GF_TrunEntry);
		if (!ent) return GF_OUT_OF_MEM;
		gf_list_add(ptr->entries, ent);
	}
	//unpack flags
	ptr->ctrn_first_dur = (flags>>22) & 0x3;
	ptr->ctrn_first_size = (flags>>20) & 0x3;
	ptr->ctrn_first_sample_flags = (flags>>18) & 0x3;
	ptr->ctrn_first_ctts = (flags>>16) & 0x3;
	ptr->ctrn_dur = (flags>>14) & 0x3;
	ptr->ctrn_size = (flags>>12) & 0x3;
	ptr->ctrn_sample_flags = (flags>>10) & 0x3;
	ptr->ctrn_ctts = (flags>>8) & 0x3;

	inherit_dur = flags & GF_ISOM_CTRN_INHERIT_DUR;
	inherit_size = flags & GF_ISOM_CTRN_INHERIT_SIZE;
	inherit_flags = flags & GF_ISOM_CTRN_INHERIT_FLAGS;
	inherit_ctso = flags & GF_ISOM_CTRN_INHERIT_CTSO;

	if (flags & GF_ISOM_CTRN_FIRST_SAMPLE) {
		ent = gf_list_get(ptr->entries, 0);
		first_idx = 1;
		if (!inherit_dur && ptr->ctrn_first_dur) {
			ent->Duration = gf_bs_read_int(bs, gf_isom_ctrn_field_size_bits(ptr->ctrn_first_dur) );
			ISOM_DECREASE_SIZE(ptr, ctrn_field_size(ptr->ctrn_first_dur) );
		}
		if (!inherit_size && ptr->ctrn_first_size) {
			ent->size = gf_bs_read_int(bs, gf_isom_ctrn_field_size_bits(ptr->ctrn_first_size) );
			ISOM_DECREASE_SIZE(ptr, ctrn_field_size(ptr->ctrn_first_size) );
		}
		if (!inherit_flags && ptr->ctrn_first_sample_flags) {
			ent->flags = ctrn_read_flags(bs, gf_isom_ctrn_field_size_bits(ptr->ctrn_first_sample_flags) );
			ISOM_DECREASE_SIZE(ptr, ctrn_field_size(ptr->ctrn_first_sample_flags) );
		}
		if (!inherit_ctso && ptr->ctrn_first_ctts) {
			ent->CTS_Offset = gf_bs_read_int(bs, gf_isom_ctrn_field_size_bits(ptr->ctrn_first_ctts) );
			ISOM_DECREASE_SIZE(ptr, ctrn_field_size(ptr->ctrn_first_ctts) );
			if (ptr->ctso_multiplier)
				ent->CTS_Offset *= (s32) ptr->ctso_multiplier;
		}
	}
	count = ptr->sample_count - first_idx;
	if (!inherit_dur && ptr->ctrn_dur) {
		u32 nbbits = gf_isom_ctrn_field_size_bits(ptr->ctrn_dur);
		ISOM_DECREASE_SIZE(ptr, count * nbbits / 8);
		for (i=first_idx; i<ptr->sample_count; i++) {
			ent = gf_list_get(ptr->entries, i);
			ent->Duration = gf_bs_read_int(bs, nbbits);
		}
	}
	if (!inherit_size && ptr->ctrn_size) {
		u32 nbbits = gf_isom_ctrn_field_size_bits(ptr->ctrn_size);
		ISOM_DECREASE_SIZE(ptr, count * nbbits / 8);
		for (i=first_idx; i<ptr->sample_count; i++) {
			ent = gf_list_get(ptr->entries, i);
			ent->size = gf_bs_read_int(bs, nbbits);
		}
	}
	if (!inherit_flags && ptr->ctrn_sample_flags) {
		u32 nbbits = gf_isom_ctrn_field_size_bits(ptr->ctrn_sample_flags);
		ISOM_DECREASE_SIZE(ptr, count * nbbits / 8);
		for (i=first_idx; i<ptr->sample_count; i++) {
			ent = gf_list_get(ptr->entries, i);
			ent->flags = ctrn_read_flags(bs, nbbits);
		}
	}
	if (!inherit_ctso && ptr->ctrn_ctts) {
		u32 nbbits = gf_isom_ctrn_field_size_bits(ptr->ctrn_ctts);
		ISOM_DECREASE_SIZE(ptr, count * nbbits / 8);
		for (i=first_idx; i<ptr->sample_count; i++) {
			ent = gf_list_get(ptr->entries, i);
			ent->CTS_Offset = gf_bs_read_int(bs, nbbits);
			if (ptr->ctso_multiplier)
				ent->CTS_Offset *= (s32) ptr->ctso_multiplier;
		}
	}

	return GF_OK;
}

fixed #2255


void dvvC_box_del(GF_Box *s)
{
	GF_DOVIConfigurationBox *ptr = (GF_DOVIConfigurationBox*)s;
	gf_free(ptr);
}

fixed #2255


GF_Err prhd_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_ProjectionHeaderBox *ptr = (GF_ProjectionHeaderBox *)s;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;
	gf_bs_write_u32(bs, ptr->yaw);
	gf_bs_write_u32(bs, ptr->pitch);
	gf_bs_write_u32(bs, ptr->roll);
	return GF_OK;
}

fixed #2255


GF_Err sgpd_box_size(GF_Box *s)
{
	u32 i, nb_descs;
	Bool use_def_size = GF_TRUE;
	GF_SampleGroupDescriptionBox *p = (GF_SampleGroupDescriptionBox *)s;

	p->size += 8;

	//we force all sample groups to version 1, v0 being deprecated
	if (!p->version)
		p->version = 1;
	p->size += 4;

	if (p->version>=2)
		p->size += 4;
	p->default_length = 0;

	nb_descs = gf_list_count(p->group_descriptions);
	for (i=0; i<nb_descs; i++) {
		void *ptr = gf_list_get(p->group_descriptions, i);
		u32 size = sgpd_size_entry(p->grouping_type, ptr);
		p->size += size;
		if (use_def_size && !p->default_length) {
			p->default_length = size;
		} else if (p->default_length != size) {
			use_def_size = GF_FALSE;
			p->default_length = 0;
		}
	}
	if (p->version>=1) {
		if (!p->default_length) p->size += nb_descs * 4;
	}
	return GF_OK;
}

fixed #2255


GF_Err sbgp_box_write(GF_Box *s, GF_BitStream *bs)
{
	u32 i;
	GF_Err e;
	GF_SampleGroupBox *p = (GF_SampleGroupBox*)s;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;
	gf_bs_write_u32(bs, p->grouping_type);
	if (p->version==1)
		gf_bs_write_u32(bs, p->grouping_type_parameter);

	gf_bs_write_u32(bs, p->entry_count);
	for (i = 0; i<p->entry_count; i++ ) {
		gf_bs_write_u32(bs, p->sample_entries[i].sample_count);
		gf_bs_write_u32(bs, p->sample_entries[i].group_description_index);
	}
	return GF_OK;
}

fixed #2255


GF_Err tfdt_box_size(GF_Box *s)
{
	GF_TFBaseMediaDecodeTimeBox *ptr = (GF_TFBaseMediaDecodeTimeBox *)s;

	if (!ptr->version && (ptr->baseMediaDecodeTime<=0xFFFFFFFF)) {
		//ptr->version = 0;
		ptr->size += 4;
	} else {
		ptr->version = 1;
		ptr->size += 8;
	}
	return GF_OK;
}

fixed #2255


GF_Err fiin_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem)
{
	FDItemInformationBox *ptr = (FDItemInformationBox *)s;
	switch(a->type) {
	case GF_ISOM_BOX_TYPE_PAEN:
		BOX_FIELD_LIST_ASSIGN(partition_entries)
		return GF_OK;
	case GF_ISOM_BOX_TYPE_SEGR:
		BOX_FIELD_ASSIGN(session_info, FDSessionGroupBox)
		return GF_OK;
	case GF_ISOM_BOX_TYPE_GITN:
		BOX_FIELD_ASSIGN(group_id_to_name, GroupIdToNameBox)
		return GF_OK;
	}
	return GF_OK;
}

fixed #2255


GF_Err reftype_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 bytesToRead;
	u32 i;
	GF_TrackReferenceTypeBox *ptr = (GF_TrackReferenceTypeBox *)s;

	bytesToRead = (u32) (ptr->size);
	if (!bytesToRead) return GF_OK;

	ptr->trackIDCount = (u32) (bytesToRead) / sizeof(u32);
	ptr->trackIDs = (GF_ISOTrackID *) gf_malloc(ptr->trackIDCount * sizeof(GF_ISOTrackID));
	if (!ptr->trackIDs) return GF_OUT_OF_MEM;

	for (i = 0; i < ptr->trackIDCount; i++) {
		ptr->trackIDs[i] = gf_bs_read_u32(bs);
	}
	return GF_OK;
}

fixed #2255


GF_Err stvi_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_StereoVideoBox *ptr = (GF_StereoVideoBox *)s;

	ISOM_DECREASE_SIZE(ptr, 12);
	gf_bs_read_int(bs, 30);
	ptr->single_view_allowed = gf_bs_read_int(bs, 2);
	ptr->stereo_scheme = gf_bs_read_u32(bs);
	ptr->sit_len = gf_bs_read_u32(bs);
	ISOM_DECREASE_SIZE(ptr, ptr->sit_len);

	ptr->stereo_indication_type = gf_malloc(sizeof(char)*ptr->sit_len);
	if (!ptr->stereo_indication_type) return GF_OUT_OF_MEM;

	gf_bs_read_data(bs, ptr->stereo_indication_type, ptr->sit_len);
	return GF_OK;
}

fixed #2255


void mhac_box_del(GF_Box *s)
{
	GF_MHAConfigBox *ptr = (GF_MHAConfigBox *) s;
	if (ptr->mha_config) gf_free(ptr->mha_config);
	gf_free(s);
}

fixed #2255


static u32 ctrn_u32_to_index(u32 val)
{
	if (!val) return 0;
	if (val<=255) return 1;
	if (val<=65535) return 2;
	return 3;
}

fixed #2255


GF_Err udta_box_size(GF_Box *s)
{
	GF_Err e;
	u32 i;
	GF_UserDataMap *map;
	GF_UserDataBox *ptr = (GF_UserDataBox *)s;

	i=0;
	while ((map = (GF_UserDataMap *)gf_list_enum(ptr->recordList, &i))) {
		//warning: here we are not passing the actual "parent" of the list
		//but the UDTA box. The parent itself is not an box, we don't care about it
		e = gf_isom_box_array_size(s, map->boxes);
		if (e) return e;
	}
	return GF_OK;
}

fixed #2255


GF_Err trex_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_TrackExtendsBox *ptr = (GF_TrackExtendsBox *) s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	gf_bs_write_u32(bs, ptr->trackID);
	//we always write 1 in trex default sample desc as using 0 breaks chrome/opera/...
	gf_bs_write_u32(bs, ptr->def_sample_desc_index ? ptr->def_sample_desc_index : 1);
	gf_bs_write_u32(bs, ptr->def_sample_duration);
	gf_bs_write_u32(bs, ptr->def_sample_size);
	gf_bs_write_u32(bs, ptr->def_sample_flags);
	return GF_OK;
}

fixed #2255


GF_Err trex_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_TrackExtendsBox *ptr = (GF_TrackExtendsBox *)s;

	ISOM_DECREASE_SIZE(ptr, 20);
	ptr->trackID = gf_bs_read_u32(bs);
	ptr->def_sample_desc_index = gf_bs_read_u32(bs);
	ptr->def_sample_duration = gf_bs_read_u32(bs);
	ptr->def_sample_size = gf_bs_read_u32(bs);
	ptr->def_sample_flags = gf_bs_read_u32(bs);
	return GF_OK;
}

fixed #2255


GF_Err sidx_box_size(GF_Box *s)
{
	GF_SegmentIndexBox *ptr = (GF_SegmentIndexBox*) s;

	ptr->size += 12;
	if (ptr->version==0) {
		ptr->size += 8;
	} else {
		ptr->size += 16;
	}
	ptr->size += ptr->nb_refs * 12;
	return GF_OK;
}

fixed #2255


void tref_box_del(GF_Box *s)
{
	GF_TrackReferenceBox *ptr = (GF_TrackReferenceBox *)s;
	if (ptr == NULL) return;
	gf_free(ptr);
}

fixed #2255


GF_Err pasp_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_PixelAspectRatioBox *ptr = (GF_PixelAspectRatioBox*)s;
	ISOM_DECREASE_SIZE(ptr, 8);
	ptr->hSpacing = gf_bs_read_u32(bs);
	ptr->vSpacing = gf_bs_read_u32(bs);
	return GF_OK;
}

fixed #2255


GF_Err trak_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem)
{
	GF_TrackBox *ptr = (GF_TrackBox *)s;
	if (!a) return GF_OK;
	switch(a->type) {
	case GF_ISOM_BOX_TYPE_TKHD:
		BOX_FIELD_ASSIGN(Header, GF_TrackHeaderBox)
		return GF_OK;
	case GF_ISOM_BOX_TYPE_EDTS:
		BOX_FIELD_ASSIGN(editBox, GF_EditBox)
		return GF_OK;
	case GF_ISOM_BOX_TYPE_UDTA:
		BOX_FIELD_ASSIGN(udta, GF_UserDataBox)
		return GF_OK;
	case GF_ISOM_BOX_TYPE_META:
		BOX_FIELD_ASSIGN(meta, GF_MetaBox)
		return GF_OK;
	case GF_ISOM_BOX_TYPE_TREF:
		BOX_FIELD_ASSIGN(References, GF_TrackReferenceBox)
		return GF_OK;
	case GF_ISOM_BOX_TYPE_MDIA:
		BOX_FIELD_ASSIGN(Media, GF_MediaBox)
		if (!is_rem)
			((GF_MediaBox *)a)->mediaTrack = ptr;
		return GF_OK;
	case GF_ISOM_BOX_TYPE_TRGR:
		BOX_FIELD_ASSIGN(groups, GF_TrackGroupBox)
		return GF_OK;
	case GF_QT_BOX_TYPE_TAPT:
		BOX_FIELD_ASSIGN(Aperture, GF_Box)
		return GF_OK;
	case GF_ISOM_BOX_TYPE_SENC:
		BOX_FIELD_ASSIGN(sample_encryption, GF_SampleEncryptionBox)
		return GF_OK;
	case GF_ISOM_BOX_TYPE_UUID:
		if (((GF_UnknownUUIDBox *)a)->internal_4cc == GF_ISOM_BOX_UUID_PSEC) {
			BOX_FIELD_ASSIGN(sample_encryption, GF_SampleEncryptionBox)
			return GF_OK;
		}
	}
	return GF_OK;
}

fixed #2255


GF_Box *chnl_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_ChannelLayoutBox, GF_ISOM_BOX_TYPE_CHNL);
	return (GF_Box *)tmp;
}

fixed #2255


void sbgp_box_del(GF_Box *a)
{
	GF_SampleGroupBox *p = (GF_SampleGroupBox *)a;
	if (p->sample_entries) gf_free(p->sample_entries);
	gf_free(p);
}

fixed #2255


GF_Err tfdt_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_TFBaseMediaDecodeTimeBox *ptr = (GF_TFBaseMediaDecodeTimeBox *) s;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	if (ptr->version==1) {
		gf_bs_write_u64(bs, ptr->baseMediaDecodeTime);
	} else {
		gf_bs_write_u32(bs, (u32) ptr->baseMediaDecodeTime);
	}
	return GF_OK;
}

fixed #2255


GF_Err lsr1_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_LASeRSampleEntryBox *ptr = (GF_LASeRSampleEntryBox*)s;

	e = gf_isom_base_sample_entry_read((GF_SampleEntryBox *)ptr, bs);
	if (e) return e;

	ISOM_DECREASE_SIZE(ptr, 8);

	return gf_isom_box_array_read(s, bs);
}

fixed #2255


static void ctrn_write_ctso(GF_TrackFragmentRunBox *ctrn, GF_BitStream *bs, u32 ctso, u32 field_size)
{
	if (!field_size) return;

	if (ctrn->ctso_multiplier) {
		gf_bs_write_int(bs, ctso / ctrn->ctso_multiplier, field_size);
	} else {
		gf_bs_write_int(bs, ctso, field_size);
	}
}

fixed #2255


GF_Box *tsro_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_TimeOffHintEntryBox, GF_ISOM_BOX_TYPE_TSRO);
	return (GF_Box *)tmp;
}

fixed #2255


void paen_box_del(GF_Box *s)
{
	gf_free(s);
}

fixed #2255


GF_Err fiin_box_size(GF_Box *s)
{
	u32 pos=0;
	FDItemInformationBox *ptr = (FDItemInformationBox *) s;
	s->size+= 2;
	gf_isom_check_position_list(s, ptr->partition_entries, &pos);
	return GF_OK;
}

fixed #2255


GF_Err st3d_box_size(GF_Box *s)
{
	s->size += 1;
	return GF_OK;
}

fixed #2255


void trik_box_del(GF_Box *s)
{
	GF_TrickPlayBox *ptr = (GF_TrickPlayBox *) s;
	if (ptr == NULL) return;
	if (ptr->entries) gf_free(ptr->entries);
	gf_free(ptr);
}

fixed #2255


GF_Err extr_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_ExtraDataBox *ptr = (GF_ExtraDataBox *) s;
	if (!s) return GF_BAD_PARAM;

	e = gf_isom_box_write_header(s, bs);
	if (e) return e;

	if (ptr->feci) {
		e = gf_isom_box_write((GF_Box *)ptr->feci, bs);
		if (e) return e;
	}
	gf_bs_write_data(bs, ptr->data, ptr->data_length);
	return GF_OK;
}

fixed #2255


GF_Err ctrn_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u32 i, count, flags;
	GF_TrunEntry *ent;
	GF_TrackFragmentRunBox *ctrn = (GF_TrackFragmentRunBox *) s;
	if (!s) return GF_BAD_PARAM;
	flags = ctrn->flags;
	ctrn->flags = ctrn->ctrn_flags;
	ctrn->type = GF_ISOM_BOX_TYPE_CTRN;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;
	ctrn->flags = flags;
	ctrn->type = GF_ISOM_BOX_TYPE_TRUN;

	gf_bs_write_u16(bs, ctrn->sample_count);
	if (ctrn->flags & GF_ISOM_TRUN_DATA_OFFSET) {
		if (ctrn->ctrn_flags & GF_ISOM_CTRN_DATAOFFSET_16) {
			gf_bs_write_u16(bs, ctrn->data_offset);
		} else {
			gf_bs_write_u32(bs, ctrn->data_offset);
		}
	}
	if (ctrn->ctso_multiplier) {
		gf_bs_write_u16(bs, ctrn->ctso_multiplier);
	}
	/*we always write first sample using first flags*/
	ent = gf_list_get(ctrn->entries, 0);
	gf_bs_write_int(bs, ent->Duration, gf_isom_ctrn_field_size_bits(ctrn->ctrn_first_dur) );
	gf_bs_write_int(bs, ent->size, gf_isom_ctrn_field_size_bits(ctrn->ctrn_first_size) );
	ctrn_write_sample_flags(bs, ent->flags, gf_isom_ctrn_field_size_bits(ctrn->ctrn_first_sample_flags) );
	ctrn_write_ctso(ctrn,bs, ent->CTS_Offset, gf_isom_ctrn_field_size_bits(ctrn->ctrn_first_ctts) );

	count = gf_list_count(ctrn->entries);
	if (ctrn->ctrn_dur) {
		u32 nbbits = gf_isom_ctrn_field_size_bits(ctrn->ctrn_dur);
		for (i=1; i<count; i++) {
			GF_TrunEntry *a_ent = gf_list_get(ctrn->entries, i);
			gf_bs_write_int(bs, a_ent->Duration, nbbits);
		}
	}
	if (ctrn->ctrn_size) {
		u32 nbbits = gf_isom_ctrn_field_size_bits(ctrn->ctrn_size);
		for (i=1; i<count; i++) {
			GF_TrunEntry *a_ent = gf_list_get(ctrn->entries, i);
			gf_bs_write_int(bs, a_ent->size, nbbits);
		}
	}
	if (ctrn->ctrn_sample_flags) {
		u32 nbbits = gf_isom_ctrn_field_size_bits(ctrn->ctrn_sample_flags);
		for (i=1; i<count; i++) {
			GF_TrunEntry *a_ent = gf_list_get(ctrn->entries, i);
			ctrn_write_sample_flags(bs, a_ent->flags, nbbits);
		}
	}
	if (ctrn->ctrn_ctts) {
		u32 nbbits = gf_isom_ctrn_field_size_bits(ctrn->ctrn_ctts);
		for (i=1; i<count; i++) {
			GF_TrunEntry *a_ent = gf_list_get(ctrn->entries, i);
			ctrn_write_ctso(ctrn, bs, a_ent->CTS_Offset, nbbits);
		}
	}

	return GF_OK;
}

fixed #2255


GF_Err clap_box_size(GF_Box *s)
{
	s->size += 32;
	return GF_OK;
}

fixed #2255


GF_Err bloc_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u32 i;
	GF_BaseLocationBox *ptr = (GF_BaseLocationBox *) s;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;
	gf_bs_write_data(bs, (const char *) ptr->baseLocation, 256);
	gf_bs_write_data(bs, (const char *) ptr->basePurlLocation, 256);
	for (i=0; i < 64; i++ ) {
		gf_bs_write_u64(bs, 0);
	}
	return GF_OK;
}

fixed #2255


GF_Err xtra_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_XtraBox *ptr = (GF_XtraBox *)s;
	while (ptr->size) {
		GF_XtraTag *tag;
		u32 prop_type = 0;

		char *data=NULL, *data2=NULL;
		ISOM_DECREASE_SIZE_NO_ERR(ptr, 8)
		s32 tag_size = gf_bs_read_u32(bs);
		u32 name_size = gf_bs_read_u32(bs);
		if (tag_size < 8) return GF_ISOM_INVALID_FILE;

		tag_size -= 8;
		if ((tag_size>ptr->size) || (name_size>ptr->size)) {
			return GF_ISOM_INVALID_FILE;
		}
		ISOM_DECREASE_SIZE_NO_ERR(ptr, 10)

		ISOM_DECREASE_SIZE_NO_ERR(ptr, name_size)
		data = gf_malloc(sizeof(char) * (name_size+1));
		gf_bs_read_data(bs, data, name_size);
		data[name_size] = 0;
		tag_size-=name_size;

		u32 flags = gf_bs_read_u32(bs);
		u32 prop_size = gf_bs_read_u32(bs);
		tag_size-=8;

		if (prop_size>4) {
			tag_size-=2;
			prop_type = gf_bs_read_u16(bs);
			prop_size -= 6;
			ISOM_DECREASE_SIZE_NO_ERR(ptr, prop_size)
			//add 3 extra bytes for UTF16 case string dump (3 because we need 0-aligned short value)
			data2 = gf_malloc(sizeof(char) * (prop_size+3));
			gf_bs_read_data(bs, data2, prop_size);
			data2[prop_size] = 0;
			data2[prop_size+1] = 0;
			data2[prop_size+2] = 0;
			tag_size-=prop_size;
		} else {
			prop_size = 0;
		}
		GF_SAFEALLOC(tag, GF_XtraTag)
		tag->flags = flags;
		tag->name = data;
		tag->prop_size = prop_size;
		tag->prop_value = data2;
		tag->prop_type = prop_type;
		gf_list_add(ptr->tags, tag);

		if (tag_size) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[isom] invalid tag size in Xtra !\n"));
		}
	}
	return GF_OK;
}

fixed #2255


GF_Err tref_box_read(GF_Box *s, GF_BitStream *bs)
{
	return gf_isom_box_array_read(s, bs);
}

fixed #2255


static u32 ctrn_sample_flags_to_index(u32 val)
{
	if (!val) return 0;
	if (val & 0x0000FFFF)
		return 3;
	if (val & 0x00FF0000)
		return 2;
	return 1;
}

fixed #2255


GF_Err stvi_box_size(GF_Box *s)
{
	GF_StereoVideoBox *ptr = (GF_StereoVideoBox *)s;

	ptr->size+= 12 + ptr->sit_len;
	return GF_OK;
}

fixed #2255


GF_Err mvcg_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u32 i;
	GF_MultiviewGroupBox *ptr = (GF_MultiviewGroupBox *) s;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	gf_bs_write_u32(bs, ptr->multiview_group_id);
	gf_bs_write_u16(bs, ptr->num_entries);
	gf_bs_write_u8(bs, 0);

	for (i=0; i<ptr->num_entries; i++) {
		gf_bs_write_u8(bs, ptr->entries[i].entry_type);
		switch (ptr->entries[i].entry_type) {
		case 0:
			gf_bs_write_u32(bs, ptr->entries[i].trackID);
			break;
		case 1:
			gf_bs_write_u32(bs, ptr->entries[i].trackID);
			gf_bs_write_u16(bs, ptr->entries[i].tierID);
			break;
		case 2:
			gf_bs_write_int(bs, 0, 6);
			gf_bs_write_int(bs, ptr->entries[i].output_view_id, 10);
			break;
		case 3:
			gf_bs_write_int(bs, 0, 6)	;
			gf_bs_write_int(bs, ptr->entries[i].start_view_id, 10);
			gf_bs_write_u16(bs, ptr->entries[i].view_count);
			break;
		}
	}
	return GF_OK;
}

fixed #2255


GF_Err clap_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_CleanApertureBox *ptr = (GF_CleanApertureBox*)s;
	ISOM_DECREASE_SIZE(ptr, 32);
	ptr->cleanApertureWidthN = gf_bs_read_u32(bs);
	ptr->cleanApertureWidthD = gf_bs_read_u32(bs);
	ptr->cleanApertureHeightN = gf_bs_read_u32(bs);
	ptr->cleanApertureHeightD = gf_bs_read_u32(bs);
	ptr->horizOffN = (s32) gf_bs_read_u32(bs);
	ptr->horizOffD = gf_bs_read_u32(bs);
	ptr->vertOffN = (s32) gf_bs_read_u32(bs);
	ptr->vertOffD = gf_bs_read_u32(bs);
	return GF_OK;
}

fixed #2255


GF_Err ainf_box_read(GF_Box *s,GF_BitStream *bs)
{
	GF_AssetInformationBox *ptr = (GF_AssetInformationBox *) s;

	ISOM_DECREASE_SIZE(s, 4)
	ptr->profile_version = gf_bs_read_u32(bs);
	return gf_isom_read_null_terminated_string(s, bs, s->size, &ptr->APID);
}

fixed #2255


void saiz_box_del(GF_Box *s)
{
	GF_SampleAuxiliaryInfoSizeBox*ptr = (GF_SampleAuxiliaryInfoSizeBox*)s;
	if (ptr == NULL) return;
	if (ptr->sample_info_size) gf_free(ptr->sample_info_size);
	gf_free(ptr);
}

fixed #2255


GF_Err leva_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 i;
	GF_LevelAssignmentBox *ptr = (GF_LevelAssignmentBox*)s;

	ISOM_DECREASE_SIZE(ptr, 1)
	ptr->level_count = gf_bs_read_u8(bs);
	//each level is at least 5 bytes
	if (ptr->size / 5 < ptr->level_count)
		return GF_ISOM_INVALID_FILE;

	GF_SAFE_ALLOC_N(ptr->levels, ptr->level_count, GF_LevelAssignment);
	if (!ptr->levels) return GF_OUT_OF_MEM;

	for (i = 0; i < ptr->level_count; i++) {
		GF_LevelAssignment *level = &ptr->levels[i];
		u8 tmp;
		if (!level || ptr->size < 5) return GF_BAD_PARAM;
		ISOM_DECREASE_SIZE(ptr, 5)

		level->track_id = gf_bs_read_u32(bs);
		tmp = gf_bs_read_u8(bs);
		level->padding_flag = tmp >> 7;
		level->type = tmp & 0x7F;
		if (level->type == 0) {
			ISOM_DECREASE_SIZE(ptr, 4)
			level->grouping_type = gf_bs_read_u32(bs);
		}
		else if (level->type == 1) {
			ISOM_DECREASE_SIZE(ptr, 8)
			level->grouping_type = gf_bs_read_u32(bs);
			level->grouping_type_parameter = gf_bs_read_u32(bs);
		}
		else if (level->type == 4) {
			ISOM_DECREASE_SIZE(ptr, 4)
			level->sub_track_id = gf_bs_read_u32(bs);
		}
	}
	return GF_OK;
}

fixed #2255


GF_Err dvcC_box_size(GF_Box *s)
{
	GF_DOVIConfigurationBox *ptr = (GF_DOVIConfigurationBox *)s;

	ptr->size += 24;
	return GF_OK;
}

fixed #2255


GF_Err jp2h_box_read(GF_Box *s,GF_BitStream *bs)
{
	return gf_isom_box_array_read(s, bs);
}

fixed #2255


GF_Err pcmC_box_size(GF_Box *s)
{
	s->size += 2;
	return GF_OK;
}

fixed #2255


GF_Box *vmhd_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_VideoMediaHeaderBox, GF_ISOM_BOX_TYPE_VMHD);
	tmp->flags = 1;
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err ihdr_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_J2KImageHeaderBox *ptr = (GF_J2KImageHeaderBox *) s;

	e = gf_isom_box_write_header(s, bs);
	if (e) return e;

	gf_bs_write_u32(bs, ptr->height);
	gf_bs_write_u32(bs, ptr->width);
	gf_bs_write_u16(bs, ptr->nb_comp);
	gf_bs_write_u8(bs, ptr->bpc);
	gf_bs_write_u8(bs, ptr->Comp);
	gf_bs_write_u8(bs, ptr->UnkC);
	gf_bs_write_u8(bs, ptr->IPR);
	return GF_OK;
}

fixed #2255


GF_Err ssix_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 i,j;
	GF_SubsegmentIndexBox *ptr = (GF_SubsegmentIndexBox*)s;

	ISOM_DECREASE_SIZE(ptr, 4)
	ptr->subsegment_count = gf_bs_read_u32(bs);
	//each subseg has at least one range_count (4 bytes), abort if not enough bytes (broken box)
	if (ptr->size / 4 < ptr->subsegment_count || (u64)ptr->subsegment_count > (u64)SIZE_MAX/sizeof(GF_SubsegmentInfo))
		return GF_ISOM_INVALID_FILE;

	ptr->subsegment_alloc = ptr->subsegment_count;
	GF_SAFE_ALLOC_N(ptr->subsegments, ptr->subsegment_count, GF_SubsegmentInfo);
	if (!ptr->subsegments)
	    return GF_OUT_OF_MEM;
	for (i = 0; i < ptr->subsegment_count; i++) {
		GF_SubsegmentInfo *subseg = &ptr->subsegments[i];
		ISOM_DECREASE_SIZE(ptr, 4)
		subseg->range_count = gf_bs_read_u32(bs);
		//each range is 4 bytes, abort if not enough bytes
		if (ptr->size / 4 < subseg->range_count || (u64)subseg->range_count > (u64)SIZE_MAX/sizeof(GF_SubsegmentRangeInfo))
			return GF_ISOM_INVALID_FILE;
		subseg->ranges = (GF_SubsegmentRangeInfo*) gf_malloc(sizeof(GF_SubsegmentRangeInfo) * subseg->range_count);
		if (!subseg->ranges) return GF_OUT_OF_MEM;
		for (j = 0; j < subseg->range_count; j++) {
			ISOM_DECREASE_SIZE(ptr, 4)
			subseg->ranges[j].level = gf_bs_read_u8(bs);
			subseg->ranges[j].range_size = gf_bs_read_u24(bs);
		}
	}
	return GF_OK;
}

fixed #2255


static u32 ctrn_read_flags(GF_BitStream *bs, u32 nbbits)
{
	u32 val = gf_bs_read_int(bs, nbbits);
	if (nbbits==16) val <<= 16;
	else if (nbbits==8) val <<= 24;
	return val;
}

fixed #2255


GF_Err strk_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem)
{
	GF_SubTrackBox *ptr = (GF_SubTrackBox *)s;
	if (!a) return GF_OK;
	switch (a->type) {
	case GF_ISOM_BOX_TYPE_STRI:
		BOX_FIELD_ASSIGN(info, GF_SubTrackInformationBox)
		return GF_OK;
	case GF_ISOM_BOX_TYPE_STRD:
		BOX_FIELD_ASSIGN(strd, GF_Box)
		return GF_OK;
	}
	return GF_OK;
}

fixed #2255


GF_Box *csgp_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_CompactSampleGroupBox, GF_ISOM_BOX_TYPE_CSGP);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err emsg_box_size(GF_Box *s)
{
	GF_EventMessageBox *ptr = (GF_EventMessageBox*) s;

	if (ptr->version) {
		ptr->size += 20;
	} else {
		ptr->size += 16;
	}
	ptr->size+=2; //1 NULL-terminated strings
	if (ptr->scheme_id_uri) ptr->size += strlen(ptr->scheme_id_uri);
	if (ptr->value) ptr->size += strlen(ptr->value);
	if (ptr->message_data)
		ptr->size += ptr->message_data_size;

	return GF_OK;
}

fixed #2255


void pcmC_box_del(GF_Box *s)
{
	gf_free(s);
}

fixed #2255


GF_Err svhd_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_SphericalVideoInfoBox *ptr = (GF_SphericalVideoInfoBox *)s;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;
	if (ptr->string)
		gf_bs_write_data(bs, ptr->string, (u32) strlen(ptr->string));
	gf_bs_write_u8(bs, 0);
	return GF_OK;
}

fixed #2255


GF_Err trgt_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_TrackGroupTypeBox *ptr = (GF_TrackGroupTypeBox *)s;
	ISOM_DECREASE_SIZE(ptr, 4);
	ptr->track_group_id = gf_bs_read_u32(bs);
	return GF_OK;
}

fixed #2255


GF_Err dvvC_box_size(GF_Box *s)
{
	return dvcC_box_size(s);
}

fixed #2255


GF_Err mhac_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_MHAConfigBox *ptr = (GF_MHAConfigBox *) s;

	e = gf_isom_box_write_header(s, bs);
	if (e) return e;
	gf_bs_write_u8(bs, ptr->configuration_version);
	gf_bs_write_u8(bs, ptr->mha_pl_indication);
	gf_bs_write_u8(bs, ptr->reference_channel_layout);
	gf_bs_write_u16(bs, ptr->mha_config ? ptr->mha_config_size : 0);
	if (ptr->mha_config && ptr->mha_config_size)
		gf_bs_write_data(bs, ptr->mha_config, ptr->mha_config_size);

	return GF_OK;
}

fixed #2255


GF_Box *fdpa_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_FDpacketBox, GF_ISOM_BOX_TYPE_FDPA);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *mvcg_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_MultiviewGroupBox, GF_ISOM_BOX_TYPE_MVCG);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err jp2h_box_size(GF_Box *s)
{
	return GF_OK;
}

fixed #2255


GF_Err stri_box_size(GF_Box *s)
{
	GF_SubTrackInformationBox *ptr = (GF_SubTrackInformationBox *)s;

	ptr->size += 8 + 4 * ptr->attribute_count;
	return GF_OK;
}

fixed #2255


GF_Box *sgpd_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_SampleGroupDescriptionBox, GF_ISOM_BOX_TYPE_SGPD);
	/*version 0 is deprecated, use v1 by default*/
	tmp->version = 1;
	tmp->group_descriptions = gf_list_new();
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err subs_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_SubSampleInformationBox *ptr = (GF_SubSampleInformationBox *)s;
	u32 entry_count, i, j;
	u16 subsample_count;

	ISOM_DECREASE_SIZE(ptr, 4);
	entry_count = gf_bs_read_u32(bs);

	for (i=0; i<entry_count; i++) {
		u32 subs_size=0;
		GF_SubSampleInfoEntry *pSamp = (GF_SubSampleInfoEntry*) gf_malloc(sizeof(GF_SubSampleInfoEntry));
		if (!pSamp) return GF_OUT_OF_MEM;

		memset(pSamp, 0, sizeof(GF_SubSampleInfoEntry));
		pSamp->SubSamples = gf_list_new();
		pSamp->sample_delta = gf_bs_read_u32(bs);
		subsample_count = gf_bs_read_u16(bs);
		subs_size=6;

		for (j=0; j<subsample_count; j++) {
			GF_SubSampleEntry *pSubSamp = (GF_SubSampleEntry*) gf_malloc(sizeof(GF_SubSampleEntry));
			if (!pSubSamp) return GF_OUT_OF_MEM;

			memset(pSubSamp, 0, sizeof(GF_SubSampleEntry));
			if (ptr->version==1) {
				pSubSamp->subsample_size = gf_bs_read_u32(bs);
				subs_size+=4;
			} else {
				pSubSamp->subsample_size = gf_bs_read_u16(bs);
				subs_size+=2;
			}
			pSubSamp->subsample_priority = gf_bs_read_u8(bs);
			pSubSamp->discardable = gf_bs_read_u8(bs);
			pSubSamp->reserved = gf_bs_read_u32(bs);
			subs_size+=6;

			gf_list_add(pSamp->SubSamples, pSubSamp);
		}
		gf_list_add(ptr->Samples, pSamp);
		ISOM_DECREASE_SIZE(ptr, subs_size);
	}
	return GF_OK;
}

fixed #2255


void fiin_box_del(GF_Box *s)
{
	FDItemInformationBox *ptr = (FDItemInformationBox *)s;
	if (ptr == NULL) return;
	if (ptr->partition_entries) gf_list_del(ptr->partition_entries);
	gf_free(ptr);
}

fixed #2255


GF_Err ihdr_box_read(GF_Box *s,GF_BitStream *bs)
{
	GF_J2KImageHeaderBox *ptr = (GF_J2KImageHeaderBox *) s;

	ISOM_DECREASE_SIZE(s, 14)

	ptr->height = gf_bs_read_u32(bs);
	ptr->width = gf_bs_read_u32(bs);
	ptr->nb_comp = gf_bs_read_u16(bs);
	ptr->bpc = gf_bs_read_u8(bs);
	ptr->Comp = gf_bs_read_u8(bs);
	ptr->UnkC = gf_bs_read_u8(bs);
	ptr->IPR = gf_bs_read_u8(bs);

	return GF_OK;
}

fixed #2255


GF_Box *fpar_box_new()
{
	ISOM_DECL_BOX_ALLOC(FilePartitionBox, GF_ISOM_BOX_TYPE_FPAR);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err dmlp_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_TrueHDConfigBox *ptr = (GF_TrueHDConfigBox *)s;
	ISOM_DECREASE_SIZE(ptr, 10)
	ptr->format_info = gf_bs_read_u32(bs);
	ptr->peak_data_rate = gf_bs_read_int(bs, 15);
	gf_bs_read_int(bs, 1);
	gf_bs_read_u32(bs);
	return GF_OK;
}

fixed #2255


GF_Err trep_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_TrackExtensionPropertiesBox *ptr = (GF_TrackExtensionPropertiesBox *) s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	gf_bs_write_u32(bs, ptr->trackID);
	return GF_OK;
}

fixed #2255


GF_Err dac3_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_AC3ConfigBox *ptr = (GF_AC3ConfigBox *)s;

	if (ptr->cfg.is_ec3) s->type = GF_ISOM_BOX_TYPE_DEC3;
	e = gf_isom_box_write_header(s, bs);
	if (ptr->cfg.is_ec3) s->type = GF_ISOM_BOX_TYPE_DAC3;
	if (e) return e;

	return gf_odf_ac3_cfg_write_bs(&ptr->cfg, bs);
}

fixed #2255


GF_Err trgr_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem)
{
	GF_TrackGroupBox *ptr = (GF_TrackGroupBox *)s;

	BOX_FIELD_LIST_ASSIGN(groups)
	return gf_list_add(ptr->groups, a);
}

fixed #2255


void st3d_box_del(GF_Box *s)
{
	gf_free(s);
}

fixed #2255


GF_Err extr_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_ExtraDataBox *ptr = (GF_ExtraDataBox *)s;

	e = gf_isom_box_parse((GF_Box**) &ptr->feci, bs);
	if (e) return e;
	if (!ptr->feci || ptr->feci->size > ptr->size) return GF_ISOM_INVALID_MEDIA;
	ptr->data_length = (u32) (ptr->size - ptr->feci->size);
	ptr->data = gf_malloc(sizeof(char)*ptr->data_length);
	if (!ptr->data) return GF_OUT_OF_MEM;
	gf_bs_read_data(bs, ptr->data, ptr->data_length);

	return GF_OK;
}

fixed #2255


GF_Err fecr_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 i;
	FECReservoirBox *ptr = (FECReservoirBox *)s;

	ISOM_DECREASE_SIZE(ptr, (ptr->version ? 4 : 2) );
	ptr->nb_entries = gf_bs_read_int(bs, ptr->version ? 32 : 16);

	if (ptr->nb_entries > ptr->size / (ptr->version ? 8 : 6) || (u64)ptr->nb_entries > (u64)SIZE_MAX/sizeof(FECReservoirEntry) ) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of entries %d in fecr\n", ptr->nb_entries));
		return GF_ISOM_INVALID_FILE;
	}

	ISOM_DECREASE_SIZE(ptr, ptr->nb_entries * (ptr->version ? 8 : 6) );
	GF_SAFE_ALLOC_N(ptr->entries, ptr->nb_entries, FECReservoirEntry);
	if (!ptr->entries) return GF_OUT_OF_MEM;

	for (i=0; i<ptr->nb_entries; i++) {
		ptr->entries[i].item_id = gf_bs_read_int(bs, ptr->version ? 32 : 16);
		ptr->entries[i].symbol_count = gf_bs_read_u32(bs);
	}
	return GF_OK;
}

fixed #2255


GF_Err dac3_box_size(GF_Box *s)
{
	GF_AC3ConfigBox *ptr = (GF_AC3ConfigBox *)s;

	if (ptr->cfg.is_ec3) {
		u32 i;
		s->size += 2;
		for (i=0; i<ptr->cfg.nb_streams; i++) {
			s->size += 3;
			if (ptr->cfg.streams[i].nb_dep_sub)
				s->size += 1;
		}
	} else {
		s->size += 3;
	}
	return GF_OK;
}

fixed #2255


GF_Err pcrb_box_size(GF_Box *s)
{
	GF_PcrInfoBox *ptr = (GF_PcrInfoBox*) s;

	ptr->size += 4;
	ptr->size += ptr->subsegment_count * 6;

	return GF_OK;
}

fixed #2255


GF_Err trgt_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_TrackGroupTypeBox *ptr = (GF_TrackGroupTypeBox *) s;
	if (!s) return GF_BAD_PARAM;
	s->type = ptr->group_type;
	e = gf_isom_full_box_write(s, bs);
	s->type = GF_ISOM_BOX_TYPE_TRGT;
	if (e) return e;
	gf_bs_write_u32(bs, ptr->track_group_id);
	return GF_OK;
}

fixed #2255


GF_Box *jp2h_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_J2KHeaderBox, GF_ISOM_BOX_TYPE_JP2H);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err vmhd_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_VideoMediaHeaderBox *ptr = (GF_VideoMediaHeaderBox *)s;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;
	gf_bs_write_u64(bs, ptr->reserved);
	return GF_OK;
}

fixed #2255


GF_Err vmhd_box_size(GF_Box *s)
{
	GF_VideoMediaHeaderBox *ptr = (GF_VideoMediaHeaderBox *)s;
	ptr->size += 8;
	return GF_OK;
}

fixed #2255


GF_Err udta_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u32 i;
	GF_UserDataMap *map;
	GF_UserDataBox *ptr = (GF_UserDataBox *)s;

	e = gf_isom_box_write_header(s, bs);
	if (e) return e;
	i=0;
	while ((map = (GF_UserDataMap *)gf_list_enum(ptr->recordList, &i))) {
		//warning: here we are not passing the actual "parent" of the list
		//but the UDTA box. The parent itself is not an box, we don't care about it
		e = gf_isom_box_array_write(s, map->boxes, bs);
		if (e) return e;
	}
	return GF_OK;
}

fixed #2255


GF_Err dOps_box_size(GF_Box *s)
{
	GF_OpusSpecificBox *ptr = (GF_OpusSpecificBox *)s;
	ptr->size += 11;
	if (ptr->opcfg.ChannelMappingFamily)
		ptr->size += 2 + ptr->opcfg.OutputChannelCount;

	return GF_OK;
}

fixed #2255


GF_Err sgpd_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 entry_count;
	GF_SampleGroupDescriptionBox *p = (GF_SampleGroupDescriptionBox *)s;

	ISOM_DECREASE_SIZE(p, 8);
	p->grouping_type = gf_bs_read_u32(bs);

	if (p->version>=1) {
		ISOM_DECREASE_SIZE(p, 4);
		p->default_length = gf_bs_read_u32(bs);
	}
	if (p->version>=2) {
		ISOM_DECREASE_SIZE(p, 4);
		p->default_description_index = gf_bs_read_u32(bs);
	}
	entry_count = gf_bs_read_u32(bs);

	if (entry_count>p->size)
		return GF_ISOM_INVALID_FILE;

	while (entry_count) {
		void *ptr;
		u32 parsed_bytes=0;
		u32 size = p->default_length;
		if ((p->version>=1) && !size) {
			size = gf_bs_read_u32(bs);
			ISOM_DECREASE_SIZE(p, 4);
		}
		ptr = sgpd_parse_entry(p->grouping_type, bs, (s32) p->size, size, &parsed_bytes);
		//don't return an error, just stop parsing so that we skip over the sgpd box
		if (!ptr) return GF_OK;
		gf_list_add(p->group_descriptions, ptr);

		ISOM_DECREASE_SIZE(p, parsed_bytes);
		entry_count--;
	}
	return GF_OK;
}

fixed #2255


void chnl_box_del(GF_Box *s)
{
	gf_free(s);
}

fixed #2255


void svhd_box_del(GF_Box *s)
{
	GF_SphericalVideoInfoBox *ptr = (GF_SphericalVideoInfoBox *)s;
	if (ptr->string) gf_free(ptr->string);
	gf_free(s);
}

fixed #2255


GF_Err pdin_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 i;
	GF_ProgressiveDownloadBox *ptr = (GF_ProgressiveDownloadBox*)s;

	ptr->count = (u32) (ptr->size) / 8;
	ptr->rates = (u32*)gf_malloc(sizeof(u32)*ptr->count);
	if (!ptr->rates) return GF_OUT_OF_MEM;
	ptr->times = (u32*)gf_malloc(sizeof(u32)*ptr->count);
	if (!ptr->times) return GF_OUT_OF_MEM;
	for (i=0; i<ptr->count; i++) {
		ptr->rates[i] = gf_bs_read_u32(bs);
		ptr->times[i] = gf_bs_read_u32(bs);
	}
	return GF_OK;
}

fixed #2255


GF_Box *trgr_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_TrackGroupBox, GF_ISOM_BOX_TYPE_TRGR);
	tmp->groups = gf_list_new();
	if (!tmp->groups) {
		gf_free(tmp);
		return NULL;
	}
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *pcmC_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_PCMConfigBox, GF_ISOM_BOX_TYPE_PCMC);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err emsg_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u32 len;
	GF_EventMessageBox *ptr = (GF_EventMessageBox*) s;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	if (ptr->version==1) {
		gf_bs_write_u32(bs, ptr->timescale);
		gf_bs_write_u64(bs, ptr->presentation_time_delta);
		gf_bs_write_u32(bs, ptr->event_duration);
		gf_bs_write_u32(bs, ptr->event_id);
	}

	len = ptr->scheme_id_uri ? (u32) strlen(ptr->scheme_id_uri) : 0;
	if (len) gf_bs_write_data(bs, ptr->scheme_id_uri, len);
	gf_bs_write_u8(bs, 0);

	len = ptr->value ? (u32) strlen(ptr->value) : 0;
	if (len) gf_bs_write_data(bs, ptr->value, len);
	gf_bs_write_u8(bs, 0);

	if (ptr->version==0) {
		gf_bs_write_u32(bs, ptr->timescale);
		gf_bs_write_u32(bs, (u32) ptr->presentation_time_delta);
		gf_bs_write_u32(bs, ptr->event_duration);
		gf_bs_write_u32(bs, ptr->event_id);
	}
	if (ptr->message_data)
		gf_bs_write_data(bs, ptr->message_data, ptr->message_data_size);
	return GF_OK;
}

fixed #2255


GF_Box *dec3_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_AC3ConfigBox, GF_ISOM_BOX_TYPE_DAC3);
	tmp->cfg.is_ec3 = 1;
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *paen_box_new()
{
	ISOM_DECL_BOX_ALLOC(FDPartitionEntryBox, GF_ISOM_BOX_TYPE_PAEN);
	return (GF_Box *)tmp;
}

fixed #2255


void ihdr_box_del(GF_Box *s)
{
	gf_free(s);
}

fixed #2255


GF_Err trgr_box_read(GF_Box *s, GF_BitStream *bs)
{
	return gf_isom_box_array_read(s, bs);
}

fixed #2255


GF_Box *dac3_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_AC3ConfigBox, GF_ISOM_BOX_TYPE_DAC3);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err gitn_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 i;
	GF_Err e;
	GroupIdToNameBox *ptr = (GroupIdToNameBox *)s;

	ISOM_DECREASE_SIZE(ptr, 2);
	ptr->nb_entries = gf_bs_read_u16(bs);
	if (ptr->size / 4 < ptr->nb_entries)
		return GF_ISOM_INVALID_FILE;

	GF_SAFE_ALLOC_N(ptr->entries, ptr->nb_entries, GroupIdNameEntry);
	if (!ptr->entries) return GF_OUT_OF_MEM;

	for (i=0; i<ptr->nb_entries; i++) {
		ISOM_DECREASE_SIZE(ptr, 4);
		ptr->entries[i].group_id = gf_bs_read_u32(bs);

		e = gf_isom_read_null_terminated_string(s, bs, ptr->size, &ptr->entries[i].name);
		if (e) return e;
	}
	return GF_OK;
}

fixed #2255


GF_Err strk_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_SubTrackBox *ptr = (GF_SubTrackBox *)s;
	e = gf_isom_box_array_read(s, bs);
	if (e) return e;

	if (!ptr->info) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Missing SubTrackInformationBox\n"));
		return GF_ISOM_INVALID_FILE;
	}
	return GF_OK;
}

fixed #2255


void bloc_box_del(GF_Box *s)
{
	gf_free(s);
}

fixed #2255


GF_Err fdsa_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_HintSample *ptr = (GF_HintSample *) s;
	if (!s) return GF_BAD_PARAM;

	e = gf_isom_box_write_header(s, bs);
	if (e) return e;

	e = gf_isom_box_array_write(s, ptr->packetTable, bs);
	if (e) return e;
	if (ptr->extra_data) {
		e = gf_isom_box_write((GF_Box *)ptr->extra_data, bs);
		if (e) return e;
	}
	return GF_OK;
}

fixed #2255


GF_Err txtc_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_TextConfigBox *ptr = (GF_TextConfigBox *)s;
	GF_Err e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	if (ptr->config)
		gf_bs_write_data(bs, ptr->config, (u32) strlen(ptr->config));
	gf_bs_write_u8(bs, 0);
	return GF_OK;
}

fixed #2255


GF_Err strk_box_size(GF_Box *s)
{
	return GF_OK;
}

fixed #2255


GF_Err trgr_box_size(GF_Box *s)
{
	u32 pos=0;
	GF_TrackGroupBox *ptr = (GF_TrackGroupBox *) s;
	gf_isom_check_position_list(s, ptr->groups, &pos);
	return GF_OK;
}

fixed #2255


GF_Box *tref_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_TrackReferenceBox, GF_ISOM_BOX_TYPE_TREF);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *ssix_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_SubsegmentIndexBox, GF_ISOM_BOX_TYPE_SSIX);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *pasp_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_PixelAspectRatioBox, GF_ISOM_BOX_TYPE_PASP);
	return (GF_Box *)tmp;
}

fixed #2255


void tfdt_box_del(GF_Box *s)
{
	gf_free(s);
}

fixed #2255


GF_Box *trik_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_TrickPlayBox, GF_ISOM_BOX_TYPE_TRIK);
	return (GF_Box *)tmp;
}

fixed #2255


void sdtp_box_del(GF_Box *s)
{
	GF_SampleDependencyTypeBox *ptr = (GF_SampleDependencyTypeBox*)s;
	if (ptr == NULL) return;
	if (ptr->sample_info) gf_free(ptr->sample_info);
	gf_free(ptr);
}

fixed #2255


GF_Err rvcc_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_RVCConfigurationBox *ptr = (GF_RVCConfigurationBox*) s;

	e = gf_isom_box_write_header(s, bs);
	if (e) return e;

	gf_bs_write_u16(bs, ptr->predefined_rvc_config);
	if (!ptr->predefined_rvc_config) {
		gf_bs_write_u16(bs, ptr->rvc_meta_idx);
	}
	return GF_OK;
}

fixed #2255


GF_Err ctts_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 i;
	u32 sampleCount;
	GF_CompositionOffsetBox *ptr = (GF_CompositionOffsetBox *)s;

	ISOM_DECREASE_SIZE(ptr, 4);
	ptr->nb_entries = gf_bs_read_u32(bs);

	if (ptr->nb_entries > ptr->size / 8 || (u64)ptr->nb_entries > (u64)SIZE_MAX/sizeof(GF_DttsEntry) ) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid number of entries %d in ctts\n", ptr->nb_entries));
		return GF_ISOM_INVALID_FILE;
	}

	ptr->alloc_size = ptr->nb_entries;
	ptr->entries = (GF_DttsEntry *)gf_malloc(sizeof(GF_DttsEntry)*ptr->alloc_size);
	if (!ptr->entries) return GF_OUT_OF_MEM;
	sampleCount = 0;
	for (i=0; i<ptr->nb_entries; i++) {
		ISOM_DECREASE_SIZE(ptr, 8);
		ptr->entries[i].sampleCount = gf_bs_read_u32(bs);
		if (ptr->version)
			ptr->entries[i].decodingOffset = gf_bs_read_int(bs, 32);
		else
			ptr->entries[i].decodingOffset = (s32) gf_bs_read_u32(bs);

		if (ptr->max_cts_delta <= ABS(ptr->entries[i].decodingOffset)) {
			ptr->max_cts_delta = ABS(ptr->entries[i].decodingOffset);
			//ptr->sample_num_max_cts_delta = sampleCount;
		}
		sampleCount += ptr->entries[i].sampleCount;
	}
#ifndef GPAC_DISABLE_ISOM_WRITE
	ptr->w_LastSampleNumber = sampleCount;
#endif
	return GF_OK;
}

fixed #2255


GF_Err ssix_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u32 i, j;
	GF_SubsegmentIndexBox *ptr = (GF_SubsegmentIndexBox*)s;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	gf_bs_write_u32(bs, ptr->subsegment_count);
	for (i = 0; i<ptr->subsegment_count; i++) {
		gf_bs_write_u32(bs, ptr->subsegments[i].range_count);
		for (j = 0; j < ptr->subsegments[i].range_count; j++) {
			gf_bs_write_u8(bs, ptr->subsegments[i].ranges[j].level);
			gf_bs_write_u24(bs, ptr->subsegments[i].ranges[j].range_size);
		}
	}
	return GF_OK;
}

fixed #2255


void fdpa_box_del(GF_Box *s)
{
	u32 i;
	GF_FDpacketBox *ptr = (GF_FDpacketBox *)s;
	if (ptr == NULL) return;

	if (ptr->headers) {
		for (i=0; i<ptr->header_ext_count; i++) {
			if (ptr->headers[i].data) gf_free(ptr->headers[i].data);
		}
		gf_free(ptr->headers);
	}
	gf_free(ptr);
}

fixed #2255


GF_Box *st3d_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_Stereo3DBox, GF_ISOM_BOX_TYPE_ST3D);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *dvvC_box_new()
{
	GF_DOVIConfigurationBox *tmp = (GF_DOVIConfigurationBox *)gf_malloc(sizeof(GF_DOVIConfigurationBox));
	if (tmp == NULL) return NULL;
	memset(tmp, 0, sizeof(GF_DOVIConfigurationBox));
	tmp->type = GF_ISOM_BOX_TYPE_DVVC;
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err stri_box_read(GF_Box *s, GF_BitStream *bs)
{
	size_t i;
	GF_SubTrackInformationBox *ptr = (GF_SubTrackInformationBox *)s;
	ISOM_DECREASE_SIZE(ptr, 8)
	ptr->switch_group = gf_bs_read_u16(bs);
	ptr->alternate_group = gf_bs_read_u16(bs);
	ptr->sub_track_id = gf_bs_read_u32(bs);
	ptr->attribute_count = ptr->size / 4;
	if ((u64)ptr->attribute_count > (u64)SIZE_MAX/sizeof(u32)) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid size %llu in stri\n", ptr->size));
		return GF_ISOM_INVALID_FILE;
	}
	GF_SAFE_ALLOC_N(ptr->attribute_list, (size_t)ptr->attribute_count, u32);
	if (!ptr->attribute_list) return GF_OUT_OF_MEM;
	for (i = 0; i < ptr->attribute_count; i++) {
		ISOM_DECREASE_SIZE(ptr, 4)
		ptr->attribute_list[i] = gf_bs_read_u32(bs);
	}
	return GF_OK;
}

fixed #2255


u32 gf_isom_ctrn_field_size_bits(u32 field_idx)
{
	if (field_idx==3) return 32;
	return field_idx*8;
}

fixed #2255


void dmlp_box_del(GF_Box *s)
{
	gf_free(s);
}

fixed #2255


GF_Box *strk_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_SubTrackBox, GF_ISOM_BOX_TYPE_STRK);
	return (GF_Box *)tmp;
}

fixed #2255


GF_Box *mhac_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_MHAConfigBox, GF_ISOM_BOX_TYPE_MHAC);
	tmp->configuration_version = 1;
	return (GF_Box *)tmp;
}

fixed #2255


GF_Err stsd_box_read(GF_Box *s, GF_BitStream *bs)
{
	ISOM_DECREASE_SIZE(s, 4)
	gf_bs_read_u32(bs);

	return gf_isom_box_array_read(s, bs);
}

fixed #2255


static void ctrn_write_sample_flags(GF_BitStream *bs, u32 flags, u32 field_size)
{
	if (!field_size) return;

	if (field_size==8) flags = flags>>24;
	else if (field_size==16) flags = flags>>16;
	gf_bs_write_int(bs, flags, field_size);
}

fixed #2255


GF_Err trgt_box_size(GF_Box *s)
{
	GF_TrackGroupBox *ptr = (GF_TrackGroupBox *)s;

	ptr->size+= 4;
	return GF_OK;
}

fixed #2255


GF_Err chnl_box_size(GF_Box *s)
{
	GF_ChannelLayoutBox *ptr = (GF_ChannelLayoutBox *) s;
	s->size += 1;
	if (ptr->layout.stream_structure & 1) {
		s->size += 1;
		if (ptr->layout.definedLayout==0) {
			u32 i;
			for (i=0; i<ptr->layout.channels_count; i++) {
				s->size+=1;
				if (ptr->layout.layouts[i].position==126)
					s->size+=3;
			}
		} else {
			s->size += 8;
		}
	}
	if (ptr->layout.stream_structure & 2) {
		s->size += 1;
	}
	return GF_OK;
}

fixed #2255


GF_Err saiz_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_SampleAuxiliaryInfoSizeBox*ptr = (GF_SampleAuxiliaryInfoSizeBox*)s;

	if (ptr->flags & 1) {
		ISOM_DECREASE_SIZE(ptr, 8);
		ptr->aux_info_type = gf_bs_read_u32(bs);
		ptr->aux_info_type_parameter = gf_bs_read_u32(bs);
	}
	ISOM_DECREASE_SIZE(ptr, 5);
	ptr->default_sample_info_size = gf_bs_read_u8(bs);
	ptr->sample_count = gf_bs_read_u32(bs);

	if (ptr->default_sample_info_size == 0) {
		if (ptr->size < ptr->sample_count)
		    return GF_ISOM_INVALID_FILE;

		ptr->sample_info_size = gf_malloc(sizeof(u8)*ptr->sample_count);
		ptr->sample_alloc = ptr->sample_count;
		if (!ptr->sample_info_size)
		    return GF_OUT_OF_MEM;

		ISOM_DECREASE_SIZE(ptr, ptr->sample_count);
		gf_bs_read_data(bs, (char *) ptr->sample_info_size, ptr->sample_count);
	}
	return GF_OK;
}

fixed #2255


GF_Err dvcC_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_DOVIConfigurationBox *ptr = (GF_DOVIConfigurationBox *) s;
	if (!s) return GF_BAD_PARAM;

	e = gf_isom_box_write_header(s, bs);
	if (e) return e;

	//GF_DOVIDecoderConfigurationRecord
	gf_bs_write_u8(bs,  ptr->DOVIConfig.dv_version_major);
	gf_bs_write_u8(bs,  ptr->DOVIConfig.dv_version_minor);
	gf_bs_write_int(bs, ptr->DOVIConfig.dv_profile, 7);
	gf_bs_write_int(bs, ptr->DOVIConfig.dv_level, 6);
	gf_bs_write_int(bs, ptr->DOVIConfig.rpu_present_flag, 1);
	gf_bs_write_int(bs, ptr->DOVIConfig.el_present_flag, 1);
	gf_bs_write_int(bs, ptr->DOVIConfig.bl_present_flag, 1);
	gf_bs_write_int(bs, ptr->DOVIConfig.dv_bl_signal_compatibility_id, 4);
	gf_bs_write_int(bs, 0, 28);
	gf_bs_write_u32(bs, 0);
	gf_bs_write_u32(bs, 0);
	gf_bs_write_u32(bs, 0);
	gf_bs_write_u32(bs, 0);

	return GF_OK;
}

fixed #2255


GF_Err mhap_box_write(GF_Box *s, GF_BitStream *bs)
{
	u32 i;
	GF_Err e;
	GF_MHACompatibleProfilesBox *ptr = (GF_MHACompatibleProfilesBox *) s;

	e = gf_isom_box_write_header(s, bs);
	if (e) return e;
	gf_bs_write_u8(bs, ptr->num_profiles);
	for (i=0; i<ptr->num_profiles; i++) {
		gf_bs_write_u8(bs, ptr->compat_profiles[i]);
	}
	return GF_OK;
}

fixed #2255