📄 isom_store.c
字号:
/*OK write to mdat*/ if (!Emulation) { char cache_data[4096]; u64 remain = entry->extent_length; while (remain) { u32 size_cache = (remain>4096) ? 4096 : (u32) remain; fread(cache_data, 1, size_cache, src); gf_bs_write_data(bs, cache_data, size_cache); remain -= size_cache; } } fclose(src); } else if (gf_list_count(iloc->extent_entries)) { u32 j; j=0; while ((entry = (GF_ItemExtentEntry *)gf_list_enum(iloc->extent_entries, &j))) { if (j && (maxExtendOffset<it_size) ) maxExtendOffset = it_size; /*compute new offset*/ entry->extent_offset = baseOffset + it_size; it_size += entry->extent_length; if (maxExtendSize<entry->extent_length) maxExtendSize = entry->extent_length; /*Reading from the input file*/ if (!Emulation) { char cache_data[4096]; u64 remain = entry->extent_length; gf_bs_seek(file->movieFileMap->bs, entry->original_extent_offset + iloc->original_base_offset); while (remain) { u32 size_cache = (remain>4096) ? 4096 : (u32) remain; gf_bs_read_data(file->movieFileMap->bs, cache_data, size_cache); /*Writing to the output file*/ gf_bs_write_data(bs, cache_data, size_cache); remain -= size_cache; } } } } baseOffset += it_size; *mdatSize += it_size; } else { /*we MUST have at least one extent for the dref data*/ if (!gf_list_count(iloc->extent_entries)) { GF_SAFEALLOC(entry, GF_ItemExtentEntry); gf_list_add(iloc->extent_entries, entry); } entry = (GF_ItemExtentEntry *)gf_list_get(iloc->extent_entries, 0); entry->extent_offset = 0; /*0 means full length of referenced file*/ entry->extent_length = 0; } } /*update offset & size length fields*/ if (baseOffset>0xFFFFFFFF) meta->item_locations->base_offset_size = 8; else if (baseOffset) meta->item_locations->base_offset_size = 4; if (maxExtendSize>0xFFFFFFFF) meta->item_locations->length_size = 8; else if (maxExtendSize) meta->item_locations->length_size = 4; if (maxExtendOffset>0xFFFFFFFF) meta->item_locations->offset_size = 8; else if (maxExtendOffset) meta->item_locations->offset_size = 4; return GF_OK;}//this function writes track by track in the order of tracks inside the moov...GF_Err DoWrite(MovieWriter *mw, GF_List *writers, GF_BitStream *bs, u8 Emulation, u64 StartOffset){ u32 i; GF_Err e; TrackWriter *writer; u64 offset, sampOffset, predOffset; u32 chunkNumber, descIndex, sampSize; u8 isEdited, force; u64 size, mdatSize = 0; GF_ISOFile *movie = mw->movie; /*write meta content first - WE DON'T support fragmentation of resources in ISOM atm*/ if (movie->openMode != GF_ISOM_OPEN_WRITE) { if (movie->meta) { e = DoWriteMeta(movie, movie->meta, bs, Emulation, StartOffset, &size); if (e) return e; mdatSize += size; StartOffset += size; } if (movie->moov && movie->moov->meta) { e = DoWriteMeta(movie, movie->meta, bs, Emulation, StartOffset, &size); if (e) return e; mdatSize += size; StartOffset += size; } i=0; while ((writer = (TrackWriter*)gf_list_enum(writers, &i))) { if (writer->mdia->mediaTrack->meta) { e = DoWriteMeta(movie, movie->meta, bs, Emulation, StartOffset, &size); if (e) return e; mdatSize += size; StartOffset += size; } } } offset = StartOffset; predOffset = 0; i=0; while ((writer = (TrackWriter*)gf_list_enum(writers, &i))) { while (!writer->isDone) { //To Check: are empty sample tables allowed ??? if (writer->sampleNumber > writer->mdia->information->sampleTable->SampleSize->sampleCount) { writer->isDone = 1; continue; } e = stbl_GetSampleInfos(writer->mdia->information->sampleTable, writer->sampleNumber, &sampOffset, &chunkNumber, &descIndex, &isEdited); if (e) return e; e = stbl_GetSampleSize(writer->mdia->information->sampleTable->SampleSize, writer->sampleNumber, &sampSize); if (e) return e; //update our chunks. force = 0; if (movie->openMode == GF_ISOM_OPEN_WRITE) { offset = sampOffset; if (predOffset != offset) force = 1; } //update our global offset... if (Media_IsSelfContained(writer->mdia, descIndex) ) { e = stbl_SetChunkAndOffset(writer->mdia->information->sampleTable, writer->sampleNumber, descIndex, writer->stsc, &writer->stco, offset, force); if (e) return e; if (movie->openMode == GF_ISOM_OPEN_WRITE) { predOffset = sampOffset + sampSize; } else { offset += sampSize; mdatSize += sampSize; } } else { if (predOffset != offset) force = 1; predOffset = sampOffset + sampSize; //we have a DataRef, so use the offset idicated in sampleToChunk and ChunkOffset tables... e = stbl_SetChunkAndOffset(writer->mdia->information->sampleTable, writer->sampleNumber, descIndex, writer->stsc, &writer->stco, sampOffset, force); if (e) return e; } //we write the sample if not emulation if (!Emulation) { if (Media_IsSelfContained(writer->mdia, descIndex) ) { e = WriteSample(mw, sampSize, sampOffset, isEdited, bs); if (e) return e; } } //ok, the track is done if (writer->sampleNumber == writer->mdia->information->sampleTable->SampleSize->sampleCount) { writer->isDone = 1; } else { writer->sampleNumber ++; } } } //set the mdatSize... movie->mdat->dataSize = mdatSize; return GF_OK;}//write the file track by track, with moov box before or after the mdatGF_Err WriteFlat(MovieWriter *mw, u8 moovFirst, GF_BitStream *bs){ GF_Err e; u32 i; u64 offset, finalOffset, totSize, begin, firstSize, finalSize; GF_Box *a; GF_List *writers = gf_list_new(); GF_ISOFile *movie = mw->movie; begin = totSize = 0; //first setup the writers e = SetupWriters(mw, writers, 0); if (e) goto exit; if (!moovFirst) { if (movie->openMode == GF_ISOM_OPEN_WRITE) { begin = 0; totSize = gf_isom_datamap_get_offset(movie->editFileMap); /*start boxes have not been written yet, do it*/ if (!totSize) { if (movie->is_jp2) { gf_bs_write_u32(movie->editFileMap->bs, 12); gf_bs_write_u32(movie->editFileMap->bs, GF_4CC('j','P',' ',' ')); gf_bs_write_u32(movie->editFileMap->bs, 0x0D0A870A); totSize += 12; begin += 12; } if (movie->brand) { e = gf_isom_box_size((GF_Box *)movie->brand); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->brand, movie->editFileMap->bs); if (e) goto exit; totSize += movie->brand->size; begin += movie->brand->size; } if (movie->pdin) { e = gf_isom_box_size((GF_Box *)movie->pdin); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->pdin, movie->editFileMap->bs); if (e) goto exit; totSize += movie->pdin->size; begin += movie->pdin->size; } } else { if (movie->is_jp2) begin += 12; if (movie->brand) begin += movie->brand->size; if (movie->pdin) begin += movie->pdin->size; } totSize -= begin; } else { if (movie->is_jp2) { gf_bs_write_u32(bs, 12); gf_bs_write_u32(bs, GF_4CC('j','P',' ',' ')); gf_bs_write_u32(bs, 0x0D0A870A); } if (movie->brand) { e = gf_isom_box_size((GF_Box *)movie->brand); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->brand, bs); if (e) goto exit; } /*then progressive download*/ if (movie->pdin) { e = gf_isom_box_size((GF_Box *)movie->pdin); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->pdin, bs); if (e) goto exit; } } //if the moov is at the end, write directly i=0; while ((a = (GF_Box*)gf_list_enum(movie->TopBoxes, &i))) { switch (a->type) { /*written by hand*/ case GF_ISOM_BOX_TYPE_MOOV: case GF_ISOM_BOX_TYPE_META: case GF_ISOM_BOX_TYPE_FTYP: case GF_ISOM_BOX_TYPE_PDIN: break; case GF_ISOM_BOX_TYPE_MDAT: //in case we're capturing if (movie->openMode == GF_ISOM_OPEN_WRITE) { //emulate a write to recreate our tables (media data already written) e = DoWrite(mw, writers, bs, 1, begin); if (e) goto exit; continue; } //to avoid computing the size each time write always 4 + 4 + 8 bytes before begin = gf_bs_get_position(bs); gf_bs_write_u64(bs, 0); gf_bs_write_u64(bs, 0); e = DoWrite(mw, writers, bs, 0, gf_bs_get_position(bs)); if (e) goto exit; totSize = gf_bs_get_position(bs) - begin; break; default: e = gf_isom_box_size(a); if (e) goto exit; e = gf_isom_box_write(a, bs); if (e) goto exit; break; } } //OK, write the movie box. e = WriteMoovAndMeta(movie, writers, bs); if (e) goto exit; /*if data has been written, update mdat size*/ if (totSize) { offset = gf_bs_get_position(bs); e = gf_bs_seek(bs, begin); if (e) goto exit; if (totSize > 0xFFFFFFFF) { gf_bs_write_u32(bs, 1); } else { gf_bs_write_u32(bs, (u32) totSize); } gf_bs_write_u32(bs, GF_ISOM_BOX_TYPE_MDAT); if (totSize > 0xFFFFFFFF) gf_bs_write_u64(bs, totSize); e = gf_bs_seek(bs, offset); } movie->mdat->size = totSize; goto exit; } //nope, we have to write the moov first. The pb is that //1 - we don't know its size till the mdat is written //2 - we don't know the ofset at which the mdat will start... //3 - once the mdat is written, the chunkOffset table can have changed... if (movie->is_jp2) { gf_bs_write_u32(bs, 12); gf_bs_write_u32(bs, GF_4CC('j','P',' ',' ')); gf_bs_write_u32(bs, 0x0D0A870A); } if (movie->brand) { e = gf_isom_box_size((GF_Box *)movie->brand); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->brand, bs); if (e) goto exit; } /*then progressive dnload*/ if (movie->pdin) { e = gf_isom_box_size((GF_Box *)movie->pdin); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->pdin, bs); if (e) goto exit; } //What we will do is first emulate the write from the begining... //note: this will set the size of the mdat e = DoWrite(mw, writers, bs, 1, gf_bs_get_position(bs)); if (e) goto exit; firstSize = GetMoovAndMetaSize(movie, writers); //offset = (firstSize > 0xFFFFFFFF ? firstSize + 8 : firstSize) + 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0); offset = firstSize + 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0); e = ShiftOffset(movie, writers, offset); if (e) goto exit; //get the size and see if it has changed (eg, we moved to 64 bit offsets) finalSize = GetMoovAndMetaSize(movie, writers); if (firstSize != finalSize) { //we need to remove our offsets ResetWriters(writers); //finalOffset = (finalSize > 0xFFFFFFFF ? finalSize + 8 : finalSize) + 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0); finalOffset = finalSize + 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0); //OK, now we're sure about the final size. //we don't need to re-emulate, as the only thing that changed is the offset //so just shift the offset e = ShiftOffset(movie, writers, finalOffset - offset); if (e) goto exit; } //now write our stuff e = WriteMoovAndMeta(movie, writers, bs); if (e) goto exit; e = gf_isom_box_size((GF_Box *)movie->mdat); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->mdat, bs); if (e) goto exit; //we don't need the offset as the moov is already written... ResetWriters(writers); e = DoWrite(mw, writers, bs, 0, 0); if (e) goto exit; //then the rest i=0; while ((a = (GF_Box*)gf_list_enum(movie->TopBoxes, &i))) { switch (a->type) { case GF_ISOM_BOX_TYPE_MOOV: case GF_ISOM_BOX_TYPE_META: case GF_ISOM_BOX_TYPE_FTYP: case GF_ISOM_BOX_TYPE_PDIN: case GF_ISOM_BOX_TYPE_MDAT: break; default: e = gf_isom_box_size(a); if (e) goto exit; e = gf_isom_box_write(a, bs); if (e) goto exit; } }exit: CleanWriters(writers); gf_list_del(writers); return e;}GF_Err DoFullInterleave(MovieWriter *mw, GF_List *writers, GF_BitStream *bs, u8 Emulation, u32 StartOffset){ u32 i, tracksDone; TrackWriter *tmp, *curWriter, *prevWriter; GF_Err e; u64 DTS, DTStmp, TStmp; s64 res; u32 descIndex, sampSize, chunkNumber; u16 curGroupID, curTrackPriority; u8 forceNewChunk, writeGroup, isEdited; //this is used to emulate the write ... u64 offset, totSize, sampOffset; GF_ISOFile *movie = mw->movie; e = GF_OK; totSize = 0; curGroupID = 1; prevWriter = NULL; //we emulate a write from this offset... offset = StartOffset; writeGroup = 1; tracksDone = 0; //browse each groups while (1) { writeGroup = 1; //proceed a group while (writeGroup) { //first get the appropriated sample for the min time in this group curWriter = NULL; DTStmp = (u64) -1; TStmp = 0; curTrackPriority = (u16) -1; i=0; while ((tmp = (TrackWriter*)gf_list_enum(writers, &i))) { //is it done writing ? //is it in our group ?? if (tmp->isDone || tmp->mdia->information->sampleTable->groupID != curGroupID) continue; //OK, get the current sample in this track stbl_GetSampleDTS(tmp->mdia->information->sampleTable->TimeToSample, tmp->sampleNumber, &DTS); res = TStmp ? DTStmp * tmp->timeScale - DTS * TStmp : 0; if (res < 0) continue; if ((!res) && curTrackPriority <= tmp->mdia->information->sampleTable->trackPriority) continue; curWriter = tmp; curTrackPriority = tmp->mdia->information->sampleTable->trackPriority; DTStmp = DTS; TStmp = tmp->timeScale;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -