📄 rtp_pck_3gpp.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>static void rtp_amr_flush(GP_RTPPacketizer *builder){ char *hdr; u32 hdr_size; if (!builder->bytesInPacket) return; gf_bs_get_content(builder->pck_hdr, &hdr, &hdr_size); gf_bs_del(builder->pck_hdr); builder->pck_hdr = NULL; /*overwrite last frame F bit*/ hdr[builder->last_au_sn] &= 0x7F; builder->OnData(builder->cbk_obj, hdr, hdr_size, 1); free(hdr); builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header); builder->bytesInPacket = 0; builder->last_au_sn = 0;}GF_Err gp_rtp_builder_do_amr(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize){ u32 offset, rtp_ts, block_size; if (!data) { rtp_amr_flush(builder); return GF_OK; } rtp_ts = (u32) builder->sl_header.compositionTimeStamp; offset = 0; while (data_size>offset) { u8 ft = (data[offset] & 0x78) >> 3; u8 size; if (builder->rtp_payt == GF_RTP_PAYT_AMR_WB) { size = GF_AMR_WB_FRAME_SIZE[ft]; block_size = 320; } else { size = GF_AMR_FRAME_SIZE[ft]; block_size = 160; } /*packet full or too long*/ if (builder->bytesInPacket + 1 + size > builder->Path_MTU) rtp_amr_flush(builder); /*need new*/ if (!builder->bytesInPacket) { builder->rtp_header.TimeStamp = rtp_ts; builder->rtp_header.Marker = 0; /*never set*/ builder->rtp_header.SequenceNumber += 1; builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header); assert(builder->pck_hdr==NULL); /*always have header and TOC*/ builder->pck_hdr = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); /*CMR + res (all 0, no interleaving)*/ gf_bs_write_int(builder->pck_hdr, ft, 4); gf_bs_write_int(builder->pck_hdr, 0, 4); builder->bytesInPacket = 1; /*no interleaving*/ } /*F always to 1*/ gf_bs_write_int(builder->pck_hdr, 1, 1); gf_bs_write_int(builder->pck_hdr, ft, 4); /*Q*/ gf_bs_write_int(builder->pck_hdr, (data[offset] & 0x4) ? 1 : 0, 1); gf_bs_write_int(builder->pck_hdr, 0, 2); builder->bytesInPacket ++; /*remove frame type byte*/ offset++; /*add frame data without rate_type byte header*/ if (builder->OnDataReference) { builder->OnDataReference(builder->cbk_obj, size, offset); } else { builder->OnData(builder->cbk_obj, data+offset, size, 0); } builder->last_au_sn++; builder->bytesInPacket += size; offset += size; rtp_ts += block_size; assert(builder->bytesInPacket<=builder->Path_MTU); /*take care of aggregation, flush if needed*/ if (builder->last_au_sn==builder->auh_size) rtp_amr_flush(builder); } return GF_OK;}static GFINLINE u8 qes_get_rate_size(u32 idx, u32 *rates, u32 nb_rates){ u32 i; for (i=0; i<nb_rates; i++) { if (rates[2*i]==idx) return rates[2*i+1]; } return 0;}GF_Err gp_rtp_builder_do_qcelp(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize){ u32 offset, rtp_ts; u8 hdr; if (!data) { if (builder->bytesInPacket) builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header); builder->bytesInPacket = 0; builder->last_au_sn = 0; return GF_OK; } rtp_ts = (u32) builder->sl_header.compositionTimeStamp; offset = 0; while (data_size>offset) { u8 frame_type = data[offset]; u8 size = qes_get_rate_size(frame_type, (u32 *)GF_QCELP_RATE_TO_SIZE, GF_QCELP_RATE_TO_SIZE_NB); /*reserved, not sent)*/ if (frame_type>=5) { offset += size; continue; } /*packet full or too long*/ if (builder->bytesInPacket + size > builder->Path_MTU) { builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header); builder->bytesInPacket = 0; builder->last_au_sn = 0; } /*need new*/ if (!builder->bytesInPacket) { builder->rtp_header.TimeStamp = rtp_ts; builder->rtp_header.Marker = 0; /*never set*/ builder->rtp_header.SequenceNumber += 1; builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header); hdr = 0;/*no interleaving*/ builder->OnData(builder->cbk_obj, (char*)&hdr, 1, 0); builder->bytesInPacket = 1; } if (builder->OnDataReference) { builder->OnDataReference(builder->cbk_obj, size, offset); } else { builder->OnData(builder->cbk_obj, data+offset, size, 0); } builder->bytesInPacket += size; offset += size; rtp_ts += 160; assert(builder->bytesInPacket<=builder->Path_MTU); /*take care of aggregation, flush if needed*/ builder->last_au_sn++; if (builder->last_au_sn==builder->auh_size) { builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header); builder->bytesInPacket = 0; builder->last_au_sn = 0; } } return GF_OK;}static void rtp_evrc_smv_flush(GP_RTPPacketizer *builder){ if (!builder->bytesInPacket) return; if (builder->auh_size>1) { char *hdr; u32 hdr_size; /*padding*/ if (builder->last_au_sn % 2) gf_bs_write_int(builder->pck_hdr, 0, 4); gf_bs_get_content(builder->pck_hdr, &hdr, &hdr_size); gf_bs_del(builder->pck_hdr); builder->pck_hdr = NULL; /*overwrite count*/ hdr[0] = 0; hdr[1] = builder->last_au_sn-1;/*MMM + frameCount-1*/ builder->OnData(builder->cbk_obj, hdr, hdr_size, 1); free(hdr); } builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header); builder->bytesInPacket = 0; builder->last_au_sn = 0;}GF_Err gp_rtp_builder_do_smv(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize){ u32 offset, rtp_ts; if (!data) { rtp_evrc_smv_flush(builder); return GF_OK; } rtp_ts = (u32) builder->sl_header.compositionTimeStamp; offset = 0; while (data_size>offset) { u8 frame_type = data[offset]; u8 size = qes_get_rate_size(frame_type, (u32 *)GF_SMV_EVRC_RATE_TO_SIZE, GF_SMV_EVRC_RATE_TO_SIZE_NB); /*reserved, not sent)*/ if (frame_type>=5) { offset += size; continue; } /*packet full or too long*/ if (builder->bytesInPacket + size > builder->Path_MTU) rtp_evrc_smv_flush(builder); /*need new*/ if (!builder->bytesInPacket) { builder->rtp_header.TimeStamp = rtp_ts; builder->rtp_header.Marker = 0; /*never set*/ builder->rtp_header.SequenceNumber += 1; builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header); assert(builder->pck_hdr==NULL); if (builder->auh_size>1) { builder->pck_hdr = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); /*RRLLLNNN (all 0, no interleaving)*/ gf_bs_write_u8(builder->pck_hdr, 0); /*MMM + count-1 : overriden when flushing*/ gf_bs_write_u8(builder->pck_hdr, 0); builder->bytesInPacket = 2; } } /*bundle mode: cat rate byte to TOC, on 4 bits*/ if (builder->auh_size>1) { gf_bs_write_int(builder->pck_hdr, data[offset], 4); if (!(builder->last_au_sn % 2)) builder->bytesInPacket += 1; } /*note that EVEN in header-free format the rate_type byte is removed*/ offset++; size--; /*add frame data without rate_type byte header*/ if (builder->OnDataReference) { builder->OnDataReference(builder->cbk_obj, size, offset); } else { builder->OnData(builder->cbk_obj, data+offset, size, 0); } builder->last_au_sn++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -