Beispiel #1
0
GF_Err tx3g_Read(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_Box *a;
	GF_Tx3gSampleEntryBox *ptr = (GF_Tx3gSampleEntryBox*)s;

	if (ptr->size < 18 + GPP_BOX_SIZE + GPP_STYLE_SIZE) return GF_ISOM_INVALID_FILE;

	gf_bs_read_data(bs, ptr->reserved, 6);
	ptr->dataReferenceIndex = gf_bs_read_u16(bs);
	ptr->displayFlags = gf_bs_read_u32(bs);
	ptr->horizontal_justification = gf_bs_read_u8(bs);
	ptr->vertical_justification = gf_bs_read_u8(bs);
	ptr->back_color = gpp_read_rgba(bs);
	gpp_read_box(bs, &ptr->default_box);
	gpp_read_style(bs, &ptr->default_style);
	ptr->size -= 18 + GPP_BOX_SIZE + GPP_STYLE_SIZE;

	while (ptr->size) {
		e = gf_isom_parse_box(&a, bs);
		if (e) return e;
		if (ptr->size<a->size) return GF_ISOM_INVALID_FILE;
		ptr->size -= a->size;
		if (a->type==GF_ISOM_BOX_TYPE_FTAB) {
			if (ptr->font_table) gf_isom_box_del((GF_Box *) ptr->font_table);
			ptr->font_table = (GF_FontTableBox *)a;
		} else {
			gf_isom_box_del(a);
		}
	}
	return GF_OK;
}
Beispiel #2
0
GF_Err ListItem_Read(GF_Box *s,GF_BitStream *bs)
{
	GF_Err e;
	u32 sub_type;
	GF_Box *a = NULL;
	GF_ListItemBox *ptr = (GF_ListItemBox *)s;

	/*iTunes way: there's a data atom containing the data*/
	sub_type = gf_bs_peek_bits(bs, 32, 4);
	if (sub_type == GF_ISOM_BOX_TYPE_DATA ) {
		e = gf_isom_parse_box(&a, bs);
		if (e) return e;
		if (ptr->size<a->size) return GF_ISOM_INVALID_FILE;
		ptr->size -= a->size;

		if (a && ptr->data) gf_isom_box_del((GF_Box *) ptr->data);
		ptr->data = (GF_DataBox *)a;
	}
	/*QT way*/
	else {
		ptr->data->type = 0;
		ptr->data->dataSize = gf_bs_read_u16(bs);
		gf_bs_read_u16(bs);
		ptr->data->data = (char *) gf_malloc(sizeof(char)*(ptr->data->dataSize + 1));
		gf_bs_read_data(bs, ptr->data->data, ptr->data->dataSize);
		ptr->data->data[ptr->data->dataSize] = 0;
		ptr->size -= ptr->data->dataSize;
	}
	return GF_OK;
}
Beispiel #3
0
GF_Err ghnt_Read(GF_Box *s, GF_BitStream *bs)
{
	GF_Box *a;
	GF_Err e;
	GF_HintSampleEntryBox *ptr = (GF_HintSampleEntryBox *)s;
	if (ptr == NULL) return GF_BAD_PARAM;

	if (ptr->size < 16) return GF_ISOM_INVALID_FILE;

	gf_bs_read_data(bs, ptr->reserved, 6);
	ptr->dataReferenceIndex = gf_bs_read_u16(bs);
	ptr->HintTrackVersion = gf_bs_read_u16(bs);
	ptr->LastCompatibleVersion = gf_bs_read_u16(bs);
	ptr->MaxPacketSize = gf_bs_read_u32(bs);
	ptr->size -= 16;

	while (ptr->size) {
		e = gf_isom_parse_box(&a, bs);
		if (e) return e;
		e = gf_list_add(ptr->HintDataTable, a);
		if (e) return e;
		ptr->size -= a->size;
	}
	return GF_OK;
}
Beispiel #4
0
GF_Err gf_webvtt_dump_iso_sample(FILE *dump, u32 timescale, GF_ISOSample *iso_sample)
{
	GF_Err e;
	GF_BitStream *bs;

	bs = gf_bs_new(iso_sample->data, iso_sample->dataLength, GF_BITSTREAM_READ);
	while(gf_bs_available(bs))
	{
		GF_Box *box;
		GF_WebVTTTimestamp ts;
		e = gf_isom_parse_box(&box, bs);
		if (e) return e;
		if (box->type == GF_ISOM_BOX_TYPE_VTCU) {
			GF_VTTCueBox *cuebox = (GF_VTTCueBox *)box;
			if (cuebox->id) fprintf(dump, "%s", cuebox->id->string);
			gf_webvtt_timestamp_set(&ts, (iso_sample->DTS * 1000) / timescale);
			gf_webvtt_timestamp_dump(&ts, dump, GF_FALSE);
			fprintf(dump, " --> NEXT");
			if (cuebox->settings) fprintf(dump, " %s", cuebox->settings->string);
			fprintf(dump, "\n");
			if (cuebox->payload) fprintf(dump, "%s", cuebox->payload->string);
			fprintf(dump, "\n");
		} else if (box->type == GF_ISOM_BOX_TYPE_VTTE) {
			gf_webvtt_timestamp_set(&ts, (iso_sample->DTS * 1000) / timescale);
			gf_webvtt_timestamp_dump(&ts, dump, GF_FALSE);
			fprintf(dump, " --> NEXT\n\n");
		} else if (box->type == GF_ISOM_BOX_TYPE_VTTA) {
			fprintf(dump, "%s\n\n", ((GF_StringBox *)box)->string);
		}
		gf_isom_box_del(box);
	}
	gf_bs_del(bs);
	return GF_OK;
}
Beispiel #5
0
GF_List *gf_webvtt_parse_iso_cues(GF_ISOSample *iso_sample, u64 start)
{
    GF_List         *cues;
    GF_WebVTTCue    *cue;
    GF_VTTCueBox    *cuebox;
    GF_BitStream    *bs;
    cues = gf_list_new();
    bs = gf_bs_new(iso_sample->data, iso_sample->dataLength, GF_BITSTREAM_READ);
    while(gf_bs_available(bs))
    {
        GF_Err  e;
        GF_Box  *box;
        e = gf_isom_parse_box(&box, bs);
        if (e) return NULL;
        if (box->type == GF_ISOM_BOX_TYPE_VTCU) {
            cuebox = (GF_VTTCueBox *)box;
            cue   = gf_webvtt_cue_new();
            gf_list_add(cues, cue);
            gf_webvtt_timestamp_set(&cue->start, start);
            if (cuebox->id) {
                gf_webvtt_cue_add_property(cue, WEBVTT_ID, cuebox->id->string, (u32) strlen(cuebox->id->string));
            }
            if (cuebox->settings) {
                gf_webvtt_cue_add_property(cue, WEBVTT_SETTINGS, cuebox->settings->string, (u32) strlen(cuebox->settings->string));
            }
            if (cuebox->payload) {
                gf_webvtt_cue_add_property(cue, WEBVTT_PAYLOAD, cuebox->payload->string, (u32) strlen(cuebox->payload->string));
            }
        }
        gf_isom_box_del(box);
    }
    gf_bs_del(bs);
    return cues;
}
Beispiel #6
0
GF_Err gppv_Read(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_3GPPVisualSampleEntryBox *ptr = (GF_3GPPVisualSampleEntryBox *)s;
	e = gf_isom_video_sample_entry_read((GF_VisualSampleEntryBox *)ptr, bs);
	if (e) return e;
	/*FIXME - check for any other boxes...*/
	e = gf_isom_parse_box((GF_Box **)&ptr->info, bs);
	return e;
}
Beispiel #7
0
GF_Err gppa_Read(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_3GPPAudioSampleEntryBox *ptr = (GF_3GPPAudioSampleEntryBox *)s;
	e = gf_isom_audio_sample_entry_read((GF_AudioSampleEntryBox*)s, bs);
	if (e) return e;
	e = gf_isom_parse_box((GF_Box **)&ptr->info, bs);
	if (e) return e;
	ptr->info->cfg.type = ptr->type;
	return GF_OK;
}
Beispiel #8
0
GF_EXPORT
GF_List *gf_webvtt_parse_cues_from_data(const char *data, u32 dataLength, u64 start)
{
	GF_List         *cues;
	GF_WebVTTCue    *cue;
	GF_VTTCueBox    *cuebox;
	GF_BitStream    *bs;
	char			*pre_text;
	cue = NULL;
	pre_text = NULL;
	cues = gf_list_new();
	bs = gf_bs_new(data, dataLength, GF_BITSTREAM_READ);
	while(gf_bs_available(bs))
	{
		GF_Err  e;
		GF_Box  *box;
		e = gf_isom_parse_box(&box, bs);
		if (e) return NULL;
		if (box->type == GF_ISOM_BOX_TYPE_VTCU) {
			cuebox = (GF_VTTCueBox *)box;
			cue   = gf_webvtt_cue_new();
			if (pre_text) {
				gf_webvtt_cue_add_property(cue, WEBVTT_PRECUE_TEXT, pre_text, (u32) strlen(pre_text));
				gf_free(pre_text);
				pre_text = NULL;
			}
			gf_list_add(cues, cue);
			gf_webvtt_timestamp_set(&cue->start, start);
			if (cuebox->id) {
				gf_webvtt_cue_add_property(cue, WEBVTT_ID, cuebox->id->string, (u32) strlen(cuebox->id->string));
			}
			if (cuebox->settings) {
				gf_webvtt_cue_add_property(cue, WEBVTT_SETTINGS, cuebox->settings->string, (u32) strlen(cuebox->settings->string));
			}
			if (cuebox->payload) {
				gf_webvtt_cue_add_property(cue, WEBVTT_PAYLOAD, cuebox->payload->string, (u32) strlen(cuebox->payload->string));
			}
		} else if (box->type == GF_ISOM_BOX_TYPE_VTTA) {
			GF_StringBox *sbox = (GF_StringBox *)box;
			if (cue) {
				gf_webvtt_cue_add_property(cue, WEBVTT_POSTCUE_TEXT, sbox->string, (u32) strlen(sbox->string));
			} else {
				pre_text = gf_strdup(sbox->string);
			}
		}
		gf_isom_box_del(box);
	}
	gf_bs_del(bs);
	return cues;
}
Beispiel #9
0
static void VTT_ReadConfigFromDSI(VTTDec *vttdec, GF_DefaultDescriptor *dsi)
{
	GF_BitStream *bs;
	u32 entry_type;

	bs = gf_bs_new(dsi->data, dsi->dataLength, GF_BITSTREAM_READ);
	entry_type = gf_bs_read_u32(bs);
	if (entry_type == GF_ISOM_BOX_TYPE_WVTT) {
		GF_Box *b;
		gf_isom_parse_box(&b, bs);
		vttdec->config = ((GF_StringBox *)b)->string;
		((GF_StringBox *)b)->string = NULL;
		gf_isom_box_del(b);
	}
	gf_bs_del(bs);
}
Beispiel #10
0
GF_Err gf_webvtt_dump_header_boxed(FILE *dump, const char *data, u32 dataLength, u32 *dumpedLength)
{
	GF_Err e;
	GF_Box *box;
	GF_StringBox *config;
	GF_BitStream *bs;
	*dumpedLength = 0;
	bs = gf_bs_new(data, dataLength, GF_BITSTREAM_READ);
	e = gf_isom_parse_box(&box, bs);
	if (!box || (box->type != GF_ISOM_BOX_TYPE_VTTC)) return GF_BAD_PARAM;
	config = (GF_StringBox *)box;
	if (config->string) {
		fprintf(dump, "%s", config->string);
		*dumpedLength = (u32)strlen(config->string)+1;
	}
	gf_bs_del(bs);
	gf_isom_box_del(box);
	return e;
}
Beispiel #11
0
GF_Err tx3g_Read(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_Box *a;
	GF_Tx3gSampleEntryBox *ptr = (GF_Tx3gSampleEntryBox*)s;

	if (ptr->size < 18 + GPP_BOX_SIZE + GPP_STYLE_SIZE) return GF_ISOM_INVALID_FILE;

	gf_bs_read_data(bs, ptr->reserved, 6);
	ptr->dataReferenceIndex = gf_bs_read_u16(bs);
	ptr->displayFlags = gf_bs_read_u32(bs);
	ptr->horizontal_justification = gf_bs_read_u8(bs);
	ptr->vertical_justification = gf_bs_read_u8(bs);
	ptr->back_color = gpp_read_rgba(bs);
	gpp_read_box(bs, &ptr->default_box);
	gpp_read_style(bs, &ptr->default_style);
	ptr->size -= 18 + GPP_BOX_SIZE + GPP_STYLE_SIZE;

	while (ptr->size) {
		if (ptr->size < 8) {
			/* Sometimes there are void atoms at the end of an atom and they are not parsed correctecly */
			/* So just skip them if we have less than 8 bytes to parse */
			/* "The actual size of an atom cannot be less than 8 bytes" from QTFF specs */
			ptr->size = 0;
			return GF_OK;
		}

		e = gf_isom_parse_box(&a, bs);
		if (e) return e;
		if (ptr->size<a->size) return GF_ISOM_INVALID_FILE;

		ptr->size -= a->size;
		if (a->type==GF_ISOM_BOX_TYPE_FTAB) {
			if (ptr->font_table) gf_isom_box_del((GF_Box *) ptr->font_table);
			ptr->font_table = (GF_FontTableBox *)a;
		} else {
			gf_isom_box_del(a);
		}
	}
	return GF_OK;
}
Beispiel #12
0
GF_Err tx3g_Read(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_Box *a;
	GF_Tx3gSampleEntryBox *ptr = (GF_Tx3gSampleEntryBox*)s;

	if (ptr->size < 18 + GPP_BOX_SIZE + GPP_STYLE_SIZE) return GF_ISOM_INVALID_FILE;

	gf_bs_read_data(bs, ptr->reserved, 6);
	ptr->dataReferenceIndex = gf_bs_read_u16(bs);
	ptr->displayFlags = gf_bs_read_u32(bs);
	ptr->horizontal_justification = gf_bs_read_u8(bs);
	ptr->vertical_justification = gf_bs_read_u8(bs);
	ptr->back_color = gpp_read_rgba(bs);
	gpp_read_box(bs, &ptr->default_box);
	gpp_read_style(bs, &ptr->default_style);
	ptr->size -= 18 + GPP_BOX_SIZE + GPP_STYLE_SIZE;

	while (ptr->size >= 8) {
		e = gf_isom_parse_box(&a, bs);
		if (e) return e;
		if (ptr->size<a->size) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Box \"%s\" larger than remaining bytes in tx3g - ignoring box\n", gf_4cc_to_str(a->type)));
			ptr->size = 0;
			gf_isom_box_del(a);
			return GF_OK;
		}

		ptr->size -= a->size;
		if (a->type == GF_ISOM_BOX_TYPE_FTAB) {
			if (ptr->font_table) gf_isom_box_del((GF_Box *)ptr->font_table);
			ptr->font_table = (GF_FontTableBox *)a;
		}
		else {
			e = gf_isom_box_add_default(s, a);
			if (e) return e;
		}
	}
	return GF_OK;
}
Beispiel #13
0
GF_Err ilst_Read(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u32 sub_type;
	GF_Box *a;
	GF_ItemListBox *ptr = (GF_ItemListBox *)s;
	while (ptr->size) {
		/*if no ilst type coded, break*/
		sub_type = gf_bs_peek_bits(bs, 32, 0);
		if (sub_type) {
			e = gf_isom_parse_box(&a, bs);
			if (e) return e;
			if (ptr->size<a->size) return GF_ISOM_INVALID_FILE;
			ptr->size -= a->size;
			gf_list_add(ptr->other_boxes, a);
		} else {
			gf_bs_read_u32(bs);
			ptr->size -= 4;
		}
	}
	return GF_OK;
}
Beispiel #14
0
GF_Err iinf_Read(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_Box *a;
	u32 count;
	GF_ItemInfoBox *ptr = (GF_ItemInfoBox *)s;

	e = gf_isom_full_box_read(s, bs);
	if (e) return e;
	count = gf_bs_read_u16(bs);

	while (count) {
		e = gf_isom_parse_box(&a, bs);
		if (e) return e;
		if (ptr->size<a->size) return GF_ISOM_INVALID_FILE;

		if (a->type == GF_ISOM_BOX_TYPE_INFE)
			gf_list_add(ptr->item_infos, a);
		else
			gf_isom_box_del(a);
		count --;
	}
	return GF_OK;
}
Beispiel #15
0
GF_EXPORT
GF_TextSample *gf_isom_parse_texte_sample(GF_BitStream *bs)
{
	GF_TextSample *s = gf_isom_new_text_sample();
	
	/*empty sample*/
	if (!bs || !gf_bs_available(bs)) return s;

	s->len = gf_bs_read_u16(bs);
	if (s->len) {
		/*2 extra bytes for UTF-16 term char just in case (we don't know if a BOM marker is present or 
		not since this may be a sample carried over RTP*/
		s->text = (char *) gf_malloc(sizeof(char)*(s->len+2) );
		s->text[s->len] = 0; s->text[s->len+1] = 0;
		gf_bs_read_data(bs, s->text, s->len);
	}

	while (gf_bs_available(bs)) {
		GF_Box *a;
		GF_Err e = gf_isom_parse_box(&a, bs);
		if (!e) {
			switch (a->type) {
			case GF_ISOM_BOX_TYPE_STYL:
				if (s->styles) {
					GF_TextStyleBox *st2 = (GF_TextStyleBox *)a;
					if (!s->styles->entry_count) {
						gf_isom_box_del((GF_Box*)s->styles);
						s->styles = st2;
					} else {
						s->styles->styles = (GF_StyleRecord*)gf_realloc(s->styles->styles, sizeof(GF_StyleRecord) * (s->styles->entry_count + st2->entry_count));
						memcpy(&s->styles->styles[s->styles->entry_count], st2->styles, sizeof(GF_StyleRecord) * st2->entry_count);
						s->styles->entry_count += st2->entry_count;
						gf_isom_box_del(a);
					}
				} else {
					s->styles = (GF_TextStyleBox*)a;
				}
				break;
			case GF_ISOM_BOX_TYPE_KROK:
				s->cur_karaoke = (GF_TextKaraokeBox*)a;
			case GF_ISOM_BOX_TYPE_HLIT:
			case GF_ISOM_BOX_TYPE_HREF:
			case GF_ISOM_BOX_TYPE_BLNK:
				gf_list_add(s->others, a);
				break;
			case GF_ISOM_BOX_TYPE_HCLR:
				if (s->highlight_color) gf_isom_box_del(a);
				else s->highlight_color = (GF_TextHighlightColorBox *) a;
				break;
			case GF_ISOM_BOX_TYPE_DLAY:
				if (s->scroll_delay) gf_isom_box_del(a);
				else s->scroll_delay= (GF_TextScrollDelayBox*) a;
				break;
			case GF_ISOM_BOX_TYPE_TBOX:
				if (s->box) gf_isom_box_del(a);
				else s->box= (GF_TextBoxBox *) a;
				break;
			case GF_ISOM_BOX_TYPE_TWRP:
				if (s->wrap) gf_isom_box_del(a);
				else s->wrap= (GF_TextWrapBox*) a;
				break;
			default:
				gf_isom_box_del(a);
				break;
			}
		}
	}
	return s;
}
Beispiel #16
0
GF_Err gf_isom_hint_rtp_read(GF_RTPPacket *ptr, GF_BitStream *bs)
{
	GF_Err e;
	u8 hasTLV, type;
	u16 i, count;
	u32 TLVsize, tempSize;
	GF_GenericDTE *dte;
	GF_Box *a;

	ptr->relativeTransTime = gf_bs_read_u32(bs);
	//RTP Header
	//1- reserved fields
	gf_bs_read_int(bs, 2);
	ptr->P_bit = gf_bs_read_int(bs, 1);
	ptr->X_bit = gf_bs_read_int(bs, 1);
	gf_bs_read_int(bs, 4);
	ptr->M_bit = gf_bs_read_int(bs, 1);
	ptr->payloadType = gf_bs_read_int(bs, 7);

	ptr->SequenceNumber = gf_bs_read_u16(bs);
	gf_bs_read_int(bs, 13);
	hasTLV = gf_bs_read_int(bs, 1);
	ptr->B_bit = gf_bs_read_int(bs, 1);
	ptr->R_bit = gf_bs_read_int(bs, 1);
	count = gf_bs_read_u16(bs);

	//read the TLV
	if (hasTLV) {
		tempSize = 4;	//TLVsize includes its field length
		TLVsize = gf_bs_read_u32(bs);
		while (tempSize < TLVsize) {
			e = gf_isom_parse_box(&a, bs);
			if (e) return e;
			gf_list_add(ptr->TLV, a);
			tempSize += (u32) a->size;
		}
		if (tempSize != TLVsize) return GF_ISOM_INVALID_FILE;
	}

	//read the DTEs
	for (i=0; i<count; i++) {
		Bool add_it = 0;
		type = gf_bs_read_u8(bs);
		dte = NewDTE(type);
		e = ReadDTE(dte, bs);
		if (e) return e;
		/*little opt, remove empty dte*/
		switch (type) {
		case 1:
			if ( ((GF_ImmediateDTE *)dte)->dataLength) add_it = 1;
			break;
		case 2:
			if ( ((GF_SampleDTE *)dte)->dataLength) add_it = 1;
			break;
		case 3:
			if ( ((GF_StreamDescDTE *)dte)->dataLength) add_it = 1;
			break;
		}
		if (add_it)
			gf_list_add(ptr->DataTable, dte);
		else
			DelDTE(dte);
	}
	return GF_OK;
}
Beispiel #17
0
GF_EXPORT
GF_Err gf_odf_get_text_config(GF_DefaultDescriptor *dsi, u8 oti, GF_TextConfig *cfg)
{
	u32 i, j;
	Bool has_alt_format, has_sd;
	GF_Err e;
	GF_BitStream *bs;
	if (!dsi || !dsi->data || !dsi->dataLength || !cfg) return GF_BAD_PARAM;
	if (oti != 0x08) return GF_NOT_SUPPORTED;

	/*reset*/
	ResetTextConfig(cfg);
	bs = gf_bs_new(dsi->data, dsi->dataLength, GF_BITSTREAM_READ);

	e = GF_OK;
	cfg->Base3GPPFormat = gf_bs_read_int(bs, 8);
	cfg->MPEGExtendedFormat = gf_bs_read_int(bs, 8);
	cfg->profileLevel = gf_bs_read_int(bs, 8);
	cfg->timescale = gf_bs_read_int(bs, 24);
	has_alt_format = gf_bs_read_int(bs, 1);
	cfg->sampleDescriptionFlags = gf_bs_read_int(bs, 2);
	has_sd = gf_bs_read_int(bs, 1);
	cfg->has_vid_info = gf_bs_read_int(bs, 1);
	gf_bs_read_int(bs, 3);
	cfg->layer = gf_bs_read_int(bs, 8);
	cfg->text_width = gf_bs_read_int(bs, 16);
	cfg->text_height = gf_bs_read_int(bs, 16);
	if (has_alt_format) {
		cfg->nb_compatible_formats = gf_bs_read_int(bs, 8);
		for (i=0; i<cfg->nb_compatible_formats; i++) cfg->compatible_formats[i] = gf_bs_read_int(bs, 8);
	}
#ifndef GPAC_DISABLE_ISOM
	if (has_sd) {
		u8 sample_index;
		GF_TextSampleDescriptor *txdesc;
		GF_Tx3gSampleEntryBox *a;
		s64 avail;
		u32 nb_desc = gf_bs_read_int(bs, 8);

		/*parse TTU[5]s*/
		avail = (s64) gf_bs_available(bs);
		for (i=0; i<nb_desc; i++) {
			sample_index = gf_bs_read_int(bs, 8);
			avail -= 1;
			e = gf_isom_parse_box((GF_Box **) &a, bs);
			if (e) goto exit;
			avail -= (s32) a->size;

			if (avail<0) {
				e = GF_NON_COMPLIANT_BITSTREAM;
				goto exit;
			}
			txdesc = (GF_TextSampleDescriptor *)gf_malloc(sizeof(GF_TextSampleDescriptor));
			txdesc->sample_index = sample_index;
			txdesc->displayFlags = a->displayFlags;
			txdesc->back_color = a->back_color;
			txdesc->default_pos = a->default_box;
			txdesc->default_style = a->default_style;
			txdesc->vert_justif = a->vertical_justification;
			txdesc->horiz_justif = a->horizontal_justification;
			txdesc->font_count = a->font_table ? a->font_table->entry_count : 0;
			if (txdesc->font_count) {
				txdesc->fonts = (GF_FontRecord*)gf_malloc(sizeof(GF_FontRecord)*txdesc->font_count);
				for (j=0; j<txdesc->font_count; j++) {
					txdesc->fonts[j].fontID = a->font_table->fonts[j].fontID;
					txdesc->fonts[j].fontName = a->font_table->fonts[j].fontName ? gf_strdup(a->font_table->fonts[j].fontName) : NULL;
				}
			}
			gf_list_add(cfg->sample_descriptions, txdesc);
			gf_isom_box_del((GF_Box *)a);
		}
	}
#endif

	if (cfg->has_vid_info) {
		cfg->video_width = gf_bs_read_int(bs, 16);
		cfg->video_height = gf_bs_read_int(bs, 16);
		cfg->horiz_offset = gf_bs_read_int(bs, 16);
		cfg->vert_offset = gf_bs_read_int(bs, 16);
	}
	
exit:
	gf_bs_del(bs);
	if (e) ResetTextConfig(cfg);
	return e;
}