📄 rtp_depacketizer.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / RTP input module * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/internal/ietf_dev.h>#include <gpac/esi.h>#include <gpac/base_coding.h>#include <gpac/constants.h>#include <gpac/mpeg4_odf.h>#include <gpac/avparse.h>static void gf_rtp_parse_mpeg4(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *payload, u32 size){ u32 aux_size, au_size, first_idx, au_hdr_size, pay_start, num_au; s32 au_idx; GF_BitStream *hdr_bs, *aux_bs; hdr_bs = gf_bs_new(payload, size, GF_BITSTREAM_READ); aux_bs = gf_bs_new(payload, size, GF_BITSTREAM_READ);// printf("parsing packet %d size %d ts %d M %d\n", hdr->SequenceNumber, size, hdr->TimeStamp, hdr->Marker); /*global AU header len*/ au_hdr_size = 0; if (rtp->sl_map.auh_first_min_len) { au_hdr_size = gf_bs_read_u16(hdr_bs); gf_bs_read_u16(aux_bs); } /*jump to aux section, skip it and get payload start*/ gf_bs_read_int(aux_bs, au_hdr_size); gf_bs_align(aux_bs); if (rtp->sl_map.AuxiliaryDataSizeLength) { aux_size = gf_bs_read_int(aux_bs, rtp->sl_map.AuxiliaryDataSizeLength); gf_bs_read_int(aux_bs, aux_size); gf_bs_align(aux_bs); } pay_start = (u32) gf_bs_get_position(aux_bs); gf_bs_del(aux_bs); first_idx = 0; au_idx = 0; rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp; rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp; num_au = 0; rtp->sl_hdr.accessUnitEndFlag = hdr->Marker; /*override some defaults for RFC 3016*/ if (rtp->flags & GF_RTP_NEW_AU) { rtp->sl_hdr.accessUnitStartFlag = 1; } else { rtp->sl_hdr.accessUnitStartFlag = 0; } rtp->sl_hdr.randomAccessPointFlag = 0; while (1) { /*get default AU size*/ au_size = rtp->sl_map.ConstantSize; /*not signaled, assume max one AU per packet*/ if (!au_size) au_size = size - pay_start; if ((!num_au && rtp->sl_map.auh_first_min_len) || (num_au && rtp->sl_map.auh_min_len)) { /*ISMACryp*/ if (rtp->flags & GF_RTP_HAS_ISMACRYP) { rtp->sl_hdr.isma_encrypted = 1; if (rtp->flags & GF_RTP_ISMA_SEL_ENC) { rtp->sl_hdr.isma_encrypted = gf_bs_read_int(hdr_bs, 1); gf_bs_read_int(hdr_bs, 7); } /*Note: ISMACryp ALWAYS indicates IV (BSO) and KEYIDX, even when sample is not encrypted. This is quite a waste when using selective encryption....*/ if (!num_au) { rtp->sl_hdr.isma_BSO = gf_bs_read_int(hdr_bs, 8*rtp->sl_map.IV_length); } /*NOT SUPPORTED YET*/ else if (rtp->sl_map.IV_delta_length) { rtp->sl_hdr.isma_BSO += gf_bs_read_int(hdr_bs, 8*rtp->sl_map.IV_delta_length); } if (rtp->sl_map.KI_length) { /*NOT SUPPORTED YET*/ if (!num_au || !(rtp->flags & GF_RTP_ISMA_HAS_KEY_IDX) ) { gf_bs_skip_bytes(hdr_bs, rtp->sl_map.KI_length); } } } /*AU size*/ if (rtp->sl_map.SizeLength) { au_size = gf_bs_read_int(hdr_bs, rtp->sl_map.SizeLength); if (au_size > size - pay_start) au_size = size - pay_start; au_hdr_size -= rtp->sl_map.SizeLength; } /*AU index*/ if (! num_au) { au_idx = first_idx = gf_bs_read_int(hdr_bs, rtp->sl_map.IndexLength); au_hdr_size -= rtp->sl_map.IndexLength; } else { au_idx += 1 + (s32) gf_bs_read_int(hdr_bs, rtp->sl_map.IndexDeltaLength); au_hdr_size -= rtp->sl_map.IndexDeltaLength; } /*CTS flag*/ if (rtp->sl_map.CTSDeltaLength) { rtp->sl_hdr.compositionTimeStampFlag = gf_bs_read_int(hdr_bs, 1); au_hdr_size -= 1; } else { /*get CTS from IDX*/ if (rtp->sl_map.ConstantDuration) { rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp + (au_idx - first_idx) * rtp->sl_map.ConstantDuration; } else { rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp + (au_idx - first_idx) * rtp->sl_hdr.au_duration; } } /*CTS in-band*/ if (rtp->sl_hdr.compositionTimeStampFlag) { rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp + (s32) gf_bs_read_int(hdr_bs, rtp->sl_map.CTSDeltaLength); au_hdr_size -= rtp->sl_map.CTSDeltaLength; } /*DTS flag is always present (needed for reconstruction of TSs in case of packet loss)*/ if (rtp->sl_map.DTSDeltaLength) { rtp->sl_hdr.decodingTimeStampFlag = gf_bs_read_int(hdr_bs, 1); au_hdr_size -= 1; } else { /*NO DTS otherwise*/ rtp->sl_hdr.decodingTimeStampFlag = 0; } if (rtp->sl_hdr.decodingTimeStampFlag) { u32 ts_off = gf_bs_read_int(hdr_bs, rtp->sl_map.DTSDeltaLength); /*TODO FIXME may not be true in case of TS wrapping*/ if (hdr->TimeStamp > ts_off) rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp - ts_off; au_hdr_size -= rtp->sl_map.DTSDeltaLength; } /*RAP flag*/ if (rtp->sl_map.RandomAccessIndication) { rtp->sl_hdr.randomAccessPointFlag = gf_bs_read_int(hdr_bs, 1); au_hdr_size -= 1; } /*stream state - map directly to seqNum*/ if (rtp->sl_map.StreamStateIndication) { rtp->sl_hdr.AU_sequenceNumber = gf_bs_read_int(hdr_bs, rtp->sl_map.StreamStateIndication); au_hdr_size -= rtp->sl_map.StreamStateIndication; } else { rtp->sl_hdr.AU_sequenceNumber = au_idx; } } /*no header present, update CTS/DTS - note we're sure there's no interleaving*/ else { if (num_au) { rtp->sl_hdr.compositionTimeStamp += rtp->sl_map.ConstantDuration; rtp->sl_hdr.decodingTimeStamp += rtp->sl_map.ConstantDuration; } } /*we cannot map RTP SN to SL SN since an RTP packet may carry several SL ones - only inc by 1 seq nums*/ rtp->sl_hdr.packetSequenceNumber += 1; /*force indication of CTS whenever we have a new AU*/ rtp->sl_hdr.compositionTimeStampFlag = (rtp->flags & GF_RTP_NEW_AU) ? 1 : 0; /*locate VOP start code*/ if (rtp->sl_hdr.accessUnitStartFlag && (rtp->flags & GF_RTP_M4V_CHECK_RAP)) { u32 i; Bool is_rap = 0; unsigned char *pay = (unsigned char *) payload + pay_start; i=0; while (i<au_size-4) { if (!pay[i] && !pay[i+1] && (pay[i+2]==1) && (pay[i+3]==0xB6)) { is_rap = ((pay[i+4] & 0xC0)==0) ? 1 : 0; break; } i++; } rtp->sl_hdr.randomAccessPointFlag = is_rap ? 1 : 0; } rtp->on_sl_packet(rtp->udta, payload + pay_start, au_size, &rtp->sl_hdr, GF_OK); rtp->sl_hdr.compositionTimeStampFlag = 0; if (rtp->flags & GF_RTP_HAS_ISMACRYP) rtp->sl_hdr.isma_BSO += au_size; if (au_hdr_size < rtp->sl_map.auh_min_len) break; pay_start += au_size; if (pay_start >= size) break; num_au ++; } if (hdr->Marker) rtp->flags |= GF_RTP_NEW_AU; else rtp->flags &= ~GF_RTP_NEW_AU; gf_bs_del(hdr_bs);}static void gf_rtp_parse_mpeg12_audio(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *payload, u32 size){ u16 offset; u32 mp3hdr, ts; GF_BitStream *bs; rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp; rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp; rtp->sl_hdr.accessUnitStartFlag = rtp->sl_hdr.accessUnitEndFlag ? 1 : 0; if (rtp->flags & GF_RTP_NEW_AU) rtp->sl_hdr.accessUnitStartFlag = 1; /*get frag header*/ bs = gf_bs_new(payload, size, GF_BITSTREAM_READ); gf_bs_read_u16(bs); offset = gf_bs_read_u16(bs); gf_bs_del(bs); payload += 4; size -= 4; mp3hdr = 0; while (1) { /*frame start if no offset*/ rtp->sl_hdr.accessUnitStartFlag = offset ? 0 : 1; /*new frame, store size*/ rtp->sl_hdr.compositionTimeStampFlag = 0; if (rtp->sl_hdr.accessUnitStartFlag) { mp3hdr = GF_4CC((u8) payload[0], (u8) payload[1], (u8) payload[2], (u8) payload[3]); rtp->sl_hdr.accessUnitLength = gf_mp3_frame_size(mp3hdr); rtp->sl_hdr.compositionTimeStampFlag = 1; } if (!rtp->sl_hdr.accessUnitLength) break; /*fragmented frame*/ if (rtp->sl_hdr.accessUnitLength>size) { rtp->on_sl_packet(rtp->udta, payload, rtp->sl_hdr.accessUnitLength, &rtp->sl_hdr, GF_OK); rtp->sl_hdr.accessUnitLength -= size; rtp->sl_hdr.accessUnitStartFlag = rtp->sl_hdr.accessUnitEndFlag = 0; return; } /*complete frame*/ rtp->sl_hdr.accessUnitEndFlag = 1; rtp->on_sl_packet(rtp->udta, payload, rtp->sl_hdr.accessUnitLength, &rtp->sl_hdr, GF_OK); payload += rtp->sl_hdr.accessUnitLength; size -= rtp->sl_hdr.accessUnitLength; rtp->sl_hdr.accessUnitLength = 0; /*if fragmented there shall not be other frames in the packet*/ if (!rtp->sl_hdr.accessUnitStartFlag) return; if (!size) break; offset = 0; /*get ts*/ ts = gf_mp3_window_size(mp3hdr); rtp->sl_hdr.compositionTimeStamp += ts; rtp->sl_hdr.decodingTimeStamp += ts; } rtp->flags |= GF_RTP_NEW_AU;}static void gf_rtp_parse_mpeg12_video(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *payload, u32 size){ u8 pic_type; rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp; rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp; pic_type = payload[2] & 0x7; payload += 4; size -= 4; /*missed something*/ if (rtp->sl_hdr.compositionTimeStamp != hdr->TimeStamp) rtp->flags |= GF_RTP_NEW_AU; rtp->sl_hdr.accessUnitStartFlag = (rtp->flags & GF_RTP_NEW_AU) ? 1 : 0; rtp->sl_hdr.accessUnitEndFlag = hdr->Marker ? 1 : 0; rtp->sl_hdr.randomAccessPointFlag = (pic_type==1) ? 1 : 0; if (rtp->sl_hdr.accessUnitStartFlag) { rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp; rtp->sl_hdr.compositionTimeStampFlag = 1; } else { rtp->sl_hdr.compositionTimeStampFlag = 0; } rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK); if (hdr->Marker) { rtp->flags |= GF_RTP_NEW_AU; } else { rtp->flags &= ~GF_RTP_NEW_AU; }}static void gf_rtp_parse_amr(GF_RTPDepacketizer *rtp, 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 (!(rtp->flags & GF_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; rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp; /*then each frame*/ for (i=0; i<nbFrame; i++) { c = payload[i + 1]; type = ((c & 0x78) >> 3); if (rtp->payt==GF_RTP_PAYT_AMR) { frame_size = GF_AMR_FRAME_SIZE[type]; } else { frame_size = GF_AMR_WB_FRAME_SIZE[type]; } rtp->sl_hdr.compositionTimeStampFlag = 1; rtp->sl_hdr.accessUnitStartFlag = 1; rtp->sl_hdr.accessUnitEndFlag = 0; /*send TOC*/ rtp->on_sl_packet(rtp->udta, &payload[i+1], 1, &rtp->sl_hdr, GF_OK); rtp->sl_hdr.packetSequenceNumber ++; rtp->sl_hdr.compositionTimeStampFlag = 0; rtp->sl_hdr.accessUnitStartFlag = 0; rtp->sl_hdr.accessUnitEndFlag = 1; /*send payload*/ rtp->on_sl_packet(rtp->udta, data, frame_size, &rtp->sl_hdr, GF_OK); data += frame_size; rtp->sl_hdr.compositionTimeStamp += 160; }}static void gf_rtp_parse_h263(GF_RTPDepacketizer *rtp, 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) { rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp; rtp->sl_hdr.compositionTimeStampFlag = 1; rtp->sl_hdr.accessUnitStartFlag = 1; rtp->sl_hdr.accessUnitEndFlag = 0; if (rtp->sl_hdr.accessUnitStartFlag) { /*the first 16 bytes are NOT sent on the wire*/ rtp->sl_hdr.randomAccessPointFlag = (payload[offset+2]&0x02) ? 0 : 1; } /*send missing start code*/ rtp->on_sl_packet(rtp->udta, (char *) blank, 2, &rtp->sl_hdr, GF_OK); /*send payload*/ rtp->sl_hdr.compositionTimeStampFlag = 0; rtp->sl_hdr.accessUnitStartFlag = 0; rtp->sl_hdr.randomAccessPointFlag = 0; /*if M bit set, end of frame*/ rtp->sl_hdr.accessUnitEndFlag = hdr->Marker; rtp->on_sl_packet(rtp->udta, payload + offset, size - offset, &rtp->sl_hdr, GF_OK); } else { /*middle/end of frames - if M bit set, end of frame*/ rtp->sl_hdr.accessUnitEndFlag = hdr->Marker; rtp->on_sl_packet(rtp->udta, payload + offset, size - offset, &rtp->sl_hdr, GF_OK); }}static void gf_rtp_ttxt_flush(GF_RTPDepacketizer *rtp, u32 ts){ GF_BitStream *bs; char *data; u32 data_size; if (!rtp->inter_bs) return; rtp->sl_hdr.compositionTimeStamp = ts; rtp->sl_hdr.compositionTimeStampFlag = 1; rtp->sl_hdr.accessUnitStartFlag = 1; rtp->sl_hdr.accessUnitEndFlag = 0; rtp->sl_hdr.randomAccessPointFlag = 1; bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_bs_write_int(bs, rtp->sl_hdr.idleFlag, 1); rtp->sl_hdr.idleFlag = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -