📄 hinting.c
字号:
return GF_OK;}GF_Err Write_ImmediateDTE(GF_ImmediateDTE *dte, GF_BitStream *bs){ char data[14]; gf_bs_write_u8(bs, dte->source); gf_bs_write_u8(bs, dte->dataLength); gf_bs_write_data(bs, dte->data, dte->dataLength); if (dte->dataLength < 14) { memset(data, 0, 14); gf_bs_write_data(bs, data, 14 - dte->dataLength); } return GF_OK;}GF_Err Write_SampleDTE(GF_SampleDTE *dte, GF_BitStream *bs){ gf_bs_write_u8(bs, dte->source); gf_bs_write_u8(bs, dte->trackRefIndex); gf_bs_write_u16(bs, dte->dataLength); gf_bs_write_u32(bs, dte->sampleNumber); gf_bs_write_u32(bs, dte->byteOffset); gf_bs_write_u16(bs, dte->bytesPerComp); gf_bs_write_u16(bs, dte->samplesPerComp); return GF_OK;}GF_Err Write_StreamDescDTE(GF_StreamDescDTE *dte, GF_BitStream *bs){ gf_bs_write_u8(bs, dte->source); gf_bs_write_u8(bs, dte->trackRefIndex); gf_bs_write_u16(bs, dte->dataLength); gf_bs_write_u32(bs, dte->streamDescIndex); gf_bs_write_u32(bs, dte->byteOffset); gf_bs_write_u32(bs, dte->reserved); return GF_OK;}GF_Err WriteDTE(GF_GenericDTE *dte, GF_BitStream *bs){ switch (dte->source) { case 0: //nothing to do, it is an empty entry return Write_EmptyDTE((GF_EmptyDTE *)dte, bs); case 1: return Write_ImmediateDTE((GF_ImmediateDTE *)dte, bs); case 2: return Write_SampleDTE((GF_SampleDTE *)dte, bs); case 3: return Write_StreamDescDTE((GF_StreamDescDTE *)dte, bs); default: return GF_ISOM_INVALID_FILE; }}GF_Err OffsetDTE(GF_GenericDTE *dte, u32 offset, u32 HintSampleNumber){ GF_SampleDTE *sDTE; //offset shifting is only true for intra sample reference switch (dte->source) { case 2: break; default: return GF_OK; } sDTE = (GF_SampleDTE *)dte; //we only adjust for intra HintTrack reference if (sDTE->trackRefIndex != (s8) -1) return GF_OK; //and in the same sample if (sDTE->sampleNumber != HintSampleNumber) return GF_OK; sDTE->byteOffset += offset; return GF_OK;}GF_RTPPacket *gf_isom_hint_rtp_new(){ GF_RTPPacket *tmp = (GF_RTPPacket *)malloc(sizeof(GF_RTPPacket)); tmp->TLV = gf_list_new(); tmp->DataTable = gf_list_new(); tmp->B_bit = tmp->M_bit = tmp->P_bit = tmp->payloadType = tmp->payloadType = tmp->R_bit = tmp->X_bit = 0; tmp->relativeTransTime = 0; tmp->SequenceNumber = 0; return tmp;}void gf_isom_hint_rtp_del(GF_RTPPacket *ptr){ GF_GenericDTE *p; //the DTE while (gf_list_count(ptr->DataTable)) { p = (GF_GenericDTE *)gf_list_get(ptr->DataTable, 0); DelDTE(p); gf_list_rem(ptr->DataTable, 0); } gf_list_del(ptr->DataTable); //the TLV gf_isom_box_array_del(ptr->TLV); free(ptr);}GF_Err gf_isom_hint_rtp_read(GF_RTPPacket *ptr, GF_BitStream *bs){ GF_Err e; u8 hasTLV, type; u16 i, count; u32 TLVsize, tempSize; GF_GenericDTE *dte; GF_Box *a; ptr->relativeTransTime = gf_bs_read_u32(bs); //RTP Header //1- reserved fields gf_bs_read_int(bs, 2); ptr->P_bit = gf_bs_read_int(bs, 1); ptr->X_bit = gf_bs_read_int(bs, 1); gf_bs_read_int(bs, 4); ptr->M_bit = gf_bs_read_int(bs, 1); ptr->payloadType = gf_bs_read_int(bs, 7); ptr->SequenceNumber = gf_bs_read_u16(bs); gf_bs_read_int(bs, 13); hasTLV = gf_bs_read_int(bs, 1); ptr->B_bit = gf_bs_read_int(bs, 1); ptr->R_bit = gf_bs_read_int(bs, 1); count = gf_bs_read_u16(bs); //read the TLV if (hasTLV) { tempSize = 4; //TLVsize includes its field length TLVsize = gf_bs_read_u32(bs); while (tempSize < TLVsize) { e = gf_isom_parse_box(&a, bs); if (e) return e; gf_list_add(ptr->TLV, a); tempSize += (u32) a->size; } if (tempSize != TLVsize) return GF_ISOM_INVALID_FILE; } //read the DTEs for (i=0; i<count; i++) { Bool add_it = 0; type = gf_bs_read_u8(bs); dte = NewDTE(type); e = ReadDTE(dte, bs); if (e) return e; /*little opt, remove empty dte*/ switch (type) { case 1: if ( ((GF_ImmediateDTE *)dte)->dataLength) add_it = 1; break; case 2: if ( ((GF_SampleDTE *)dte)->dataLength) add_it = 1; break; case 3: if ( ((GF_StreamDescDTE *)dte)->dataLength) add_it = 1; break; } if (add_it) gf_list_add(ptr->DataTable, dte); else DelDTE(dte); } return GF_OK;}GF_Err gf_isom_hint_rtp_offset(GF_RTPPacket *ptr, u32 offset, u32 HintSampleNumber){ u32 count, i; GF_GenericDTE *dte; GF_Err e; count = gf_list_count(ptr->DataTable); for (i=0; i<count; i++) { dte = (GF_GenericDTE *)gf_list_get(ptr->DataTable, i); e = OffsetDTE(dte, offset, HintSampleNumber); if (e) return e; } return GF_OK;}//Gets the REAL size of the packet once rebuild, but without CSRC fields in the//headeru32 gf_isom_hint_rtp_length(GF_RTPPacket *ptr){ u32 size, count, i; GF_GenericDTE *dte; //64 bit header size = 8; //32 bit SSRC size += 4; count = gf_list_count(ptr->DataTable); for (i=0; i<count; i++) { dte = (GF_GenericDTE *)gf_list_get(ptr->DataTable, i); switch (dte->source) { case 0: break; case 1: size += ((GF_ImmediateDTE *)dte)->dataLength; break; case 2: size += ((GF_SampleDTE *)dte)->dataLength; break; case 3: size += ((GF_StreamDescDTE *)dte)->dataLength; break; } } return size;}#ifndef GPAC_READ_ONLYu32 gf_isom_hint_rtp_size(GF_RTPPacket *ptr){ GF_Box none; u32 size, count; //the RTP Header size and co size = 12; //the extra table size count = gf_list_count(ptr->TLV); if (count) { none.size = 4; //WE INCLUDE THE SIZE FIELD LENGTH none.type = 0; //REMEMBER THAT TLV ENTRIES ARE 4-BYTES ALIGNED !!! gf_isom_box_array_size(&none, ptr->TLV); size += (u32) none.size; } //the DTE (each entry is 16 bytes) count = gf_list_count(ptr->DataTable); size += count * 16; return size;}GF_Err gf_isom_hint_rtp_write(GF_RTPPacket *ptr, GF_BitStream *bs){ GF_Err e; u32 TLVcount, DTEcount, i; GF_Box none; GF_GenericDTE *dte; gf_bs_write_u32(bs, ptr->relativeTransTime); //RTP Header// gf_bs_write_int(bs, 2, 2); //version is 2 gf_bs_write_int(bs, 2, 2); gf_bs_write_int(bs, ptr->P_bit, 1); gf_bs_write_int(bs, ptr->X_bit, 1); gf_bs_write_int(bs, 0, 4); gf_bs_write_int(bs, ptr->M_bit, 1); gf_bs_write_int(bs, ptr->payloadType, 7); gf_bs_write_u16(bs, ptr->SequenceNumber); gf_bs_write_int(bs, 0, 13); TLVcount = gf_list_count(ptr->TLV); DTEcount = gf_list_count(ptr->DataTable); gf_bs_write_int(bs, TLVcount ? 1 : 0, 1); gf_bs_write_int(bs, ptr->B_bit, 1); gf_bs_write_int(bs, ptr->R_bit, 1); gf_bs_write_u16(bs, DTEcount); if (TLVcount) { //first write the size of the table ... none.size = 4; //WE INCLUDE THE SIZE FIELD LENGTH none.type = 0; gf_isom_box_array_size(&none, ptr->TLV); gf_bs_write_u32(bs, (u32) none.size); e = gf_isom_box_array_write(&none, ptr->TLV, bs); if (e) return e; } //write the DTE... for (i = 0; i < DTEcount; i++) { dte = (GF_GenericDTE *)gf_list_get(ptr->DataTable, i); e = WriteDTE(dte, bs); if (e) return e; } return GF_OK;}#endif //GPAC_READ_ONLYGF_EXPORTGF_Err gf_isom_reset_hint_reader(GF_ISOFile *the_file, u32 trackNumber, u32 sample_start, u32 ts_offset, u32 sn_offset, u32 ssrc){ GF_Err e; GF_TrackBox *trak; GF_HintSampleEntryBox *entry; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; if (!sample_start) return GF_BAD_PARAM; if (sample_start>=trak->Media->information->sampleTable->SampleSize->sampleCount) return GF_BAD_PARAM; e = Media_GetSampleDesc(trak->Media, 1, (GF_SampleEntryBox **) &entry, NULL); if (e) return e; switch (entry->type) { case GF_ISOM_BOX_TYPE_RTP_STSD: break; default: return GF_NOT_SUPPORTED; } entry->hint_ref = NULL; e = Track_FindRef(trak, GF_ISOM_REF_HINT, &entry->hint_ref); if (e) return e; entry->cur_sample = sample_start; entry->pck_sn = 1 + sn_offset; entry->ssrc = ssrc; entry->ts_offset = ts_offset; if (entry->hint_sample) gf_isom_hint_sample_del(entry->hint_sample); entry->hint_sample = NULL; return GF_OK;}static GF_Err gf_isom_load_next_hint_sample(GF_ISOFile *the_file, u32 trackNumber, GF_TrackBox *trak, GF_HintSampleEntryBox *entry){ GF_BitStream *bs; u32 descIdx; GF_ISOSample *samp; if (!entry->cur_sample) return GF_BAD_PARAM; if (entry->cur_sample>trak->Media->information->sampleTable->SampleSize->sampleCount) return GF_EOS; samp = gf_isom_get_sample(the_file, trackNumber, entry->cur_sample, &descIdx); if (!samp) return GF_IO_ERR; entry->cur_sample++; if (entry->hint_sample) gf_isom_hint_sample_del(entry->hint_sample); bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ); entry->hint_sample = gf_isom_hint_sample_new(entry->type); gf_isom_hint_sample_read(entry->hint_sample, bs, samp->dataLength); gf_bs_del(bs); entry->hint_sample->TransmissionTime = samp->DTS; gf_isom_sample_del(&samp); entry->hint_sample->sample_cache = gf_list_new(); return GF_OK;}static GF_ISOSample *gf_isom_get_data_sample(GF_HintSample *hsamp, GF_TrackBox *trak, u32 sample_num){ GF_ISOSample *samp; GF_HintDataCache *hdc; u32 i, count; count = gf_list_count(hsamp->sample_cache); for (i=0; i<count; i++) { hdc = (GF_HintDataCache *)gf_list_get(hsamp->sample_cache, i); if ((hdc->sample_num==sample_num) && (hdc->trak==trak)) return hdc->samp; } samp = gf_isom_sample_new(); Media_GetSample(trak->Media, sample_num, &samp, &i, 0, NULL); if (!samp) return NULL; GF_SAFEALLOC(hdc, GF_HintDataCache); hdc->samp = samp; hdc->sample_num = sample_num; hdc->trak = trak; /*we insert all new samples, since they're more likely to be fetched next (except for audio interleaving and other multiplex)*/ gf_list_insert(hsamp->sample_cache, hdc, 0); return samp;}GF_EXPORTGF_Err gf_isom_next_hint_packet(GF_ISOFile *the_file, u32 trackNumber, char **pck_data, u32 *pck_size, Bool *disposable, Bool *repeated, u32 *trans_ts, u32 *sample_num){ GF_RTPPacket *pck; GF_Err e; GF_BitStream *bs; GF_TrackBox *trak, *ref_trak; GF_HintSampleEntryBox *entry; u32 i, count, ts; s32 cts_off; *pck_data = NULL; *pck_size = 0; if (trans_ts) *trans_ts = 0; if (disposable) *disposable = 0; if (repeated) *repeated = 0; if (sample_num) *sample_num = 0; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; e = Media_GetSampleDesc(trak->Media, 1, (GF_SampleEntryBox **) &entry, NULL); if (e) return e; switch (entry->type) { case GF_ISOM_BOX_TYPE_RTP_STSD: break; default: return GF_NOT_SUPPORTED; } if (!entry->hint_sample) { e = gf_isom_load_next_hint_sample(the_file, trackNumber, trak, entry); if (e) return e; } pck = (GF_RTPPacket *)gf_list_get(entry->hint_sample->packetTable, 0); gf_list_rem(entry->hint_sample->packetTable, 0); if (!pck) return GF_BAD_PARAM; bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); /*write RTP header*/ gf_bs_write_int(bs, 2, 2); /*version*/ gf_bs_write_int(bs, pck->P_bit, 1); /*P bit*/ gf_bs_write_int(bs, pck->X_bit, 1); /*X bit*/ gf_bs_write_int(bs, 0, 4); /*CSRC count*/ gf_bs_write_int(bs, pck->M_bit, 1); /*M bit*/ gf_bs_write_int(bs, pck->payloadType, 7); /*payt*/ gf_bs_write_u16(bs, entry->pck_sn); /*seq num*/ entry->pck_sn++; /*look for CTS offset in TLV*/ cts_off = 0; count = gf_list_count(pck->TLV); for (i=0; i<count; i++) { GF_RTPOBox *rtpo = (GF_RTPOBox *)gf_list_get(pck->TLV, i); if (rtpo->type == GF_ISOM_BOX_TYPE_RTPO) { cts_off = rtpo->timeOffset; break; } } /*TS - TODO check TS wrapping*/ ts = (u32) (entry->hint_sample->TransmissionTime + pck->relativeTransTime + entry->ts_offset + cts_off); gf_bs_write_u32(bs, ts ); gf_bs_write_u32(bs, entry->ssrc); /*SSRC*/ /*then build all data*/ count = gf_list_count(pck->DataTable); for (i=0; i<count; i++) { GF_GenericDTE *dte = (GF_GenericDTE *)gf_list_get(pck->DataTable, i); switch (dte->source) { /*empty*/ case 0: break; /*immediate data*/ case 1: gf_bs_write_data(bs, ((GF_ImmediateDTE *)dte)->data, ((GF_ImmediateDTE *)dte)->dataLength); break; /*sample data*/ case 2: { GF_ISOSample *samp; GF_SampleDTE *sdte = (GF_SampleDTE *)dte; /*get track if not this one*/ if (sdte->trackRefIndex != (s8) -1) { if (!entry->hint_ref || !entry->hint_ref->trackIDs) { gf_isom_hint_rtp_del(pck); gf_bs_del(bs); return GF_ISOM_INVALID_FILE; } ref_trak = gf_isom_get_track_from_id(trak->moov, entry->hint_ref->trackIDs[(u32)sdte->trackRefIndex]); } else { ref_trak = trak; } samp = gf_isom_get_data_sample(entry->hint_sample, ref_trak, sdte->sampleNumber); if (!samp) { gf_isom_hint_rtp_del(pck); gf_bs_del(bs); return GF_IO_ERR; } gf_bs_write_data(bs, samp->data + sdte->byteOffset, sdte->dataLength); } break; /*sample desc data - currently NOT SUPPORTED !!!*/ case 3: break; } } if (trans_ts) *trans_ts = ts; if (disposable) *disposable = pck->B_bit; if (repeated) *repeated = pck->R_bit; if (sample_num) *sample_num = entry->cur_sample-1; gf_bs_get_content(bs, pck_data, pck_size); gf_bs_del(bs); gf_isom_hint_rtp_del(pck); if (!gf_list_count(entry->hint_sample->packetTable)) { gf_isom_hint_sample_del(entry->hint_sample); entry->hint_sample = NULL; } return GF_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -