//Create the movie for WRITE only GF_ISOFile *gf_isom_create_movie(const char *fileName, u32 OpenMode, const char *tmp_dir) { GF_Err e; GF_ISOFile *mov = gf_isom_new_movie(); if (!mov) return NULL; mov->openMode = OpenMode; //then set up our movie //in WRITE, the input dataMap is ALWAYS NULL mov->movieFileMap = NULL; //but we have the edit one if (OpenMode == GF_ISOM_OPEN_WRITE) { //THIS IS NOT A TEMP FILE, WRITE mode is used for "live capture" //this file will be the final file... mov->fileName = gf_strdup(fileName); e = gf_isom_datamap_new(fileName, NULL, GF_ISOM_DATA_MAP_WRITE, & mov->editFileMap); if (e) goto err_exit; /*brand is set to ISOM by default - it may be touched until sample data is added to track*/ gf_isom_set_brand_info( (GF_ISOFile *) mov, GF_ISOM_BRAND_ISOM, 1); } else { //we are in EDIT mode but we are creating the file -> temp file mov->finalName = (char*)gf_malloc(strlen(fileName) + 1); strcpy(mov->finalName, fileName); e = gf_isom_datamap_new("mp4_tmp_edit", tmp_dir, GF_ISOM_DATA_MAP_WRITE, & mov->editFileMap); if (e) { gf_isom_set_last_error(NULL, e); gf_isom_delete_movie(mov); return NULL; } //brand is set to ISOM by default gf_isom_set_brand_info( (GF_ISOFile *) mov, GF_ISOM_BRAND_ISOM, 1); } //create an MDAT mov->mdat = (GF_MediaDataBox *) mdat_New(); gf_list_add(mov->TopBoxes, mov->mdat); //default behaviour is capture mode, no interleaving (eg, no rewrite of mdat) mov->storageMode = GF_ISOM_STORE_FLAT; return mov; err_exit: gf_isom_set_last_error(NULL, e); if (mov) gf_isom_delete_movie(mov); return NULL; }
GF_Err gf_isom_add_meta_item_extended(GF_ISOFile *file, Bool root_meta, u32 track_num, Bool self_reference, char *resource_path, const char *item_name, u32 item_id, const char *mime_type, const char *content_encoding, GF_ImageItemProperties *image_props, const char *URL, const char *URN, char *data, u32 data_len) { GF_Err e; GF_ItemLocationEntry *location_entry; GF_ItemInfoEntryBox *infe; GF_MetaBox *meta; u32 lastItemID = 0; if (!self_reference && !item_name && !resource_path) return GF_BAD_PARAM; e = CanAccessMovie(file, GF_ISOM_OPEN_WRITE); if (e) return e; meta = gf_isom_get_meta(file, root_meta, track_num); if (!meta) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Trying to add item, but missing meta box")); return GF_BAD_PARAM; } e = FlushCaptureMode(file); if (e) return e; /*check file exists */ if (!URN && !URL && !self_reference && !data) { FILE *src = gf_fopen(resource_path, "rb"); if (!src) return GF_URL_ERROR; gf_fclose(src); } if (meta->item_infos) { u32 i; u32 item_count = gf_list_count(meta->item_infos->item_infos); for (i = 0; i < item_count; i++) { GF_ItemInfoEntryBox *e= (GF_ItemInfoEntryBox *)gf_list_get(meta->item_infos->item_infos, i); if (e->item_ID > lastItemID) lastItemID = e->item_ID; if (item_id == e->item_ID) { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[IsoMedia] Item with id %d already exists, ignoring\n", item_id)); item_id = 0; } } } infe = (GF_ItemInfoEntryBox *)infe_New(); if (item_id) { infe->item_ID = item_id; } else { infe->item_ID = ++lastItemID; } /*get relative name*/ if (item_name) { infe->item_name = gf_strdup(item_name); } else if (resource_path) { if (strrchr(resource_path, GF_PATH_SEPARATOR)) { infe->item_name = gf_strdup(strrchr(resource_path, GF_PATH_SEPARATOR) + 1); } else { infe->item_name = gf_strdup(resource_path); } } if (mime_type) { infe->content_type = gf_strdup(mime_type); } else { infe->content_type = gf_strdup("application/octet-stream"); } if (content_encoding) infe->content_encoding = gf_strdup(content_encoding); /*Creation of the ItemLocation */ location_entry = (GF_ItemLocationEntry*)gf_malloc(sizeof(GF_ItemLocationEntry)); if (!location_entry) { gf_isom_box_del((GF_Box *)infe); return GF_OUT_OF_MEM; } memset(location_entry, 0, sizeof(GF_ItemLocationEntry)); location_entry->extent_entries = gf_list_new(); /*Creates an mdat if it does not exist*/ if (!file->mdat) { file->mdat = (GF_MediaDataBox *)mdat_New(); gf_list_add(file->TopBoxes, file->mdat); } /*Creation an ItemLocation Box if it does not exist*/ if (!meta->item_locations) meta->item_locations = (GF_ItemLocationBox *)iloc_New(); gf_list_add(meta->item_locations->location_entries, location_entry); location_entry->item_ID = infe->item_ID; if (!meta->item_infos) meta->item_infos = (GF_ItemInfoBox *) iinf_New(); e = gf_list_add(meta->item_infos->item_infos, infe); if (e) return e; if (image_props) { meta_process_image_properties(meta, infe->item_ID, image_props); } /*0: the current file*/ location_entry->data_reference_index = 0; if (self_reference) { GF_ItemExtentEntry *entry; GF_SAFEALLOC(entry, GF_ItemExtentEntry); gf_list_add(location_entry->extent_entries, entry); if (!infe->item_name) infe->item_name = gf_strdup(""); return GF_OK; } /*file not copied, just referenced*/ if (URL || URN) { u32 dataRefIndex; if (!meta->file_locations) meta->file_locations = (GF_DataInformationBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_DINF); if (!meta->file_locations->dref) meta->file_locations->dref = (GF_DataReferenceBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_DREF); e = Media_FindDataRef(meta->file_locations->dref, (char *) URL, (char *) URN, &dataRefIndex); if (e) return e; if (!dataRefIndex) { e = Media_CreateDataRef(meta->file_locations->dref, (char *) URL, (char *) URN, &dataRefIndex); if (e) return e; } location_entry->data_reference_index = dataRefIndex; } /*capture mode, write to disk*/ if ((file->openMode == GF_ISOM_OPEN_WRITE) && !location_entry->data_reference_index) { FILE *src; GF_ItemExtentEntry *entry; GF_SAFEALLOC(entry, GF_ItemExtentEntry); location_entry->base_offset = gf_bs_get_position(file->editFileMap->bs); /*update base offset size*/ if (location_entry->base_offset>0xFFFFFFFF) meta->item_locations->base_offset_size = 8; else if (location_entry->base_offset && !meta->item_locations->base_offset_size) meta->item_locations->base_offset_size = 4; entry->extent_length = 0; entry->extent_offset = 0; gf_list_add(location_entry->extent_entries, entry); if (data) { gf_bs_write_data(file->editFileMap->bs, data, data_len); /*update length size*/ if (entry->extent_length>0xFFFFFFFF) meta->item_locations->length_size = 8; else if (entry->extent_length && !meta->item_locations->length_size) meta->item_locations->length_size = 4; } else if (resource_path) { src = gf_fopen(resource_path, "rb"); if (src) { char cache_data[4096]; u64 remain; gf_fseek(src, 0, SEEK_END); entry->extent_length = gf_ftell(src); gf_fseek(src, 0, SEEK_SET); remain = entry->extent_length; while (remain) { u32 size_cache = (remain>4096) ? 4096 : (u32) remain; size_t read = fread(cache_data, 1, size_cache, src); if (read==(size_t)-1) break; gf_bs_write_data(file->editFileMap->bs, cache_data, (u32) read); remain -= (u32) read; } gf_fclose(src); /*update length size*/ if (entry->extent_length>0xFFFFFFFF) meta->item_locations->length_size = 8; else if (entry->extent_length && !meta->item_locations->length_size) meta->item_locations->length_size = 4; } } } /*store full path for info*/ else if (!location_entry->data_reference_index) { if (data) { infe->full_path = (char *)gf_malloc(sizeof(char) * data_len); memcpy(infe->full_path, data, sizeof(char) * data_len); infe->data_len = data_len; } else { infe->full_path = gf_strdup(resource_path); infe->data_len = 0; } } return GF_OK; }