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; 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->other_boxes, 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); if (sample->dataLength) { 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); }
//write the file track by track, with moov box before or after the mdat GF_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; }