📄 rtp_packetizer.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project * * 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/constants.h>#include <gpac/math.h>void InitSL_RTP(GF_SLConfig *slc);GF_EXPORTGP_RTPPacketizer *gf_rtp_builder_new(u32 rtp_payt, GF_SLConfig *slc, u32 flags, void *cbk_obj, void (*OnNewPacket)(void *cbk, GF_RTPHeader *header), void (*OnPacketDone)(void *cbk, GF_RTPHeader *header), void (*OnDataReference)(void *cbk, u32 payload_size, u32 offset_from_orig), void (*OnData)(void *cbk, char *data, u32 data_size, Bool is_head) ){ GP_RTPPacketizer *tmp; if (!rtp_payt || !cbk_obj | !OnPacketDone) return NULL; GF_SAFEALLOC(tmp, GP_RTPPacketizer); if (!tmp) return NULL; if (slc) { memcpy(&tmp->sl_config, slc, sizeof(GF_SLConfig)); } else { memset(&tmp->sl_config, 0, sizeof(GF_SLConfig)); tmp->sl_config.useTimestampsFlag = 1; tmp->sl_config.timestampLength = 32; } tmp->OnNewPacket = OnNewPacket; tmp->OnDataReference = OnDataReference; tmp->OnData = OnData; tmp->cbk_obj = cbk_obj; tmp->OnPacketDone = OnPacketDone; tmp->rtp_payt = rtp_payt; tmp->flags = flags; //default init tmp->sl_header.AU_sequenceNumber = 1; tmp->sl_header.packetSequenceNumber = 1; //we assume we start on a new AU tmp->sl_header.accessUnitStartFlag = 1; return tmp;}GF_EXPORTvoid gf_rtp_builder_del(GP_RTPPacketizer *builder){ if (!builder) return; if (builder->payload) gf_bs_del(builder->payload); if (builder->pck_hdr) gf_bs_del(builder->pck_hdr); free(builder);}GF_EXPORTGF_Err gf_rtp_builder_process(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize, u32 duration, u8 descIndex){ if (!builder) return GF_BAD_PARAM; switch (builder->rtp_payt) { case GF_RTP_PAYT_MPEG4: return gp_rtp_builder_do_mpeg4(builder, data, data_size, IsAUEnd, FullAUSize); case GF_RTP_PAYT_MPEG12_VIDEO: return gp_rtp_builder_do_mpeg12_video(builder, data, data_size, IsAUEnd, FullAUSize); case GF_RTP_PAYT_MPEG12_AUDIO: return gp_rtp_builder_do_mpeg12_audio(builder, data, data_size, IsAUEnd, FullAUSize); case GF_RTP_PAYT_H263: return gp_rtp_builder_do_h264(builder, data, data_size, IsAUEnd, FullAUSize); case GF_RTP_PAYT_AMR: case GF_RTP_PAYT_AMR_WB: return gp_rtp_builder_do_amr(builder, data, data_size, IsAUEnd, FullAUSize); case GF_RTP_PAYT_3GPP_TEXT: return gp_rtp_builder_do_tx3g(builder, data, data_size, IsAUEnd, FullAUSize, duration, descIndex); case GF_RTP_PAYT_H264_AVC: return gp_rtp_builder_do_avc(builder, data, data_size, IsAUEnd, FullAUSize); case GF_RTP_PAYT_QCELP: return gp_rtp_builder_do_qcelp(builder, data, data_size, IsAUEnd, FullAUSize); case GF_RTP_PAYT_EVRC_SMV: return gp_rtp_builder_do_smv(builder, data, data_size, IsAUEnd, FullAUSize); case GF_RTP_PAYT_LATM: return gp_rtp_builder_do_latm(builder, data, data_size, IsAUEnd, FullAUSize, duration); default: return GF_BAD_PARAM; }}//Compute the #params of the slMapGF_EXPORTvoid gf_rtp_builder_init(GP_RTPPacketizer *builder, u8 PayloadType, u32 PathMTU, u32 max_ptime, u32 StreamType, u32 OTI, u32 PL_ID, u32 avgSize, u32 maxSize, u32 avgTS, u32 maxDTS, u32 IV_length, u32 KI_length, char *pref_mode) { u32 k, totDelta, ismacrypt_flags; memset(&builder->slMap, 0, sizeof(GP_RTPSLMap)); builder->Path_MTU = PathMTU; builder->PayloadType = PayloadType; builder->slMap.StreamType = StreamType; builder->slMap.ObjectTypeIndication = OTI; builder->slMap.PL_ID = PL_ID; builder->max_ptime = max_ptime; if (pref_mode) strcpy(builder->slMap.mode, pref_mode); //some cst vars builder->rtp_header.Version = 2; builder->rtp_header.PayloadType = builder->PayloadType; /*our max config is with 1 packet only (SingleSL)*/ builder->first_sl_in_rtp = 1; /*no AUX data*/ builder->slMap.AuxiliaryDataSizeLength= 0; /*just compute max aggregation size*/ switch (builder->rtp_payt) { case GF_RTP_PAYT_QCELP: case GF_RTP_PAYT_EVRC_SMV: case GF_RTP_PAYT_AMR: case GF_RTP_PAYT_AMR_WB: { u32 nb_pck = 1; u32 block_size = 160; /*compute max frames per packet - if no avg size, use max size per codec*/ if (builder->flags & GP_RTP_PCK_USE_MULTI) { if (builder->rtp_payt == GF_RTP_PAYT_QCELP) { if (!avgSize) avgSize = 35; nb_pck = (PathMTU-1) / avgSize; /*one-byte header*/ if (nb_pck>10) nb_pck=10; /*cf RFC2658*/ } else if (builder->rtp_payt == GF_RTP_PAYT_EVRC_SMV) { if (!avgSize) avgSize = 23; nb_pck = (PathMTU) / avgSize; if (nb_pck>32) nb_pck=32; /*cf RFC3558*/ } else if (builder->rtp_payt == GF_RTP_PAYT_AMR_WB) { if (!avgSize) avgSize = 61; nb_pck = (PathMTU-1) / avgSize; block_size = 320; } else { if (!avgSize) avgSize = 32; nb_pck = (PathMTU-1) / avgSize; } if (max_ptime) { u32 max_pck = max_ptime / block_size; if (nb_pck > max_pck) nb_pck = max_pck; } } if (nb_pck<=1) { builder->flags &= ~(GP_RTP_PCK_USE_MULTI|GP_RTP_PCK_USE_INTERLEAVING); builder->auh_size = 1; } else { builder->auh_size = nb_pck; } /*remove all MPEG-4 and ISMA flags */ builder->flags &= 0x07; } return; case GF_RTP_PAYT_LATM: case GF_RTP_PAYT_MPEG4: break; default: /*remove all MPEG-4 and ISMA flags */ builder->flags &= 0x07; /*disable aggregation for visual streams*/ if (StreamType==GF_STREAM_VISUAL) builder->flags &= ~GP_RTP_PCK_USE_MULTI; else if (avgSize && (PathMTU <= avgSize) ) builder->flags &= ~GP_RTP_PCK_USE_MULTI; return; } builder->slMap.IV_length = IV_length; builder->slMap.KI_length = KI_length; ismacrypt_flags = 0; if (builder->flags & GP_RTP_PCK_SELECTIVE_ENCRYPTION) ismacrypt_flags |= GP_RTP_PCK_SELECTIVE_ENCRYPTION; if (builder->flags & GP_RTP_PCK_KEY_IDX_PER_AU) ismacrypt_flags |= GP_RTP_PCK_KEY_IDX_PER_AU; /*mode setup*/ if (!strnicmp(builder->slMap.mode, "AAC", 3)) { builder->flags = GP_RTP_PCK_USE_MULTI | GP_RTP_PCK_SIGNAL_SIZE | GP_RTP_PCK_SIGNAL_AU_IDX | ismacrypt_flags; if (builder->flags & GP_RTP_PCK_USE_INTERLEAVING) builder->slMap.ConstantDuration = avgTS; /*AAC LBR*/ if (maxSize < 63) { strcpy(builder->slMap.mode, "AAC-lbr"); builder->slMap.IndexLength = builder->slMap.IndexDeltaLength = 2; builder->slMap.SizeLength = 6; } /*AAC HBR*/ else { strcpy(builder->slMap.mode, "AAC-hbr"); builder->slMap.IndexLength = builder->slMap.IndexDeltaLength = 3; builder->slMap.SizeLength = 13; } goto check_header; } if (!strnicmp(builder->slMap.mode, "CELP", 4)) { /*CELP-cbr*/ if (maxSize == avgSize) { /*reset flags (interleaving forbidden)*/ builder->flags = GP_RTP_PCK_USE_MULTI | ismacrypt_flags; strcpy(builder->slMap.mode, "CELP-cbr"); builder->slMap.ConstantSize = avgSize; builder->slMap.ConstantDuration = avgTS; } /*CELP VBR*/ else { strcpy(builder->slMap.mode, "CELP-vbr"); builder->slMap.IndexLength = builder->slMap.IndexDeltaLength = 2; builder->slMap.SizeLength = 6; if (builder->flags & GP_RTP_PCK_USE_INTERLEAVING) builder->slMap.ConstantDuration = avgTS; builder->flags = GP_RTP_PCK_USE_MULTI | GP_RTP_PCK_SIGNAL_SIZE | GP_RTP_PCK_SIGNAL_AU_IDX | ismacrypt_flags; } goto check_header; } /*generic setup by flags*/ /*size*/ if (builder->flags & GP_RTP_PCK_SIGNAL_SIZE) { if (avgSize==maxSize) { builder->slMap.SizeLength = 0; builder->slMap.ConstantSize = maxSize; } else { builder->slMap.SizeLength = gf_get_bit_size(maxSize ? maxSize : PathMTU); builder->slMap.ConstantSize = 0; } } else { builder->slMap.SizeLength = 0; if (builder->flags & GP_RTP_PCK_USE_MULTI) builder->slMap.ConstantSize = (avgSize==maxSize) ? maxSize : 0; else builder->slMap.ConstantSize = 0; } /*single SL per RTP*/ if (!(builder->flags & GP_RTP_PCK_USE_MULTI)) { if ( builder->sl_config.AUSeqNumLength && (builder->flags & GP_RTP_PCK_SIGNAL_AU_IDX)) { builder->slMap.IndexLength = builder->sl_config.AUSeqNumLength; } else { builder->slMap.IndexLength = 0; } /*one packet per RTP so no delta*/ builder->slMap.IndexDeltaLength = 0; builder->slMap.IV_delta_length = 0; /*CTS Delta is always 0 since we have one SL packet per RTP*/ builder->slMap.CTSDeltaLength = 0; /*DTS Delta depends on the video type*/ if ((builder->flags & GP_RTP_PCK_SIGNAL_TS) && maxDTS ) builder->slMap.DTSDeltaLength = gf_get_bit_size(maxDTS); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -