📄 stbl_write.c
字号:
if (sdtp->sampleCount + 1 < sampleNumber) { u32 missed = sampleNumber-1 - sdtp->sampleCount; sdtp->sample_info = (u8*) realloc(sdtp->sample_info, sizeof(u8) * (sdtp->sampleCount+missed) ); while (missed) { u8 isRAP; if (stbl->SyncSample) stbl_GetSampleRAP(stbl->SyncSample, sdtp->sampleCount+1, &isRAP, NULL, NULL); else isRAP = 1; sdtp->sample_info[sdtp->sampleCount] = isRAP ? 0x20 : 0; sdtp->sampleCount++; missed--; } } sdtp->sample_info = (u8*) realloc(sdtp->sample_info, sizeof(u8) * (sdtp->sampleCount + 1)); if (!sdtp->sample_info) return GF_OUT_OF_MEM; if (sdtp->sampleCount < sampleNumber) { sdtp->sample_info[sdtp->sampleCount] = 0x29; } else { u32 snum = sampleNumber-1; memmove(sdtp->sample_info+snum+1, sdtp->sample_info+snum, sizeof(u8) * (sdtp->sampleCount - snum) ); sdtp->sample_info[snum] = 0x29; } //update our list sdtp->sampleCount ++; return GF_OK;}//this function is always called in INCREASING order of shadow sample numbersGF_Err stbl_AddShadow(GF_ShadowSyncBox *stsh, u32 sampleNumber, u32 shadowNumber){ GF_StshEntry *ent; u32 i, count; count = gf_list_count(stsh->entries); for (i=0; i<count; i++) { ent = (GF_StshEntry*)gf_list_get(stsh->entries, i); if (ent->shadowedSampleNumber == shadowNumber) { ent->syncSampleNumber = sampleNumber; return GF_OK; } else if (ent->shadowedSampleNumber > shadowNumber) break; } ent = (GF_StshEntry*)malloc(sizeof(GF_StshEntry)); if (!ent) return GF_OUT_OF_MEM; ent->shadowedSampleNumber = shadowNumber; ent->syncSampleNumber = sampleNumber; if (i == gf_list_count(stsh->entries)) { return gf_list_add(stsh->entries, ent); } else { return gf_list_insert(stsh->entries, ent, i ? i-1 : 0); }}//used in edit/write, where sampleNumber == chunkNumberGF_Err stbl_AddChunkOffset(GF_MediaBox *mdia, u32 sampleNumber, u32 StreamDescIndex, u64 offset){ GF_SampleTableBox *stbl; GF_ChunkOffsetBox *stco; GF_ChunkLargeOffsetBox *co64; GF_StscEntry *ent, *tmp; u32 count, i, k, *newOff; u64 *newLarge; stbl = mdia->information->sampleTable; count = gf_list_count(mdia->information->sampleTable->SampleToChunk->entryList); if (count + 1 < sampleNumber ) return GF_BAD_PARAM; ent = (GF_StscEntry*)malloc(sizeof(GF_StscEntry)); ent->isEdited = 0; if (Media_IsSelfContained(mdia, StreamDescIndex)) ent->isEdited = 1; ent->sampleDescriptionIndex = StreamDescIndex; ent->samplesPerChunk = 1; //we know 1 chunk == 1 sample, so easy... ent->firstChunk = sampleNumber; ent->nextChunk = sampleNumber + 1; //add the offset to the chunk... //and we change our offset if (stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) { stco = (GF_ChunkOffsetBox *)stbl->ChunkOffset; //if the new offset is a large one, we have to rewrite our table entry by entry (32->64 bit conv)... if (offset > 0xFFFFFFFF) { co64 = (GF_ChunkLargeOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_CO64); co64->entryCount = stco->entryCount + 1; co64->offsets = (u64*)malloc(sizeof(u64) * co64->entryCount); k = 0; for (i=0;i<stco->entryCount; i++) { if (i + 1 == sampleNumber) { co64->offsets[i] = offset; k = 1; } co64->offsets[i+k] = (u64) stco->offsets[i]; } if (!k) co64->offsets[co64->entryCount - 1] = offset; gf_isom_box_del(stbl->ChunkOffset); stbl->ChunkOffset = (GF_Box *) co64; } else { //no, we can use this one. if (sampleNumber > stco->entryCount) { if (!stco->alloc_size) stco->alloc_size = stco->entryCount; if (stco->entryCount == stco->alloc_size) { stco->alloc_size += 50; newOff = (u32*)malloc(sizeof(u32) * stco->alloc_size); memcpy(newOff, stco->offsets, sizeof(u32) * stco->entryCount); free(stco->offsets); stco->offsets = newOff; } stco->offsets[stco->entryCount] = (u32) offset; stco->entryCount += 1; } else { //nope. we're inserting newOff = (u32*)malloc(sizeof(u32) * (stco->entryCount + 1)); k=0; for (i=0; i<stco->entryCount; i++) { if (i+1 == sampleNumber) { newOff[i] = (u32) offset; k=1; } newOff[i+k] = stco->offsets[i]; } free(stco->offsets); stco->offsets = newOff; stco->entryCount ++; stco->alloc_size = stco->entryCount; } } } else { //use large offset... co64 = (GF_ChunkLargeOffsetBox *)stbl->ChunkOffset; if (sampleNumber > co64->entryCount) { if (!co64->alloc_size) co64->alloc_size = co64->entryCount; if (co64->entryCount == co64->alloc_size) { co64->alloc_size += 50; newLarge = (u64*)malloc(sizeof(u64) * co64->alloc_size); memcpy(newLarge, co64->offsets, sizeof(u64) * co64->entryCount); free(co64->offsets); co64->offsets = newLarge; } co64->offsets[co64->entryCount] = offset; co64->entryCount += 1; } else { //nope. we're inserting newLarge = (u64*)malloc(sizeof(u64) * (co64->entryCount + 1)); k=0; for (i=0; i<co64->entryCount; i++) { if (i+1 == sampleNumber) { newLarge[i] = offset; k=1; } newLarge[i+k] = co64->offsets[i]; } free(co64->offsets); co64->offsets = newLarge; co64->entryCount++; co64->alloc_size++; } } //OK, now if we've inserted a chunk, update the sample to chunk info... if (sampleNumber == count + 1) { ent->nextChunk = count + 1; if (stbl->SampleToChunk->currentEntry) stbl->SampleToChunk->currentEntry->nextChunk = ent->firstChunk; stbl->SampleToChunk->currentEntry = ent; stbl->SampleToChunk->currentIndex = count; stbl->SampleToChunk->firstSampleInCurrentChunk = sampleNumber; //write - edit mode: sample number = chunk number stbl->SampleToChunk->currentChunk = sampleNumber; stbl->SampleToChunk->ghostNumber = 1; return gf_list_add(stbl->SampleToChunk->entryList, ent); } for (i = sampleNumber - 1; i<count; i++) { tmp = (GF_StscEntry*)gf_list_get(stbl->SampleToChunk->entryList, i); if (tmp) tmp->firstChunk +=1; } return gf_list_insert(stbl->SampleToChunk->entryList, ent, sampleNumber-1);}GF_Err stbl_SetChunkOffset(GF_MediaBox *mdia, u32 sampleNumber, u64 offset){ GF_StscEntry *ent; u32 i; GF_ChunkLargeOffsetBox *co64; GF_SampleTableBox *stbl = mdia->information->sampleTable; if (!sampleNumber || !stbl) return GF_BAD_PARAM; ent = (GF_StscEntry*)gf_list_get(stbl->SampleToChunk->entryList, sampleNumber - 1); //we edit our entry if self contained if (Media_IsSelfContained(mdia, ent->sampleDescriptionIndex)) ent->isEdited = 1; //and we change our offset if (stbl->ChunkOffset->type == GF_ISOM_BOX_TYPE_STCO) { //if the new offset is a large one, we have to rewrite our table... if (offset > 0xFFFFFFFF) { co64 = (GF_ChunkLargeOffsetBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_CO64); co64->entryCount = ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->entryCount; co64->offsets = (u64*)malloc(sizeof(u64)*co64->entryCount); for (i=0;i<co64->entryCount; i++) { co64->offsets[i] = (u64) ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->offsets[i]; } co64->offsets[ent->firstChunk - 1] = offset; gf_isom_box_del(stbl->ChunkOffset); stbl->ChunkOffset = (GF_Box *) co64; return GF_OK; } ((GF_ChunkOffsetBox *)stbl->ChunkOffset)->offsets[ent->firstChunk - 1] = (u32) offset; } else { ((GF_ChunkLargeOffsetBox *)stbl->ChunkOffset)->offsets[ent->firstChunk - 1] = offset; } return GF_OK;}GF_Err stbl_SetSampleCTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 offset){ u32 i, j, sampNum, *CTSs; GF_DttsEntry *ent; GF_CompositionOffsetBox *ctts = stbl->CompositionOffset; //if we're setting the CTS of a sample we've skipped... if (ctts->w_LastSampleNumber < sampleNumber) { //add some 0 till we get to the sample while (ctts->w_LastSampleNumber + 1 != sampleNumber) { AddCompositionOffset(ctts, 0); } return AddCompositionOffset(ctts, offset); } if (ctts->unpack_mode) { GF_DttsEntry *dtts = (GF_DttsEntry *)gf_list_get(ctts->entryList, sampleNumber-1); if (!dtts) return GF_BAD_PARAM; dtts->decodingOffset = offset; return GF_OK; } //NOPE we are inserting a sample... CTSs = (u32*)malloc(sizeof(u32) * ctts->w_LastSampleNumber); sampNum = 0; i=0; while ((ent = (GF_DttsEntry *)gf_list_enum(ctts->entryList, &i))) { for (j = 0; j<ent->sampleCount; j++) { if (sampNum + 1 == sampleNumber) { CTSs[sampNum] = offset; } else { CTSs[sampNum] = ent->decodingOffset; } sampNum ++; } } //delete the entries while (gf_list_count(ctts->entryList)) { ent = (GF_DttsEntry*)gf_list_get(ctts->entryList, 0); free(ent); gf_list_rem(ctts->entryList, 0); } //rewrite the table ent = (GF_DttsEntry*)malloc(sizeof(GF_DttsEntry)); ent->sampleCount = 1; ent->decodingOffset = CTSs[0]; i = 1; //reset the read cache (entry insertion) ctts->r_currentEntryIndex = 1; ctts->r_FirstSampleInEntry = 1; while (1) { if (i == ctts->w_LastSampleNumber) { gf_list_add(ctts->entryList, ent); break; } if (CTSs[i] == ent->decodingOffset) { ent->sampleCount += 1; } else { gf_list_add(ctts->entryList, ent); ent = (GF_DttsEntry*)malloc(sizeof(GF_DttsEntry)); ent->sampleCount = 1; ent->decodingOffset = CTSs[i]; ctts->r_FirstSampleInEntry = i; } if (i==sampleNumber) ctts->r_currentEntryIndex = gf_list_count(ctts->entryList) + 1; i++; } free(CTSs); return GF_OK;}GF_Err stbl_SetSampleSize(GF_SampleSizeBox *stsz, u32 SampleNumber, u32 size){ u32 i; if (!SampleNumber || (stsz->sampleCount < SampleNumber)) return GF_BAD_PARAM; if (stsz->sampleSize) { if (stsz->sampleSize == size) return GF_OK; if (stsz->sampleCount == 1) { stsz->sampleSize = size; return GF_OK; } //nope, we have to rewrite a table stsz->sizes = (u32*)malloc(sizeof(u32)*stsz->sampleCount); for (i=0; i<stsz->sampleCount; i++) stsz->sizes[i] = stsz->sampleSize; stsz->sampleSize = 0; } stsz->sizes[SampleNumber - 1] = size; return GF_OK;}GF_Err stbl_SetSampleRAP(GF_SyncSampleBox *stss, u32 SampleNumber, u8 isRAP){ u32 i, j, k, *newNum, nextSamp; nextSamp = 0; //check if we have already a sync sample for (i = 0; i < stss->entryCount; i++) { if (stss->sampleNumbers[i] == SampleNumber) { if (isRAP) return GF_OK; //remove it... newNum = (u32*)malloc(sizeof(u32) * (stss->entryCount-1)); k = 0; for (j=0; j<stss->entryCount; j++) { if (stss->sampleNumbers[j] == SampleNumber) { k=1; } else { newNum[j-k] = stss->sampleNumbers[j]; } } stss->entryCount -=1; free(stss->sampleNumbers); stss->sampleNumbers = newNum; return GF_OK; } if (stss->sampleNumbers[i] > SampleNumber) break; } //we need to insert a RAP somewhere if RAP ... if (!isRAP) return GF_OK; newNum = (u32*)malloc(sizeof(u32) * (stss->entryCount + 1)); k = 0; for (j = 0 ; j<stss->entryCount; j++) { if (j == i) { newNum[j] = SampleNumber; k = 1; } newNum[j+k] = stss->sampleNumbers[j]; } if (!k) { newNum[stss->entryCount] = SampleNumber; } free(stss->sampleNumbers); stss->sampleNumbers = newNum; stss->entryCount ++; return GF_OK;}GF_Err stbl_SetRedundant(GF_SampleTableBox *stbl, u32 sampleNumber){ if (stbl->SampleDep->sampleCount < sampleNumber) { return stbl_AddRedundant(stbl, sampleNumber); } else { stbl->SampleDep->sample_info[sampleNumber-1] = 0x29; return GF_OK; }}GF_Err stbl_SetSyncShadow(GF_ShadowSyncBox *stsh, u32 sampleNumber, u32 syncSample){ u32 i, count; GF_StshEntry *ent; count = gf_list_count(stsh->entries); for (i=0; i<count; i++) { ent = (GF_StshEntry*)gf_list_get(stsh->entries, i); if (ent->shadowedSampleNumber == sampleNumber) { ent->syncSampleNumber = syncSample; return GF_OK; } if (ent->shadowedSampleNumber > sampleNumber) break; } //we need a new one... ent = (GF_StshEntry*)malloc(sizeof(GF_StshEntry)); ent->shadowedSampleNumber = sampleNumber; ent->syncSampleNumber = syncSample; //insert or append ? if (i == gf_list_count(stsh->entries)) { //don't update the cache ... return gf_list_add(stsh->entries, ent); } else { //update the cache stsh->r_LastEntryIndex = i; stsh->r_LastFoundSample = sampleNumber; return gf_list_insert(stsh->entries, ent, i); }}//always called before removing the sample from SampleSizeGF_Err stbl_RemoveDTS(GF_SampleTableBox *stbl, u32 sampleNumber, u32 LastAUDefDuration){ u64 *DTSs, curDTS; u32 i, j, k, sampNum; GF_SttsEntry *ent; GF_TimeToSampleBox *stts; stts = stbl->TimeToSample; //gasp, we're removing the only sample: empty the sample table if (stbl->SampleSize->sampleCount == 1) { if (gf_list_count(stts->entryList)) { gf_list_rem(stts->entryList, 0); } //update the reading cache stts->r_FirstSampleInEntry = stts->r_currentEntryIndex = 0; stts->r_CurrentDTS = 0; return GF_OK; } //unpack the DTSs... DTSs = (u64*)malloc(sizeof(u64) * (stbl->SampleSize->sampleCount - 1)); curDTS = 0; sampNum = 0; ent = NULL; k=0; i=0; while ((ent = (GF_SttsEntry *)gf_list_enum(stts->entryList, &i))) { for (j = 0; j<ent->sampleCount; j++) { if (sampNum == sampleNumber - 1) { k=1; } else { DTSs[sampNum-k] = curDTS; } curDTS += ent->sampleDelta; sampNum ++; } } //delete the table.. while (gf_list_count(stts->entryList)) { ent = (GF_SttsEntry*)gf_list_get(stts->entryList, 0); free(ent); gf_list_rem(stts->entryList, 0); } //rewrite the table ent = (GF_SttsEntry*)malloc(sizeof(GF_SttsEntry)); ent->sampleCount = 0; gf_list_add(stts->entryList, ent); if (stbl->SampleSize->sampleCount == 2) { ent->sampleDelta = LastAUDefDuration; } else { ent->sampleDelta = (u32) DTSs[1]; DTSs[0] = 0; } i = 0; while (1) { if (i+2 == stbl->SampleSize->sampleCount) { //and by default, our last sample has the same delta as the prev
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -