Skip to content

Commit

Permalink
initial support for imdt and imda for items - cf #2749
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanlf committed Feb 29, 2024
1 parent 69b32ce commit 86d4529
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 17 deletions.
3 changes: 3 additions & 0 deletions include/gpac/internal/isomedia_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ enum
GF_ISOM_BOX_TYPE_MDAT = GF_4CC( 'm', 'd', 'a', 't' ),
GF_ISOM_BOX_TYPE_IDAT = GF_4CC( 'i', 'd', 'a', 't' ),
GF_ISOM_BOX_TYPE_IMDA = GF_4CC( 'i', 'm', 'd', 'a' ),
GF_ISOM_BOX_TYPE_IMDT = GF_4CC( 'i', 'm', 'd', 't' ),
GF_ISOM_BOX_TYPE_MDHD = GF_4CC( 'm', 'd', 'h', 'd' ),
GF_ISOM_BOX_TYPE_MINF = GF_4CC( 'm', 'i', 'n', 'f' ),
GF_ISOM_BOX_TYPE_MOOV = GF_4CC( 'm', 'o', 'o', 'v' ),
Expand Down Expand Up @@ -738,6 +739,7 @@ typedef struct
u8 *data;

u32 imda_id;
//0: regular mdat, 1: imda, 2: imda with items refering to it (edit/write mode)
u8 is_imda;
} GF_MediaDataBox;

Expand Down Expand Up @@ -1134,6 +1136,7 @@ typedef struct
{
GF_ISOM_FULL_BOX
GF_ISOM_DATAENTRY_FIELDS
u32 imda_ref_id;
} GF_DataEntryURLBox;

typedef struct
Expand Down
17 changes: 17 additions & 0 deletions src/isomedia/box_code_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,13 @@ GF_Err url_box_read(GF_Box *s, GF_BitStream *bs)
{
GF_DataEntryURLBox *ptr = (GF_DataEntryURLBox *)s;

//imdt case
if (ptr->type == GF_ISOM_BOX_TYPE_IMDT) {
ISOM_DECREASE_SIZE(ptr, 4);
ptr->imda_ref_id = gf_bs_read_u32(bs);
return GF_OK;
}

if (ptr->size) {
u32 location_size = (u32) ptr->size;
if (location_size < 1) {
Expand Down Expand Up @@ -629,6 +636,11 @@ GF_Err url_box_write(GF_Box *s, GF_BitStream *bs)

e = gf_isom_full_box_write(s, bs);
if (e) return e;
//imdt case
if (ptr->type == GF_ISOM_BOX_TYPE_IMDT) {
gf_bs_write_u32(bs, ptr->imda_ref_id);
return GF_OK;
}
//the flag set indicates we have a string (WE HAVE TO for URLs)
if ( !(ptr->flags & 1)) {
if (ptr->location) {
Expand All @@ -642,6 +654,11 @@ GF_Err url_box_size(GF_Box *s)
{
GF_DataEntryURLBox *ptr = (GF_DataEntryURLBox *)s;

//imdt case
if (ptr->type == GF_ISOM_BOX_TYPE_IMDT) {
ptr->size+=4;
return GF_OK;
}
if ( !(ptr->flags & 1)) {
if (ptr->location) ptr->size += 1 + strlen(ptr->location);
}
Expand Down
13 changes: 7 additions & 6 deletions src/isomedia/box_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,11 +367,12 @@ GF_Err dinf_box_dump(GF_Box *a, FILE * trace)

GF_Err url_box_dump(GF_Box *a, FILE * trace)
{
GF_DataEntryURLBox *p;

p = (GF_DataEntryURLBox *)a;
gf_isom_box_dump_start(a, "URLDataEntryBox", trace);
if (p->location) {
GF_DataEntryURLBox *p = (GF_DataEntryURLBox *)a;
const char *name = (p->type==GF_ISOM_BOX_TYPE_IMDT) ? "DataEntryImdaBox" : "URLDataEntryBox";
gf_isom_box_dump_start(a, name, trace);
if (p->type==GF_ISOM_BOX_TYPE_IMDT) {
gf_fprintf(trace, " imda_ID=\"%u\">\n", p->imda_ref_id);
} else if (p->location) {
gf_fprintf(trace, " URL=\"%s\">\n", p->location);
} else {
gf_fprintf(trace, ">\n");
Expand All @@ -383,7 +384,7 @@ GF_Err url_box_dump(GF_Box *a, FILE * trace)
}
}
}
gf_isom_box_dump_done("URLDataEntryBox", a, trace);
gf_isom_box_dump_done(name, a, trace);
return GF_OK;
}

Expand Down
3 changes: 2 additions & 1 deletion src/isomedia/box_funcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* GPAC - Multimedia Framework C SDK
*
* Authors: Jean Le Feuvre
* Copyright (c) Telecom ParisTech 2000-2023
* Copyright (c) Telecom ParisTech 2000-2024
* All rights reserved
*
* This file is part of GPAC / ISO Media File Format sub-project
Expand Down Expand Up @@ -1145,6 +1145,7 @@ static struct box_registry_entry {
BOX_DEFINE_CHILD( GF_ISOM_BOX_TYPE_DINF, dinf, "minf meta"),
FBOX_DEFINE_FLAGS( GF_ISOM_BOX_TYPE_URL, url, "dref", 0, 1),
FBOX_DEFINE_FLAGS( GF_ISOM_BOX_TYPE_URN, urn, "dref", 0, 1),
FBOX_DEFINE_FLAGS( GF_ISOM_BOX_TYPE_IMDT, url, "dref", 0, 0),
FBOX_DEFINE( GF_ISOM_BOX_TYPE_CPRT, cprt, "udta", 0),
FBOX_DEFINE( GF_ISOM_BOX_TYPE_KIND, kind, "udta", 0),
FBOX_DEFINE( GF_ISOM_BOX_TYPE_HDLR, hdlr, "mdia meta minf", 0), //minf container is OK in QT ...
Expand Down
7 changes: 6 additions & 1 deletion src/isomedia/isom_intern.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* GPAC - Multimedia Framework C SDK
*
* Authors: Jean Le Feuvre
* Copyright (c) Telecom ParisTech 2000-2023
* Copyright (c) Telecom ParisTech 2000-2024
* All rights reserved
*
* This file is part of GPAC / ISO Media File Format sub-project
Expand Down Expand Up @@ -527,6 +527,11 @@ static GF_Err gf_isom_parse_movie_boxes_internal(GF_ISOFile *mov, u32 *boxType,
}
}
}
//keep all imda boxes for later rewrite
else if (((GF_MediaDataBox *)a)->is_imda) {
e = gf_list_add(mov->TopBoxes, a);
if (e) return e;
}
/*if we don't have any MDAT yet, create one (edit-write mode)
We only work with one mdat, but we're puting it at the place
of the first mdat found when opening a file for editing*/
Expand Down
46 changes: 41 additions & 5 deletions src/isomedia/isom_store.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* GPAC - Multimedia Framework C SDK
*
* Authors: Jean Le Feuvre
* Copyright (c) Telecom ParisTech 2000-2023
* Copyright (c) Telecom ParisTech 2000-2024
* All rights reserved
*
* This file is part of GPAC / ISO Media File Format sub-project
Expand Down Expand Up @@ -979,10 +979,22 @@ GF_Err DoWriteMeta(GF_ISOFile *file, GF_MetaBox *meta, GF_BitStream *bs, Bool Em
if (!entry) return GF_OUT_OF_MEM;
gf_list_add(iloc->extent_entries, entry);
}
entry = (GF_ItemExtentEntry *)gf_list_get(iloc->extent_entries, 0);
entry->extent_offset = 0;
/*0 means full length of referenced file*/
entry->extent_length = 0;
//if we use imdt, do NOT reset the extent length
GF_Box *url = gf_list_get(meta->file_locations->dref->child_boxes, iloc->data_reference_index-1);
if (!url || (url->type != GF_ISOM_BOX_TYPE_IMDT)) {
entry = (GF_ItemExtentEntry *)gf_list_get(iloc->extent_entries, 0);
entry->extent_offset = 0;
/*0 means full length of referenced file*/
entry->extent_length = 0;
} else {
u32 idx, icount = gf_list_count(file->TopBoxes);
for (idx=0; idx<icount; idx++) {
GF_MediaDataBox *mdat = (GF_MediaDataBox *)gf_list_get(file->TopBoxes, idx);
if (mdat->type!=GF_ISOM_BOX_TYPE_MDAT) continue;
if (!mdat->is_imda) continue;
mdat->is_imda = 2; //mark as used
}
}
}
}

Expand Down Expand Up @@ -2710,6 +2722,30 @@ GF_Err WriteToFile(GF_ISOFile *movie, Bool for_fragments)
e = WriteInplace(&mw, bs);
}

//rewrite all imda boxes
u32 i, count = gf_list_count(movie->TopBoxes);
for (i=0; i<count; i++) {
GF_MediaDataBox *mdat = (GF_MediaDataBox *)gf_list_get(movie->TopBoxes, i);
if (mdat->type!=GF_ISOM_BOX_TYPE_MDAT) continue;
//not an imda or not used by any item
//we could further optimize and do a partial purge of imda content
if (mdat->is_imda != 2) continue;

u64 offset = mdat->bsOffset-12;
u32 size = mdat->dataSize+12;
u64 orig_pos = gf_bs_get_position(movie->movieFileMap->bs);
gf_bs_seek(movie->movieFileMap->bs, offset);
while (size) {
u8 buf[2048];
u32 read = (size>2048) ? 2048 : size;
gf_bs_read_data(movie->movieFileMap->bs, buf, read);
gf_bs_write_data(bs, buf, read);
size -= read;
}
gf_bs_seek(movie->movieFileMap->bs, orig_pos);
}


gf_bs_del(bs);
if (!is_stdout)
gf_fclose(stream);
Expand Down
34 changes: 30 additions & 4 deletions src/isomedia/meta.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,20 +287,46 @@ static GF_Err gf_isom_extract_meta_item_intern(GF_ISOFile *file, Bool root_meta,
return GF_BAD_PARAM;
}
}
else if (location_entry->construction_method == 2) {
GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[IsoMedia] Item %d use from-item construction method, not supported - patch welcome\n", item_num));
return GF_NOT_SUPPORTED;
}
/* when construction_method==1, data_reference_index is ignored */
/*FIXME*/
else if (location_entry->data_reference_index) {
char *item_url = NULL, *item_urn = NULL;
GF_Box *a = (GF_Box *)gf_list_get(meta->file_locations->dref->child_boxes, location_entry->data_reference_index-1);
GF_FullBox *a = (GF_FullBox *)gf_list_get(meta->file_locations->dref->child_boxes, location_entry->data_reference_index-1);
if (!a) return GF_ISOM_INVALID_FILE;
if (a->type==GF_ISOM_BOX_TYPE_URL) {
item_url = ((GF_DataEntryURLBox*)a)->location;
if (!(a->flags & 1)) {
item_url = ((GF_DataEntryURLBox*)a)->location;
}
} else if (a->type==GF_ISOM_BOX_TYPE_URN) {
item_url = ((GF_DataEntryURNBox*)a)->location;
item_urn = ((GF_DataEntryURNBox*)a)->nameURN;
}
GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[IsoMedia] Item already outside the ISO file at URL: %s, URN: %s\n", (item_url?item_url:"N/A"), (item_urn?item_urn:"N/A") ));
return GF_OK;
if (item_url || item_urn) {
GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[IsoMedia] Item already outside the ISO file at URL: %s, URN: %s\n", (item_url?item_url:"N/A"), (item_urn?item_urn:"N/A") ));
return GF_OK;
}
if (a->type==GF_ISOM_BOX_TYPE_IMDT) {
Bool found = GF_FALSE;
u32 imda_id = ((GF_DataEntryURLBox*)a)->imda_ref_id;
count = gf_list_count(file->TopBoxes);
for (i=0; i<count; i++) {
GF_MediaDataBox *imda = (GF_MediaDataBox *)gf_list_get(file->TopBoxes, i);
if (imda->type != GF_ISOM_BOX_TYPE_MDAT) continue;
if (!imda->is_imda) continue;
if (imda->imda_id != imda_id) continue;
idat_offset = imda->bsOffset;
found = GF_TRUE;
break;
}
if (!found) {
GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[IsoMedia] Item %d references an inexistant imda box of id %u\n", item_num, imda_id));
return GF_BAD_PARAM;
}
}
}

/*don't extract self-reference item*/
Expand Down

0 comments on commit 86d4529

Please sign in to comment.