📄 rtp_depacketizer.c
字号:
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(rtp->inter_bs)); gf_bs_write_u8(bs, rtp->sidx); gf_bs_write_u24(bs, rtp->sl_hdr.au_duration); gf_bs_write_u16(bs, rtp->txt_len); gf_bs_get_content(bs, &data, &data_size); gf_bs_del(bs); rtp->on_sl_packet(rtp->udta, data, data_size, &rtp->sl_hdr, GF_OK); free(data); rtp->sl_hdr.accessUnitStartFlag = 0; rtp->sl_hdr.accessUnitEndFlag = 1; gf_bs_get_content(rtp->inter_bs, &data, &data_size); rtp->on_sl_packet(rtp->udta, data, data_size, &rtp->sl_hdr, GF_OK); free(data); gf_bs_del(rtp->inter_bs); rtp->inter_bs = NULL; rtp->nb_txt_frag = rtp->cur_txt_frag = rtp->sidx = rtp->txt_len = rtp->nb_mod_frag = 0;}static void gf_rtp_parse_ttxt(GF_RTPDepacketizer *rtp, 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*/ gf_rtp_ttxt_flush(rtp, (u32) rtp->sl_hdr.compositionTimeStamp); /*bad ttu(1)*/ if (ttu_len<8) break; rtp->sl_hdr.compositionTimeStamp = ts; rtp->sl_hdr.compositionTimeStampFlag = 1; rtp->sl_hdr.accessUnitStartFlag = 1; rtp->sl_hdr.accessUnitEndFlag = 1; rtp->sl_hdr.randomAccessPointFlag = 1; gf_bs_read_u8(bs); rtp->sl_hdr.au_duration = gf_bs_read_u24(bs); rtp->on_sl_packet(rtp->udta, payload + pay_start, ttu_len + 1, &rtp->sl_hdr, GF_OK); gf_bs_skip_bytes(bs, ttu_len - 6); ts += rtp->sl_hdr.au_duration; } /*text segment*/ else if (type==2) { /*TS changed, flush packet*/ if (rtp->sl_hdr.compositionTimeStamp < ts) { gf_rtp_ttxt_flush(rtp, (u32) rtp->sl_hdr.compositionTimeStamp); } if (ttu_len<9) break; rtp->sl_hdr.compositionTimeStamp = ts; rtp->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 (!rtp->nb_txt_frag) { rtp->nb_txt_frag = nb_frag; rtp->cur_txt_frag = 0; rtp->sidx = sidx; } /*flush prev if any mismatch*/ if ((nb_frag != rtp->nb_txt_frag) || (rtp->cur_txt_frag > cur_frag)) { gf_rtp_ttxt_flush(rtp, (u32) rtp->sl_hdr.compositionTimeStamp); rtp->nb_txt_frag = nb_frag; rtp->sidx = sidx; } if (!rtp->inter_bs) rtp->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*/ rtp->cur_txt_frag = cur_frag; gf_bs_write_data(rtp->inter_bs, payload+10, txt_size); gf_bs_skip_bytes(bs, txt_size); rtp->sl_hdr.au_duration = duration; /*done*/ if (hdr->Marker) { rtp->txt_len = (u32) gf_bs_get_position(rtp->inter_bs); gf_rtp_ttxt_flush(rtp, ts); } } else if ((type==3) || (type==4)) { if (!rtp->inter_bs) rtp->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); /*first modifier, store effective written text*/ if (type==3) rtp->txt_len = (u32) gf_bs_get_position(rtp->inter_bs); if (ttu_len<6) break; nb_frag = gf_bs_read_int(bs, 4); if (!rtp->nb_mod_frag) rtp->nb_mod_frag = nb_frag; else if (rtp->nb_mod_frag != nb_frag) { gf_rtp_ttxt_flush(rtp, (u32) rtp->sl_hdr.compositionTimeStamp); rtp->nb_mod_frag = nb_frag; } gf_bs_read_int(bs, 4); /*cur_frag, ignore*/ rtp->sl_hdr.au_duration = gf_bs_read_u24(bs); gf_bs_write_data(rtp->inter_bs, payload+7, ttu_len-6); gf_bs_skip_bytes(bs, ttu_len-6); /*done*/ if (hdr->Marker) gf_rtp_ttxt_flush(rtp, ts); } } gf_bs_del(bs);}static void gf_rtp_h264_flush(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, Bool missed_end){ char *data; u32 data_size, nal_s; if (!rtp->inter_bs) return; data = NULL; data_size = 0; gf_bs_get_content(rtp->inter_bs, &data, &data_size); gf_bs_del(rtp->inter_bs); rtp->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; rtp->sl_hdr.accessUnitEndFlag = hdr->Marker; rtp->sl_hdr.compositionTimeStampFlag = 1; rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp; rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp; rtp->sl_hdr.decodingTimeStampFlag = 1; rtp->on_sl_packet(rtp->udta, data, data_size, &rtp->sl_hdr, GF_OK); rtp->sl_hdr.accessUnitStartFlag = 0; rtp->sl_hdr.randomAccessPointFlag = 0; free(data);}static void gf_rtp_parse_h264(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *payload, u32 size){ char nalhdr[4]; u32 nal_type; if (rtp->h264_pck_mode==2) return; nal_type = payload[0] & 0x1F; /*set start*/ if (rtp->sl_hdr.compositionTimeStamp != hdr->TimeStamp) { rtp->sl_hdr.accessUnitEndFlag = 0; rtp->sl_hdr.accessUnitStartFlag = 1; rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp; rtp->sl_hdr.compositionTimeStampFlag = 1; rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp; rtp->sl_hdr.decodingTimeStampFlag = 1; rtp->sl_hdr.randomAccessPointFlag = 0; } /*single NALU*/ if (nal_type<23) { if (nal_type==5) { rtp->sl_hdr.randomAccessPointFlag = 1; rtp->flags &= ~GF_RTP_AVC_WAIT_RAP; } else if (rtp->flags & GF_RTP_AVC_WAIT_RAP) return; rtp->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; rtp->on_sl_packet(rtp->udta, nalhdr, 4, &rtp->sl_hdr, GF_OK); rtp->sl_hdr.accessUnitStartFlag = 0; rtp->sl_hdr.compositionTimeStampFlag = 0; rtp->sl_hdr.accessUnitEndFlag = hdr->Marker; /*send NAL payload*/ rtp->on_sl_packet(rtp->udta, payload, size, &rtp->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) { rtp->sl_hdr.randomAccessPointFlag = 1; rtp->flags &= ~GF_RTP_AVC_WAIT_RAP; } if (rtp->flags & GF_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) { rtp->on_sl_packet(rtp->udta, nalhdr, 4, &rtp->sl_hdr, GF_OK); rtp->sl_hdr.accessUnitStartFlag = 0; rtp->sl_hdr.compositionTimeStampFlag = 0; } rtp->sl_hdr.accessUnitEndFlag = (hdr->Marker && (offset+nal_size==size)) ? 1 : 0; if (send) rtp->on_sl_packet(rtp->udta, payload+offset, nal_size, &rtp->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) gf_rtp_h264_flush(rtp, hdr, 1); if ((payload[1] & 0x1F) == 5) { rtp->flags &= ~GF_RTP_AVC_WAIT_RAP; rtp->sl_hdr.randomAccessPointFlag = 1; } else if (rtp->flags & GF_RTP_AVC_WAIT_RAP) return; /*setup*/ if (!rtp->inter_bs) { u8 nal_hdr; rtp->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(rtp->inter_bs, 0); gf_bs_write_u8(rtp->inter_bs, nal_hdr); } gf_bs_write_data(rtp->inter_bs, payload+2, size-2); if (is_end || hdr->Marker) gf_rtp_h264_flush(rtp, hdr, 0); }}static void gf_rtp_parse_latm(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *payload, u32 size){ u32 remain, latm_hdr_size, latm_size; rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp; rtp->sl_hdr.compositionTimeStampFlag = 1; rtp->sl_hdr.accessUnitStartFlag = rtp->sl_hdr.accessUnitEndFlag = 1; rtp->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; } rtp->on_sl_packet(rtp->udta, (char *) payload, latm_size, &rtp->sl_hdr, GF_OK); payload += latm_size; remain -= (latm_size+latm_hdr_size); rtp->sl_hdr.compositionTimeStamp += rtp->sl_hdr.au_duration; }}static u32 gf_rtp_get_payload_type(GF_RTPMap *map, GF_SDPMedia *media){ u32 i, j; if (!stricmp(map->payload_name, "MP4V-ES") ) return GF_RTP_PAYT_MPEG4; else if (!stricmp(map->payload_name, "mpeg4-generic")) return GF_RTP_PAYT_MPEG4; else if (!stricmp(map->payload_name, "enc-mpeg4-generic")) return GF_RTP_PAYT_MPEG4; /*optibase mm400 card hack*/ else if (!stricmp(map->payload_name, "enc-generic-mp4") ) { free(map->payload_name); map->payload_name = strdup("enc-mpeg4-generic"); return GF_RTP_PAYT_MPEG4; } /*LATM: only without multiplexing (not tested but should be straight AUs)*/ else if (!stricmp(map->payload_name, "MP4A-LATM")) { GF_SDP_FMTP *fmtp; i=0; while ((fmtp = (GF_SDP_FMTP *) gf_list_enum(media->FMTP, &i))) { GF_X_Attribute *att; if (fmtp->PayloadType != map->PayloadType) continue; //this is our payload. check cpresent is 0 j=0; while ((att = (GF_X_Attribute *)gf_list_enum(fmtp->Attributes, &j))) { if (!stricmp(att->Name, "cpresent") && atoi(att->Value)) return 0; } } return GF_RTP_PAYT_LATM; } else if (!stricmp(map->payload_name, "MPA")) return GF_RTP_PAYT_MPEG12_AUDIO; else if (!stricmp(map->payload_name, "MPV")) return GF_RTP_PAYT_MPEG12_VIDEO; else if (!stricmp(map->payload_name, "H263-1998") || !stricmp(map->payload_name, "H263-2000")) return GF_RTP_PAYT_H263; else if (!stricmp(map->payload_name, "AMR")) return GF_RTP_PAYT_AMR; else if (!stricmp(map->payload_name, "AMR-WB")) return GF_RTP_PAYT_AMR_WB; else if (!stricmp(map->payload_name, "3gpp-tt")) return GF_RTP_PAYT_3GPP_TEXT; else if (!stricmp(map->payload_name, "H264")) return GF_RTP_PAYT_H264_AVC; else return 0;}static GF_Err payt_set_param(GF_RTPDepacketizer *rtp, char *param_name, char *param_val){ u32 i, val; char valS[3]; GF_BitStream *bs; if (!rtp || !param_name) return GF_BAD_PARAM; /*1 - mpeg4-generic / RFC 3016 payload type items*/ /*PL (not needed when IOD is here)*/ if (!stricmp(param_name, "Profile-level-id")) { if (rtp->payt == GF_RTP_PAYT_H264_AVC) { sscanf(param_val, "%x", &rtp->sl_map.PL_ID); } else { rtp->sl_map.PL_ID = atoi(param_val); } } /*decoder specific info (not needed when IOD is here)*/ else if (!stricmp(param_name, "config")) { u32 len = strlen(param_val); //decode the buffer - the string buffer is MSB hexadecimal bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); valS[2] = 0; for (i=0; i<len;i+=2) { valS[0] = param_val[i]; valS[1] = param_val[i+1]; sscanf(valS, "%x", &val); gf_bs_write_u8(bs, val); } if (rtp->sl_map.config) free(rtp->sl_map.config); rtp->sl_map.config = NULL; gf_bs_get_content(bs, &rtp->sl_map.config, &rtp->sl_map.configSize); gf_bs_del(bs); } /*mpeg4-generic payload type items required*/ /*constant size (size of all AUs) */ else if (!stricmp(param_name, "ConstantSize")) { rtp->sl_map.ConstantSize = atoi(param_val); } /*constant size (size of all AUs) */ else if (!stricmp(param_name, "ConstantDuration")) { rtp->sl_map.ConstantDuration = atoi(param_val); } /*object type indication (not needed when IOD is here)*/ else if (!stricmp(param_name, "ObjectType")) { rtp->sl_map.ObjectTypeIndication = atoi(param_val); } else if (!stricmp(param_name, "StreamType")) rtp->sl_map.StreamType = atoi(param_val); else if (!stricmp(param_name, "mode")) { strcpy(rtp->sl_map.mode, param_val); /*in case no IOD and no streamType/OTI in the file*/ if (!stricmp(param_val, "AAC-hbr") || !stricmp(param_val, "AAC-lbr") || !stricmp(param_val, "CELP-vbr") || !stricmp(param_val, "CELP-cbr")) { rtp->sl_map.StreamType = GF_STREAM_AUDIO; rtp->sl_map.ObjectTypeIndication = 0x40; } } else if (!stricmp(param_name, "DTSDeltaLength")) rtp->sl_map.DTSDeltaLength = atoi(param_val); else if (!stricmp(param_name, "CTSDeltaLength")) rtp->sl_map.CTSDeltaLength = atoi(param_val); else if (!stricmp(param_name, "SizeLength")) rtp->sl_map.SizeLength = atoi(param_val); else if (!stricmp(param_name, "IndexLength")) rtp->sl_map.IndexLength = atoi(param_val); else if (!stricmp(param_name, "IndexDeltaLength")) rtp->sl_map.IndexDeltaLength = atoi(param_val); else if (!stricmp(param_name, "RandomAccessIndication")) rtp->sl_map.RandomAccessIndication = atoi(param_val); else if (!stricmp(param_name, "StreamStateIndication")) rtp->sl_map.StreamStateIndication = atoi(param_val); else if (!stricmp(param_name, "AuxiliaryDataSizeLength")) rtp->sl_map.AuxiliaryDataSizeLength = atoi(param_val); /*H264/AVC config - we only handle mode 0 and 1*/ else if (!stricmp(param_name, "packetization-mode")) rtp->h264_pck_mode = 1; /*AMR config*/ else if (!stricmp(param_name, "octet-align")) rtp->flags |= GF_RTP_AMR_ALIGN; /*ISMACryp config*/ else if (!stricmp(param_name, "ISMACrypCryptoSuite")) { if (!stricmp(param_val, "AES_CTR_128")) rtp->isma_scheme = GF_4CC('i','A','E','C'); else rtp->isma_scheme = 0; } else if (!stricmp(param_name, "ISMACrypSelectiveEncryption")) { if (!stricmp(param_val, "1") || !stricmp(param_val, "true")) rtp->flags |= GF_RTP_ISMA_SEL_ENC; else rtp->flags &= ~GF_RTP_ISMA_SEL_ENC; } else if (!stricmp(param_name, "ISMACrypIVLength")) rtp->sl_map.IV_length = atoi(param_val); else if (!stricmp(param_name, "ISMACrypDeltaIVLength")) rtp->sl_map.IV_delta_length = atoi(param_val); else if (!stricmp(param_name, "ISMACrypKeyIndicatorLength")) rtp->sl_map.KI_length = atoi(param_val); else if (!stricmp(param_name, "ISMACrypKeyIndicatorPerAU")) { if (!stricmp(param_val, "1") || !stricmp(param_val, "true")) rtp->flags |= GF_RTP_ISMA_HAS_KEY_IDX; else rtp->flags &= ~GF_RTP_ISMA_HAS_KEY_IDX; } else if (!stricmp(param_name, "ISMACrypKey")) rtp->key = strdup(param_val); return GF_OK;}static GF_Err gf_rtp_payt_setup(GF_RTPDepacketizer *rtp, GF_RTPMap *map, GF_SDPMedia *media){ u32 i, j; GF_SDP_FMTP *fmtp; /*reset sl map*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -