📄 isom_write.c
字号:
trak = (GF_TrackBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TRAK); if (!trak) { gf_isom_set_last_error(movie, GF_OUT_OF_MEM); return 0; } tkhd = (GF_TrackHeaderBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TKHD); if (!tkhd) { gf_isom_set_last_error(movie, GF_OUT_OF_MEM); gf_isom_box_del((GF_Box *)trak); return 0; } now = gf_isom_get_mp4time(); tkhd->creationTime = now; tkhd->modificationTime = now; //OK, set up the media trak e = NewMedia(&mdia, MediaType, TimeScale); if (e) { gf_isom_box_del((GF_Box *)mdia); gf_isom_box_del((GF_Box *)trak); gf_isom_box_del((GF_Box *)tkhd); return 0; } //OK, add this media to our track mdia->mediaTrack = trak; e = trak_AddBox((GF_Box*)trak, (GF_Box *) tkhd); if (e) goto err_exit; e = trak_AddBox((GF_Box*)trak, (GF_Box *) mdia); if (e) goto err_exit; tkhd->trackID = trakID; //some default properties for Audio, Visual or private tracks if (MediaType == GF_ISOM_MEDIA_VISUAL) { /*320-240 pix in 16.16*/ tkhd->width = 0x01400000; tkhd->height = 0x00F00000; } else if (MediaType == GF_ISOM_MEDIA_AUDIO) { tkhd->volume = 0x0100; } mdia->mediaHeader->creationTime = mdia->mediaHeader->modificationTime = now; trak->Header->creationTime = trak->Header->modificationTime = now; //OK, add our trak e = moov_AddBox((GF_Box*)movie->moov, (GF_Box *)trak); if (e) goto err_exit; //set the new ID available if (trakID+1> movie->moov->mvhd->nextTrackID) movie->moov->mvhd->nextTrackID = trakID+1; //and return our track number return gf_isom_get_track_by_id(movie, trakID);err_exit: if (tkhd) gf_isom_box_del((GF_Box *)tkhd); if (trak) gf_isom_box_del((GF_Box *)trak); if (mdia) gf_isom_box_del((GF_Box *)mdia); return 0;}//Create a new StreamDescription in the file. The URL and URN are used to describe external mediaGF_EXPORTGF_Err gf_isom_new_mpeg4_description(GF_ISOFile *movie, u32 trackNumber, GF_ESD *esd, char *URLname, char *URNname, u32 *outDescriptionIndex){ GF_TrackBox *trak; GF_Err e; u32 dataRefIndex; GF_ESD *new_esd; GF_TrackReferenceTypeBox *dpnd; GF_TrackReferenceBox *tref; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media || !esd || !esd->decoderConfig || !esd->slConfig) return GF_BAD_PARAM; dpnd = NULL; tref = NULL; //get or create the data ref e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex); if (e) return e; if (!dataRefIndex) { e = Media_CreateDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex); if (e) return e; } //duplicate our desc e = gf_odf_desc_copy((GF_Descriptor *)esd, (GF_Descriptor **)&new_esd); if (e) return e;; trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); e = Track_SetStreamDescriptor(trak, 0, dataRefIndex, new_esd, outDescriptionIndex); if (e) { gf_odf_desc_del((GF_Descriptor *)new_esd); return e; } if (new_esd->URLString) { } return e;}//Add samples to a track. Use streamDescriptionIndex to specify the desired stream (if several)GF_EXPORTGF_Err gf_isom_add_sample(GF_ISOFile *movie, u32 trackNumber, u32 StreamDescriptionIndex, GF_ISOSample *sample){ GF_Err e; GF_TrackBox *trak; GF_SampleEntryBox *entry; u32 dataRefIndex; u64 data_offset; u32 descIndex; GF_DataEntryURLBox *Dentry; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak) return GF_BAD_PARAM; e = FlushCaptureMode(movie); if (e) return e; e = unpack_track(trak); if (e) return e; //REWRITE ANY OD STUFF if (trak->Media->handler->handlerType == GF_ISOM_MEDIA_OD) { e = Media_ParseODFrame(trak->Media, sample); if (e) return e; } //OK, add the sample //1- Get the streamDescriptionIndex and dataRefIndex //not specified, get the latest used... descIndex = StreamDescriptionIndex; if (!StreamDescriptionIndex) { descIndex = trak->Media->information->sampleTable->currentEntryIndex; } e = Media_GetSampleDesc(trak->Media, descIndex, &entry, &dataRefIndex); if (e) return e; if (!entry || !dataRefIndex) return GF_BAD_PARAM; //set the current to this one trak->Media->information->sampleTable->currentEntryIndex = descIndex; //get this dataRef and return false if not self contained Dentry = (GF_DataEntryURLBox*)gf_list_get(trak->Media->information->dataInformation->dref->boxList, dataRefIndex - 1); if (!Dentry || Dentry->flags != 1) return GF_BAD_PARAM; //Open our data map. We are adding stuff, so use EDIT e = gf_isom_datamap_open(trak->Media, dataRefIndex, 1); if (e) return e; //Get the offset... data_offset = gf_isom_datamap_get_offset(trak->Media->information->dataHandler); //add the meta data e = Media_AddSample(trak->Media, data_offset, sample, descIndex, 0); if (e) return e; //add the media data e = gf_isom_datamap_add_data(trak->Media->information->dataHandler, sample->data, sample->dataLength); if (e) return e; trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); return SetTrackDuration(trak);}GF_Err gf_isom_add_sample_shadow(GF_ISOFile *movie, u32 trackNumber, GF_ISOSample *sample){ GF_Err e; GF_TrackBox *trak; GF_ISOSample *prev; GF_SampleEntryBox *entry; u32 dataRefIndex; u64 data_offset; u32 descIndex; u32 sampleNum, prevSampleNum; GF_DataEntryURLBox *Dentry; Bool offset_times = 0; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !sample) return GF_BAD_PARAM; e = FlushCaptureMode(movie); if (e) return e; e = unpack_track(trak); if (e) return e; /*REWRITE ANY OD STUFF*/ if (trak->Media->handler->handlerType == GF_ISOM_MEDIA_OD) { e = Media_ParseODFrame(trak->Media, sample); if (e) return e; } e = findEntryForTime(trak->Media->information->sampleTable, sample->DTS, 0, &sampleNum, &prevSampleNum); if (e) return e; /*we need the EXACT match*/ if (!sampleNum) return GF_BAD_PARAM; prev = gf_isom_get_sample_info(movie, trackNumber, sampleNum, &descIndex, NULL); if (!prev) return gf_isom_last_error(movie); /*for conformance*/ if (sample->DTS==prev->DTS) offset_times = 1; gf_isom_sample_del(&prev); e = Media_GetSampleDesc(trak->Media, descIndex, &entry, &dataRefIndex); if (e) return e; if (!entry || !dataRefIndex) return GF_BAD_PARAM; trak->Media->information->sampleTable->currentEntryIndex = descIndex; //get this dataRef and return false if not self contained Dentry = (GF_DataEntryURLBox*)gf_list_get(trak->Media->information->dataInformation->dref->boxList, dataRefIndex - 1); if (!Dentry || Dentry->flags != 1) return GF_BAD_PARAM; //Open our data map. We are adding stuff, so use EDIT e = gf_isom_datamap_open(trak->Media, dataRefIndex, 1); if (e) return e; data_offset = gf_isom_datamap_get_offset(trak->Media->information->dataHandler); if (offset_times) sample->DTS += 1; e = Media_AddSample(trak->Media, data_offset, sample, descIndex, sampleNum); if (offset_times) sample->DTS -= 1; if (e) return e; //add the media data e = gf_isom_datamap_add_data(trak->Media->information->dataHandler, sample->data, sample->dataLength); if (e) return e; //OK, update duration e = Media_SetDuration(trak); if (e) return e; trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); return SetTrackDuration(trak);}GF_Err gf_isom_append_sample_data(GF_ISOFile *movie, u32 trackNumber, char *data, u32 data_size){ GF_Err e; GF_TrackBox *trak; GF_SampleEntryBox *entry; u32 dataRefIndex; u32 descIndex; GF_DataEntryURLBox *Dentry; if (!data_size) return GF_OK; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak) return GF_BAD_PARAM; if (trak->Media->handler->handlerType == GF_ISOM_MEDIA_OD) return GF_BAD_PARAM; //OK, add the sample descIndex = trak->Media->information->sampleTable->currentEntryIndex; e = Media_GetSampleDesc(trak->Media, descIndex, &entry, &dataRefIndex); if (e) return e; if (!entry || !dataRefIndex) return GF_BAD_PARAM; //get this dataRef and return false if not self contained Dentry = (GF_DataEntryURLBox*)gf_list_get(trak->Media->information->dataInformation->dref->boxList, dataRefIndex - 1); if (!Dentry || Dentry->flags != 1) return GF_BAD_PARAM; //Open our data map. We are adding stuff, so use EDIT e = gf_isom_datamap_open(trak->Media, dataRefIndex, 1); if (e) return e; //add the media data e = gf_isom_datamap_add_data(trak->Media->information->dataHandler, data, data_size); if (e) return e; //update data size return stbl_SampleSizeAppend(trak->Media->information->sampleTable->SampleSize, data_size);}//Add sample reference to a track. The SampleOffset is the offset of the data in the referenced file//you must have created a StreamDescription with URL or URN specifying your referenced file//the data offset specifies the begining of the chunk//Use streamDescriptionIndex to specify the desired stream (if several)GF_Err gf_isom_add_sample_reference(GF_ISOFile *movie, u32 trackNumber, u32 StreamDescriptionIndex, GF_ISOSample *sample, u64 dataOffset){ GF_TrackBox *trak; GF_SampleEntryBox *entry; u32 dataRefIndex; u32 descIndex; GF_DataEntryURLBox *Dentry; GF_Err e; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak) return GF_BAD_PARAM; e = unpack_track(trak); if (e) return e; //OD is not allowed as a data ref if (trak->Media->handler->handlerType == GF_ISOM_MEDIA_OD) { return GF_BAD_PARAM; } //OK, add the sample //1- Get the streamDescriptionIndex and dataRefIndex //not specified, get the latest used... descIndex = StreamDescriptionIndex; if (!StreamDescriptionIndex) { descIndex = trak->Media->information->sampleTable->currentEntryIndex; } e = Media_GetSampleDesc(trak->Media, descIndex, &entry, &dataRefIndex); if (e) return e; if (!entry || !dataRefIndex) return GF_BAD_PARAM; //set the current to this one trak->Media->information->sampleTable->currentEntryIndex = descIndex; //get this dataRef and return false if self contained Dentry =(GF_DataEntryURLBox*) gf_list_get(trak->Media->information->dataInformation->dref->boxList, dataRefIndex - 1); if (Dentry->flags == 1) return GF_BAD_PARAM; //add the meta data e = Media_AddSample(trak->Media, dataOffset, sample, descIndex, 0); if (e) return e; trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); //OK, update duration e = Media_SetDuration(trak); if (e) return e; return SetTrackDuration(trak);}//set the duration of the last media sample. If not set, the duration of the last sample is the//duration of the previous one if any, or 1000 (default value).GF_Err gf_isom_set_last_sample_duration(GF_ISOFile *movie, u32 trackNumber, u32 duration){ GF_TrackBox *trak; GF_SttsEntry *ent; u64 mdur; GF_Err e; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak) return GF_BAD_PARAM; mdur = trak->Media->mediaHeader->duration; //get the last entry ent = (GF_SttsEntry*)gf_list_get(trak->Media->information->sampleTable->TimeToSample->entryList, gf_list_count(trak->Media->information->sampleTable->TimeToSample->entryList)-1); if (!ent) return GF_BAD_PARAM; mdur -= ent->sampleDelta; if (duration) { mdur += duration; //we only have one sample if (ent->sampleCount == 1) { ent->sampleDelta = duration; } else { if (ent->sampleDelta == duration) return GF_OK; ent->sampleCount -= 1; ent = (GF_SttsEntry*)malloc(sizeof(GF_SttsEntry)); ent->sampleCount = 1; ent->sampleDelta = duration; //add this entry gf_list_add(trak->Media->information->sampleTable->TimeToSample->entryList, ent); //and update the write cache trak->Media->information->sampleTable->TimeToSample->w_currentEntry = ent; trak->Media->information->sampleTable->TimeToSample->w_currentSampleNum = trak->Media->information->sampleTable->SampleSize->sampleCount; } } trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); trak->Media->mediaHeader->duration = mdur; return SetTrackDuration(trak);}//update a sample data in the media. Note that the sample MUST existsGF_Err gf_isom_update_sample(GF_ISOFile *movie, u32 trackNumber, u32 sampleNumber, GF_ISOSample *sample, Bool data_only){ GF_Err e; GF_TrackBox *trak; e = CanAccessMovie(movie, GF_ISOM_OPEN_EDIT); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak) return GF_BAD_PARAM; e = unpack_track(trak); if (e) return e; //block for hint tracks if (trak->Media->handler->handlerType == GF_ISOM_MEDIA_HINT) return GF_BAD_PARAM; //REWRITE ANY OD STUFF if (trak->Media->handler->handlerType == GF_ISOM_MEDIA_OD) { e = Media_ParseODFrame(trak->Media, sample); if (e) return e; } //OK, update it e = Media_UpdateSample(trak->Media, sampleNumber, sample, data_only); if (e) return e; trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); return GF_OK;}//update a sample data in the media. Note that the sample MUST exists,//that sample->data MUST be NULL and sample->dataLength must be NON NULL;GF_Err gf_isom_update_sample_reference(GF_ISOFile *movie, u32 trackNumber, u32 sampleNumber, GF_ISOSample *sample, u64 data_offset){ GF_Err e; GF_TrackBox *trak; e = CanAccessMovie(movie, GF_ISOM_OPEN_EDIT); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak) return GF_BAD_PARAM; //block for hint tracks if (trak->Media->handler->handlerType == GF_ISOM_MEDIA_HINT) return GF_BAD_PARAM; if (!sampleNumber || !sample) return GF_BAD_PARAM; e = unpack_track(trak); if (e) return e; //OD is not allowed as a data ref if (trak->Media->handler->handlerType == GF_ISOM_MEDIA_OD) { return GF_BAD_PARAM; } //OK, update it e = Media_UpdateSampleReference(trak->Media, sampleNumber, sample, data_offset); if (e) return e; trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); return GF_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -