📄 isom_intern.c
字号:
return NULL; } return mov;}u64 gf_isom_get_mp4time(){ u32 calctime, msec; u64 ret; gf_utc_time_since_1970(&calctime, &msec); calctime += GF_ISOM_MAC_TIME_OFFSET; ret = calctime; return ret;}void gf_isom_delete_movie(GF_ISOFile *mov){ //these are our two main files if (mov->movieFileMap) gf_isom_datamap_del(mov->movieFileMap);#ifndef GPAC_READ_ONLY if (mov->editFileMap) { gf_isom_datamap_del(mov->editFileMap); } if (mov->finalName) free(mov->finalName);#endif gf_isom_box_array_del(mov->TopBoxes); if (mov->fileName) free(mov->fileName); free(mov);}GF_TrackBox *gf_isom_get_track_from_id(GF_MovieBox *moov, u32 trackID) { u32 i, count; GF_TrackBox *trak; if (!moov || !trackID) return NULL; count = gf_list_count(moov->trackList); for (i = 0; i<count; i++) { trak = (GF_TrackBox*)gf_list_get(moov->trackList, i); if (trak->Header->trackID == trackID) return trak; } return NULL;}GF_TrackBox *gf_isom_get_track_from_file(GF_ISOFile *movie, u32 trackNumber){ GF_TrackBox *trak; if (!movie) return NULL; trak = gf_isom_get_track(movie->moov, trackNumber); if (!trak) movie->LastError = GF_BAD_PARAM; return trak;}//WARNING: MOVIETIME IS EXPRESSED IN MEDIA TSGF_Err GetMediaTime(GF_TrackBox *trak, u64 movieTime, u64 *MediaTime, s64 *SegmentStartTime, s64 *MediaOffset, u8 *useEdit){ GF_Err e; u32 i; u64 time, lastSampleTime, m_time; s64 mtime; GF_EdtsEntry *ent; Double scale_ts; u32 sampleNumber, prevSampleNumber; u64 firstDTS; GF_SampleTableBox *stbl = trak->Media->information->sampleTable; *useEdit = 1; *MediaTime = 0; //no segment yet... *SegmentStartTime = -1; *MediaOffset = -1; if (!trak->moov->mvhd->timeScale || !trak->Media->mediaHeader->timeScale) { return GF_ISOM_INVALID_FILE; } //no samples... if (!stbl->SampleSize->sampleCount) { lastSampleTime = 0; } else { lastSampleTime = trak->Media->mediaHeader->duration; } //No edits, 1 to 1 mapping if (! trak->editBox || !trak->editBox->editList) { *MediaTime = movieTime; //check this is in our media time line if (*MediaTime > lastSampleTime) *MediaTime = lastSampleTime; *useEdit = 0; return GF_OK; } //browse the edit list and get the time scale_ts = trak->moov->mvhd->timeScale; scale_ts /= trak->Media->mediaHeader->timeScale; scale_ts *= ((s64)movieTime + 1); m_time = (u64) (scale_ts); time = 0; ent = NULL; i=0; while ((ent = (GF_EdtsEntry *)gf_list_enum(trak->editBox->editList->entryList, &i))) { if (time + ent->segmentDuration > m_time) { goto ent_found; } time += ent->segmentDuration; } //we had nothing in the list (strange file but compliant...) //return the 1 to 1 mapped vale of the last media sample if (!ent) { *MediaTime = movieTime; //check this is in our media time line if (*MediaTime > lastSampleTime) *MediaTime = lastSampleTime; *useEdit = 0; return GF_OK; } //request for a bigger time that what we can give: return the last sample (undefined behavior...) *MediaTime = lastSampleTime; return GF_OK;ent_found: //OK, we found our entry, set the SegmentTime *SegmentStartTime = time; //we request an empty list, there's no media here... if (ent->mediaTime < 0) { *MediaTime = 0; return GF_OK; } //we request a dwell edit if (! ent->mediaRate) { *MediaTime = ent->mediaTime; //no media offset *MediaOffset = 0; *useEdit = 2; return GF_OK; } /*WARNING: this can be "-1" when doing searchForward mode (to prevent jumping to next entry)*/ mtime = ent->mediaTime + movieTime - (time * trak->Media->mediaHeader->timeScale / trak->moov->mvhd->timeScale); if (mtime<0) mtime = 0; *MediaTime = (u64) mtime;#if 0 // //Sanity check: is the requested time valid ? This is to cope with wrong EditLists //we have the translated time, but we need to make sure we have a sample at this time ... //we have to find a COMPOSITION time e = findEntryForTime(stbl, (u32) *MediaTime, 1, &sampleNumber, &prevSampleNumber); if (e) return e; //first case: our time is after the last sample DTS (it's a broken editList somehow) //set the media time to the last sample if (!sampleNumber && !prevSampleNumber) { *MediaTime = lastSampleTime; return GF_OK; } //get the appropriated sample if (!sampleNumber) sampleNumber = prevSampleNumber; stbl_GetSampleDTS(stbl->TimeToSample, sampleNumber, &DTS); CTS = 0; if (stbl->CompositionOffset) stbl_GetSampleCTS(stbl->CompositionOffset, sampleNumber, &CTS);#endif //now get the entry sample (the entry time gives the CTS, and we need the DTS e = findEntryForTime(stbl, (u32) ent->mediaTime, 1, &sampleNumber, &prevSampleNumber); if (e) return e; //oops, the mediaTime indicates a sample that is not in our media ! if (!sampleNumber && !prevSampleNumber) { *MediaTime = lastSampleTime; return GF_ISOM_INVALID_FILE; } if (!sampleNumber) sampleNumber = prevSampleNumber; stbl_GetSampleDTS(stbl->TimeToSample, sampleNumber, &firstDTS); //and store the "time offset" of the desired sample in this segment //this is weird, used to rebuild the timeStamp when reading from the track, not the //media ... *MediaOffset = firstDTS; return GF_OK;}GF_Err GetNextMediaTime(GF_TrackBox *trak, u64 movieTime, u64 *OutMovieTime){ u32 i; u64 time; GF_EdtsEntry *ent; *OutMovieTime = 0; if (! trak->editBox || !trak->editBox->editList) return GF_BAD_PARAM; time = 0; ent = NULL; i=0; while ((ent = (GF_EdtsEntry *)gf_list_enum(trak->editBox->editList->entryList, &i))) { if (time * trak->Media->mediaHeader->timeScale >= movieTime * trak->moov->mvhd->timeScale) { /*skip empty edits*/ if (ent->mediaTime >= 0) { *OutMovieTime = time * trak->Media->mediaHeader->timeScale / trak->moov->mvhd->timeScale; if (*OutMovieTime>0) *OutMovieTime -= 1; return GF_OK; } } time += ent->segmentDuration; } //request for a bigger time that what we can give: return the last sample (undefined behavior...) *OutMovieTime = trak->moov->mvhd->duration; return GF_EOS;}GF_Err GetPrevMediaTime(GF_TrackBox *trak, u64 movieTime, u64 *OutMovieTime){ u32 i; u64 time; GF_EdtsEntry *ent; *OutMovieTime = 0; if (! trak->editBox || !trak->editBox->editList) return GF_BAD_PARAM; time = 0; ent = NULL; i=0; while ((ent = (GF_EdtsEntry *)gf_list_enum(trak->editBox->editList->entryList, &i))) { if (ent->mediaTime == -1) { if ( (time + ent->segmentDuration) * trak->Media->mediaHeader->timeScale >= movieTime * trak->moov->mvhd->timeScale) { *OutMovieTime = time * trak->Media->mediaHeader->timeScale / trak->moov->mvhd->timeScale; return GF_OK; } continue; } /*get the first entry whose end is greater than or equal to the desired time*/ time += ent->segmentDuration; if ( time * trak->Media->mediaHeader->timeScale >= movieTime * trak->moov->mvhd->timeScale) { *OutMovieTime = time * trak->Media->mediaHeader->timeScale / trak->moov->mvhd->timeScale; return GF_OK; } } *OutMovieTime = 0; return GF_OK;}#ifndef GPAC_READ_ONLYvoid gf_isom_insert_moov(GF_ISOFile *file){ u64 now; GF_MovieHeaderBox *mvhd; if (file->moov) return; //OK, create our boxes (mvhd, iods, ...) file->moov = (GF_MovieBox *) moov_New(); file->moov->mov = file; //Header SetUp now = gf_isom_get_mp4time(); mvhd = (GF_MovieHeaderBox *) mvhd_New(); mvhd->creationTime = now; mvhd->modificationTime = now; mvhd->nextTrackID = 1; //600 is our default movie TimeScale mvhd->timeScale = 600; file->interleavingTime = mvhd->timeScale; moov_AddBox((GF_Box*)file->moov, (GF_Box *)mvhd); gf_list_add(file->TopBoxes, file->moov);}//Create the movie for WRITE onlyGF_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 = 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*)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_EdtsEntry *CreateEditEntry(u64 EditDuration, u64 MediaTime, u8 EditMode){ GF_EdtsEntry *ent; ent = (GF_EdtsEntry*)malloc(sizeof(GF_EdtsEntry)); if (!ent) return NULL; switch (EditMode) { case GF_ISOM_EDIT_EMPTY: ent->mediaRate = 1; ent->mediaTime = -1; break; case GF_ISOM_EDIT_DWELL: ent->mediaRate = 0; ent->mediaTime = MediaTime; break; default: ent->mediaRate = 1; ent->mediaTime = MediaTime; break; } ent->segmentDuration = EditDuration; return ent;}#endif //GPAC_READ_ONLY
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -