//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_ISOFile *gf_isom_new_movie() { GF_ISOFile *mov = (GF_ISOFile*)gf_malloc(sizeof(GF_ISOFile)); if (mov == NULL) { gf_isom_set_last_error(NULL, GF_OUT_OF_MEM); return NULL; } memset(mov, 0, sizeof(GF_ISOFile)); /*init the boxes*/ mov->TopBoxes = gf_list_new(); if (!mov->TopBoxes) { gf_isom_set_last_error(NULL, GF_OUT_OF_MEM); gf_free(mov); return NULL; } /*default storage mode is flat*/ mov->storageMode = GF_ISOM_STORE_FLAT; return mov; }
//used to check if a TrackID is available u8 RequestTrack(GF_MovieBox *moov, u32 TrackID) { u32 i; GF_TrackBox *trak; i=0; while ((trak = (GF_TrackBox *)gf_list_enum(moov->trackList, &i))) { if (trak->Header->trackID == TrackID) { gf_isom_set_last_error(moov->mov, GF_BAD_PARAM); return 0; } } return 1; }
//Create and parse the movie for READ - EDIT only GF_ISOFile *gf_isom_open_file(const char *fileName, u32 OpenMode, const char *tmp_dir) { GF_Err e; u64 bytes; GF_ISOFile *mov = gf_isom_new_movie(); if (! mov) return NULL; mov->fileName = gf_strdup(fileName); mov->openMode = OpenMode; if ( (OpenMode == GF_ISOM_OPEN_READ) || (OpenMode == GF_ISOM_OPEN_READ_DUMP) ) { //always in read ... mov->openMode = GF_ISOM_OPEN_READ; mov->es_id_default_sync = -1; //for open, we do it the regular way and let the GF_DataMap assign the appropriate struct //this can be FILE (the only one supported...) as well as remote //(HTTP, ...),not suported yet //the bitstream IS PART OF the GF_DataMap //as this is read-only, use a FileMapping. this is the only place where //we use file mapping e = gf_isom_datamap_new(fileName, NULL, GF_ISOM_DATA_MAP_READ_ONLY, &mov->movieFileMap); if (e) { gf_isom_set_last_error(NULL, e); gf_isom_delete_movie(mov); return NULL; } #ifndef GPAC_DISABLE_ISOM_FRAGMENTS if (OpenMode == GF_ISOM_OPEN_READ_DUMP) mov->FragmentsFlags |= GF_ISOM_FRAG_READ_DEBUG; #endif } else { #ifdef GPAC_DISABLE_ISOM_WRITE //not allowed for READ_ONLY lib gf_isom_delete_movie(mov); gf_isom_set_last_error(NULL, GF_ISOM_INVALID_MODE); return NULL; #else //set a default output name for edited file mov->finalName = (char*)gf_malloc(strlen(fileName) + 5); if (!mov->finalName) { gf_isom_set_last_error(NULL, GF_OUT_OF_MEM); gf_isom_delete_movie(mov); return NULL; } strcpy(mov->finalName, "out_"); strcat(mov->finalName, fileName); //open the original file with edit tag e = gf_isom_datamap_new(fileName, NULL, GF_ISOM_DATA_MAP_EDIT, &mov->movieFileMap); //if the file doesn't exist, we assume it's wanted and create one from scratch if (e) { gf_isom_set_last_error(NULL, e); gf_isom_delete_movie(mov); return NULL; } //and create a temp fileName for the edit 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; } mov->es_id_default_sync = -1; #endif } //OK, let's parse the movie... mov->LastError = gf_isom_parse_movie_boxes(mov, &bytes, 0); if (mov->LastError) { gf_isom_set_last_error(NULL, mov->LastError); gf_isom_delete_movie(mov); return NULL; } if (OpenMode == GF_ISOM_OPEN_CAT_FRAGMENTS) { gf_isom_datamap_del(mov->movieFileMap); /*reopen the movie file map in cat mode*/ e = gf_isom_datamap_new(fileName, tmp_dir, GF_ISOM_DATA_MAP_CAT, & mov->movieFileMap); } return mov; }