📄 track.c
字号:
} } //add size first stbl_AppendSize(trak->Media->information->sampleTable, size); //then TS stbl_AppendTime(trak->Media->information->sampleTable, duration); //add chunk on first sample if (!j) { data_offset = base_offset; //aggregated offset if (!(traf->tfhd->flags & GF_ISOM_TRAF_BASE_OFFSET)) data_offset += chunk_size; if (trun->flags & GF_ISOM_TRUN_DATA_OFFSET) data_offset += trun->data_offset; stbl_AppendChunk(trak->Media->information->sampleTable, data_offset); //then sampleToChunk stbl_AppendSampleToChunk(trak->Media->information->sampleTable, DescIndex, trun->sample_count); } chunk_size += size; //CTS cts_offset = (trun->flags & GF_ISOM_TRUN_CTS_OFFSET) ? ent->CTS_Offset : 0; stbl_AppendCTSOffset(trak->Media->information->sampleTable, cts_offset); //flags sync = GF_ISOM_GET_FRAG_SYNC(flags); stbl_AppendRAP(trak->Media->information->sampleTable, sync); pad = GF_ISOM_GET_FRAG_PAD(flags); if (pad) stbl_AppendPadding(trak->Media->information->sampleTable, pad); degr = GF_ISOM_GET_FRAG_DEG(flags); if (degr) stbl_AppendDegradation(trak->Media->information->sampleTable, degr); } } //end of the fragment, update offset *moof_offset += chunk_size; return GF_OK;}#endif#ifndef GPAC_READ_ONLY//used to check if a TrackID is availableu8 RequestTrack(GF_MovieBox *moov, u32 TrackID){ u32 i; GF_TrackBox *trak; i=0; while ((trak = (GF_TrackBox *)gf_list_enum(moov->trackList, &i))) { if (trak->Header->trackID == TrackID) { gf_isom_set_last_error(moov->mov, GF_BAD_PARAM); return 0; } } return 1;}GF_Err Track_RemoveRef(GF_TrackBox *trak, u32 ReferenceType){ GF_TrackReferenceBox *ref; GF_Box *a; u32 i; if (! trak) return GF_BAD_PARAM; if (! trak->References) return GF_OK; ref = trak->References; i=0; while ((a = (GF_Box *)gf_list_enum(ref->boxList, &i))) { if (a->type == ReferenceType) { gf_isom_box_del(a); gf_list_rem(ref->boxList, i-1); return GF_OK; } } return GF_OK; }GF_Err NewMedia(GF_MediaBox **mdia, u32 MediaType, u32 TimeScale){ GF_MediaHeaderBox *mdhd; GF_Box *mediaInfo; GF_HandlerBox *hdlr; GF_MediaInformationBox *minf; GF_DataInformationBox *dinf; GF_SampleTableBox *stbl; GF_SampleDescriptionBox *stsd; GF_DataReferenceBox *dref; char *str; GF_Err e; if (*mdia || !mdia) return GF_BAD_PARAM; e = GF_OK; minf = NULL; mdhd = NULL; hdlr = NULL; dinf = NULL; stbl = NULL; stsd = NULL; dref = NULL; mediaInfo = NULL; //first create the media *mdia = (GF_MediaBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MDIA); mdhd = (GF_MediaHeaderBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MDHD); //"handler name" is for debugging purposes. Let's stick our name here ;) switch (MediaType) { case GF_ISOM_MEDIA_VISUAL: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_VMHD); str = "GPAC ISO Video Handler"; break; case GF_ISOM_MEDIA_AUDIO: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_SMHD); str = "GPAC ISO Audio Handler"; break; case GF_ISOM_MEDIA_HINT: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_HMHD); str = "GPAC ISO Hint Handler"; break; case GF_ISOM_MEDIA_OD: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD); str = "GPAC MPEG-4 OD Handler"; break; case GF_ISOM_MEDIA_OCR: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD); str = "GPAC MPEG-4 OCR Handler"; break; case GF_ISOM_MEDIA_SCENE: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD); str = "GPAC MPEG-4 BIFS Handler"; break; case GF_ISOM_MEDIA_MPEG7: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD); str = "GPAC MPEG-4 MPEG-7 Handler"; break; case GF_ISOM_MEDIA_OCI: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD); str = "GPAC MPEG-4 OCI Handler"; break; case GF_ISOM_MEDIA_IPMP: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD); str = "GPAC MPEG-4 IPMP Handler"; break; case GF_ISOM_MEDIA_MPEGJ: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD); str = "GPAC MPEG-4 MPEG-J Handler"; break; case GF_ISOM_MEDIA_TEXT: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD); str = "GPAC Streaming Text Handler"; break; default: mediaInfo = gf_isom_box_new(GF_ISOM_BOX_TYPE_NMHD); str = "GPAC IsoMedia Handler"; break; } hdlr = (GF_HandlerBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_HDLR); minf = (GF_MediaInformationBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MINF); mdhd->timeScale = TimeScale; hdlr->handlerType = MediaType; hdlr->nameUTF8 = strdup(str); //first set-up the sample table... stbl = (GF_SampleTableBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STBL); dinf = (GF_DataInformationBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_DINF); stbl->SampleDescription = (GF_SampleDescriptionBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STSD); stbl->ChunkOffset = gf_isom_box_new(GF_ISOM_BOX_TYPE_STCO); //by default create a regular table stbl->SampleSize = (GF_SampleSizeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STSZ); stbl->SampleToChunk = (GF_SampleToChunkBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STSC); stbl->TimeToSample = (GF_TimeToSampleBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STTS); //Create a data reference WITHOUT DATA ENTRY (we don't know anything yet about the media Data) dref = (GF_DataReferenceBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_DREF); e = dinf_AddBox((GF_Box*)dinf, (GF_Box *)dref); if (e) goto err_exit; e = minf_AddBox((GF_Box*)minf, (GF_Box *) mediaInfo); if (e) goto err_exit; e = minf_AddBox((GF_Box*)minf, (GF_Box *) stbl); if (e) goto err_exit; e = minf_AddBox((GF_Box*)minf, (GF_Box *) dinf); if (e) goto err_exit; e = mdia_AddBox((GF_Box*)*mdia, (GF_Box *) mdhd); if (e) goto err_exit; e = mdia_AddBox((GF_Box*)*mdia, (GF_Box *) minf); if (e) goto err_exit; e = mdia_AddBox((GF_Box*)*mdia, (GF_Box *) hdlr); if (e) goto err_exit; return GF_OK;err_exit: if (mdhd) gf_isom_box_del((GF_Box *)mdhd); if (minf) gf_isom_box_del((GF_Box *)minf); if (hdlr) { if (hdlr->nameUTF8) free(hdlr->nameUTF8); gf_isom_box_del((GF_Box *)hdlr); } return e;}GF_Err Track_SetStreamDescriptor(GF_TrackBox *trak, u32 StreamDescriptionIndex, u32 DataReferenceIndex, GF_ESD *esd, u32 *outStreamIndex){ GF_Err e; GF_MPEGSampleEntryBox *entry; GF_MPEGVisualSampleEntryBox *entry_v; GF_MPEGAudioSampleEntryBox *entry_a; GF_TrackReferenceBox *tref; GF_TrackReferenceTypeBox *dpnd; u16 tmpRef; entry = NULL; tref = NULL; if (!trak || !esd || (!outStreamIndex && !DataReferenceIndex) ) return GF_BAD_PARAM; if (!Track_IsMPEG4Stream(trak->Media->handler->handlerType)) return GF_ISOM_INVALID_MEDIA; esd->ESID = 0; //set SL to predefined if no url if (esd->URLString == NULL) { if (!esd->slConfig) esd->slConfig = (GF_SLConfig*) gf_odf_desc_new(GF_ODF_SLC_TAG); esd->slConfig->predefined = SLPredef_MP4; esd->slConfig->durationFlag = 0; esd->slConfig->useTimestampsFlag = 1; } //get the REF box if needed if (esd->dependsOnESID || esd->OCRESID ) { if (!trak->References) { tref = (GF_TrackReferenceBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TREF); e = trak_AddBox((GF_Box*)trak, (GF_Box *)tref); if (e) return e; } tref = trak->References; } //Update Stream dependancies e = Track_FindRef(trak, GF_ISOM_REF_DECODE, &dpnd); if (e) return e; if (!dpnd && esd->dependsOnESID) { dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_DPND); e = tref_AddBox((GF_Box*)tref, (GF_Box *) dpnd); if (e) return e; e = reftype_AddRefTrack(dpnd, esd->dependsOnESID, NULL); if (e) return e; } else if (dpnd && !esd->dependsOnESID) { Track_RemoveRef(trak, GF_ISOM_BOX_TYPE_DPND); } esd->dependsOnESID = 0; //Update GF_Clock dependancies e = Track_FindRef(trak, GF_ISOM_REF_OCR, &dpnd); if (e) return e; if (!dpnd && esd->OCRESID) { dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_SYNC); e = tref_AddBox((GF_Box*)tref, (GF_Box *) dpnd); if (e) return e; e = reftype_AddRefTrack(dpnd, esd->OCRESID, NULL); if (e) return e; } else if (dpnd && !esd->OCRESID) { Track_RemoveRef(trak, GF_ISOM_BOX_TYPE_SYNC); } else if (dpnd && esd->OCRESID) { if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA; dpnd->trackIDs[0] = esd->OCRESID; } esd->OCRESID = 0; //brand new case: we have to change the IPI desc if (esd->ipiPtr) { e = Track_FindRef(trak, GF_ISOM_REF_IPI, &dpnd); if (e) return e; if (!dpnd) { tmpRef = 0; dpnd = (GF_TrackReferenceTypeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_IPIR); e = tref_AddBox((GF_Box*)tref, (GF_Box *) dpnd); if (e) return e; e = reftype_AddRefTrack(dpnd, esd->ipiPtr->IPI_ES_Id, &tmpRef); if (e) return e; //and replace the tag and value... esd->ipiPtr->IPI_ES_Id = tmpRef; esd->ipiPtr->tag = GF_ODF_ISOM_IPI_PTR_TAG; } else { //Watch out! ONLY ONE IPI dependancy is allowed per stream if (dpnd->trackIDCount != 1) return GF_ISOM_INVALID_MEDIA; //if an existing one is there, what shall we do ??? //donno, erase it dpnd->trackIDs[0] = esd->ipiPtr->IPI_ES_Id; //and replace the tag and value... esd->ipiPtr->IPI_ES_Id = 1; esd->ipiPtr->tag = GF_ODF_ISOM_IPI_PTR_TAG; } } /*don't store the lang desc in ESD, use the media header language info*/ if (esd->langDesc) { trak->Media->mediaHeader->packedLanguage[0] = (esd->langDesc->langCode>>16)&0xFF; trak->Media->mediaHeader->packedLanguage[1] = (esd->langDesc->langCode>>8)&0xFF; trak->Media->mediaHeader->packedLanguage[2] = (esd->langDesc->langCode)&0xFF; gf_odf_desc_del((GF_Descriptor *)esd->langDesc); esd->langDesc = NULL; } //we have a streamDescritpionIndex, use it if (StreamDescriptionIndex) { entry = (GF_MPEGSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, StreamDescriptionIndex - 1); if (!entry) return GF_ISOM_INVALID_FILE; switch (entry->type) { case GF_ISOM_BOX_TYPE_MP4S: //OK, delete the previous ESD gf_odf_desc_del((GF_Descriptor *) entry->esd->desc); entry->esd->desc = esd; break; case GF_ISOM_BOX_TYPE_MP4V: entry_v = (GF_MPEGVisualSampleEntryBox*) entry; //OK, delete the previous ESD gf_odf_desc_del((GF_Descriptor *) entry_v->esd->desc); entry_v->esd->desc = esd; break; case GF_ISOM_BOX_TYPE_MP4A: entry_a = (GF_MPEGAudioSampleEntryBox*) entry; //OK, delete the previous ESD gf_odf_desc_del((GF_Descriptor *) entry_a->esd->desc); entry_a->esd->desc = esd; break; case GF_ISOM_BOX_TYPE_AVC1: e = AVC_UpdateESD((GF_MPEGVisualSampleEntryBox*)entry, esd); if (e) return e; break; default: gf_odf_desc_del((GF_Descriptor *) esd); break; } } else { //need to check we're not in URL mode where only ONE description is allowed... StreamDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); if (StreamDescriptionIndex) { entry = (GF_MPEGSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, StreamDescriptionIndex - 1); if (!entry) return GF_ISOM_INVALID_FILE; if (entry->esd->desc->URLString) return GF_BAD_PARAM; } //OK, check the handler and create the entry switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_VISUAL: if (esd->decoderConfig->objectTypeIndication==0x21) { entry_v = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_AVC1); if (!entry_v) return GF_OUT_OF_MEM; e = AVC_UpdateESD((GF_MPEGVisualSampleEntryBox*)entry_v, esd); } else { entry_v = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MP4V); if (!entry_v) return GF_OUT_OF_MEM; entry_v->esd = (GF_ESDBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_ESDS); entry_v->esd->desc = esd; } //type cast possible now entry = (GF_MPEGSampleEntryBox*) entry_v; break; case GF_ISOM_MEDIA_AUDIO: entry_a = (GF_MPEGAudioSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MP4A); entry_a->samplerate_hi = trak->Media->mediaHeader->timeScale; if (!entry_a) return GF_OUT_OF_MEM; entry_a->esd = (GF_ESDBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_ESDS); entry_a->esd->desc = esd; //type cast possible now entry = (GF_MPEGSampleEntryBox*) entry_a; break; default: entry = (GF_MPEGSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MP4S); entry->esd = (GF_ESDBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_ESDS); entry->esd->desc = esd; break; } entry->dataReferenceIndex = DataReferenceIndex; //and add the entry to our table... e = stsd_AddBox(trak->Media->information->sampleTable->SampleDescription, (GF_Box *) entry); if (e) return e; if(outStreamIndex) *outStreamIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); } return GF_OK;}#endif //GPAC_READ_ONLY
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -