| /* | |
| * GPAC - Multimedia Framework C SDK | |
| * | |
| * Author: Romain Bouqueau, Jean Le Feuvre | |
| * Copyright (c) Romain Bouqueau 2012- Telecom Paris 2019-2022 | |
| * All rights reserved | |
| * | |
| * Note: this development was kindly sponsorized by Vizion'R (http://vizionr.com) | |
| * | |
| * This file is part of GPAC / ISO Media File Format sub-project | |
| * | |
| * GPAC is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU Lesser General Public License as published by | |
| * the Free Software Foundation either version 2, or (at your option) | |
| * any later version. | |
| * | |
| * GPAC is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library see the file COPYING. If not, write to | |
| * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
| * | |
| */ | |
| #include <gpac/internal/isomedia_dev.h> | |
| #ifndef GPAC_DISABLE_ISOM_ADOBE | |
| #ifndef GPAC_DISABLE_ISOM | |
| #ifndef GPAC_DISABLE_ISOM_FRAGMENTS | |
| void abst_box_del(GF_Box *s) | |
| { | |
| GF_AdobeBootstrapInfoBox *ptr = (GF_AdobeBootstrapInfoBox *)s; | |
| if (ptr == NULL) return; | |
| if (ptr->movie_identifier) | |
| gf_free(ptr->movie_identifier); | |
| if (ptr->drm_data) | |
| gf_free(ptr->drm_data); | |
| if (ptr->meta_data) | |
| gf_free(ptr->meta_data); | |
| while (gf_list_count(ptr->server_entry_table)) { | |
| gf_free(gf_list_get(ptr->server_entry_table, 0)); | |
| gf_list_rem(ptr->server_entry_table, 0); | |
| } | |
| gf_list_del(ptr->server_entry_table); | |
| while (gf_list_count(ptr->quality_entry_table)) { | |
| gf_free(gf_list_get(ptr->quality_entry_table, 0)); | |
| gf_list_rem(ptr->quality_entry_table, 0); | |
| } | |
| gf_list_del(ptr->quality_entry_table); | |
| while (gf_list_count(ptr->segment_run_table_entries)) { | |
| gf_isom_box_del((GF_Box *)gf_list_get(ptr->segment_run_table_entries, 0)); | |
| gf_list_rem(ptr->segment_run_table_entries, 0); | |
| } | |
| gf_list_del(ptr->segment_run_table_entries); | |
| while (gf_list_count(ptr->fragment_run_table_entries)) { | |
| gf_isom_box_del((GF_Box *)gf_list_get(ptr->fragment_run_table_entries, 0)); | |
| gf_list_rem(ptr->fragment_run_table_entries, 0); | |
| } | |
| gf_list_del(ptr->fragment_run_table_entries); | |
| gf_free(ptr); | |
| } | |
| GF_Err abst_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_AdobeBootstrapInfoBox *ptr = (GF_AdobeBootstrapInfoBox *)s; | |
| int i; | |
| u32 tmp_strsize; | |
| char *tmp_str; | |
| Bool zfound=GF_FALSE; | |
| GF_Err e = GF_OK; | |
| ISOM_DECREASE_SIZE(ptr, 25) | |
| ptr->bootstrapinfo_version = gf_bs_read_u32(bs); | |
| ptr->profile = gf_bs_read_int(bs, 2); | |
| ptr->live = gf_bs_read_int(bs, 1); | |
| ptr->update = gf_bs_read_int(bs, 1); | |
| ptr->reserved = gf_bs_read_int(bs, 4); | |
| ptr->time_scale = gf_bs_read_u32(bs); | |
| ptr->current_media_time = gf_bs_read_u64(bs); | |
| ptr->smpte_time_code_offset = gf_bs_read_u64(bs); | |
| i=0; | |
| if (ptr->size<8) return GF_ISOM_INVALID_FILE; | |
| tmp_strsize =(u32)ptr->size; | |
| tmp_str = gf_malloc(sizeof(char)*(tmp_strsize+1)); | |
| if (!tmp_str) return GF_OUT_OF_MEM; | |
| memset(tmp_str, 0, sizeof(char)*(tmp_strsize+1) ); | |
| while (tmp_strsize) { | |
| ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1) | |
| tmp_str[i] = gf_bs_read_u8(bs); | |
| tmp_strsize--; | |
| if (!tmp_str[i]) { | |
| zfound = GF_TRUE; | |
| break; | |
| } | |
| i++; | |
| } | |
| if (!zfound) { | |
| e = GF_ISOM_INVALID_FILE; | |
| goto exit; | |
| } | |
| if (i) { | |
| ptr->movie_identifier = gf_strdup(tmp_str); | |
| } | |
| ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1) | |
| ptr->server_entry_count = gf_bs_read_u8(bs); | |
| for (i=0; i<ptr->server_entry_count; i++) { | |
| int j=0; | |
| zfound = GF_FALSE; | |
| tmp_strsize=(u32)ptr->size; | |
| while (tmp_strsize) { | |
| ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1) | |
| tmp_str[j] = gf_bs_read_u8(bs); | |
| tmp_strsize--; | |
| if (!tmp_str[j]) { | |
| zfound = GF_TRUE; | |
| break; | |
| } | |
| j++; | |
| } | |
| if (!zfound) { | |
| e = GF_ISOM_INVALID_FILE; | |
| goto exit; | |
| } | |
| if (j) { | |
| gf_list_add(ptr->server_entry_table, gf_strdup(tmp_str)); | |
| } | |
| } | |
| if (ptr->server_entry_count != gf_list_count(ptr->server_entry_table)) { | |
| e = GF_ISOM_INVALID_FILE; | |
| goto exit; | |
| } | |
| ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1) | |
| ptr->quality_entry_count = gf_bs_read_u8(bs); | |
| for (i=0; i<ptr->quality_entry_count; i++) { | |
| int j=0; | |
| zfound = GF_FALSE; | |
| tmp_strsize=(u32)ptr->size; | |
| while (tmp_strsize) { | |
| ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1) | |
| tmp_str[j] = gf_bs_read_u8(bs); | |
| tmp_strsize--; | |
| if (!tmp_str[j]) { | |
| zfound = GF_TRUE; | |
| break; | |
| } | |
| j++; | |
| } | |
| if (!zfound) { | |
| e = GF_ISOM_INVALID_FILE; | |
| goto exit; | |
| } | |
| if (j) { | |
| gf_list_add(ptr->quality_entry_table, gf_strdup(tmp_str)); | |
| } | |
| } | |
| if (ptr->quality_entry_count != gf_list_count(ptr->quality_entry_table)) { | |
| e = GF_ISOM_INVALID_FILE; | |
| goto exit; | |
| } | |
| i=0; | |
| tmp_strsize=(u32)ptr->size; | |
| zfound = GF_FALSE; | |
| while (tmp_strsize) { | |
| ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1) | |
| tmp_str[i] = gf_bs_read_u8(bs); | |
| tmp_strsize--; | |
| if (!tmp_str[i]) { | |
| zfound = GF_TRUE; | |
| break; | |
| } | |
| i++; | |
| } | |
| if (!zfound) { | |
| e = GF_ISOM_INVALID_FILE; | |
| goto exit; | |
| } | |
| if (i) { | |
| ptr->drm_data = gf_strdup(tmp_str); | |
| } | |
| i=0; | |
| tmp_strsize=(u32)ptr->size; | |
| zfound = GF_FALSE; | |
| while (tmp_strsize) { | |
| ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1) | |
| tmp_str[i] = gf_bs_read_u8(bs); | |
| tmp_strsize--; | |
| if (!tmp_str[i]) { | |
| zfound = GF_TRUE; | |
| break; | |
| } | |
| i++; | |
| } | |
| if (!zfound) { | |
| e = GF_ISOM_INVALID_FILE; | |
| goto exit; | |
| } | |
| if (i) { | |
| ptr->meta_data = gf_strdup(tmp_str); | |
| } | |
| ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1) | |
| ptr->segment_run_table_count = gf_bs_read_u8(bs); | |
| for (i=0; i<ptr->segment_run_table_count; i++) { | |
| GF_AdobeSegmentRunTableBox *asrt = NULL; | |
| e = gf_isom_box_parse_ex((GF_Box **)&asrt, bs, GF_ISOM_BOX_TYPE_ABST, GF_FALSE, ptr->size); | |
| if (e) { | |
| if (asrt) gf_isom_box_del((GF_Box*)asrt); | |
| goto exit; | |
| } | |
| gf_list_add(ptr->segment_run_table_entries, asrt); | |
| ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, asrt->size) | |
| } | |
| if (ptr->segment_run_table_count != gf_list_count(ptr->segment_run_table_entries)) { | |
| e = GF_ISOM_INVALID_FILE; | |
| goto exit; | |
| } | |
| ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, 1) | |
| ptr->fragment_run_table_count = gf_bs_read_u8(bs); | |
| for (i=0; i<ptr->fragment_run_table_count; i++) { | |
| GF_AdobeFragmentRunTableBox *afrt = NULL; | |
| e = gf_isom_box_parse_ex((GF_Box **)&afrt, bs, GF_ISOM_BOX_TYPE_ABST, GF_FALSE, ptr->size); | |
| if (e) { | |
| if (afrt) gf_isom_box_del((GF_Box*)afrt); | |
| goto exit; | |
| } | |
| gf_list_add(ptr->fragment_run_table_entries, afrt); | |
| ISOM_DECREASE_SIZE_GOTO_EXIT(ptr, afrt->size) | |
| } | |
| if (ptr->fragment_run_table_count != gf_list_count(ptr->fragment_run_table_entries)) { | |
| e = GF_ISOM_INVALID_FILE; | |
| goto exit; | |
| } | |
| exit: | |
| gf_free(tmp_str); | |
| return e; | |
| } | |
| GF_Box *abst_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_AdobeBootstrapInfoBox, GF_ISOM_BOX_TYPE_ABST); | |
| tmp->server_entry_table = gf_list_new(); | |
| tmp->quality_entry_table = gf_list_new(); | |
| tmp->segment_run_table_entries = gf_list_new(); | |
| tmp->fragment_run_table_entries = gf_list_new(); | |
| return (GF_Box *)tmp; | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err abst_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_Err e; | |
| unsigned int i; | |
| GF_AdobeBootstrapInfoBox *ptr = (GF_AdobeBootstrapInfoBox *)s; | |
| e = gf_isom_full_box_write(s, bs); | |
| if (e) return e; | |
| gf_bs_write_u32(bs, ptr->bootstrapinfo_version); | |
| gf_bs_write_int(bs, ptr->profile, 2); | |
| gf_bs_write_int(bs, ptr->live, 1); | |
| gf_bs_write_int(bs, ptr->update, 1); | |
| gf_bs_write_int(bs, ptr->reserved, 4); | |
| gf_bs_write_u32(bs, ptr->time_scale); | |
| gf_bs_write_u64(bs, ptr->current_media_time); | |
| gf_bs_write_u64(bs, ptr->smpte_time_code_offset); | |
| if (ptr->movie_identifier) | |
| gf_bs_write_data(bs, ptr->movie_identifier, (u32)strlen(ptr->movie_identifier) + 1); | |
| else | |
| gf_bs_write_u8(bs, 0); | |
| gf_bs_write_u8(bs, ptr->server_entry_count); | |
| for (i=0; i<ptr->server_entry_count; i++) { | |
| char *str = (char*)gf_list_get(ptr->server_entry_table, i); | |
| gf_bs_write_data(bs, str, (u32)strlen(str) + 1); | |
| } | |
| gf_bs_write_u8(bs, ptr->quality_entry_count); | |
| for (i=0; i<ptr->quality_entry_count; i++) { | |
| char *str = (char*)gf_list_get(ptr->quality_entry_table, i); | |
| gf_bs_write_data(bs, str, (u32)strlen(str) + 1); | |
| } | |
| if (ptr->drm_data) | |
| gf_bs_write_data(bs, ptr->drm_data, (u32)strlen(ptr->drm_data) + 1); | |
| else | |
| gf_bs_write_u8(bs, 0); | |
| if (ptr->meta_data) | |
| gf_bs_write_data(bs, ptr->meta_data, (u32)strlen(ptr->meta_data) + 1); | |
| else | |
| gf_bs_write_u8(bs, 0); | |
| gf_bs_write_u8(bs, ptr->segment_run_table_count); | |
| for (i=0; i<ptr->segment_run_table_count; i++) { | |
| e = gf_isom_box_write((GF_Box *)gf_list_get(ptr->segment_run_table_entries, i), bs); | |
| if (e) return e; | |
| } | |
| gf_bs_write_u8(bs, ptr->fragment_run_table_count); | |
| for (i=0; i<ptr->fragment_run_table_count; i++) { | |
| e = gf_isom_box_write((GF_Box *)gf_list_get(ptr->fragment_run_table_entries, i), bs); | |
| if (e) return e; | |
| } | |
| return GF_OK; | |
| } | |
| GF_Err abst_box_size(GF_Box *s) | |
| { | |
| GF_Err e; | |
| u32 i; | |
| GF_AdobeBootstrapInfoBox *ptr = (GF_AdobeBootstrapInfoBox *)s; | |
| s->size += 25 | |
| + (ptr->movie_identifier ? (strlen(ptr->movie_identifier) + 1) : 1) | |
| + 1; | |
| for (i=0; i<ptr->server_entry_count; i++) | |
| s->size += strlen(gf_list_get(ptr->server_entry_table, i)) + 1; | |
| s->size += 1; | |
| for (i=0; i<ptr->quality_entry_count; i++) | |
| s->size += strlen(gf_list_get(ptr->quality_entry_table, i)) + 1; | |
| s->size += (ptr->drm_data ? (strlen(ptr->drm_data) + 1) : 1) | |
| + (ptr->meta_data ? (strlen(ptr->meta_data) + 1) : 1) | |
| + 1; | |
| for (i=0; i<ptr->segment_run_table_count; i++) { | |
| GF_Box *box = (GF_Box *)gf_list_get(ptr->segment_run_table_entries, i); | |
| e = gf_isom_box_size(box); | |
| if (e) return e; | |
| s->size += box->size; | |
| } | |
| s->size += 1; | |
| for (i=0; i<ptr->fragment_run_table_count; i++) { | |
| GF_Box *box = (GF_Box *)gf_list_get(ptr->fragment_run_table_entries, i); | |
| e = gf_isom_box_size(box); | |
| if (e) return e; | |
| s->size += box->size; | |
| } | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| void afra_box_del(GF_Box *s) | |
| { | |
| GF_AdobeFragRandomAccessBox *ptr = (GF_AdobeFragRandomAccessBox *)s; | |
| if (ptr == NULL) return; | |
| while (gf_list_count(ptr->local_access_entries)) { | |
| gf_free(gf_list_get(ptr->local_access_entries, 0)); | |
| gf_list_rem(ptr->local_access_entries, 0); | |
| } | |
| gf_list_del(ptr->local_access_entries); | |
| while (gf_list_count(ptr->global_access_entries)) { | |
| gf_free(gf_list_get(ptr->global_access_entries, 0)); | |
| gf_list_rem(ptr->global_access_entries, 0); | |
| } | |
| gf_list_del(ptr->global_access_entries); | |
| gf_free(ptr); | |
| } | |
| GF_Err afra_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| unsigned int i; | |
| GF_AdobeFragRandomAccessBox *ptr = (GF_AdobeFragRandomAccessBox *)s; | |
| ISOM_DECREASE_SIZE(ptr, 9) | |
| ptr->long_ids = gf_bs_read_int(bs, 1); | |
| ptr->long_offsets = gf_bs_read_int(bs, 1); | |
| ptr->global_entries = gf_bs_read_int(bs, 1); | |
| ptr->reserved = gf_bs_read_int(bs, 5); | |
| ptr->time_scale = gf_bs_read_u32(bs); | |
| ptr->entry_count = gf_bs_read_u32(bs); | |
| if (ptr->size / ( (ptr->long_offsets ? 16 : 12) ) < ptr->entry_count) | |
| return GF_ISOM_INVALID_FILE; | |
| for (i=0; i<ptr->entry_count; i++) { | |
| GF_AfraEntry *ae = gf_malloc(sizeof(GF_AfraEntry)); | |
| if (!ae) return GF_OUT_OF_MEM; | |
| gf_list_add(ptr->local_access_entries, ae); | |
| ISOM_DECREASE_SIZE(ptr, 8) | |
| ae->time = gf_bs_read_u64(bs); | |
| if (ptr->long_offsets) { | |
| ISOM_DECREASE_SIZE(ptr, 8) | |
| ae->offset = gf_bs_read_u64(bs); | |
| } else { | |
| ISOM_DECREASE_SIZE(ptr, 4) | |
| ae->offset = gf_bs_read_u32(bs); | |
| } | |
| } | |
| if (ptr->global_entries) { | |
| ISOM_DECREASE_SIZE(ptr, 4) | |
| ptr->global_entry_count = gf_bs_read_u32(bs); | |
| for (i=0; i<ptr->global_entry_count; i++) { | |
| GF_GlobalAfraEntry *ae = gf_malloc(sizeof(GF_GlobalAfraEntry)); | |
| if (!ae) return GF_OUT_OF_MEM; | |
| gf_list_add(ptr->global_access_entries, ae); | |
| ISOM_DECREASE_SIZE(ptr, 8) | |
| ae->time = gf_bs_read_u64(bs); | |
| if (ptr->long_ids) { | |
| ISOM_DECREASE_SIZE(ptr, 8) | |
| ae->segment = gf_bs_read_u32(bs); | |
| ae->fragment = gf_bs_read_u32(bs); | |
| } else { | |
| ISOM_DECREASE_SIZE(ptr, 4) | |
| ae->segment = gf_bs_read_u16(bs); | |
| ae->fragment = gf_bs_read_u16(bs); | |
| } | |
| if (ptr->long_offsets) { | |
| ISOM_DECREASE_SIZE(ptr, 16) | |
| ae->afra_offset = gf_bs_read_u64(bs); | |
| ae->offset_from_afra = gf_bs_read_u64(bs); | |
| } else { | |
| ISOM_DECREASE_SIZE(ptr, 8) | |
| ae->afra_offset = gf_bs_read_u32(bs); | |
| ae->offset_from_afra = gf_bs_read_u32(bs); | |
| } | |
| } | |
| } | |
| return GF_OK; | |
| } | |
| GF_Box *afra_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_AdobeFragRandomAccessBox, GF_ISOM_BOX_TYPE_AFRA); | |
| tmp->local_access_entries = gf_list_new(); | |
| tmp->global_access_entries = gf_list_new(); | |
| return (GF_Box *)tmp; | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err afra_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_Err e; | |
| unsigned int i; | |
| GF_AdobeFragRandomAccessBox *ptr = (GF_AdobeFragRandomAccessBox *)s; | |
| e = gf_isom_full_box_write(s, bs); | |
| if (e) return e; | |
| gf_bs_write_int(bs, ptr->long_ids, 1); | |
| gf_bs_write_int(bs, ptr->long_offsets, 1); | |
| gf_bs_write_int(bs, ptr->global_entries, 1); | |
| gf_bs_write_int(bs, 0, 5); | |
| gf_bs_write_u32(bs, ptr->time_scale); | |
| gf_bs_write_u32(bs, ptr->entry_count); | |
| for (i=0; i<ptr->entry_count; i++) { | |
| GF_AfraEntry *ae = (GF_AfraEntry *)gf_list_get(ptr->local_access_entries, i); | |
| gf_bs_write_u64(bs, ae->time); | |
| if (ptr->long_offsets) | |
| gf_bs_write_u64(bs, ae->offset); | |
| else | |
| gf_bs_write_u32(bs, (u32)ae->offset); | |
| } | |
| if (ptr->global_entries) { | |
| gf_bs_write_u32(bs, ptr->global_entry_count); | |
| for (i=0; i<ptr->global_entry_count; i++) { | |
| GF_GlobalAfraEntry *gae = (GF_GlobalAfraEntry *)gf_list_get(ptr->global_access_entries, i); | |
| gf_bs_write_u64(bs, gae->time); | |
| if (ptr->long_ids) { | |
| gf_bs_write_u32(bs, gae->segment); | |
| gf_bs_write_u32(bs, gae->fragment); | |
| } else { | |
| gf_bs_write_u16(bs, (u16)gae->segment); | |
| gf_bs_write_u16(bs, (u16)gae->fragment); | |
| } | |
| if (ptr->long_offsets) { | |
| gf_bs_write_u64(bs, gae->afra_offset); | |
| gf_bs_write_u64(bs, gae->offset_from_afra); | |
| } else { | |
| gf_bs_write_u32(bs, (u32)gae->afra_offset); | |
| gf_bs_write_u32(bs, (u32)gae->offset_from_afra); | |
| } | |
| } | |
| } | |
| return GF_OK; | |
| } | |
| GF_Err afra_box_size(GF_Box *s) | |
| { | |
| GF_AdobeFragRandomAccessBox *ptr = (GF_AdobeFragRandomAccessBox *)s; | |
| s->size += 9 | |
| + ptr->entry_count * (ptr->long_offsets ? 16 : 12) | |
| + (ptr->global_entries ? 4 + ptr->global_entry_count * (4 + (ptr->long_offsets ? 16 : 8) + (ptr->long_ids ? 8 : 4)) : 0); | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| void asrt_box_del(GF_Box *s) | |
| { | |
| GF_AdobeSegmentRunTableBox *ptr = (GF_AdobeSegmentRunTableBox *)s; | |
| if (ptr == NULL) return; | |
| while (gf_list_count(ptr->quality_segment_url_modifiers)) { | |
| gf_free(gf_list_get(ptr->quality_segment_url_modifiers, 0)); | |
| gf_list_rem(ptr->quality_segment_url_modifiers, 0); | |
| } | |
| gf_list_del(ptr->quality_segment_url_modifiers); | |
| while (gf_list_count(ptr->segment_run_entry_table)) { | |
| gf_free(gf_list_get(ptr->segment_run_entry_table, 0)); | |
| gf_list_rem(ptr->segment_run_entry_table, 0); | |
| } | |
| gf_list_del(ptr->segment_run_entry_table); | |
| gf_free(ptr); | |
| } | |
| GF_Err asrt_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| unsigned int i; | |
| GF_AdobeSegmentRunTableBox *ptr = (GF_AdobeSegmentRunTableBox *)s; | |
| ISOM_DECREASE_SIZE(ptr, 1) | |
| ptr->quality_entry_count = gf_bs_read_u8(bs); | |
| if (ptr->size < ptr->quality_entry_count) | |
| return GF_ISOM_INVALID_FILE; | |
| for (i=0; i<ptr->quality_entry_count; i++) { | |
| int j=0; | |
| u32 tmp_strsize=(u32)ptr->size; | |
| if (!tmp_strsize) return GF_ISOM_INVALID_FILE; | |
| char *tmp_str = (char*) gf_malloc(tmp_strsize+1); | |
| if (!tmp_str) return GF_OUT_OF_MEM; | |
| gf_list_add(ptr->quality_segment_url_modifiers, tmp_str); | |
| tmp_str[tmp_strsize]=0; | |
| while (tmp_strsize) { | |
| tmp_str[j] = gf_bs_read_u8(bs); | |
| ISOM_DECREASE_SIZE(ptr, 1) | |
| tmp_strsize--; | |
| if (!tmp_str[j]) | |
| break; | |
| j++; | |
| } | |
| } | |
| ISOM_DECREASE_SIZE(ptr, 4) | |
| ptr->segment_run_entry_count = gf_bs_read_u32(bs); | |
| if (ptr->size / 8 < ptr->segment_run_entry_count) | |
| return GF_ISOM_INVALID_FILE; | |
| for (i=0; i<ptr->segment_run_entry_count; i++) { | |
| GF_AdobeSegmentRunEntry *sre = gf_malloc(sizeof(GF_AdobeSegmentRunEntry)); | |
| if (!sre) return GF_OUT_OF_MEM; | |
| gf_list_add(ptr->segment_run_entry_table, sre); | |
| ISOM_DECREASE_SIZE(ptr, 8) | |
| sre->first_segment = gf_bs_read_u32(bs); | |
| sre->fragment_per_segment = gf_bs_read_u32(bs); | |
| } | |
| return GF_OK; | |
| } | |
| GF_Box *asrt_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_AdobeSegmentRunTableBox, GF_ISOM_BOX_TYPE_ASRT); | |
| tmp->quality_segment_url_modifiers = gf_list_new(); | |
| tmp->segment_run_entry_table = gf_list_new(); | |
| return (GF_Box *)tmp; | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err asrt_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_Err e; | |
| unsigned int i; | |
| GF_AdobeSegmentRunTableBox *ptr = (GF_AdobeSegmentRunTableBox *)s; | |
| e = gf_isom_full_box_write(s, bs); | |
| if (e) return e; | |
| gf_bs_write_u8(bs, ptr->quality_entry_count); | |
| for (i=0; i<ptr->quality_entry_count; i++) { | |
| char *str = (char*)gf_list_get(ptr->quality_segment_url_modifiers, i); | |
| gf_bs_write_data(bs, str, (u32)strlen(str) + 1); | |
| } | |
| gf_bs_write_u32(bs, ptr->segment_run_entry_count); | |
| for (i=0; i<ptr->segment_run_entry_count; i++) { | |
| GF_AdobeSegmentRunEntry *sre = (GF_AdobeSegmentRunEntry *)gf_list_get(ptr->segment_run_entry_table, i); | |
| gf_bs_write_u32(bs, sre->first_segment); | |
| gf_bs_write_u32(bs, sre->fragment_per_segment); | |
| } | |
| return GF_OK; | |
| } | |
| GF_Err asrt_box_size(GF_Box *s) | |
| { | |
| int i; | |
| GF_AdobeSegmentRunTableBox *ptr = (GF_AdobeSegmentRunTableBox *)s; | |
| s->size += 5; | |
| for (i=0; i<ptr->quality_entry_count; i++) | |
| s->size += strlen(gf_list_get(ptr->quality_segment_url_modifiers, i)) + 1; | |
| s->size += ptr->segment_run_entry_count * sizeof(GF_AdobeSegmentRunEntry); | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| void afrt_box_del(GF_Box *s) | |
| { | |
| GF_AdobeFragmentRunTableBox *ptr = (GF_AdobeFragmentRunTableBox *)s; | |
| if (ptr == NULL) return; | |
| while (gf_list_count(ptr->quality_segment_url_modifiers)) { | |
| gf_free(gf_list_get(ptr->quality_segment_url_modifiers, 0)); | |
| gf_list_rem(ptr->quality_segment_url_modifiers, 0); | |
| } | |
| gf_list_del(ptr->quality_segment_url_modifiers); | |
| while (gf_list_count(ptr->fragment_run_entry_table)) { | |
| gf_free(gf_list_get(ptr->fragment_run_entry_table, 0)); | |
| gf_list_rem(ptr->fragment_run_entry_table, 0); | |
| } | |
| gf_list_del(ptr->fragment_run_entry_table); | |
| gf_free(ptr); | |
| } | |
| GF_Err afrt_box_read(GF_Box *s, GF_BitStream *bs) | |
| { | |
| unsigned int i; | |
| GF_AdobeFragmentRunTableBox *ptr = (GF_AdobeFragmentRunTableBox *)s; | |
| ISOM_DECREASE_SIZE(ptr, 5) | |
| ptr->timescale = gf_bs_read_u32(bs); | |
| ptr->quality_entry_count = gf_bs_read_u8(bs); | |
| if (ptr->size < ptr->quality_entry_count) | |
| return GF_ISOM_INVALID_FILE; | |
| for (i=0; i<ptr->quality_entry_count; i++) { | |
| int j=0; | |
| u32 tmp_strsize = (u32) ptr->size; | |
| if (!tmp_strsize) return GF_ISOM_INVALID_FILE; | |
| char *tmp_str = (char*) gf_malloc(tmp_strsize+1); | |
| if (!tmp_str) return GF_OUT_OF_MEM; | |
| gf_list_add(ptr->quality_segment_url_modifiers, tmp_str); | |
| tmp_str[tmp_strsize]=0; | |
| while (tmp_strsize) { | |
| tmp_str[j] = gf_bs_read_u8(bs); | |
| ISOM_DECREASE_SIZE(ptr, 1) | |
| tmp_strsize--; | |
| if (!tmp_str[j]) | |
| break; | |
| j++; | |
| } | |
| } | |
| ISOM_DECREASE_SIZE(ptr, 4) | |
| ptr->fragment_run_entry_count = gf_bs_read_u32(bs); | |
| if (ptr->size / 16 < ptr->fragment_run_entry_count) | |
| return GF_ISOM_INVALID_FILE; | |
| for (i=0; i<ptr->fragment_run_entry_count; i++) { | |
| GF_AdobeFragmentRunEntry *fre = gf_malloc(sizeof(GF_AdobeFragmentRunEntry)); | |
| if (!fre) return GF_OUT_OF_MEM; | |
| gf_list_add(ptr->fragment_run_entry_table, fre); | |
| ISOM_DECREASE_SIZE(ptr, 16) | |
| fre->first_fragment = gf_bs_read_u32(bs); | |
| fre->first_fragment_timestamp = gf_bs_read_u64(bs); | |
| fre->fragment_duration = gf_bs_read_u32(bs); | |
| if (!fre->fragment_duration) { | |
| ISOM_DECREASE_SIZE(ptr, 1) | |
| fre->discontinuity_indicator = gf_bs_read_u8(bs); | |
| } | |
| } | |
| return GF_OK; | |
| } | |
| GF_Box *afrt_box_new() | |
| { | |
| ISOM_DECL_BOX_ALLOC(GF_AdobeFragmentRunTableBox, GF_ISOM_BOX_TYPE_AFRT); | |
| tmp->quality_segment_url_modifiers = gf_list_new(); | |
| tmp->fragment_run_entry_table = gf_list_new(); | |
| return (GF_Box *)tmp; | |
| } | |
| #ifndef GPAC_DISABLE_ISOM_WRITE | |
| GF_Err afrt_box_write(GF_Box *s, GF_BitStream *bs) | |
| { | |
| GF_Err e; | |
| unsigned int i; | |
| GF_AdobeFragmentRunTableBox *ptr = (GF_AdobeFragmentRunTableBox *)s; | |
| e = gf_isom_full_box_write(s, bs); | |
| if (e) return e; | |
| gf_bs_write_u32(bs, ptr->timescale); | |
| gf_bs_write_u8(bs, ptr->quality_entry_count); | |
| for (i=0; i<ptr->quality_entry_count; i++) { | |
| char *str = (char*)gf_list_get(ptr->quality_segment_url_modifiers, i); | |
| gf_bs_write_data(bs, str, (u32)strlen(str) + 1); | |
| } | |
| gf_bs_write_u32(bs, ptr->fragment_run_entry_count); | |
| for (i=0; i<ptr->fragment_run_entry_count; i++) { | |
| GF_AdobeFragmentRunEntry *fre = (GF_AdobeFragmentRunEntry *)gf_list_get(ptr->fragment_run_entry_table, i); | |
| gf_bs_write_u32(bs, fre->first_fragment); | |
| gf_bs_write_u64(bs, fre->first_fragment_timestamp); | |
| gf_bs_write_u32(bs, fre->fragment_duration); | |
| if (!fre->fragment_duration) | |
| gf_bs_write_u8(bs, fre->discontinuity_indicator); | |
| } | |
| return GF_OK; | |
| } | |
| GF_Err afrt_box_size(GF_Box *s) | |
| { | |
| u32 i; | |
| GF_AdobeFragmentRunTableBox *ptr = (GF_AdobeFragmentRunTableBox *)s; | |
| s->size += 5; | |
| for (i=0; i<ptr->quality_entry_count; i++) | |
| s->size += strlen(gf_list_get(ptr->quality_segment_url_modifiers, i)) + 1; | |
| s->size += 4; | |
| for (i=0; i<ptr->fragment_run_entry_count; i++) { | |
| GF_AdobeFragmentRunEntry *fre = (GF_AdobeFragmentRunEntry *)gf_list_get(ptr->fragment_run_entry_table, i); | |
| if (fre->fragment_duration) | |
| s->size += 16; | |
| else | |
| s->size += 17; | |
| } | |
| return GF_OK; | |
| } | |
| #endif /*GPAC_DISABLE_ISOM_WRITE*/ | |
| #endif /*GPAC_DISABLE_ISOM_FRAGMENTS*/ | |
| #endif /*GPAC_DISABLE_ISOM*/ | |
| #endif /*GPAC_DISABLE_ISOM_ADOBE*/ |