📄 media.c
字号:
if (a->flags & 1) return 1; /*QT specific*/ if (a->type == GF_4CC('a', 'l', 'i', 's')) return 1; return 0;}//look for a sync sample from a given point in media timeGF_Err Media_FindSyncSample(GF_SampleTableBox *stbl, u32 searchFromSample, u32 *sampleNumber, u8 mode){ u8 isRAP; u32 next, prev; if (!stbl || !stbl->SyncSample) return GF_BAD_PARAM; //set to current sample if we don't find a RAP *sampleNumber = searchFromSample; //this is not the exact sample, but the prev move to next sample if enough samples.... if ( (mode == GF_ISOM_SEARCH_SYNC_FORWARD) && (searchFromSample == stbl->SampleSize->sampleCount) ) { return GF_OK; } if ( (mode == GF_ISOM_SEARCH_SYNC_BACKWARD) && !searchFromSample) { *sampleNumber = 1; return GF_OK; } //get the entry stbl_GetSampleRAP(stbl->SyncSample, searchFromSample, &isRAP, &prev, &next); if (isRAP) { (*sampleNumber) = searchFromSample; return GF_OK; } //nothing yet, go for next time... if (mode == GF_ISOM_SEARCH_SYNC_FORWARD) { if (next) *sampleNumber = next; } else { if (prev) *sampleNumber = prev; } return GF_OK;}//create a DataReference if not existing (only for WRITE-edit mode)GF_Err Media_FindDataRef(GF_DataReferenceBox *dref, char *URLname, char *URNname, u32 *dataRefIndex){ u32 i; GF_DataEntryURLBox *entry; if (!dref) return GF_BAD_PARAM; *dataRefIndex = 0; i=0; while ((entry = (GF_DataEntryURLBox*)gf_list_enum(dref->boxList, &i))) { if (entry->type == GF_ISOM_BOX_TYPE_URL) { //self-contained case if (entry->flags == 1) { //if nothing specified, get the dataRef if (!URLname && !URNname) { *dataRefIndex = i; return GF_OK; } } else { //OK, check if we have URL if (URLname && !strcmp(URLname, entry->location)) { *dataRefIndex = i; return GF_OK; } } } else { //this is a URN one, only check the URN name (URL optional) if (URNname && !strcmp(URNname, ((GF_DataEntryURNBox *)entry)->nameURN)) { *dataRefIndex = i; return GF_OK; } } } return GF_OK;}//Get the total media duration based on the TimeToSample tableGF_Err Media_SetDuration(GF_TrackBox *trak){ GF_ESD *esd; u64 DTS; GF_SttsEntry *ent; u32 nbSamp = trak->Media->information->sampleTable->SampleSize->sampleCount; //we need to check how many samples we have. // == 1 -> last sample duration == default duration // > 1 -> last sample duration == prev sample duration switch (nbSamp) { case 0: trak->Media->mediaHeader->duration = 0; if (Track_IsMPEG4Stream(trak->Media->handler->handlerType)) { Media_GetESD(trak->Media, 1, &esd, 1); if (esd && esd->URLString) trak->Media->mediaHeader->duration = (u64) -1; } return GF_OK;// case 1:// trak->Media->mediaHeader->duration = trak->Media->mediaHeader->timeScale;// return GF_OK; default: //we assume a constant frame rate for the media and assume the last sample //will be hold the same time as the prev one stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, nbSamp, &DTS); ent = (GF_SttsEntry*)gf_list_last(trak->Media->information->sampleTable->TimeToSample->entryList); trak->Media->mediaHeader->duration = DTS;#if 1 trak->Media->mediaHeader->duration += ent->sampleDelta;#else if (!ent) { u64 DTSprev; stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, nbSamp-1, &DTSprev); trak->Media->mediaHeader->duration += (DTS - DTSprev); } else {#ifndef GPAC_READ_ONLY if (trak->moov->mov->editFileMap && trak->Media->information->sampleTable->CompositionOffset) { u32 count, i; u64 max_ts; GF_DttsEntry *cts_ent; GF_CompositionOffsetBox *ctts = trak->Media->information->sampleTable->CompositionOffset; if (ctts->w_LastSampleNumber==nbSamp) { count = gf_list_count(ctts->entryList); max_ts = trak->Media->mediaHeader->duration; while (count) { count -= 1; cts_ent = gf_list_get(ctts->entryList, count); if (nbSamp<cts_ent->sampleCount) break; for (i=0; i<cts_ent->sampleCount; i++) { stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, nbSamp-i, &DTS); if ((s32) cts_ent->decodingOffset < 0) max_ts = DTS; else max_ts = DTS + cts_ent->decodingOffset; if (max_ts>=trak->Media->mediaHeader->duration) { trak->Media->mediaHeader->duration = max_ts; } else { break; } } if (max_ts<trak->Media->mediaHeader->duration) { break; } nbSamp-=cts_ent->sampleCount; } } }#endif trak->Media->mediaHeader->duration += ent->sampleDelta; }#endif return GF_OK; }}#ifndef GPAC_READ_ONLY GF_Err Media_CreateDataRef(GF_DataReferenceBox *dref, char *URLname, char *URNname, u32 *dataRefIndex){ GF_Err e; GF_DataEntryURLBox *entry; GF_Err dref_AddDataEntry(GF_DataReferenceBox *ptr, GF_Box *entry); if (!URLname && !URNname) { //THIS IS SELF CONTAIN, create a regular entry if needed entry = (GF_DataEntryURLBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_URL); entry->location = NULL; entry->flags = 0; entry->flags |= 1; e = dref_AddDataEntry(dref, (GF_Box *)entry); if (e) return e; *dataRefIndex = gf_list_count(dref->boxList); return GF_OK; } else if (!URNname && URLname) { //THIS IS URL entry = (GF_DataEntryURLBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_URL); entry->flags = 0; entry->location = (char*)malloc(strlen(URLname)+1); if (! entry->location) { gf_isom_box_del((GF_Box *)entry); return GF_OUT_OF_MEM; } strcpy(entry->location, URLname); e = dref_AddDataEntry(dref, (GF_Box *)entry); if (e) return e; *dataRefIndex = gf_list_count(dref->boxList); return GF_OK; } else { //THIS IS URN entry = (GF_DataEntryURLBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_URN); ((GF_DataEntryURNBox *)entry)->flags = 0; ((GF_DataEntryURNBox *)entry)->nameURN = (char*)malloc(strlen(URNname)+1); if (! ((GF_DataEntryURNBox *)entry)->nameURN) { gf_isom_box_del((GF_Box *)entry); return GF_OUT_OF_MEM; } strcpy(((GF_DataEntryURNBox *)entry)->nameURN, URNname); //check for URL if (URLname) { ((GF_DataEntryURNBox *)entry)->location = (char*)malloc(strlen(URLname)+1); if (! ((GF_DataEntryURNBox *)entry)->location) { gf_isom_box_del((GF_Box *)entry); return GF_OUT_OF_MEM; } strcpy(((GF_DataEntryURNBox *)entry)->location, URLname); } e = dref_AddDataEntry(dref, (GF_Box *)entry); if (e) return e; *dataRefIndex = gf_list_count(dref->boxList); return GF_OK; } return GF_OK;}GF_Err Media_AddSample(GF_MediaBox *mdia, u64 data_offset, GF_ISOSample *sample, u32 StreamDescIndex, u32 syncShadowNumber){ GF_Err e; GF_SampleTableBox *stbl; u32 sampleNumber, i; if (!mdia || !sample) return GF_BAD_PARAM; stbl = mdia->information->sampleTable; //get a valid sampleNumber for this new guy e = stbl_AddDTS(stbl, sample->DTS, &sampleNumber, mdia->mediaHeader->timeScale); if (e) return e; //add size e = stbl_AddSize(stbl->SampleSize, sampleNumber, sample->dataLength); if (e) return e; //adds CTS offset if (sample->CTS_Offset) { //if we don't have a CTS table, add it... if (!stbl->CompositionOffset) stbl->CompositionOffset = (GF_CompositionOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_CTTS); //then add our CTS (the prev samples with no CTS offset will be automatically added... e = stbl_AddCTS(stbl, sampleNumber, sample->CTS_Offset); if (e) return e; } else if (stbl->CompositionOffset) { e = stbl_AddCTS(stbl, sampleNumber, sample->CTS_Offset); if (e) return e; } //The first non sync sample we see must create a syncTable if (sample->IsRAP) { //insert it only if we have a sync table if (stbl->SyncSample) { e = stbl_AddRAP(stbl->SyncSample, sampleNumber); if (e) return e; } } else { //non-sync sample. Create a SyncSample table if needed if (!stbl->SyncSample) { stbl->SyncSample = (GF_SyncSampleBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STSS); //all the prev samples are sync for (i=0; i<stbl->SampleSize->sampleCount; i++) { if (i+1 != sampleNumber) { e = stbl_AddRAP(stbl->SyncSample, i+1); if (e) return e; } } } } if (sample->IsRAP==2) { e = stbl_AddRedundant(stbl, sampleNumber); if (e) return e; } //and update the chunks e = stbl_AddChunkOffset(mdia, sampleNumber, StreamDescIndex, data_offset); if (e) return e; if (!syncShadowNumber) return GF_OK; if (!stbl->ShadowSync) stbl->ShadowSync = (GF_ShadowSyncBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STSH); return stbl_AddShadow(mdia->information->sampleTable->ShadowSync, sampleNumber, syncShadowNumber);}GF_Err UpdateSample(GF_MediaBox *mdia, u32 sampleNumber, u32 size, u32 CTS, u64 offset, u8 isRap){ u32 i; GF_SampleTableBox *stbl = mdia->information->sampleTable; //set size, offset, RAP, CTS ... stbl_SetSampleSize(stbl->SampleSize, sampleNumber, size); stbl_SetChunkOffset(mdia, sampleNumber, offset); //do we have a CTS? if (stbl->CompositionOffset) { stbl_SetSampleCTS(stbl, sampleNumber, CTS); } else { //do we need one ?? if (CTS) { stbl->CompositionOffset = (GF_CompositionOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_CTTS); stbl_AddCTS(stbl, sampleNumber, CTS); } } //do we have a sync ??? if (stbl->SyncSample) { stbl_SetSampleRAP(stbl->SyncSample, sampleNumber, isRap); } else { //do we need one if (! isRap) { stbl->SyncSample = (GF_SyncSampleBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STSS); //what a pain: all the sample we had have to be sync ... for (i=0; i<stbl->SampleSize->sampleCount; i++) { if (i+1 != sampleNumber) stbl_AddRAP(stbl->SyncSample, i+1); } } } if (isRap==2) { stbl_SetRedundant(stbl, sampleNumber); } return GF_OK;}GF_Err Media_UpdateSample(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample *sample, Bool data_only){ GF_Err e; u32 drefIndex, chunkNum, descIndex; u64 newOffset, DTS; u8 isEdited; GF_DataEntryURLBox *Dentry; GF_SampleTableBox *stbl; GF_Err stbl_AddBox(GF_SampleTableBox *ptr, GF_Box *a); if (!mdia || !sample || !sampleNumber || !mdia->mediaTrack->moov->mov->editFileMap) return GF_BAD_PARAM; stbl = mdia->information->sampleTable; if (!data_only) { //check we have the sampe dts e = stbl_GetSampleDTS(stbl->TimeToSample, sampleNumber, &DTS); if (e) return e; if (DTS != sample->DTS) return GF_BAD_PARAM; } //get our infos stbl_GetSampleInfos(stbl, sampleNumber, &newOffset, &chunkNum, &descIndex, &isEdited); //then check the data ref e = Media_GetSampleDesc(mdia, descIndex, NULL, &drefIndex); if (e) return e; Dentry = (GF_DataEntryURLBox*)gf_list_get(mdia->information->dataInformation->dref->boxList, drefIndex - 1); if (!Dentry) return GF_ISOM_INVALID_FILE; if (Dentry->flags != 1) return GF_BAD_PARAM; //MEDIA DATA EDIT: write this new sample to the edit temp file newOffset = gf_isom_datamap_get_offset(mdia->mediaTrack->moov->mov->editFileMap); e = gf_isom_datamap_add_data(mdia->mediaTrack->moov->mov->editFileMap, sample->data, sample->dataLength); if (e) return e; if (data_only) { stbl_SetSampleSize(stbl->SampleSize, sampleNumber, sample->dataLength); return stbl_SetChunkOffset(mdia, sampleNumber, newOffset); } return UpdateSample(mdia, sampleNumber, sample->dataLength, sample->CTS_Offset, newOffset, sample->IsRAP);}GF_Err Media_UpdateSampleReference(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample *sample, u64 data_offset){ GF_Err e; u32 drefIndex, chunkNum, descIndex; u64 off, DTS; u8 isEdited; GF_DataEntryURLBox *Dentry; GF_SampleTableBox *stbl; GF_Err stbl_AddBox(GF_SampleTableBox *ptr, GF_Box *a); if (!mdia) return GF_BAD_PARAM; stbl = mdia->information->sampleTable; //check we have the sampe dts e = stbl_GetSampleDTS(stbl->TimeToSample, sampleNumber, &DTS); if (e) return e; if (DTS != sample->DTS) return GF_BAD_PARAM; //get our infos stbl_GetSampleInfos(stbl, sampleNumber, &off, &chunkNum, &descIndex, &isEdited); //then check the data ref e = Media_GetSampleDesc(mdia, descIndex, NULL, &drefIndex); if (e) return e; Dentry = (GF_DataEntryURLBox*)gf_list_get(mdia->information->dataInformation->dref->boxList, drefIndex - 1); if (!Dentry) return GF_ISOM_INVALID_FILE; //we only modify self-contained data if (Dentry->flags == 1) return GF_ISOM_INVALID_MODE; //and we don't modify the media data return UpdateSample(mdia, sampleNumber, sample->dataLength, sample->CTS_Offset, data_offset, sample->IsRAP);}#endif //GPAC_READ_ONLY
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -