📄 isom_read.c
字号:
if (!IsMP4Description(entry->type)) return 0; return entry->type;}//Get the HandlerDescription name. GF_EXPORTGF_Err gf_isom_get_handler_name(GF_ISOFile *the_file, u32 trackNumber, const char **outName){ GF_TrackBox *trak; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !outName) return GF_BAD_PARAM; *outName = trak->Media->handler->nameUTF8; return GF_OK;}//Check the DataReferences of this trackGF_EXPORTGF_Err gf_isom_check_data_reference(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex){ GF_Err e; u32 drefIndex; GF_TrackBox *trak; if (!StreamDescriptionIndex || !trackNumber) return GF_BAD_PARAM; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; e = Media_GetSampleDesc(trak->Media, StreamDescriptionIndex , NULL, &drefIndex); if (e) return e; if (!drefIndex) return GF_BAD_PARAM; return Media_CheckDataEntry(trak->Media, drefIndex);}//get the location of the data. If URL && URN are NULL, the data is in this fileGF_EXPORTGF_Err gf_isom_get_data_reference(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex, const char **outURL, const char **outURN){ GF_TrackBox *trak; GF_DataEntryURLBox *url; GF_DataEntryURNBox *urn; u32 drefIndex; GF_Err e; if (!StreamDescriptionIndex || !trackNumber) return GF_BAD_PARAM; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; e = Media_GetSampleDesc(trak->Media, StreamDescriptionIndex , NULL, &drefIndex); if (e) return e; if (!drefIndex) return GF_BAD_PARAM; url = (GF_DataEntryURLBox*)gf_list_get(trak->Media->information->dataInformation->dref->boxList, drefIndex - 1); if (!url) return GF_ISOM_INVALID_FILE; *outURL = *outURN = NULL; if (url->type == GF_ISOM_BOX_TYPE_URL) { *outURL = url->location; *outURN = NULL; } else if (url->type == GF_ISOM_BOX_TYPE_URN) { urn = (GF_DataEntryURNBox *) url; *outURN = urn->nameURN; *outURL = urn->location; } else { *outURN = NULL; *outURL = NULL; } return GF_OK;}//Get the number of samples//return 0 if error or emptyGF_EXPORTu32 gf_isom_get_sample_count(GF_ISOFile *the_file, u32 trackNumber){ GF_TrackBox *trak; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return 0; return trak->Media->information->sampleTable->SampleSize->sampleCount;}u32 gf_isom_get_constant_sample_size(GF_ISOFile *the_file, u32 trackNumber){ GF_TrackBox *trak; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return 0; return trak->Media->information->sampleTable->SampleSize->sampleSize;}GF_EXPORTBool gf_isom_has_time_offset(GF_ISOFile *the_file, u32 trackNumber){ u32 i; GF_CompositionOffsetBox *ctts; GF_DttsEntry *pe; GF_TrackBox *trak; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !trak->Media->information->sampleTable->CompositionOffset) return 0; //return true at the first offset found ctts = trak->Media->information->sampleTable->CompositionOffset; i=0; while ((pe = (GF_DttsEntry*)gf_list_enum(ctts->entryList, &i))) { if (pe->decodingOffset && pe->sampleCount) return 1; } return 0;}GF_EXPORTBool gf_isom_has_sync_shadows(GF_ISOFile *the_file, u32 trackNumber){ GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return 0; if (!trak->Media->information->sampleTable->ShadowSync) return 0; if (gf_list_count(trak->Media->information->sampleTable->ShadowSync->entries) ) return 1; return 0;}Bool gf_isom_has_sample_dependency(GF_ISOFile *the_file, u32 trackNumber){ GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return 0; if (!trak->Media->information->sampleTable->SampleDep) return 0; return 1;}//return a sample give its number, and set the SampleDescIndex of this sample//this index allows to retrieve the stream description if needed (2 media in 1 track)//return NULL if errorGF_EXPORTGF_ISOSample *gf_isom_get_sample(GF_ISOFile *the_file, u32 trackNumber, u32 sampleNumber, u32 *sampleDescriptionIndex){ GF_Err e; u32 descIndex; GF_TrackBox *trak; GF_ISOSample *samp; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return NULL; if (!sampleNumber) return NULL; samp = gf_isom_sample_new(); if (!samp) return NULL; e = Media_GetSample(trak->Media, sampleNumber, &samp, &descIndex, 0, NULL); if (e) { gf_isom_set_last_error(the_file, e); gf_isom_sample_del(&samp); return NULL; } if (sampleDescriptionIndex) *sampleDescriptionIndex = descIndex; return samp;}GF_EXPORTu32 gf_isom_get_sample_duration(GF_ISOFile *the_file, u32 trackNumber, u32 sampleNumber){ u64 dur; u64 dts; GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !sampleNumber) return 0; stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, sampleNumber, &dur); if (sampleNumber == trak->Media->information->sampleTable->SampleSize->sampleCount) { return (u32) (trak->Media->mediaHeader->duration - dur); } stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, sampleNumber+1, &dts); return (u32) (dts - dur);}//same as gf_isom_get_sample but doesn't fetch media dataGF_EXPORTGF_ISOSample *gf_isom_get_sample_info(GF_ISOFile *the_file, u32 trackNumber, u32 sampleNumber, u32 *sampleDescriptionIndex, u64 *data_offset){ GF_Err e; GF_TrackBox *trak; GF_ISOSample *samp; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return NULL; if (!sampleNumber) return NULL; samp = gf_isom_sample_new(); if (!samp) return NULL; e = Media_GetSample(trak->Media, sampleNumber, &samp, sampleDescriptionIndex, 1, data_offset); if (e) { gf_isom_set_last_error(the_file, e); gf_isom_sample_del(&samp); return NULL; } return samp;}//same as gf_isom_get_sample but doesn't fetch media dataGF_EXPORTu64 gf_isom_get_sample_dts(GF_ISOFile *the_file, u32 trackNumber, u32 sampleNumber){ u64 dts; GF_TrackBox *trak; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return 0; if (!sampleNumber) return 0; if (stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, sampleNumber, &dts) != GF_OK) return 0; return dts;}GF_EXPORTBool gf_isom_is_self_contained(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex){ GF_TrackBox *trak; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return 0; return Media_IsSelfContained(trak->Media, sampleDescriptionIndex);}//return a sample given a desired display time IN MEDIA TIME SCALE//and set the StreamDescIndex of this sample//this index allows to retrieve the stream description if needed (2 media in 1 track)//return NULL if error//WARNING: the sample may not be sync even though the sync was requested (depends on the media)GF_EXPORTGF_Err gf_isom_get_sample_for_media_time(GF_ISOFile *the_file, u32 trackNumber, u64 desiredTime, u32 *StreamDescriptionIndex, u8 SearchMode, GF_ISOSample **sample, u32 *SampleNum){ GF_Err e; u32 sampleNumber, prevSampleNumber, syncNum, shadowSync; GF_TrackBox *trak; GF_ISOSample *shadow; GF_SampleTableBox *stbl; u8 useShadow, IsSync; if (!sample) return GF_BAD_PARAM; if (SampleNum) *SampleNum = 0; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; stbl = trak->Media->information->sampleTable; e = findEntryForTime(stbl, desiredTime, 1, &sampleNumber, &prevSampleNumber); if (e) return e; //if no shadow table, reset to sync only useShadow = 0; if (!stbl->ShadowSync && (SearchMode == GF_ISOM_SEARCH_SYNC_SHADOW)) SearchMode = GF_ISOM_SEARCH_SYNC_BACKWARD; //if no syncTable, disable syncSearching, as all samples ARE sync if (! trak->Media->information->sampleTable->SyncSample) { if (SearchMode == GF_ISOM_SEARCH_SYNC_FORWARD) SearchMode = GF_ISOM_SEARCH_FORWARD; if (SearchMode == GF_ISOM_SEARCH_SYNC_BACKWARD) SearchMode = GF_ISOM_SEARCH_BACKWARD; } //not found, return EOF or browse backward if (!sampleNumber && !prevSampleNumber) { if (SearchMode == GF_ISOM_SEARCH_SYNC_BACKWARD || SearchMode == GF_ISOM_SEARCH_BACKWARD) { sampleNumber = trak->Media->information->sampleTable->SampleSize->sampleCount; } if (!sampleNumber) return GF_EOS; } //check in case we have the perfect sample IsSync = 0; //according to the direction adjust the sampleNum value switch (SearchMode) { case GF_ISOM_SEARCH_SYNC_FORWARD: IsSync = 1; case GF_ISOM_SEARCH_FORWARD: //not the exact one if (!sampleNumber) { if (prevSampleNumber != stbl->SampleSize->sampleCount) { sampleNumber = prevSampleNumber + 1; } else { sampleNumber = prevSampleNumber; } } break; //if dummy mode, reset to default browsing case GF_ISOM_SEARCH_SYNC_BACKWARD: IsSync = 1; case GF_ISOM_SEARCH_SYNC_SHADOW: case GF_ISOM_SEARCH_BACKWARD: default: //first case, not found.... if (!sampleNumber && !prevSampleNumber) { sampleNumber = stbl->SampleSize->sampleCount; } else if (!sampleNumber) { sampleNumber = prevSampleNumber; } break; } //get the sync sample num if (IsSync) { //get the SyncNumber e = Media_FindSyncSample(trak->Media->information->sampleTable, sampleNumber, &syncNum, SearchMode); if (e) return e; if (syncNum) sampleNumber = syncNum; syncNum = 0; } //if we are in shadow mode, get the previous sync sample //in case we can't find a good SyncShadow else if (SearchMode == GF_ISOM_SEARCH_SYNC_SHADOW) { //get the SyncNumber e = Media_FindSyncSample(trak->Media->information->sampleTable, sampleNumber, &syncNum, GF_ISOM_SEARCH_SYNC_BACKWARD); if (e) return e; } //OK sampleNumber is exactly the sample we need (except for shadow) *sample = gf_isom_sample_new(); if (*sample == NULL) return GF_OUT_OF_MEM; //we are in shadow mode, we need to browse both SyncSample and ShadowSyncSample to get //the desired sample... if (SearchMode == GF_ISOM_SEARCH_SYNC_SHADOW) { //get the shadowing number stbl_GetSampleShadow(stbl->ShadowSync, &sampleNumber, &shadowSync); //now sampleNumber is the closest previous shadowed sample. //1- If we have a closer sync sample, use it. //2- if the shadowSync is 0, we don't have any shadowing, use syncNum if ((sampleNumber < syncNum) || (!shadowSync)) { sampleNumber = syncNum; } else { //otherwise, we have a better alternate sample in the shadowSync for this sample useShadow = 1; } } e = Media_GetSample(trak->Media, sampleNumber, sample, StreamDescriptionIndex, 0, NULL); if (e) { gf_isom_sample_del(sample); return e; } //optionally get the sample number if (SampleNum) *SampleNum = sampleNumber; //in shadow mode, we only get the data of the shadowing sample ! if (useShadow) { //we have to use StreamDescriptionIndex in case the sample data is in another desc //though this is unlikely as non optimized... shadow = gf_isom_get_sample(the_file, trackNumber, shadowSync, StreamDescriptionIndex); //if no sample, the shadowSync is broken, return the sample if (!shadow) return GF_OK; (*sample)->IsRAP = 1; free((*sample)->data); (*sample)->dataLength = shadow->dataLength; (*sample)->data = shadow->data; //set data length to 0 to keep the buffer alive... shadow->dataLength = 0; gf_isom_sample_del(&shadow); } return GF_OK;}GF_EXPORTGF_Err gf_isom_get_sample_for_movie_time(GF_ISOFile *the_file, u32 trackNumber, u64 movieTime, u32 *StreamDescriptionIndex, u8 SearchMode, GF_ISOSample **sample, u32 *sampleNumber){ GF_Err e; GF_TrackBox *trak; u64 mediaTime; s64 segStartTime, mediaOffset; u32 sampNum; u8 useEdit; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; if (*sample || !sample) return GF_BAD_PARAM; //check 0-duration tracks (BIFS and co). Check we're not searching forward if (!trak->Header->duration) { if (movieTime && ( (SearchMode == GF_ISOM_SEARCH_SYNC_FORWARD) || (SearchMode == GF_ISOM_SEARCH_FORWARD)) ) { *sample = NULL; if (sampleNumber) *sampleNumber = 0; *StreamDescriptionIndex = 0; return GF_EOS; } } else if (movieTime * trak->moov->mvhd->timeScale > trak->Header->duration * trak->Media->mediaHeader->timeScale) { *sample = NULL; if (sampleNumber) *sampleNumber = 0; *StreamDescriptionIndex = 0; return GF_EOS; } //get the media time for this movie time... mediaTime = segStartTime = 0; *StreamDescriptionIndex = 0; e = GetMediaTime(trak, movieTime, &mediaTime, &segStartTime, &mediaOffset, &useEdit); if (e) return e; /*here we check if we were playing or not and return no sample in normal search modes*/ if (useEdit && mediaOffset == -1) { if ((SearchMode==GF_ISOM_SEARCH_FORWARD) || (SearchMode==GF_ISOM_SEARCH_BACKWARD)) { /*get next sample time in MOVIE timescale*/ if (SearchMode==GF_ISOM_SEARCH_FORWARD) e = GetNextMediaTime(trak, movieTime, &mediaTime); else e = GetPrevMediaTime(trak, movieTime, &mediaTime); if (e) return e; return gf_isom_get_sample_for_movie_time(the_file, trackNumber, (u32) mediaTime, StreamDescriptionIndex, GF_ISOM_SEARCH_SYNC_FORWARD, sample, sampleNumber); } if (sampleNumber) *sampleNumber = 0; *sample = gf_isom_sample_new(); (*sample)->DTS = movieTime; return GF_OK; } /*dwell edit in non-sync mode, fetch next/prev sample depending on mode. Otherwise return the dwell entry*/ if (useEdit==2) { if ((SearchMode==GF_ISOM_SEARCH_FORWARD) || (SearchMode==GF_ISOM_SEARCH_BACKWARD)) { /*get next sample time in MOVIE timescale*/ if (SearchMode==GF_ISOM_SEARCH_FORWARD) e = GetNextMediaTime(trak, movieTime, &mediaTime); else e = GetPrevMediaTime(trak, movieTime, &mediaTime); if (e) return e; return gf_isom_get_sample_for_movie_time(the_file, trackNumber, (u32) mediaTime, StreamDescriptionIndex, GF_ISOM_SEARCH_SYNC_FORWARD, sample, sampleNumber); } } //OK, we have a sample so fetch it e = gf_isom_get_sample_for_media_time(the_file, trackNumber, mediaTime, StreamDescriptionIndex, SearchMode, sample, &sampNum); if (e) return e; //OK, now the trick: we have to rebuild the time stamps, according //to the media time scale (used by SLConfig) - add the edit start time but stay in //the track TS if (useEdit) { u64 _ts = segStartTime; _ts *= trak->Media->mediaHeader->timeScale; _ts /= trak->moov->mvhd->timeScale; (*sample)->DTS += _ts; /*watchout, the sample fetched may be before the first sample in the edit list (when seeking)*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -