📄 rtp_payloads.c
字号:
void RP_ParsePayloadAMR(RTPStream *ch, GF_RTPHeader *hdr, char *payload, u32 size){ unsigned char c, type; char *data; /*we support max 30 frames in one RTP packet...*/ u32 nbFrame, i, frame_size; /*not supported yet*/ if (!(ch->flags & RTP_AMR_ALIGN) ) return; /*process toc and locate start of payload data*/ nbFrame = 0; while (1) { c = payload[nbFrame + 1]; nbFrame++; if (!(c & 0x80)) break; } data = payload + nbFrame + 1; ch->sl_hdr.compositionTimeStamp = hdr->TimeStamp; /*then each frame*/ for (i=0; i<nbFrame; i++) { c = payload[i + 1]; type = ((c & 0x78) >> 3); if (ch->rtptype==GP_RTP_PAYT_AMR) { frame_size = GF_AMR_FRAME_SIZE[type]; } else { frame_size = GF_AMR_WB_FRAME_SIZE[type]; } ch->sl_hdr.compositionTimeStampFlag = 1; ch->sl_hdr.accessUnitStartFlag = 1; ch->sl_hdr.accessUnitEndFlag = 0; /*send TOC*/ gf_term_on_sl_packet(ch->owner->service, ch->channel, &payload[i+1], 1, &ch->sl_hdr, GF_OK); ch->sl_hdr.packetSequenceNumber ++; ch->sl_hdr.compositionTimeStampFlag = 0; ch->sl_hdr.accessUnitStartFlag = 0; ch->sl_hdr.accessUnitEndFlag = 1; /*send payload*/ gf_term_on_sl_packet(ch->owner->service, ch->channel, data, frame_size, &ch->sl_hdr, GF_OK); data += frame_size; ch->sl_hdr.compositionTimeStamp += 160; }}void RP_ParsePayloadH263(RTPStream *ch, GF_RTPHeader *hdr, char *payload, u32 size){ GF_BitStream *bs; Bool P_bit, V_bit; u32 plen, plen_bits, offset; char blank[2]; bs = gf_bs_new(payload, size, GF_BITSTREAM_READ); /*reserved*/ gf_bs_read_int(bs, 5); P_bit = gf_bs_read_int(bs, 1); V_bit = gf_bs_read_int(bs, 1); plen = gf_bs_read_int(bs, 6); plen_bits = gf_bs_read_int(bs, 3); /*VRC not supported yet*/ if (V_bit) { gf_bs_read_u8(bs); } /*extra picture header not supported yet*/ if (plen) { gf_bs_skip_bytes(bs, plen); } offset = (u32) gf_bs_get_position(bs); gf_bs_del(bs); blank[0] = blank[1] = 0; /*start*/ if (P_bit) { ch->sl_hdr.compositionTimeStamp = hdr->TimeStamp; ch->sl_hdr.compositionTimeStampFlag = 1; ch->sl_hdr.accessUnitStartFlag = 1; ch->sl_hdr.accessUnitEndFlag = 0; if (ch->sl_hdr.accessUnitStartFlag) { /*the first 16 bytes are NOT sent on the wire*/ ch->sl_hdr.randomAccessPointFlag = (payload[offset+2]&0x02) ? 0 : 1; } /*send missing start code*/ gf_term_on_sl_packet(ch->owner->service, ch->channel, (char *) blank, 2, &ch->sl_hdr, GF_OK); /*send payload*/ ch->sl_hdr.compositionTimeStampFlag = 0; ch->sl_hdr.accessUnitStartFlag = 0; ch->sl_hdr.randomAccessPointFlag = 0; /*if M bit set, end of frame*/ ch->sl_hdr.accessUnitEndFlag = hdr->Marker; gf_term_on_sl_packet(ch->owner->service, ch->channel, payload + offset, size - offset, &ch->sl_hdr, GF_OK); } else { /*middle/end of frames - if M bit set, end of frame*/ ch->sl_hdr.accessUnitEndFlag = hdr->Marker; gf_term_on_sl_packet(ch->owner->service, ch->channel, payload + offset, size - offset, &ch->sl_hdr, GF_OK); }}void rtp_ttxt_flush(RTPStream *ch, u32 ts){ GF_BitStream *bs; char *data; u32 data_size; if (!ch->inter_bs) return; ch->sl_hdr.compositionTimeStamp = ts; ch->sl_hdr.compositionTimeStampFlag = 1; ch->sl_hdr.accessUnitStartFlag = 1; ch->sl_hdr.accessUnitEndFlag = 0; ch->sl_hdr.randomAccessPointFlag = 1; bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_bs_write_int(bs, ch->sl_hdr.idleFlag, 1); ch->sl_hdr.idleFlag = 0; gf_bs_write_int(bs, 0, 4); gf_bs_write_int(bs, 1, 3); gf_bs_write_u16(bs, 8 + (u16) gf_bs_get_position(ch->inter_bs)); gf_bs_write_u8(bs, ch->sidx); gf_bs_write_u24(bs, ch->sl_hdr.au_duration); gf_bs_write_u16(bs, ch->txt_len); gf_bs_get_content(bs, &data, &data_size); gf_bs_del(bs); gf_term_on_sl_packet(ch->owner->service, ch->channel, data, data_size, &ch->sl_hdr, GF_OK); free(data); ch->sl_hdr.accessUnitStartFlag = 0; ch->sl_hdr.accessUnitEndFlag = 1; gf_bs_get_content(ch->inter_bs, &data, &data_size); gf_term_on_sl_packet(ch->owner->service, ch->channel, data, data_size, &ch->sl_hdr, GF_OK); free(data); gf_bs_del(ch->inter_bs); ch->inter_bs = NULL; ch->nb_txt_frag = ch->cur_txt_frag = ch->sidx = ch->txt_len = ch->nb_mod_frag = 0;}void RP_ParsePayloadText(RTPStream *ch, GF_RTPHeader *hdr, char *payload, u32 size){ Bool is_utf_16; u32 type, ttu_len, pay_start, duration, ts, sidx, txt_size; u32 nb_frag, cur_frag; GF_BitStream *bs; ts = hdr->TimeStamp; bs = gf_bs_new(payload, size, GF_BITSTREAM_READ); while (gf_bs_available(bs)) { pay_start = (u32) gf_bs_get_position(bs); is_utf_16 = gf_bs_read_int(bs, 1); gf_bs_read_int(bs, 4); type = gf_bs_read_int(bs, 3); ttu_len = gf_bs_read_u16(bs); if (ttu_len<2) break; if (type==1) { /*flush any existing packet*/ rtp_ttxt_flush(ch, (u32) ch->sl_hdr.compositionTimeStamp); /*bad ttu(1)*/ if (ttu_len<8) break; ch->sl_hdr.compositionTimeStamp = ts; ch->sl_hdr.compositionTimeStampFlag = 1; ch->sl_hdr.accessUnitStartFlag = 1; ch->sl_hdr.accessUnitEndFlag = 1; ch->sl_hdr.randomAccessPointFlag = 1; gf_bs_read_u8(bs); ch->sl_hdr.au_duration = gf_bs_read_u24(bs); gf_term_on_sl_packet(ch->owner->service, ch->channel, payload + pay_start, ttu_len + 1, &ch->sl_hdr, GF_OK); gf_bs_skip_bytes(bs, ttu_len - 6); ts += ch->sl_hdr.au_duration; } /*text segment*/ else if (type==2) { /*TS changed, flush packet*/ if (ch->sl_hdr.compositionTimeStamp < ts) { rtp_ttxt_flush(ch, (u32) ch->sl_hdr.compositionTimeStamp); } if (ttu_len<9) break; ch->sl_hdr.compositionTimeStamp = ts; ch->sl_hdr.idleFlag = is_utf_16; nb_frag = gf_bs_read_int(bs, 4); cur_frag = gf_bs_read_int(bs, 4); duration = gf_bs_read_u24(bs); sidx = gf_bs_read_u8(bs); gf_bs_read_u16(bs);/*complete text sample size, ignored*/ txt_size = size - 10; /*init - 3GPP/MPEG-4 spliting is IMHO stupid: - nb frag & cur frags are not needed: rtp reordering insures packet are in order, and !!!we assume fragments are sent in order!!! - any other TTU suffices to indicate end of text string (modifiers or != RTP TS) - replacing these 8bits field with a 16 bit absolute character offset would add error recovery */ if (!ch->nb_txt_frag) { ch->nb_txt_frag = nb_frag; ch->cur_txt_frag = 0; ch->sidx = sidx; } /*flush prev if any mismatch*/ if ((nb_frag != ch->nb_txt_frag) || (ch->cur_txt_frag>cur_frag)) { rtp_ttxt_flush(ch, (u32) ch->sl_hdr.compositionTimeStamp); ch->nb_txt_frag = nb_frag; ch->sidx = sidx; } if (!ch->inter_bs) ch->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); /*we don't reorder - RTP reordering is done at lower level, if this is out of order too bad*/ ch->cur_txt_frag = cur_frag; gf_bs_write_data(ch->inter_bs, payload+10, txt_size); gf_bs_skip_bytes(bs, txt_size); ch->sl_hdr.au_duration = duration; /*done*/ if (hdr->Marker) { ch->txt_len = (u32) gf_bs_get_position(ch->inter_bs); rtp_ttxt_flush(ch, ts); } } else if ((type==3) || (type==4)) { if (!ch->inter_bs) ch->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); /*first modifier, store effective written text*/ if (type==3) ch->txt_len = (u32) gf_bs_get_position(ch->inter_bs); if (ttu_len<6) break; nb_frag = gf_bs_read_int(bs, 4); if (!ch->nb_mod_frag) ch->nb_mod_frag = nb_frag; else if (ch->nb_mod_frag != nb_frag) { rtp_ttxt_flush(ch, (u32) ch->sl_hdr.compositionTimeStamp); ch->nb_mod_frag = nb_frag; } gf_bs_read_int(bs, 4); /*cur_frag, ignore*/ ch->sl_hdr.au_duration = gf_bs_read_u24(bs); gf_bs_write_data(ch->inter_bs, payload+7, ttu_len-6); gf_bs_skip_bytes(bs, ttu_len-6); /*done*/ if (hdr->Marker) rtp_ttxt_flush(ch, ts); } } gf_bs_del(bs);}static void rtp_avc_flush(RTPStream*ch, GF_RTPHeader *hdr, Bool missed_end){ char *data; u32 data_size, nal_s; if (!ch->inter_bs) return; data = NULL; data_size = 0; gf_bs_get_content(ch->inter_bs, &data, &data_size); gf_bs_del(ch->inter_bs); ch->inter_bs = NULL; nal_s = data_size-4; data[0] = nal_s>>24; data[1] = nal_s>>16; data[2] = nal_s>>8; data[3] = nal_s&0xFF; /*set F-bit since nal is corrupted*/ if (missed_end) data[4] |= 0x80; ch->sl_hdr.accessUnitEndFlag = hdr->Marker; ch->sl_hdr.compositionTimeStampFlag = 1; ch->sl_hdr.compositionTimeStamp = hdr->TimeStamp; ch->sl_hdr.decodingTimeStamp = hdr->TimeStamp; ch->sl_hdr.decodingTimeStampFlag = 1; gf_term_on_sl_packet(ch->owner->service, ch->channel, data, data_size, &ch->sl_hdr, GF_OK); ch->sl_hdr.accessUnitStartFlag = 0; ch->sl_hdr.randomAccessPointFlag = 0; free(data);}void RP_ParsePayloadH264(RTPStream *ch, GF_RTPHeader *hdr, char *payload, u32 size){ char nalhdr[4]; u32 nal_type; if (ch->packetization_mode==2) return; nal_type = payload[0] & 0x1F; /*set start*/ if (ch->sl_hdr.compositionTimeStamp != hdr->TimeStamp) { ch->sl_hdr.accessUnitEndFlag = 0; ch->sl_hdr.accessUnitStartFlag = 1; ch->sl_hdr.compositionTimeStamp = hdr->TimeStamp; ch->sl_hdr.compositionTimeStampFlag = 1; ch->sl_hdr.decodingTimeStamp = hdr->TimeStamp; ch->sl_hdr.decodingTimeStampFlag = 1; ch->sl_hdr.randomAccessPointFlag = 0; } /*single NALU*/ if (nal_type<23) { if (nal_type==5) { ch->sl_hdr.randomAccessPointFlag = 1; ch->flags &= ~RTP_AVC_WAIT_RAP; } else if (ch->flags & RTP_AVC_WAIT_RAP) return; ch->sl_hdr.accessUnitEndFlag = 0; /*signal NALU size on 4 bytes*/ nalhdr[0] = size>>24; nalhdr[1] = size>>16; nalhdr[2] = size>>8; nalhdr[3] = size&0xFF; gf_term_on_sl_packet(ch->owner->service, ch->channel, nalhdr, 4, &ch->sl_hdr, GF_OK); ch->sl_hdr.accessUnitStartFlag = 0; ch->sl_hdr.compositionTimeStampFlag = 0; ch->sl_hdr.accessUnitEndFlag = hdr->Marker; /*send NAL payload*/ gf_term_on_sl_packet(ch->owner->service, ch->channel, payload, size, &ch->sl_hdr, GF_OK); } /*STAP-A NALU*/ else if (nal_type==24) { u32 offset = 1; while (offset<size) { Bool send = 1; u32 nal_size = (u8) payload[offset]; nal_size<<=8; nal_size |= (u8) payload[offset+1]; offset += 2; if ((payload[offset] & 0x1F) == 5) { ch->sl_hdr.randomAccessPointFlag = 1; ch->flags &= ~RTP_AVC_WAIT_RAP; } if (ch->flags & RTP_AVC_WAIT_RAP) send = 0; /*signal NALU size on 4 bytes*/ nalhdr[0] = nal_size>>24; nalhdr[1] = nal_size>>16; nalhdr[2] = nal_size>>8; nalhdr[3] = nal_size&0xFF; if (send) { gf_term_on_sl_packet(ch->owner->service, ch->channel, nalhdr, 4, &ch->sl_hdr, GF_OK); ch->sl_hdr.accessUnitStartFlag = 0; ch->sl_hdr.compositionTimeStampFlag = 0; } ch->sl_hdr.accessUnitEndFlag = (hdr->Marker && (offset+nal_size==size)) ? 1 : 0; if (send) gf_term_on_sl_packet(ch->owner->service, ch->channel, payload+offset, nal_size, &ch->sl_hdr, GF_OK); offset += nal_size; } } /*FU-A NALU*/ else if (nal_type==28) { Bool is_start = payload[1] & 0x80; Bool is_end = payload[1] & 0x40; /*flush*/ if (is_start) rtp_avc_flush(ch, hdr, 1); if ((payload[1] & 0x1F) == 5) { ch->flags &= ~RTP_AVC_WAIT_RAP; ch->sl_hdr.randomAccessPointFlag = 1; } else if (ch->flags & RTP_AVC_WAIT_RAP) return; /*setup*/ if (!ch->inter_bs) { u8 nal_hdr; ch->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); /*copy F and NRI*/ nal_hdr = payload[0] & 0xE0; /*start bit not set, signal corrupted data (we missed start packet)*/ if (!is_start) nal_hdr |= 0x80; /*copy NALU type*/ nal_hdr |= (payload[1] & 0x1F); /*dummy size field*/ gf_bs_write_u32(ch->inter_bs, 0); gf_bs_write_u8(ch->inter_bs, nal_hdr); } gf_bs_write_data(ch->inter_bs, payload+2, size-2); if (is_end || hdr->Marker) rtp_avc_flush(ch, hdr, 0); }}void RP_ParsePayloadLATM(RTPStream *ch, GF_RTPHeader *hdr, char *payload, u32 size){ u32 remain, latm_hdr_size, latm_size; ch->sl_hdr.compositionTimeStamp = hdr->TimeStamp; ch->sl_hdr.compositionTimeStampFlag = 1; ch->sl_hdr.accessUnitStartFlag = ch->sl_hdr.accessUnitEndFlag = 1; ch->sl_hdr.randomAccessPointFlag = 1; remain = size; while (remain) { latm_hdr_size = latm_size = 0; while (1) { u8 c = *payload; latm_hdr_size += 1; latm_size += c; payload ++; if (c < 0xFF) break; } gf_term_on_sl_packet(ch->owner->service, ch->channel, (char *) payload, latm_size, &ch->sl_hdr, GF_OK); payload += latm_size; remain -= (latm_size+latm_hdr_size); ch->sl_hdr.compositionTimeStamp += ch->unit_duration; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -