static GF_Err WriteInterleaved(MovieWriter *mw, GF_BitStream *bs, Bool drift_inter) { GF_Err e; u32 i; GF_Box *a; u64 firstSize, finalSize, offset, finalOffset; GF_List *writers = gf_list_new(); GF_ISOFile *movie = mw->movie; //first setup the writers e = SetupWriters(mw, writers, 1); if (e) goto exit; 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; } 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; } e = DoInterleave(mw, writers, bs, 1, gf_bs_get_position(bs), drift_inter); if (e) goto exit; firstSize = GetMoovAndMetaSize(movie, writers); offset = firstSize; if (movie->mdat && movie->mdat->dataSize) offset += 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; if (movie->mdat->dataSize) finalOffset += 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0); //OK, now we're sure about the final size -> shift the offsets //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; firstSize = GetMoovAndMetaSize(movie, writers); } //now write our stuff e = WriteMoovAndMeta(movie, writers, bs); if (e) goto exit; /*we have 8 extra bytes for large size (not computed in gf_isom_box_size) */ if (movie->mdat && movie->mdat->dataSize) { if (movie->mdat->dataSize > 0xFFFFFFFF) movie->mdat->dataSize += 8; 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 we are writing... ResetWriters(writers); e = DoInterleave(mw, writers, bs, 0, 0, drift_inter); 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; }
//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; }
static GF_Err WriteInterleaved(MovieWriter *mw, GF_BitStream *bs, Bool drift_inter) { GF_Err e; u8 converted; u32 i; GF_Box *a; u64 offset, shift_offset, prev; GF_List *writers = gf_list_new(); GF_ISOFile *movie = mw->movie; //first setup the writers e = SetupWriters(mw, writers, 1); if (e) goto exit; 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; } 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; } e = DoInterleave(mw, writers, bs, 1, gf_bs_get_position(bs), drift_inter); if (e) goto exit; shift_offset = 0; prev = 0; for (;;) { offset = GetMoovAndMetaSize(movie, writers); if (offset==prev) break; prev = offset; if (movie->mdat && movie->mdat->dataSize) offset += 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0); e = ShiftOffset(movie, writers, offset-shift_offset,&converted); if (e) goto exit; shift_offset = offset; } //now write our stuff e = WriteMoovAndMeta(movie, writers, bs); if (e) goto exit; /*we have 8 extra bytes for large size (not computed in gf_isom_box_size) */ if (movie->mdat && movie->mdat->dataSize) { if (movie->mdat->dataSize > 0xFFFFFFFF) movie->mdat->dataSize += 8; 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 we are writing... ResetWriters(writers); e = DoInterleave(mw, writers, bs, 0, 0, drift_inter); 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; }