LCOV - code coverage report
Current view: top level - ietf - rtp_pck_3gpp.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 215 352 61.1 %
Date: 2021-04-29 23:48:07 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / IETF RTP/RTSP/SDP sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/internal/ietf_dev.h>
      27             : 
      28             : #ifndef GPAC_DISABLE_STREAMING
      29             : 
      30             : #include <gpac/constants.h>
      31             : 
      32       21421 : static void rtp_amr_flush(GP_RTPPacketizer *builder)
      33             : {
      34             :         u8 *hdr;
      35             :         u32 hdr_size;
      36       21425 :         if (!builder->bytesInPacket) return;
      37       21417 :         gf_bs_get_content(builder->pck_hdr, &hdr, &hdr_size);
      38       21417 :         gf_bs_del(builder->pck_hdr);
      39       21417 :         builder->pck_hdr = NULL;
      40             :         /*overwrite last frame F bit*/
      41       21417 :         hdr[builder->last_au_sn] &= 0x7F;
      42       21417 :         builder->OnData(builder->cbk_obj, hdr, hdr_size, GF_TRUE);
      43       21417 :         gf_free(hdr);
      44       21417 :         builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
      45       21417 :         builder->bytesInPacket = 0;
      46       21417 :         builder->last_au_sn = 0;
      47             : }
      48             : 
      49       21421 : GF_Err gp_rtp_builder_do_amr(GP_RTPPacketizer *builder, u8 *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize)
      50             : {
      51             :         u32 offset, rtp_ts, block_size;
      52             : 
      53       21421 :         if (!data) {
      54           4 :                 rtp_amr_flush(builder);
      55           4 :                 return GF_OK;
      56             :         }
      57             : 
      58       21417 :         rtp_ts = (u32) builder->sl_header.compositionTimeStamp;
      59             : 
      60             :         offset = 0;
      61       64251 :         while (data_size>offset) {
      62       21417 :                 u8 ft = (data[offset] & 0x78) >> 3;
      63             :                 u8 size;
      64             : 
      65       21417 :                 if (builder->rtp_payt == GF_RTP_PAYT_AMR_WB) {
      66       19869 :                         size = (u32)GF_AMR_WB_FRAME_SIZE[ft];
      67             :                         block_size = 320;
      68             :                 } else {
      69        1548 :                         size = (u32)GF_AMR_FRAME_SIZE[ft];
      70             :                         block_size = 160;
      71             :                 }
      72             : 
      73             :                 /*packet full or too long*/
      74       21417 :                 if (builder->bytesInPacket + 1 + size > builder->Path_MTU)
      75           0 :                         rtp_amr_flush(builder);
      76             : 
      77             :                 /*need new*/
      78       21417 :                 if (!builder->bytesInPacket) {
      79       21417 :                         builder->rtp_header.TimeStamp = rtp_ts;
      80       21417 :                         builder->rtp_header.Marker = 0;      /*never set*/
      81       21417 :                         builder->rtp_header.SequenceNumber += 1;
      82       21417 :                         builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
      83             :                         assert(builder->pck_hdr==NULL);
      84             : 
      85             :                         /*always have header and TOC*/
      86       21417 :                         builder->pck_hdr = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
      87             :                         /*CMR + res (all 0, no interleaving)*/
      88       21417 :                         gf_bs_write_int(builder->pck_hdr, ft, 4);
      89       21417 :                         gf_bs_write_int(builder->pck_hdr, 0, 4);
      90       21417 :                         builder->bytesInPacket = 1;
      91             :                         /*no interleaving*/
      92             :                 }
      93             : 
      94             :                 /*F always to 1*/
      95       21417 :                 gf_bs_write_int(builder->pck_hdr, 1, 1);
      96       21417 :                 gf_bs_write_int(builder->pck_hdr, ft, 4);
      97             :                 /*Q*/
      98       21417 :                 gf_bs_write_int(builder->pck_hdr, (data[offset] & 0x4) ? 1 : 0, 1);
      99       21417 :                 gf_bs_write_int(builder->pck_hdr, 0, 2);
     100       21417 :                 builder->bytesInPacket ++;
     101             : 
     102             :                 /*remove frame type byte*/
     103       21417 :                 offset++;
     104             : 
     105             :                 /*add frame data without rate_type byte header*/
     106       21417 :                 if (builder->OnDataReference) {
     107       21366 :                         builder->OnDataReference(builder->cbk_obj, size, offset);
     108             :                 } else {
     109          51 :                         builder->OnData(builder->cbk_obj, data+offset, size, GF_FALSE);
     110             :                 }
     111       21417 :                 builder->last_au_sn++;
     112       21417 :                 builder->bytesInPacket += size;
     113       21417 :                 offset += size;
     114       21417 :                 rtp_ts += block_size;
     115             :                 assert(builder->bytesInPacket<=builder->Path_MTU);
     116             :                 /*take care of aggregation, flush if needed*/
     117       21417 :                 if (builder->last_au_sn==builder->auh_size) rtp_amr_flush(builder);
     118             :         }
     119             :         return GF_OK;
     120             : }
     121             : 
     122             : static GFINLINE u8 qes_get_rate_size(u32 idx, const unsigned int *rates, const unsigned int nb_rates)
     123             : {
     124             :         u32 i;
     125       42614 :         for (i=0; i<nb_rates; i++) {
     126       58350 :                 if (rates[2*i]==idx) return rates[2*i+1];
     127             :         }
     128             :         return 0;
     129             : }
     130             : 
     131         555 : GF_Err gp_rtp_builder_do_qcelp(GP_RTPPacketizer *builder, u8 *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize)
     132             : {
     133             :         u32 offset, rtp_ts;
     134             :         u8 hdr;
     135             : 
     136         555 :         if (!data) {
     137           3 :                 if (builder->bytesInPacket) builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     138           3 :                 builder->bytesInPacket = 0;
     139           3 :                 builder->last_au_sn = 0;
     140           3 :                 return GF_OK;
     141             :         }
     142             : 
     143         552 :         rtp_ts = (u32) builder->sl_header.compositionTimeStamp;
     144             : 
     145             : 
     146             :         offset = 0;
     147        1656 :         while (data_size>offset) {
     148         552 :                 u8 frame_type = data[offset];
     149         552 :                 u8 size = qes_get_rate_size(frame_type, GF_QCELP_RATE_TO_SIZE, GF_QCELP_RATE_TO_SIZE_NB);
     150             :                 /*reserved, not sent)*/
     151         552 :                 if (frame_type>=5) {
     152           0 :                         offset += size;
     153           0 :                         continue;
     154             :                 }
     155             :                 /*packet full or too long*/
     156         552 :                 if (builder->bytesInPacket + size > builder->Path_MTU) {
     157           0 :                         builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     158           0 :                         builder->bytesInPacket = 0;
     159           0 :                         builder->last_au_sn = 0;
     160             :                 }
     161             : 
     162             :                 /*need new*/
     163         552 :                 if (!builder->bytesInPacket) {
     164         552 :                         builder->rtp_header.TimeStamp = rtp_ts;
     165         552 :                         builder->rtp_header.Marker = 0;      /*never set*/
     166         552 :                         builder->rtp_header.SequenceNumber += 1;
     167         552 :                         builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     168         552 :                         hdr = 0;/*no interleaving*/
     169         552 :                         builder->OnData(builder->cbk_obj, (char*)&hdr, 1, GF_FALSE);
     170         552 :                         builder->bytesInPacket = 1;
     171             :                 }
     172         552 :                 if (builder->OnDataReference) {
     173         501 :                         builder->OnDataReference(builder->cbk_obj, size, offset);
     174             :                 } else {
     175          51 :                         builder->OnData(builder->cbk_obj, data+offset, size, GF_FALSE);
     176             :                 }
     177         552 :                 builder->bytesInPacket += size;
     178         552 :                 offset += size;
     179         552 :                 rtp_ts += 160;
     180             :                 assert(builder->bytesInPacket<=builder->Path_MTU);
     181             : 
     182             :                 /*take care of aggregation, flush if needed*/
     183         552 :                 builder->last_au_sn++;
     184         552 :                 if (builder->last_au_sn==builder->auh_size) {
     185         552 :                         builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     186         552 :                         builder->bytesInPacket = 0;
     187         552 :                         builder->last_au_sn = 0;
     188             :                 }
     189             :         }
     190             :         return GF_OK;
     191             : }
     192             : 
     193       15185 : static void rtp_evrc_smv_flush(GP_RTPPacketizer *builder)
     194             : {
     195       15185 :         if (!builder->bytesInPacket) return;
     196       15184 :         if (builder->auh_size>1) {
     197             :                 u8 *hdr;
     198             :                 u32 hdr_size;
     199             :                 /*padding*/
     200           0 :                 if (builder->last_au_sn % 2) gf_bs_write_int(builder->pck_hdr, 0, 4);
     201           0 :                 gf_bs_get_content(builder->pck_hdr, &hdr, &hdr_size);
     202           0 :                 gf_bs_del(builder->pck_hdr);
     203           0 :                 builder->pck_hdr = NULL;
     204             :                 /*overwrite count*/
     205           0 :                 hdr[0] = 0;
     206           0 :                 hdr[1] = builder->last_au_sn-1;/*MMM + frameCount-1*/
     207           0 :                 builder->OnData(builder->cbk_obj, hdr, hdr_size, GF_TRUE);
     208           0 :                 gf_free(hdr);
     209             :         }
     210       15184 :         builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     211       15184 :         builder->bytesInPacket = 0;
     212       15184 :         builder->last_au_sn = 0;
     213             : }
     214             : 
     215       15185 : GF_Err gp_rtp_builder_do_smv(GP_RTPPacketizer *builder, u8 *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize)
     216             : {
     217             :         u32 offset, rtp_ts;
     218             : 
     219       15185 :         if (!data) {
     220           1 :                 rtp_evrc_smv_flush(builder);
     221           1 :                 return GF_OK;
     222             :         }
     223             : 
     224       15184 :         rtp_ts = (u32) builder->sl_header.compositionTimeStamp;
     225             : 
     226             :         offset = 0;
     227       45552 :         while (data_size>offset) {
     228       15184 :                 u8 frame_type = data[offset];
     229       15184 :                 u8 size = qes_get_rate_size(frame_type, GF_SMV_EVRC_RATE_TO_SIZE, GF_SMV_EVRC_RATE_TO_SIZE_NB);
     230             : 
     231             :                 /*reserved, not sent)*/
     232       15184 :                 if (frame_type>=5) {
     233           0 :                         offset += size;
     234           0 :                         continue;
     235             :                 }
     236             :                 /*packet full or too long*/
     237       15184 :                 if (builder->bytesInPacket + size > builder->Path_MTU)
     238           0 :                         rtp_evrc_smv_flush(builder);
     239             : 
     240             :                 /*need new*/
     241       15184 :                 if (!builder->bytesInPacket) {
     242       15184 :                         builder->rtp_header.TimeStamp = rtp_ts;
     243       15184 :                         builder->rtp_header.Marker = 0;      /*never set*/
     244       15184 :                         builder->rtp_header.SequenceNumber += 1;
     245       15184 :                         builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     246             :                         assert(builder->pck_hdr==NULL);
     247             : 
     248       15184 :                         if (builder->auh_size>1) {
     249           0 :                                 builder->pck_hdr = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     250             :                                 /*RRLLLNNN (all 0, no interleaving)*/
     251           0 :                                 gf_bs_write_u8(builder->pck_hdr, 0);
     252             :                                 /*MMM + count-1 : overridden when flushing*/
     253           0 :                                 gf_bs_write_u8(builder->pck_hdr, 0);
     254           0 :                                 builder->bytesInPacket = 2;
     255             :                         }
     256             :                 }
     257             : 
     258             :                 /*bundle mode: cat rate byte to TOC, on 4 bits*/
     259       15184 :                 if (builder->auh_size>1) {
     260           0 :                         gf_bs_write_int(builder->pck_hdr, data[offset], 4);
     261           0 :                         if (!(builder->last_au_sn % 2)) builder->bytesInPacket += 1;
     262             :                 }
     263             :                 /*note that EVEN in header-free format the rate_type byte is removed*/
     264       15184 :                 offset++;
     265       15184 :                 size--;
     266             : 
     267             :                 /*add frame data without rate_type byte header*/
     268       15184 :                 if (builder->OnDataReference) {
     269       15184 :                         builder->OnDataReference(builder->cbk_obj, size, offset);
     270             :                 } else {
     271           0 :                         builder->OnData(builder->cbk_obj, data+offset, size, GF_FALSE);
     272             :                 }
     273       15184 :                 builder->last_au_sn++;
     274       15184 :                 builder->bytesInPacket += size;
     275       15184 :                 offset += size;
     276       15184 :                 rtp_ts += 160;
     277             :                 assert(builder->bytesInPacket<=builder->Path_MTU);
     278             :                 /*take care of aggregation, flush if needed*/
     279       15184 :                 if (builder->last_au_sn==builder->auh_size) rtp_evrc_smv_flush(builder);
     280             :         }
     281             :         return GF_OK;
     282             : }
     283             : 
     284         463 : GF_Err gp_rtp_builder_do_h263(GP_RTPPacketizer *builder, u8 *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize)
     285             : {
     286             :         u8 hdr[2];
     287             :         Bool Pbit;
     288             :         u32 offset, size, max_size;
     289             : 
     290         463 :         builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp;
     291             : 
     292             :         /*the H263 hinter doesn't perform inter-sample concatenation*/
     293         463 :         if (!data) return GF_OK;
     294             : 
     295             :         Pbit = GF_TRUE;
     296             : 
     297             :         /*skip 16 0'ed bits of start code*/
     298             :         offset = 2;
     299         460 :         data_size -= 2;
     300         460 :         max_size = builder->Path_MTU - 2;
     301             : 
     302        1380 :         while(data_size > 0) {
     303             :                 GF_BitStream *bs;
     304         460 :                 if(data_size > max_size) {
     305             :                         size = max_size;
     306           0 :                         builder->rtp_header.Marker = 0;
     307             :                 } else {
     308             :                         size = data_size;
     309         460 :                         builder->rtp_header.Marker = 1;
     310             :                 }
     311             : 
     312         460 :                 data_size -= size;
     313             : 
     314             :                 /*create new RTP Packet */
     315         460 :                 builder->rtp_header.SequenceNumber += 1;
     316         460 :                 builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     317             : 
     318         460 :                 bs = gf_bs_new(hdr, 2, GF_BITSTREAM_WRITE);
     319         460 :                 gf_bs_write_int(bs, 0, 5);
     320         460 :                 gf_bs_write_int(bs, Pbit, 1);
     321         460 :                 gf_bs_write_int(bs, 0, 10);
     322         460 :                 gf_bs_del(bs);
     323             : 
     324             :                 /*add header*/
     325         460 :                 builder->OnData(builder->cbk_obj, (char*) hdr, 2, GF_TRUE);
     326             :                 /*add payload*/
     327         460 :                 if (builder->OnDataReference)
     328         443 :                         builder->OnDataReference(builder->cbk_obj, size, offset);
     329             :                 else
     330          17 :                         builder->OnData(builder->cbk_obj, data + offset, size, GF_FALSE);
     331             : 
     332         460 :                 builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     333             : 
     334         460 :                 offset += size;
     335             :                 Pbit = GF_FALSE;
     336             :         }
     337             :         return GF_OK;
     338             : }
     339             : 
     340          55 : GF_Err gp_rtp_builder_do_mp2t(GP_RTPPacketizer *builder, u8 *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize)
     341             : {
     342             :         u32 offset, size, max_size;
     343             : 
     344          55 :         builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp;
     345             : 
     346          55 :         if (!data) return GF_OK;
     347             : 
     348          54 :         max_size = builder->Path_MTU;
     349             :         offset = 0;
     350         162 :         while (data_size > 0) {
     351          54 :                 if (data_size > max_size) {
     352           0 :                         size = max_size / 188;
     353           0 :                         size *= 188;
     354             :                 } else {
     355             :                         size = data_size;
     356             :                 }
     357             : 
     358          54 :                 data_size -= size;
     359             : 
     360             :                 /*create new RTP Packet */
     361          54 :                 builder->rtp_header.SequenceNumber += 1;
     362          54 :                 builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     363             : 
     364             :                 /*add payload*/
     365          54 :                 if (builder->OnDataReference)
     366           0 :                         builder->OnDataReference(builder->cbk_obj, size, offset);
     367             :                 else
     368          54 :                         builder->OnData(builder->cbk_obj, data + offset, size, GF_TRUE);
     369             : 
     370          54 :                 builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     371             : 
     372          54 :                 offset += size;
     373             :         }
     374             :         return GF_OK;
     375             : }
     376        1932 : GF_Err gp_rtp_builder_do_tx3g(GP_RTPPacketizer *builder, u8 *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize, u32 duration, u8 descIndex)
     377             : {
     378             :         GF_BitStream *bs;
     379             :         u8 *hdr;
     380             :         u32 samp_size, txt_size, pay_start, hdr_size, txt_done, cur_frag, nb_frag;
     381             :         Bool is_utf_16 = GF_FALSE;
     382             : 
     383        1932 :         if (!data) {
     384             :                 /*flush packet*/
     385           9 :                 if (builder->bytesInPacket) {
     386           0 :                         builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     387           0 :                         builder->bytesInPacket = 0;
     388             :                 }
     389             :                 return GF_OK;
     390             :         }
     391             :         /*cfg packet*/
     392        1923 :         txt_size = data[0];
     393        1923 :         txt_size <<= 8;
     394        1923 :         txt_size |= (unsigned char) data[1];
     395             :         /*remove BOM*/
     396             :         pay_start = 2;
     397        1923 :         if (txt_size>2) {
     398             :                 /*seems 3GP only accepts BE UTF-16 (no LE, no UTF32)*/
     399         958 :                 if (((u8) data[2]==(u8) 0xFE) && ((u8) data[3]==(u8) 0xFF)) {
     400             :                         is_utf_16 = GF_TRUE;
     401             :                         pay_start = 4;
     402           0 :                         txt_size -= 2;
     403             :                 }
     404             :         }
     405        1923 :         samp_size = data_size - pay_start;
     406             : 
     407             :         /*if TTU does not fit in packet flush packet*/
     408        1923 :         if (builder->bytesInPacket && (builder->bytesInPacket + 3 + 6 + samp_size > builder->Path_MTU)) {
     409           0 :                 builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     410           0 :                 builder->bytesInPacket = 0;
     411             :         }
     412             :         //we only deal with static SIDX
     413        1923 :         descIndex += GF_RTP_TX3G_SIDX_OFFSET;
     414             : 
     415             :         /*first TTU in packet*/
     416        1923 :         if (!builder->bytesInPacket) {
     417        1923 :                 builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp;
     418        1923 :                 builder->rtp_header.Marker = 1;
     419        1923 :                 builder->rtp_header.SequenceNumber += 1;
     420        1923 :                 builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     421             :         }
     422             :         /*fits entirely*/
     423        1923 :         if (builder->bytesInPacket + 3 + 6 + samp_size <= builder->Path_MTU) {
     424        1923 :                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     425        1923 :                 gf_bs_write_int(bs, is_utf_16, 1);
     426        1923 :                 gf_bs_write_int(bs, 0, 4);
     427        1923 :                 gf_bs_write_int(bs, 1, 3);
     428        1923 :                 gf_bs_write_u16(bs, 8 + samp_size);
     429        1923 :                 gf_bs_write_u8(bs, descIndex);
     430        1923 :                 gf_bs_write_u24(bs, duration);
     431        1923 :                 gf_bs_write_u16(bs, txt_size);
     432        1923 :                 gf_bs_get_content(bs, &hdr, &hdr_size);
     433        1923 :                 gf_bs_del(bs);
     434        1923 :                 builder->OnData(builder->cbk_obj, (char *) hdr, hdr_size, GF_FALSE);
     435        1923 :                 builder->bytesInPacket += hdr_size;
     436        1923 :                 gf_free(hdr);
     437             : 
     438        1923 :                 if (txt_size) {
     439         958 :                         if (builder->OnDataReference) {
     440         957 :                                 builder->OnDataReference(builder->cbk_obj, samp_size, pay_start);
     441             :                         } else {
     442           1 :                                 builder->OnData(builder->cbk_obj, data + pay_start, samp_size, GF_FALSE);
     443             :                         }
     444         958 :                         builder->bytesInPacket += samp_size;
     445             :                 }
     446             :                 /*disable aggregation*/
     447        1923 :                 if (!(builder->flags & GP_RTP_PCK_USE_MULTI)) {
     448        1923 :                         builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     449        1923 :                         builder->bytesInPacket = 0;
     450             :                 }
     451             :                 return GF_OK;
     452             :         }
     453             :         /*doesn't fit and already data, flush packet*/
     454           0 :         if (builder->bytesInPacket) {
     455           0 :                 builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     456           0 :                 builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp;
     457             :                 /*split unit*/
     458           0 :                 builder->rtp_header.Marker = 0;
     459           0 :                 builder->rtp_header.SequenceNumber += 1;
     460           0 :                 builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     461           0 :                 builder->bytesInPacket = 0;
     462             :         }
     463             :         /*write all type2 units (text only) - FIXME: split at char boundaries, NOT SUPPORTED YET*/
     464             :         txt_done = 0;
     465             :         nb_frag = 1;
     466             :         /*all fragments needed for Type2 units*/
     467           0 :         while (txt_done + (builder->Path_MTU-10) < txt_size) {
     468             :                 txt_done += (builder->Path_MTU-10);
     469           0 :                 nb_frag += 1;
     470             :         }
     471             :         /*all fragments needed for Type3/4 units*/
     472             :         txt_done = txt_size;
     473           0 :         while (txt_done + (builder->Path_MTU-7) < samp_size) {
     474             :                 txt_done += (builder->Path_MTU-7);
     475           0 :                 nb_frag += 1;
     476             :         }
     477             : 
     478             : 
     479             :         cur_frag = 0;
     480             :         txt_done = 0;
     481           0 :         while (txt_done<txt_size) {
     482             :                 u32 size;
     483           0 :                 if (txt_done + (builder->Path_MTU-10) < txt_size) {
     484           0 :                         size = builder->Path_MTU-10;
     485             :                 } else {
     486           0 :                         size = txt_size - txt_done;
     487             :                 }
     488             : 
     489           0 :                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     490           0 :                 gf_bs_write_int(bs, is_utf_16, 1);
     491           0 :                 gf_bs_write_int(bs, 0, 4);
     492           0 :                 gf_bs_write_int(bs, 2, 3);
     493           0 :                 gf_bs_write_u16(bs, 9 + size);
     494           0 :                 gf_bs_write_int(bs, nb_frag, 4);
     495           0 :                 gf_bs_write_int(bs, cur_frag, 4);
     496           0 :                 gf_bs_write_u24(bs, duration);
     497           0 :                 gf_bs_write_u8(bs, descIndex);
     498             :                 /*SLEN is the full original length minus text len and BOM (put here for buffer allocation purposes)*/
     499           0 :                 gf_bs_write_u16(bs, samp_size);
     500           0 :                 gf_bs_get_content(bs, &hdr, &hdr_size);
     501           0 :                 gf_bs_del(bs);
     502           0 :                 builder->OnData(builder->cbk_obj, (char *) hdr, hdr_size, GF_FALSE);
     503           0 :                 builder->bytesInPacket += hdr_size;
     504           0 :                 gf_free(hdr);
     505             : 
     506           0 :                 if (builder->OnDataReference) {
     507           0 :                         builder->OnDataReference(builder->cbk_obj, size, pay_start + txt_done);
     508             :                 } else {
     509           0 :                         builder->OnData(builder->cbk_obj, data + pay_start + txt_done, size, GF_FALSE);
     510             :                 }
     511           0 :                 builder->bytesInPacket += size;
     512           0 :                 cur_frag++;
     513             : 
     514             :                 /*flush packet*/
     515           0 :                 if (cur_frag == nb_frag) {
     516             :                         txt_done = txt_size;
     517           0 :                         if (pay_start + txt_done == data_size) {
     518           0 :                                 builder->rtp_header.Marker = 1;
     519           0 :                                 builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     520           0 :                                 builder->bytesInPacket = 0;
     521             :                         }
     522             :                 } else {
     523           0 :                         txt_done += size;
     524           0 :                         builder->rtp_header.Marker = 0;
     525           0 :                         builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     526           0 :                         builder->rtp_header.SequenceNumber += 1;
     527           0 :                         builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     528           0 :                         builder->bytesInPacket = 0;
     529             :                 }
     530             :         }
     531             : 
     532             :         txt_done = txt_size;
     533             : 
     534             :         /*write all modifiers - OPT: split at modifiers boundaries*/
     535           0 :         while (txt_done<samp_size) {
     536             :                 u32 size, type;
     537           0 :                 type = (txt_done == txt_size) ? 3 : 4;
     538             : 
     539           0 :                 if (txt_done + (builder->Path_MTU-7) < samp_size) {
     540           0 :                         size = builder->Path_MTU-10;
     541             :                 } else {
     542           0 :                         size = samp_size - txt_done;
     543             :                 }
     544             : 
     545           0 :                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     546           0 :                 gf_bs_write_int(bs, is_utf_16, 1);
     547           0 :                 gf_bs_write_int(bs, 0, 4);
     548           0 :                 gf_bs_write_int(bs, type, 3);
     549           0 :                 gf_bs_write_u16(bs, 6 + size);
     550           0 :                 gf_bs_write_int(bs, nb_frag, 4);
     551           0 :                 gf_bs_write_int(bs, cur_frag, 4);
     552           0 :                 gf_bs_write_u24(bs, duration);
     553             : 
     554           0 :                 gf_bs_get_content(bs, &hdr, &hdr_size);
     555           0 :                 gf_bs_del(bs);
     556           0 :                 builder->OnData(builder->cbk_obj, (char *) hdr, hdr_size, GF_FALSE);
     557           0 :                 builder->bytesInPacket += hdr_size;
     558           0 :                 gf_free(hdr);
     559             : 
     560           0 :                 if (builder->OnDataReference) {
     561           0 :                         builder->OnDataReference(builder->cbk_obj, size, pay_start + txt_done);
     562             :                 } else {
     563           0 :                         builder->OnData(builder->cbk_obj, data + pay_start + txt_done, size, GF_FALSE);
     564             :                 }
     565           0 :                 builder->bytesInPacket += size;
     566           0 :                 cur_frag++;
     567           0 :                 if (cur_frag==nb_frag) {
     568           0 :                         builder->rtp_header.Marker = 1;
     569           0 :                         builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     570           0 :                         builder->bytesInPacket = 0;
     571             :                 } else {
     572           0 :                         builder->rtp_header.Marker = 0;
     573           0 :                         builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     574           0 :                         builder->rtp_header.SequenceNumber += 1;
     575           0 :                         builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     576           0 :                         builder->bytesInPacket = 0;
     577             :                 }
     578           0 :                 txt_done += size;
     579             :         }
     580             :         return GF_OK;
     581             : }
     582             : 
     583             : 
     584             : #if GPAC_ENABLE_3GPP_DIMS_RTP
     585             : GF_Err gp_rtp_builder_do_dims(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize, u32 duration)
     586             : {
     587             :         u32 frag_state;
     588             :         GF_BitStream *bs;
     589             :         u32 offset;
     590             :         Bool is_last_du;
     591             : 
     592             :         /*the DIMS hinter doesn't perform inter-sample concatenation*/
     593             :         if (!data) return GF_OK;
     594             : 
     595             :         offset = 0;
     596             :         builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp;
     597             :         bs = gf_bs_new(data, data_size, GF_BITSTREAM_READ);
     598             :         while (offset < data_size) {
     599             :                 u32 du_offset = 0;
     600             :                 u32 hdr_offset = 0;
     601             :                 u32 orig_size, du_size;
     602             : 
     603             :                 orig_size = du_size = 2+gf_bs_read_u16(bs);
     604             :                 /*if dims size is >0xFFFF, use our internal hack for large units*/
     605             :                 if (du_size==2) {
     606             :                         orig_size = du_size = 2+gf_bs_read_u32(bs);
     607             :                         hdr_offset = 4;
     608             :                 }
     609             :                 gf_bs_skip_bytes(bs, du_size-2);
     610             : 
     611             :                 /*prepare M-bit*/
     612             :                 is_last_du = (offset+du_size==data_size) ? GF_TRUE : GF_FALSE;
     613             : 
     614             :                 frag_state = 0;
     615             :                 while (du_size) {
     616             :                         u32 size_offset = 0;
     617             :                         u32 size;
     618             :                         //size = du_size;
     619             : 
     620             :                         /*does not fit, flush required*/
     621             :                         if (builder->bytesInPacket && (du_size + 1 + builder->bytesInPacket > builder->Path_MTU)) {
     622             :                                 builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     623             :                                 builder->bytesInPacket = 0;
     624             :                         }
     625             : 
     626             :                         /*fragmentation required*/
     627             :                         if (du_size + 1 > builder->Path_MTU) {
     628             :                                 size = builder->Path_MTU - 1;
     629             :                                 /*first fragment*/
     630             :                                 if (!frag_state) {
     631             :                                         /*size field is skipped !!*/
     632             :                                         size_offset = 2 + hdr_offset;
     633             :                                         frag_state = 1;
     634             : 
     635             :                                         while (du_size - size_offset <= size) {
     636             :                                                 size--;
     637             :                                         }
     638             :                                 }
     639             :                                 /*any middle fragment*/
     640             :                                 else frag_state = 2;
     641             : 
     642             :                                 builder->rtp_header.Marker = 0;
     643             :                         }
     644             :                         /*last fragment*/
     645             :                         else if (frag_state) {
     646             :                                 size = du_size;
     647             :                                 frag_state = 3;
     648             :                                 builder->rtp_header.Marker = is_last_du;
     649             :                         } else {
     650             :                                 size = du_size;
     651             :                                 builder->rtp_header.Marker = is_last_du;
     652             :                         }
     653             : 
     654             :                         if (frag_state && builder->bytesInPacket) {
     655             :                                 builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     656             :                                 builder->bytesInPacket = 0;
     657             :                         }
     658             : 
     659             :                         /*need a new packet*/
     660             :                         if (!builder->bytesInPacket) {
     661             :                                 char dims_rtp_hdr[1];
     662             : 
     663             :                                 /*the unit is critical, increase counter (coded on 3 bits)*/
     664             :                                 if (! (data[2+hdr_offset] & GF_DIMS_UNIT_P) && (frag_state <= 1) ) {
     665             :                                         builder->last_au_sn++;
     666             :                                         builder->last_au_sn %= 8;
     667             :                                 }
     668             :                                 /*set CTR value*/
     669             :                                 dims_rtp_hdr[0] = builder->last_au_sn;
     670             :                                 /*if M-bit is set in the dims unit header, replicate it*/
     671             :                                 if (data[2+hdr_offset] & (1<<1) ) dims_rtp_hdr[0] |= (1<<6);
     672             :                                 /*add unit fragmentation type*/
     673             :                                 dims_rtp_hdr[0] |= (frag_state<<3);
     674             : 
     675             :                                 builder->rtp_header.SequenceNumber += 1;
     676             :                                 builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     677             :                                 builder->OnData(builder->cbk_obj, (char *) dims_rtp_hdr, 1, GF_TRUE);
     678             :                                 builder->bytesInPacket = 1;
     679             :                         }
     680             : 
     681             :                         /*add payload*/
     682             :                         if (builder->OnDataReference)
     683             :                                 builder->OnDataReference(builder->cbk_obj, size, offset+du_offset+size_offset);
     684             :                         else
     685             :                                 builder->OnData(builder->cbk_obj, data+offset+du_offset+size_offset, size, GF_FALSE);
     686             : 
     687             :                         /*if fragmentation, force packet flush even on last packet since aggregation unit do not
     688             :                         use the same packet format*/
     689             :                         if (frag_state) {
     690             :                                 builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     691             :                                 builder->bytesInPacket = 0;
     692             :                         } else {
     693             :                                 builder->bytesInPacket += size;
     694             :                         }
     695             :                         du_offset += size+size_offset;
     696             :                         assert(du_size>= size+size_offset);
     697             :                         du_size -= size+size_offset;
     698             :                 }
     699             :                 offset += orig_size;
     700             :         }
     701             :         if (builder->bytesInPacket) {
     702             :                 builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     703             :                 builder->bytesInPacket = 0;
     704             :         }
     705             :         gf_bs_del(bs);
     706             :         return GF_OK;
     707             : }
     708             : #endif
     709             : 
     710             : 
     711             : 
     712          61 : static void gf_rtp_ac3_flush(GP_RTPPacketizer *builder)
     713             : {
     714             :         char hdr[2];
     715          64 :         if (!builder->bytesInPacket) return;
     716             : 
     717          58 :         hdr[0] = builder->ac3_ft;
     718          58 :         hdr[1] = builder->last_au_sn;
     719          58 :         builder->OnData(builder->cbk_obj, hdr, 2, GF_TRUE);
     720             : 
     721          58 :         builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     722          58 :         builder->bytesInPacket = 0;
     723          58 :         builder->last_au_sn = 0;
     724          58 :         builder->ac3_ft = 0;
     725             : }
     726             : 
     727          61 : GF_Err gp_rtp_builder_do_ac3(GP_RTPPacketizer *builder, u8 *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize)
     728             : {
     729             :         char hdr[2];
     730             :         u32 offset, nb_pck;
     731             : 
     732             :         /*flush*/
     733          61 :         if (!data) {
     734           3 :                 gf_rtp_ac3_flush(builder);
     735           3 :                 return GF_OK;
     736             :         }
     737             : 
     738          58 :         if (
     739             :             /*AU does not fit*/
     740          58 :             (builder->bytesInPacket + data_size > builder->Path_MTU)
     741          58 :             ||
     742             :             /*aggregation is not enabled*/
     743          58 :             !(builder->flags & GP_RTP_PCK_USE_MULTI)
     744           0 :             ||
     745             :             /*max ptime is exceeded*/
     746           0 :             (builder->max_ptime && ( (u32) builder->sl_header.compositionTimeStamp >= builder->rtp_header.TimeStamp + builder->max_ptime) )
     747             : 
     748             :         ) {
     749          58 :                 gf_rtp_ac3_flush(builder);
     750             :         }
     751             : 
     752             :         /*fits*/
     753          58 :         if (builder->bytesInPacket + data_size < builder->Path_MTU) {
     754             :                 /*need a new packet*/
     755          58 :                 if (!builder->bytesInPacket) {
     756          58 :                         builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp;
     757          58 :                         builder->ac3_ft = 0;
     758          58 :                         builder->rtp_header.Marker = 1;
     759          58 :                         builder->rtp_header.SequenceNumber += 1;
     760          58 :                         builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     761             :                         /*2 bytes header*/
     762          58 :                         builder->bytesInPacket = 2;
     763             :                 }
     764             : 
     765             :                 /*add payload*/
     766          58 :                 if (builder->OnDataReference)
     767          29 :                         builder->OnDataReference(builder->cbk_obj, data_size, 0);
     768             :                 else
     769          29 :                         builder->OnData(builder->cbk_obj, data, data_size, GF_FALSE);
     770             : 
     771          58 :                 builder->bytesInPacket += data_size;
     772          58 :                 builder->last_au_sn++;
     773          58 :                 return GF_OK;
     774             :         }
     775             : 
     776             :         /*need fragmentation*/
     777             :         assert(!builder->bytesInPacket);
     778             :         offset = 0;
     779           0 :         nb_pck = data_size / (builder->Path_MTU-2);
     780           0 :         if (data_size % (builder->Path_MTU-2)) nb_pck++;
     781           0 :         builder->last_au_sn = nb_pck;
     782             : 
     783           0 :         while (offset < data_size) {
     784           0 :                 u32 pck_size = MIN(data_size-offset, builder->Path_MTU-2);
     785             : 
     786           0 :                 builder->rtp_header.Marker = 0;
     787           0 :                 builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp;
     788           0 :                 builder->rtp_header.SequenceNumber += 1;
     789             : 
     790           0 :                 if (!offset) {
     791           0 :                         builder->ac3_ft = (pck_size > 5*data_size/8) ? 1 : 2;
     792             :                 } else {
     793           0 :                         builder->ac3_ft = 3;
     794           0 :                         if (offset + pck_size == data_size)
     795           0 :                                 builder->rtp_header.Marker = 1;
     796             :                 }
     797           0 :                 builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
     798             : 
     799           0 :                 hdr[0] = builder->ac3_ft;
     800           0 :                 hdr[1] = builder->last_au_sn;
     801           0 :                 builder->OnData(builder->cbk_obj, hdr, 2, GF_TRUE);
     802             : 
     803             :                 /*add payload*/
     804           0 :                 if (builder->OnDataReference)
     805           0 :                         builder->OnDataReference(builder->cbk_obj, pck_size, offset);
     806             :                 else
     807           0 :                         builder->OnData(builder->cbk_obj, data+offset, pck_size, GF_FALSE);
     808             : 
     809           0 :                 builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
     810           0 :                 offset += pck_size;
     811           0 :                 builder->bytesInPacket = 0;
     812             :         }
     813             : 
     814             :         return GF_OK;
     815             : }
     816             : 
     817             : #endif /*GPAC_DISABLE_STREAMING*/
     818             : 

Generated by: LCOV version 1.13