LCOV - code coverage report
Current view: top level - ietf - rtp_depacketizer.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 740 977 75.7 %
Date: 2021-04-29 23:48:07 Functions: 21 21 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-2020
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / RTP input module
       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/base_coding.h>
      31             : #include <gpac/constants.h>
      32             : #include <gpac/isomedia.h>
      33             : #include <gpac/mpeg4_odf.h>
      34             : #include <gpac/avparse.h>
      35             : 
      36          23 : static void gf_rtp_parse_pass_through(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
      37             : {
      38          23 :         if (!rtp) return;
      39             : 
      40          23 :         rtp->sl_hdr.accessUnitStartFlag = 1;
      41          23 :         if (rtp->sl_hdr.compositionTimeStamp != hdr->TimeStamp)
      42             :                 rtp->sl_hdr.accessUnitStartFlag = 1;
      43             : 
      44          23 :         rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
      45          23 :         rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp;
      46          23 :         rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
      47          23 :         rtp->sl_hdr.randomAccessPointFlag = 1;
      48          23 :         rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK);
      49             : }
      50             : 
      51         104 : static void gf_rtp_parse_mpeg4(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
      52             : {
      53             :         u32 aux_size, first_idx, au_hdr_size, num_au;
      54             :         u64 pay_start, au_size;
      55             :         s32 au_idx;
      56             :         GF_BitStream *hdr_bs, *aux_bs;
      57             : 
      58         104 :         hdr_bs = gf_bs_new(payload, size, GF_BITSTREAM_READ);
      59         104 :         aux_bs = gf_bs_new(payload, size, GF_BITSTREAM_READ);
      60             : 
      61             :         /*global AU header len*/
      62             :         au_hdr_size = 0;
      63         104 :         if (rtp->sl_map.auh_first_min_len) {
      64          75 :                 au_hdr_size = gf_bs_read_u16(hdr_bs);
      65          75 :                 gf_bs_read_u16(aux_bs);
      66             :         }
      67             : 
      68             :         /*jump to aux section, skip it and get payload start*/
      69         104 :         gf_bs_read_int(aux_bs, au_hdr_size);
      70         104 :         gf_bs_align(aux_bs);
      71         104 :         if (rtp->sl_map.AuxiliaryDataSizeLength) {
      72           0 :                 aux_size = gf_bs_read_int(aux_bs, rtp->sl_map.AuxiliaryDataSizeLength);
      73           0 :                 gf_bs_read_int(aux_bs, aux_size);
      74           0 :                 gf_bs_align(aux_bs);
      75             :         }
      76         104 :         pay_start = gf_bs_get_position(aux_bs);
      77         104 :         gf_bs_del(aux_bs);
      78             : 
      79             :         first_idx = 0;
      80             :         au_idx = 0;
      81             : 
      82         104 :         rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
      83         104 :         rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp;
      84             : 
      85             :         num_au = 0;
      86             : 
      87         104 :         rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
      88             :         /*override some defaults for RFC 3016*/
      89         104 :         if (rtp->flags & GF_RTP_NEW_AU) {
      90         102 :                 rtp->sl_hdr.accessUnitStartFlag = 1;
      91             :         } else {
      92           2 :                 rtp->sl_hdr.accessUnitStartFlag = 0;
      93             :         }
      94         104 :         rtp->sl_hdr.randomAccessPointFlag = 0;
      95             : 
      96             :         while (1) {
      97             :                 /*get default AU size*/
      98         744 :                 au_size = rtp->sl_map.ConstantSize;
      99             :                 /*not signaled, assume max one AU per packet*/
     100         424 :                 if (!au_size) au_size = size - pay_start;
     101             : 
     102         424 :                 if ((!num_au && rtp->sl_map.auh_first_min_len) || (num_au && rtp->sl_map.auh_min_len)) {
     103             :                         /*ISMACryp*/
     104         395 :                         if (rtp->flags & GF_RTP_HAS_ISMACRYP) {
     105             :                                 u32 nbbits;
     106           0 :                                 rtp->sl_hdr.isma_encrypted = 1;
     107           0 :                                 if (rtp->flags & GF_RTP_ISMA_SEL_ENC) {
     108           0 :                                         rtp->sl_hdr.isma_encrypted = gf_bs_read_int(hdr_bs, 1);
     109           0 :                                         gf_bs_read_int(hdr_bs, 7);
     110           0 :                                         au_hdr_size -= 8;
     111             :                                 }
     112             :                                 /*Note: ISMACryp ALWAYS indicates IV (BSO) and KEYIDX, even when sample is not encrypted.
     113             :                                 This is quite a waste when using selective encryption....*/
     114           0 :                                 if (!num_au) {
     115           0 :                                         nbbits = 8*rtp->sl_map.IV_length;
     116           0 :                                         if (nbbits) {
     117           0 :                                                 rtp->sl_hdr.isma_BSO = gf_bs_read_int(hdr_bs, nbbits);
     118           0 :                                                 au_hdr_size -= nbbits;
     119             :                                         }
     120             :                                 }
     121             :                                 /*NOT SUPPORTED YET*/
     122           0 :                                 else if (rtp->sl_map.IV_delta_length) {
     123           0 :                                         nbbits = 8*rtp->sl_map.IV_delta_length;
     124             :                                         if (nbbits) {
     125           0 :                                                 rtp->sl_hdr.isma_BSO += gf_bs_read_int(hdr_bs, nbbits);
     126           0 :                                                 au_hdr_size -= nbbits;
     127             :                                         }
     128             :                                 }
     129           0 :                                 if (rtp->sl_map.KI_length) {
     130             :                                         /*NOT SUPPORTED YET*/
     131           0 :                                         if (!num_au || !(rtp->flags & GF_RTP_ISMA_HAS_KEY_IDX) ) {
     132           0 :                                                 nbbits = 8*rtp->sl_map.KI_length;
     133             :                                                 if (nbbits) {
     134           0 :                                                         gf_bs_read_int(hdr_bs, nbbits);
     135           0 :                                                         au_hdr_size -= nbbits;
     136             :                                                 }
     137             :                                         }
     138             :                                 }
     139             :                         }
     140             : 
     141             :                         /*AU size*/
     142         395 :                         if (rtp->sl_map.SizeLength) {
     143         395 :                                 au_size = gf_bs_read_int(hdr_bs, rtp->sl_map.SizeLength);
     144         395 :                                 if (au_size > size - pay_start) au_size = size - pay_start;
     145         395 :                                 au_hdr_size -= rtp->sl_map.SizeLength;
     146             :                         }
     147             :                         /*AU index*/
     148         395 :                         if (! num_au) {
     149          75 :                                 au_idx = first_idx = gf_bs_read_int(hdr_bs, rtp->sl_map.IndexLength);
     150          75 :                                 au_hdr_size -= rtp->sl_map.IndexLength;
     151             :                         } else {
     152         320 :                                 au_idx += 1 + (u32) gf_bs_read_int(hdr_bs, rtp->sl_map.IndexDeltaLength);
     153         320 :                                 au_hdr_size -= rtp->sl_map.IndexDeltaLength;
     154             :                         }
     155             :                         /*CTS flag*/
     156         395 :                         if (rtp->sl_map.CTSDeltaLength) {
     157           0 :                                 rtp->sl_hdr.compositionTimeStampFlag = gf_bs_read_int(hdr_bs, 1);
     158           0 :                                 au_hdr_size -= 1;
     159             :                         } else {
     160             :                                 /*get CTS from IDX*/
     161         395 :                                 if (rtp->sl_map.ConstantDuration) {
     162         395 :                                         rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp + (au_idx - first_idx) * rtp->sl_map.ConstantDuration;
     163             :                                 } else {
     164           0 :                                         rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp + (au_idx - first_idx) * rtp->sl_hdr.au_duration;
     165             :                                 }
     166             :                         }
     167             : 
     168             :                         /*CTS in-band*/
     169         395 :                         if (rtp->sl_hdr.compositionTimeStampFlag) {
     170           0 :                                 rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp + (u32) gf_bs_read_int(hdr_bs, rtp->sl_map.CTSDeltaLength);
     171           0 :                                 au_hdr_size -= rtp->sl_map.CTSDeltaLength;
     172             :                         }
     173             :                         /*DTS flag is always present (needed for reconstruction of TSs in case of packet loss)*/
     174         395 :                         if (rtp->sl_map.DTSDeltaLength) {
     175           0 :                                 rtp->sl_hdr.decodingTimeStampFlag = gf_bs_read_int(hdr_bs, 1);
     176           0 :                                 au_hdr_size -= 1;
     177             :                         } else {
     178             :                                 /*NO DTS otherwise*/
     179         395 :                                 rtp->sl_hdr.decodingTimeStampFlag = 0;
     180             :                         }
     181         395 :                         if (rtp->sl_hdr.decodingTimeStampFlag) {
     182           0 :                                 u32 ts_off = gf_bs_read_int(hdr_bs, rtp->sl_map.DTSDeltaLength);
     183             :                                 /*TODO FIXME may not be true in case of TS wrapping*/
     184           0 :                                 if (hdr->TimeStamp > ts_off) rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp - ts_off;
     185           0 :                                 au_hdr_size -= rtp->sl_map.DTSDeltaLength;
     186             :                         }
     187             :                         /*RAP flag*/
     188         395 :                         if (rtp->sl_map.RandomAccessIndication) {
     189           0 :                                 rtp->sl_hdr.randomAccessPointFlag = gf_bs_read_int(hdr_bs, 1);
     190           0 :                                 au_hdr_size -= 1;
     191           0 :                                 if (rtp->sl_hdr.randomAccessPointFlag)
     192           0 :                                         rtp->sl_hdr.randomAccessPointFlag=1;
     193             :                         } else {
     194         395 :                                 rtp->sl_hdr.randomAccessPointFlag=1;
     195             :                         }
     196             :                         /*stream state - map directly to seqNum*/
     197         395 :                         if (rtp->sl_map.StreamStateIndication) {
     198           0 :                                 rtp->sl_hdr.AU_sequenceNumber = gf_bs_read_int(hdr_bs, rtp->sl_map.StreamStateIndication);
     199           0 :                                 au_hdr_size -= rtp->sl_map.StreamStateIndication;
     200             :                         }
     201             :                 }
     202             :                 /*no header present, update CTS/DTS - note we're sure there's no interleaving*/
     203             :                 else {
     204          29 :                         if (num_au) {
     205           0 :                                 rtp->sl_hdr.compositionTimeStamp += rtp->sl_map.ConstantDuration;
     206           0 :                                 rtp->sl_hdr.decodingTimeStamp += rtp->sl_map.ConstantDuration;
     207             :                         }
     208             :                 }
     209             :                 /*we cannot map RTP SN to SL SN since an RTP packet may carry several SL ones - only inc by 1 seq nums*/
     210         424 :                 rtp->sl_hdr.packetSequenceNumber += 1;
     211             : 
     212             :                 /*force indication of CTS whenever we have a new AU*/
     213             : 
     214         424 :                 rtp->sl_hdr.compositionTimeStampFlag = (rtp->flags & GF_RTP_NEW_AU) ? 1 : 0;
     215             : 
     216             :                 /*locate VOP start code*/
     217         424 :                 if (rtp->sl_hdr.accessUnitStartFlag && (rtp->flags & GF_RTP_M4V_CHECK_RAP)) {
     218             :                         u32 i;
     219             :                         Bool is_rap = GF_FALSE;
     220          27 :                         unsigned char *pay = (unsigned char *) payload + pay_start;
     221             :                         i=0;
     222          54 :                         while (i<au_size-4) {
     223          27 :                                 if (!pay[i] && !pay[i+1] && (pay[i+2]==1) && (pay[i+3]==0xB6)) {
     224          27 :                                         is_rap = ((pay[i+4] & 0xC0)==0) ? GF_TRUE : GF_FALSE;
     225          27 :                                         break;
     226             :                                 }
     227           0 :                                 i++;
     228             :                         }
     229          27 :                         rtp->sl_hdr.randomAccessPointFlag = is_rap ? 1 : 0;
     230             :                 }
     231             : 
     232         424 :                 rtp->on_sl_packet(rtp->udta, payload + pay_start, (u32) au_size, &rtp->sl_hdr, GF_OK);
     233             : 
     234         424 :                 rtp->sl_hdr.compositionTimeStampFlag = 0;
     235             : 
     236         424 :                 if (rtp->flags & GF_RTP_HAS_ISMACRYP) rtp->sl_hdr.isma_BSO += au_size;
     237             : 
     238         424 :                 if (au_hdr_size < rtp->sl_map.auh_min_len) break;
     239         349 :                 pay_start += au_size;
     240         349 :                 if (pay_start >= size) break;
     241         320 :                 num_au ++;
     242             :         }
     243             : //      assert(!au_hdr_size);
     244             : 
     245         104 :         if (hdr->Marker)
     246         102 :                 rtp->flags |= GF_RTP_NEW_AU;
     247             :         else
     248           2 :                 rtp->flags &= ~GF_RTP_NEW_AU;
     249             : 
     250         104 :         gf_bs_del(hdr_bs);
     251         104 : }
     252             : 
     253             : #ifndef GPAC_DISABLE_AV_PARSERS
     254             : 
     255          39 : static void gf_rtp_parse_mpeg12_audio(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
     256             : {
     257             :         u16 offset;
     258             :         u32 mp3hdr, ts;
     259             :         GF_BitStream *bs;
     260             : 
     261          39 :         rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     262          39 :         rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp;
     263             : 
     264          39 :         rtp->sl_hdr.accessUnitStartFlag = rtp->sl_hdr.accessUnitEndFlag ? 1 : 0;
     265          39 :         if (rtp->flags & GF_RTP_NEW_AU) rtp->sl_hdr.accessUnitStartFlag = 1;
     266             : 
     267             :         /*get frag header*/
     268          39 :         bs = gf_bs_new(payload, size, GF_BITSTREAM_READ);
     269          39 :         gf_bs_read_u16(bs);
     270          39 :         offset = gf_bs_read_u16(bs);
     271          39 :         gf_bs_del(bs);
     272          39 :         payload += 4;
     273          39 :         size -= 4;
     274             :         mp3hdr = 0;
     275             :         while (1) {
     276             : 
     277             :                 /*frame start if no offset*/
     278          39 :                 rtp->sl_hdr.accessUnitStartFlag = offset ? 0 : 1;
     279          39 :                 rtp->sl_hdr.randomAccessPointFlag = 1;
     280             : 
     281             :                 /*new frame, store size*/
     282          39 :                 rtp->sl_hdr.compositionTimeStampFlag = 0;
     283          39 :                 if (rtp->sl_hdr.accessUnitStartFlag) {
     284          39 :                         mp3hdr = GF_4CC((u32) payload[0], (u8) payload[1], (u8) payload[2], (u8) payload[3]);
     285          39 :                         rtp->sl_hdr.accessUnitLength = gf_mp3_frame_size(mp3hdr);
     286          39 :                         rtp->sl_hdr.channels = gf_mp3_num_channels(mp3hdr);
     287          39 :                         rtp->sl_hdr.samplerate = gf_mp3_sampling_rate(mp3hdr);
     288          39 :                         if (rtp->sl_hdr.samplerate) {
     289          39 :                                 rtp->sl_hdr.au_duration = gf_mp3_window_size(mp3hdr);
     290          39 :                                 rtp->sl_hdr.au_duration *= rtp->clock_rate;
     291          39 :                                 rtp->sl_hdr.au_duration /= rtp->sl_hdr.samplerate;
     292             :                         }
     293          39 :                         rtp->sl_hdr.compositionTimeStampFlag = 1;
     294             :                 }
     295          39 :                 if (!rtp->sl_hdr.accessUnitLength) break;
     296             :                 /*fragmented frame*/
     297          39 :                 if (rtp->sl_hdr.accessUnitLength>size) {
     298           0 :                         rtp->on_sl_packet(rtp->udta, payload, rtp->sl_hdr.accessUnitLength, &rtp->sl_hdr, GF_OK);
     299           0 :                         rtp->sl_hdr.accessUnitLength -= size;
     300           0 :                         rtp->sl_hdr.accessUnitStartFlag = rtp->sl_hdr.accessUnitEndFlag = 0;
     301           0 :                         return;
     302             :                 }
     303             :                 /*complete frame*/
     304          39 :                 rtp->sl_hdr.accessUnitEndFlag = 1;
     305          39 :                 rtp->on_sl_packet(rtp->udta, payload, rtp->sl_hdr.accessUnitLength, &rtp->sl_hdr, GF_OK);
     306          39 :                 payload += rtp->sl_hdr.accessUnitLength;
     307          39 :                 size -= rtp->sl_hdr.accessUnitLength;
     308          39 :                 rtp->sl_hdr.accessUnitLength = 0;
     309             : 
     310             :                 /*if fragmented there shall not be other frames in the packet*/
     311          39 :                 if (!rtp->sl_hdr.accessUnitStartFlag) return;
     312          39 :                 if (!size) break;
     313             :                 offset = 0;
     314             :                 /*get ts*/
     315           0 :                 ts = gf_mp3_window_size(mp3hdr);
     316           0 :                 rtp->sl_hdr.compositionTimeStamp += ts;
     317           0 :                 rtp->sl_hdr.decodingTimeStamp += ts;
     318             :         }
     319          39 :         rtp->flags |= GF_RTP_NEW_AU;
     320             : }
     321             : 
     322             : #endif
     323             : 
     324          73 : static void gf_rtp_parse_mpeg12_video(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
     325             : {
     326             :         u8 pic_type;
     327             : 
     328          73 :         rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     329          73 :         rtp->sl_hdr.decodingTimeStamp = hdr->TimeStamp;
     330             : 
     331             : 
     332          73 :         pic_type = payload[2] & 0x7;
     333          73 :         payload += 4;
     334          73 :         size -= 4;
     335             : 
     336             :         /*missed something*/
     337          73 :         if (rtp->sl_hdr.compositionTimeStamp != hdr->TimeStamp) rtp->flags |= GF_RTP_NEW_AU;
     338             : 
     339          73 :         rtp->sl_hdr.accessUnitStartFlag = (rtp->flags & GF_RTP_NEW_AU) ? 1 : 0;
     340          73 :         rtp->sl_hdr.accessUnitEndFlag = hdr->Marker ? 1 : 0;
     341          73 :         rtp->sl_hdr.randomAccessPointFlag = (pic_type==1) ? 1 : 0;
     342             : 
     343          73 :         if (rtp->sl_hdr.accessUnitStartFlag) {
     344          27 :                 rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     345          27 :                 rtp->sl_hdr.compositionTimeStampFlag = 1;
     346             :         } else {
     347          46 :                 rtp->sl_hdr.compositionTimeStampFlag = 0;
     348             :         }
     349          73 :         rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK);
     350          73 :         if (hdr->Marker) {
     351          27 :                 rtp->flags |= GF_RTP_NEW_AU;
     352             :         } else {
     353          46 :                 rtp->flags &= ~GF_RTP_NEW_AU;
     354             :         }
     355          73 : }
     356             : 
     357          51 : static void gf_rtp_parse_amr(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
     358             : {
     359             :         unsigned char c;
     360             :         char *data;
     361             :         /*we support max 30 frames in one RTP packet...*/
     362             :         u32 nbFrame, i, frame_size;
     363             :         /*not supported yet*/
     364          51 :         if (!(rtp->flags & GF_RTP_AMR_ALIGN) ) return;
     365             : 
     366             :         /*process toc and locate start of payload data*/
     367             :         nbFrame = 0;
     368             :         while (1) {
     369          51 :                 c = payload[nbFrame + 1];
     370             :                 nbFrame++;
     371          51 :                 if (!(c & 0x80)) break;
     372             :         }
     373          51 :         data = payload + nbFrame + 1;
     374          51 :         rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     375             :         /*then each frame*/
     376         153 :         for (i=0; i<nbFrame; i++) {
     377             :                 u8 type;
     378          51 :                 c = payload[i + 1];
     379          51 :                 type = ((c & 0x78) >> 3);
     380          51 :                 if (rtp->payt==GF_RTP_PAYT_AMR) {
     381          51 :                         frame_size = (u32)GF_AMR_FRAME_SIZE[type];
     382             :                 } else {
     383           0 :                         frame_size = (u32)GF_AMR_WB_FRAME_SIZE[type];
     384             :                 }
     385             : 
     386          51 :                 rtp->sl_hdr.compositionTimeStampFlag = 1;
     387          51 :                 rtp->sl_hdr.accessUnitStartFlag = 1;
     388          51 :                 rtp->sl_hdr.accessUnitEndFlag = 0;
     389          51 :                 rtp->sl_hdr.randomAccessPointFlag = 1;
     390             :                 /*send TOC*/
     391          51 :                 rtp->on_sl_packet(rtp->udta, &payload[i+1], 1, &rtp->sl_hdr, GF_OK);
     392          51 :                 rtp->sl_hdr.packetSequenceNumber ++;
     393          51 :                 rtp->sl_hdr.compositionTimeStampFlag = 0;
     394          51 :                 rtp->sl_hdr.accessUnitStartFlag = 0;
     395          51 :                 rtp->sl_hdr.accessUnitEndFlag = 1;
     396             :                 /*send payload*/
     397          51 :                 rtp->on_sl_packet(rtp->udta, data, frame_size, &rtp->sl_hdr, GF_OK);
     398          51 :                 data += frame_size;
     399          51 :                 rtp->sl_hdr.compositionTimeStamp += 160;
     400             :         }
     401             : }
     402             : 
     403             : 
     404          17 : static void gf_rtp_parse_h263(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
     405             : {
     406             :         GF_BitStream *bs;
     407             :         Bool P_bit, V_bit;
     408             :         u32 plen;
     409             :         u64 offset;
     410             :         char blank[2];
     411             : 
     412          17 :         bs = gf_bs_new(payload, size, GF_BITSTREAM_READ);
     413             :         /*reserved*/
     414          17 :         gf_bs_read_int(bs, 5);
     415          17 :         P_bit = (Bool)gf_bs_read_int(bs, 1);
     416          17 :         V_bit = (Bool)gf_bs_read_int(bs, 1);
     417          17 :         plen = gf_bs_read_int(bs, 6);
     418          17 :         /*plen_bits = */gf_bs_read_int(bs, 3);
     419             : 
     420             :         /*VRC not supported yet*/
     421          17 :         if (V_bit) {
     422           0 :                 gf_bs_read_u8(bs);
     423             :         }
     424             :         /*extra picture header not supported yet*/
     425          17 :         if (plen) {
     426           0 :                 gf_bs_skip_bytes(bs, plen);
     427             :         }
     428          17 :         offset = gf_bs_get_position(bs);
     429          17 :         gf_bs_del(bs);
     430             : 
     431          17 :         blank[0] = blank[1] = 0;
     432             :         /*start*/
     433          17 :         if (P_bit) {
     434          17 :                 rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     435          17 :                 rtp->sl_hdr.compositionTimeStampFlag = 1;
     436          17 :                 rtp->sl_hdr.accessUnitStartFlag = 1;
     437          17 :                 rtp->sl_hdr.accessUnitEndFlag = 0;
     438             : 
     439             :                 /*the first 16 bytes are NOT sent on the wire*/
     440          17 :                 rtp->sl_hdr.randomAccessPointFlag = (payload[offset+2]&0x02) ? 0 : 1;
     441             : 
     442             :                 /*send missing start code*/
     443          17 :                 rtp->on_sl_packet(rtp->udta, (char *) blank, 2, &rtp->sl_hdr, GF_OK);
     444             :                 /*send payload*/
     445          17 :                 rtp->sl_hdr.compositionTimeStampFlag = 0;
     446          17 :                 rtp->sl_hdr.accessUnitStartFlag = 0;
     447          17 :                 rtp->sl_hdr.randomAccessPointFlag = 0;
     448             : 
     449             :                 /*if M bit set, end of frame*/
     450          17 :                 rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
     451          17 :                 rtp->on_sl_packet(rtp->udta, payload + offset, (u32) (size - offset), &rtp->sl_hdr, GF_OK);
     452             :         } else {
     453             :                 /*middle/end of frames - if M bit set, end of frame*/
     454           0 :                 rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
     455           0 :                 rtp->on_sl_packet(rtp->udta, payload + offset, (u32) (size - offset), &rtp->sl_hdr, GF_OK);
     456             :         }
     457          17 : }
     458             : 
     459           2 : static void gf_rtp_ttxt_flush(GF_RTPDepacketizer *rtp, u32 ts)
     460             : {
     461             :         GF_BitStream *bs;
     462             :         u8 *data;
     463             :         u32 data_size;
     464           4 :         if (!rtp->inter_bs) return;
     465             : 
     466           0 :         rtp->sl_hdr.compositionTimeStamp = ts;
     467           0 :         rtp->sl_hdr.compositionTimeStampFlag = 1;
     468           0 :         rtp->sl_hdr.accessUnitStartFlag = 1;
     469           0 :         rtp->sl_hdr.accessUnitEndFlag = 0;
     470           0 :         rtp->sl_hdr.randomAccessPointFlag = 1;
     471             : 
     472           0 :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     473           0 :         gf_bs_write_int(bs, rtp->sl_hdr.idleFlag, 1);
     474           0 :         rtp->sl_hdr.idleFlag = 0;
     475           0 :         gf_bs_write_int(bs, 0, 4);
     476           0 :         gf_bs_write_int(bs, 1, 3);
     477           0 :         gf_bs_write_u16(bs, 8 + (u16) gf_bs_get_position(rtp->inter_bs));
     478           0 :         gf_bs_write_u8(bs, rtp->sidx);
     479           0 :         gf_bs_write_u24(bs, rtp->sl_hdr.au_duration);
     480           0 :         gf_bs_write_u16(bs, rtp->txt_len);
     481           0 :         gf_bs_get_content(bs, &data, &data_size);
     482           0 :         gf_bs_del(bs);
     483             : 
     484           0 :         rtp->on_sl_packet(rtp->udta, data, data_size, &rtp->sl_hdr, GF_OK);
     485           0 :         gf_free(data);
     486           0 :         rtp->sl_hdr.accessUnitStartFlag = 0;
     487           0 :         rtp->sl_hdr.accessUnitEndFlag = 1;
     488           0 :         gf_bs_get_content(rtp->inter_bs, &data, &data_size);
     489           0 :         rtp->on_sl_packet(rtp->udta, data, data_size, &rtp->sl_hdr, GF_OK);
     490           0 :         gf_free(data);
     491             : 
     492           0 :         gf_bs_del(rtp->inter_bs);
     493           0 :         rtp->inter_bs = NULL;
     494           0 :         rtp->nb_txt_frag = rtp->cur_txt_frag = rtp->sidx = rtp->txt_len = rtp->nb_mod_frag = 0;
     495             : }
     496             : 
     497           2 : static void gf_rtp_parse_ttxt(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
     498             : {
     499             :         Bool is_utf_16;
     500             :         u32 type, ttu_len, duration, ts, sidx, txt_size;
     501             :         u32 nb_frag, cur_frag;
     502             :         u64 pay_start;
     503             :         GF_BitStream *bs;
     504             : 
     505           2 :         ts = hdr->TimeStamp;
     506             : 
     507           2 :         bs = gf_bs_new(payload, size, GF_BITSTREAM_READ);
     508           6 :         while (gf_bs_available(bs)) {
     509           2 :                 pay_start = gf_bs_get_position(bs);
     510           2 :                 is_utf_16 = (Bool)gf_bs_read_int(bs, 1);
     511           2 :                 gf_bs_read_int(bs, 4);
     512           2 :                 type = gf_bs_read_int(bs, 3);
     513           2 :                 ttu_len = gf_bs_read_u16(bs);
     514           2 :                 if (ttu_len<2) break;
     515             : 
     516           2 :                 if (type==1) {
     517             :                         /*flush any existing packet*/
     518           2 :                         gf_rtp_ttxt_flush(rtp, (u32) rtp->sl_hdr.compositionTimeStamp);
     519             : 
     520             :                         /*bad ttu(1)*/
     521           2 :                         if (ttu_len<8) break;
     522           2 :                         rtp->sl_hdr.compositionTimeStamp = ts;
     523           2 :                         rtp->sl_hdr.compositionTimeStampFlag = 1;
     524           2 :                         rtp->sl_hdr.accessUnitStartFlag = 1;
     525           2 :                         rtp->sl_hdr.accessUnitEndFlag = 1;
     526           2 :                         rtp->sl_hdr.randomAccessPointFlag = 1;
     527           2 :                         gf_bs_read_u8(bs);
     528           2 :                         rtp->sl_hdr.au_duration = gf_bs_read_u24(bs);
     529           2 :                         rtp->on_sl_packet(rtp->udta, payload + pay_start, ttu_len + 1, &rtp->sl_hdr, GF_OK);
     530           2 :                         gf_bs_skip_bytes(bs, ttu_len - 6);
     531           2 :                         ts += rtp->sl_hdr.au_duration;
     532             :                 }
     533             :                 /*text segment*/
     534           0 :                 else if (type==2) {
     535             :                         /*TS changed, flush packet*/
     536           0 :                         if (rtp->sl_hdr.compositionTimeStamp < ts) {
     537           0 :                                 gf_rtp_ttxt_flush(rtp, (u32) rtp->sl_hdr.compositionTimeStamp);
     538             :                         }
     539           0 :                         if (ttu_len<9) break;
     540           0 :                         rtp->sl_hdr.compositionTimeStamp = ts;
     541           0 :                         rtp->sl_hdr.idleFlag = is_utf_16;
     542           0 :                         nb_frag = gf_bs_read_int(bs, 4);
     543           0 :                         cur_frag = gf_bs_read_int(bs, 4);
     544           0 :                         duration = gf_bs_read_u24(bs);
     545           0 :                         sidx = gf_bs_read_u8(bs);
     546           0 :                         gf_bs_read_u16(bs);/*complete text sample size, ignored*/
     547           0 :                         txt_size = size - 10;
     548             : 
     549             :                         /*init - 3GPP/MPEG-4 splitting is IMHO stupid:
     550             :                                 - nb frag & cur frags are not needed: rtp reordering insures packet are in order, and
     551             :                         !!!we assume fragments are sent in order!!!
     552             :                                 - any other TTU suffices to indicate end of text string (modifiers or != RTP TS)
     553             :                                 - replacing these 8bits field with a 16 bit absolute character offset would add error recovery
     554             :                         */
     555           0 :                         if (!rtp->nb_txt_frag) {
     556           0 :                                 rtp->nb_txt_frag = nb_frag;
     557           0 :                                 rtp->cur_txt_frag = 0;
     558           0 :                                 rtp->sidx = sidx;
     559             :                         }
     560             :                         /*flush prev if any mismatch*/
     561           0 :                         if ((nb_frag != rtp->nb_txt_frag) || (rtp->cur_txt_frag > cur_frag)) {
     562           0 :                                 gf_rtp_ttxt_flush(rtp, (u32) rtp->sl_hdr.compositionTimeStamp);
     563           0 :                                 rtp->nb_txt_frag = nb_frag;
     564           0 :                                 rtp->sidx = sidx;
     565             :                         }
     566           0 :                         if (!rtp->inter_bs) rtp->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     567             : 
     568             :                         /*we don't reorder - RTP reordering is done at lower level, if this is out of order too bad*/
     569           0 :                         rtp->cur_txt_frag = cur_frag;
     570           0 :                         gf_bs_write_data(rtp->inter_bs, payload+10, txt_size);
     571           0 :                         gf_bs_skip_bytes(bs, txt_size);
     572             : 
     573           0 :                         rtp->sl_hdr.au_duration = duration;
     574             :                         /*done*/
     575           0 :                         if (hdr->Marker) {
     576             :                                 assert(gf_bs_get_position(rtp->inter_bs) < 1<<7);
     577           0 :                                 rtp->txt_len = (u8) gf_bs_get_position(rtp->inter_bs);
     578           0 :                                 gf_rtp_ttxt_flush(rtp, ts);
     579             :                         }
     580           0 :                 } else if ((type==3) || (type==4)) {
     581           0 :                         if (!rtp->inter_bs) rtp->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     582             :                         /*first modifier, store effective written text*/
     583           0 :                         if (type==3) {
     584             :                                 assert(gf_bs_get_position(rtp->inter_bs) < 1<<7);
     585           0 :                                 rtp->txt_len = (u8) gf_bs_get_position(rtp->inter_bs);
     586             :                         }
     587           0 :                         if (ttu_len<6) break;
     588             : 
     589           0 :                         nb_frag = gf_bs_read_int(bs, 4);
     590           0 :                         if (!rtp->nb_mod_frag) rtp->nb_mod_frag = nb_frag;
     591           0 :                         else if (rtp->nb_mod_frag != nb_frag) {
     592           0 :                                 gf_rtp_ttxt_flush(rtp, (u32) rtp->sl_hdr.compositionTimeStamp);
     593           0 :                                 rtp->nb_mod_frag = nb_frag;
     594             :                         }
     595           0 :                         gf_bs_read_int(bs, 4);  /*cur_frag, ignore*/
     596           0 :                         rtp->sl_hdr.au_duration = gf_bs_read_u24(bs);
     597           0 :                         gf_bs_write_data(rtp->inter_bs, payload+7, ttu_len-6);
     598           0 :                         gf_bs_skip_bytes(bs, ttu_len-6);
     599             : 
     600             :                         /*done*/
     601           0 :                         if (hdr->Marker) gf_rtp_ttxt_flush(rtp, ts);
     602             :                 }
     603             :         }
     604           2 :         gf_bs_del(bs);
     605           2 : }
     606             : 
     607          18 : static void gf_rtp_h264_flush(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, Bool missed_end)
     608             : {
     609             :         u8 *data;
     610             :         u32 data_size, nal_s;
     611          27 :         if (!rtp->inter_bs) return;
     612             : 
     613           9 :         data = NULL;
     614           9 :         data_size = 0;
     615           9 :         gf_bs_get_content(rtp->inter_bs, &data, &data_size);
     616           9 :         gf_bs_del(rtp->inter_bs);
     617           9 :         rtp->inter_bs = NULL;
     618           9 :         nal_s = data_size-4;
     619             : 
     620           9 :         if (rtp->flags & GF_RTP_AVC_USE_ANNEX_B) {
     621           0 :                 data[0] = data[1] = data[2] = 0;
     622           0 :                 data[3] = 1;
     623             :         } else {
     624           9 :                 data[0] = nal_s>>24;
     625           9 :                 data[1] = nal_s>>16;
     626           9 :                 data[2] = nal_s>>8;
     627           9 :                 data[3] = nal_s&0xFF;
     628             :         }
     629             :         /*set F-bit since nal is corrupted*/
     630             : //      if (missed_end) data[4] |= 0x80;
     631             : 
     632           9 :         rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
     633           9 :         rtp->sl_hdr.compositionTimeStampFlag = 1;
     634           9 :         rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     635           9 :         rtp->sl_hdr.decodingTimeStampFlag = 0;
     636             : 
     637           9 :         rtp->on_sl_packet(rtp->udta, data, data_size, &rtp->sl_hdr, GF_OK);
     638           9 :         rtp->sl_hdr.accessUnitStartFlag = 0;
     639           9 :         rtp->sl_hdr.randomAccessPointFlag = 0;
     640           9 :         gf_free(data);
     641             : }
     642             : 
     643         127 : void gf_rtp_parse_h264(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
     644             : {
     645             :         char nalhdr[4];
     646             :         u32 nal_type;
     647         127 :         if (rtp->h264_pck_mode==2) return;
     648             : 
     649         127 :         nal_type = payload[0] & 0x1F;
     650             : 
     651             :         /*set start*/
     652         127 :         if (rtp->sl_hdr.compositionTimeStamp != hdr->TimeStamp) {
     653          80 :                 rtp->sl_hdr.accessUnitEndFlag = 0;
     654          80 :                 rtp->sl_hdr.accessUnitStartFlag = 1;
     655          80 :                 rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     656          80 :                 rtp->sl_hdr.compositionTimeStampFlag = 1;
     657          80 :                 rtp->sl_hdr.decodingTimeStampFlag = 0;
     658          80 :                 rtp->sl_hdr.randomAccessPointFlag = 0;
     659             :         }
     660             : 
     661             :         /*single NALU*/
     662         127 :         if (nal_type<23) {
     663          71 :                 if (nal_type==GF_AVC_NALU_IDR_SLICE) {
     664           2 :                         rtp->sl_hdr.randomAccessPointFlag = 1;
     665           2 :                         rtp->flags &= ~GF_RTP_AVC_WAIT_RAP;
     666             :                 }
     667          69 :                 else if (rtp->flags & GF_RTP_AVC_WAIT_RAP)
     668             :                         return;
     669             : 
     670          71 :                 rtp->sl_hdr.accessUnitEndFlag = 0;
     671             : 
     672          71 :                 if (rtp->flags & GF_RTP_AVC_USE_ANNEX_B) {
     673           0 :                         nalhdr[0] = 0;
     674           0 :                         nalhdr[1] = 0;
     675           0 :                         nalhdr[2] = 0;
     676           0 :                         nalhdr[3] = 1;
     677             :                 } else {
     678             :                         /*signal NALU size on 4 bytes*/
     679          71 :                         nalhdr[0] = size>>24;
     680          71 :                         nalhdr[1] = size>>16;
     681          71 :                         nalhdr[2] = size>>8;
     682          71 :                         nalhdr[3] = size&0xFF;
     683             :                 }
     684          71 :                 rtp->on_sl_packet(rtp->udta, nalhdr, 4, &rtp->sl_hdr, GF_OK);
     685             : 
     686          71 :                 rtp->sl_hdr.accessUnitStartFlag = 0;
     687          71 :                 rtp->sl_hdr.compositionTimeStampFlag = 1;
     688          71 :                 rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     689          71 :                 rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
     690             : 
     691             :                 /*send NAL payload*/
     692          71 :                 rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK);
     693             :         }
     694             :         /*STAP-A NALU*/
     695          56 :         else if (nal_type==24) {
     696             :                 u32 offset = 1;
     697           8 :                 while (offset<size) {
     698             :                         Bool send = GF_TRUE;
     699           4 :                         u32 nal_size = (u8) payload[offset];
     700           4 :                         nal_size<<=8;
     701           4 :                         nal_size |= (u8) payload[offset+1];
     702           4 :                         offset += 2;
     703           4 :                         if ((payload[offset] & 0x1F) == GF_AVC_NALU_IDR_SLICE) {
     704           0 :                                 rtp->sl_hdr.randomAccessPointFlag = 1;
     705           0 :                                 rtp->flags &= ~GF_RTP_AVC_WAIT_RAP;
     706             :                         }
     707           4 :                         if (rtp->flags & GF_RTP_AVC_WAIT_RAP) send = GF_FALSE;
     708             : 
     709             :                         if (send) {
     710             :                                 /*signal NALU size on 4 bytes*/
     711           3 :                                 if (rtp->flags & GF_RTP_AVC_USE_ANNEX_B) {
     712           0 :                                         nalhdr[0] = 0;
     713           0 :                                         nalhdr[1] = 0;
     714           0 :                                         nalhdr[2] = 0;
     715           0 :                                         nalhdr[3] = 1;
     716             :                                 } else {
     717           3 :                                         nalhdr[0] = nal_size>>24;
     718           3 :                                         nalhdr[1] = nal_size>>16;
     719           3 :                                         nalhdr[2] = nal_size>>8;
     720           3 :                                         nalhdr[3] = nal_size&0xFF;
     721             :                                 }
     722           3 :                                 rtp->on_sl_packet(rtp->udta, nalhdr, 4, &rtp->sl_hdr, GF_OK);
     723           3 :                                 rtp->sl_hdr.accessUnitStartFlag = 0;
     724           3 :                                 rtp->sl_hdr.compositionTimeStampFlag = 0;
     725             :                         }
     726           4 :                         rtp->sl_hdr.accessUnitEndFlag = (hdr->Marker && (offset+nal_size==size)) ? 1 : 0;
     727           4 :                         if (send) rtp->on_sl_packet(rtp->udta, payload+offset, nal_size, &rtp->sl_hdr, GF_OK);
     728           4 :                         offset += nal_size;
     729             :                 }
     730             :         }
     731             :         /*FU-A NALU*/
     732          52 :         else if (nal_type==28) {
     733          52 :                 Bool is_start = payload[1] & 0x80;
     734             :                 Bool is_end = payload[1] & 0x40;
     735             :                 /*flush*/
     736          52 :                 if (is_start) gf_rtp_h264_flush(rtp, hdr, GF_TRUE);
     737             : 
     738          52 :                 if ((payload[1] & 0x1F) == GF_AVC_NALU_IDR_SLICE) {
     739          13 :                         rtp->flags &= ~GF_RTP_AVC_WAIT_RAP;
     740          13 :                         rtp->sl_hdr.randomAccessPointFlag = 1;
     741          39 :                 } else if (rtp->flags & GF_RTP_AVC_WAIT_RAP)
     742             :                         return;
     743             : 
     744             :                 /*setup*/
     745          52 :                 if (!rtp->inter_bs) {
     746             :                         u8 nal_hdr;
     747           9 :                         rtp->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     748             :                         /*copy F and NRI*/
     749           9 :                         nal_hdr = payload[0] & 0xE0;
     750             :                         /*start bit not set, signal corrupted data (we missed start packet)*/
     751             : //                      if (!is_start) nal_hdr |= 0x80;
     752             :                         /*copy NALU type*/
     753           9 :                         nal_hdr |= (payload[1] & 0x1F);
     754             :                         /*dummy size field*/
     755           9 :                         gf_bs_write_u32(rtp->inter_bs, 0);
     756           9 :                         gf_bs_write_u8(rtp->inter_bs, nal_hdr);
     757             :                 }
     758          52 :                 gf_bs_write_data(rtp->inter_bs, payload+2, size-2);
     759          52 :                 if (is_end || hdr->Marker) gf_rtp_h264_flush(rtp, hdr, GF_FALSE);
     760             :         }
     761             : }
     762             : 
     763             : #if !defined(GPAC_DISABLE_HEVC) && !defined(GPAC_DISABLE_AV_PARSERS)
     764             : 
     765           8 : static void gf_rtp_hevc_flush(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, Bool missed_end)
     766             : {
     767             :         u8 *data;
     768             :         u32 data_size, nal_s;
     769          12 :         if (!rtp->inter_bs) return;
     770             : 
     771           4 :         data = NULL;
     772           4 :         data_size = 0;
     773           4 :         gf_bs_get_content(rtp->inter_bs, &data, &data_size);
     774           4 :         gf_bs_del(rtp->inter_bs);
     775           4 :         rtp->inter_bs = NULL;
     776           4 :         nal_s = data_size-4;
     777             : 
     778           4 :         data[0] = nal_s>>24;
     779           4 :         data[1] = nal_s>>16;
     780           4 :         data[2] = nal_s>>8;
     781           4 :         data[3] = nal_s&0xFF;
     782             :         /*set F-bit since nal is corrupted*/
     783           4 :         if (missed_end) data[4] |= 0x80;
     784             : 
     785           4 :         rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
     786           4 :         rtp->sl_hdr.compositionTimeStampFlag = 1;
     787           4 :         rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     788           4 :         rtp->sl_hdr.decodingTimeStampFlag = 0;
     789           4 :         rtp->on_sl_packet(rtp->udta, data, data_size, &rtp->sl_hdr, GF_OK);
     790           4 :         rtp->sl_hdr.accessUnitStartFlag = 0;
     791           4 :         rtp->sl_hdr.randomAccessPointFlag = 0;
     792           4 :         gf_free(data);
     793             : }
     794             : 
     795         281 : static void gf_rtp_parse_hevc(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
     796             : {
     797             :         u32 nal_type;
     798             :         char nalu_size[4];
     799             : 
     800         281 :         nal_type = (payload[0] & 0x7E) >> 1;
     801             : 
     802             :         /*set start*/
     803         281 :         if (rtp->sl_hdr.compositionTimeStamp != hdr->TimeStamp) {
     804          27 :                 rtp->sl_hdr.accessUnitEndFlag = 0;
     805          27 :                 rtp->sl_hdr.accessUnitStartFlag = 1;
     806          27 :                 rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     807          27 :                 rtp->sl_hdr.compositionTimeStampFlag = 1;
     808          27 :                 rtp->sl_hdr.decodingTimeStampFlag = 0;
     809          27 :                 rtp->sl_hdr.randomAccessPointFlag = 0;
     810             :         }
     811             : 
     812             :         /*Single NALU*/
     813         281 :         if (nal_type <= 40) {
     814             :                 /*FIXME: strict condition for randomAccessPointFlag because of decoder's issue*/
     815         267 :                 if ((nal_type==GF_HEVC_NALU_SLICE_IDR_W_DLP) || (nal_type==GF_HEVC_NALU_SLICE_IDR_N_LP)) {
     816             :                         //if ((nal_type>=GF_HEVC_NALU_SLICE_BLA_W_LP) && (nal_type<=GF_HEVC_NALU_SLICE_CRA)) {
     817          15 :                         rtp->sl_hdr.randomAccessPointFlag = 1;
     818             :                 }
     819             : 
     820         267 :                 rtp->sl_hdr.accessUnitEndFlag = 0;
     821             : 
     822             :                 /*signal NALU size on 4 bytes*/
     823         267 :                 nalu_size[0] = size>>24;
     824         267 :                 nalu_size[1] = size>>16;
     825         267 :                 nalu_size[2] = size>>8;
     826         267 :                 nalu_size[3] = size&0xFF;
     827         267 :                 rtp->on_sl_packet(rtp->udta, nalu_size, 4, &rtp->sl_hdr, GF_OK);
     828             : 
     829         267 :                 rtp->sl_hdr.accessUnitStartFlag = 0;
     830         267 :                 rtp->sl_hdr.compositionTimeStampFlag = 1;
     831         267 :                 rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     832         267 :                 rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
     833             : 
     834             :                 /*send NAL payload*/
     835         267 :                 rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK);
     836             :         }
     837             :         /*AP NALU*/
     838          14 :         else if (nal_type == 48) {
     839             :                 u32 offset = 2;
     840           0 :                 while (offset<size) {
     841           0 :                         u32 nal_size = (u8) payload[offset];
     842           0 :                         nal_size<<=8;
     843           0 :                         nal_size |= (u8) payload[offset+1];
     844           0 :                         offset += 2;
     845           0 :                         nal_type = (payload[offset] & 0x7E) >> 1;
     846             :                         /*FIXME: strict condition for randomAccessPointFlag because of decoder's issue*/
     847           0 :                         if ((nal_type==GF_HEVC_NALU_SLICE_IDR_W_DLP) || (nal_type==GF_HEVC_NALU_SLICE_IDR_N_LP)) {
     848             :                                 //if ((nal_type>=GF_HEVC_NALU_SLICE_BLA_W_LP) && (nal_type<=GF_HEVC_NALU_SLICE_CRA)) {
     849           0 :                                 rtp->sl_hdr.randomAccessPointFlag = 1;
     850             :                         }
     851             : 
     852             :                         /*signal NALU size on 4 bytes*/
     853           0 :                         nalu_size[0] = nal_size>>24;
     854           0 :                         nalu_size[1] = nal_size>>16;
     855           0 :                         nalu_size[2] = nal_size>>8;
     856           0 :                         nalu_size[3] = nal_size&0xFF;
     857           0 :                         rtp->on_sl_packet(rtp->udta, nalu_size, 4, &rtp->sl_hdr, GF_OK);
     858             : 
     859           0 :                         rtp->sl_hdr.accessUnitStartFlag = 0;
     860           0 :                         rtp->sl_hdr.compositionTimeStampFlag = 0;
     861           0 :                         rtp->sl_hdr.accessUnitEndFlag = (hdr->Marker && (offset+nal_size==size)) ? 1 : 0;
     862           0 :                         rtp->on_sl_packet(rtp->udta, payload+offset, nal_size, &rtp->sl_hdr, GF_OK);
     863           0 :                         offset += nal_size;
     864             :                 }
     865             :         }
     866             :         /*FU NALU*/
     867          14 :         else if (nal_type == 49) {
     868          14 :                 Bool is_start = payload[2] & 0x80;
     869             :                 Bool is_end = payload[2] & 0x40;
     870             :                 /*flush*/
     871          14 :                 if (is_start) gf_rtp_hevc_flush(rtp, hdr, GF_TRUE);
     872             : 
     873          14 :                 nal_type = payload[2] & 0x3F;
     874             :                 /*FIXME: strict condition for randomAccessPointFlag because of decoder's issue*/
     875          14 :                 if ((nal_type==GF_HEVC_NALU_SLICE_IDR_W_DLP) || (nal_type==GF_HEVC_NALU_SLICE_IDR_N_LP)) {
     876             :                         //if ((nal_type>=GF_HEVC_NALU_SLICE_BLA_W_LP) && (nal_type<=GF_HEVC_NALU_SLICE_CRA)) {
     877          12 :                         rtp->sl_hdr.randomAccessPointFlag = 1;
     878             :                 }
     879             : 
     880             :                 /*setup*/
     881          14 :                 if (!rtp->inter_bs) {
     882             :                         char nal_hdr[2];
     883           4 :                         rtp->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     884             :                         /*coypy F bit highest bit of LayerId*/
     885           4 :                         nal_hdr[0] = payload[0] & 0x81;
     886             :                         /*assign NAL type*/
     887           4 :                         nal_hdr[0] |= (payload[2] & 0x3F) << 1;
     888             :                         /*copy LayerId and TID*/
     889           4 :                         nal_hdr[1] = payload[1];
     890             :                         /*dummy size field*/
     891           4 :                         gf_bs_write_u32(rtp->inter_bs, 0);
     892           4 :                         gf_bs_write_data(rtp->inter_bs, nal_hdr, 2);
     893             :                 }
     894          14 :                 gf_bs_write_data(rtp->inter_bs, payload+3, size-3);
     895          14 :                 if (is_end || hdr->Marker) gf_rtp_hevc_flush(rtp, hdr, GF_FALSE);
     896             :         }
     897         281 : }
     898             : #endif
     899             : 
     900             : #ifndef GPAC_DISABLE_AV_PARSERS
     901             : 
     902           9 : static void gf_rtp_parse_latm(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
     903             : {
     904             :         u32 remain, latm_hdr_size, latm_size;
     905             : 
     906           9 :         rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     907           9 :         rtp->sl_hdr.compositionTimeStampFlag = 1;
     908           9 :         rtp->sl_hdr.accessUnitStartFlag = rtp->sl_hdr.accessUnitEndFlag = 1;
     909           9 :         rtp->sl_hdr.randomAccessPointFlag = 1;
     910             : 
     911             :         remain = size;
     912          65 :         while (remain) {
     913             :                 latm_hdr_size = latm_size = 0;
     914             :                 while (1) {
     915          70 :                         u8 c = *payload;
     916          70 :                         latm_hdr_size += 1;
     917          70 :                         latm_size += c;
     918          70 :                         payload ++;
     919          70 :                         if (c < 0xFF) break;
     920             :                 }
     921             : 
     922          47 :                 rtp->on_sl_packet(rtp->udta, (char *) payload, latm_size, &rtp->sl_hdr, GF_OK);
     923          47 :                 payload += latm_size;
     924          47 :                 remain -= (latm_size+latm_hdr_size);
     925          47 :                 if (rtp->sl_hdr.au_duration)
     926          47 :                         rtp->sl_hdr.compositionTimeStamp += rtp->sl_hdr.au_duration;
     927             :                 else
     928           0 :                         rtp->sl_hdr.compositionTimeStamp += 1024;
     929             :         }
     930           9 : }
     931             : #endif
     932             : 
     933             : #if GPAC_ENABLE_3GPP_DIMS_RTP
     934             : static void gf_rtp_parse_3gpp_dims(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, char *payload, u32 size)
     935             : {
     936             :         u32 du_size, offset, dsize, hdr_size;
     937             :         char *data, dhdr[6];
     938             : 
     939             :         u32 frag_state = ((payload[0]>>3) & 0x7);
     940             : 
     941             :         rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
     942             :         rtp->sl_hdr.compositionTimeStampFlag = 1;
     943             : 
     944             :         if (rtp->flags & GF_RTP_NEW_AU) {
     945             :                 rtp->flags &= ~GF_RTP_NEW_AU;
     946             :                 rtp->sl_hdr.accessUnitStartFlag = 1;
     947             :         }
     948             :         rtp->sl_hdr.accessUnitEndFlag = 0;
     949             :         if (hdr->Marker) rtp->flags |= GF_RTP_NEW_AU;
     950             : 
     951             :         rtp->sl_hdr.randomAccessPointFlag = (payload[0] & 0x40);
     952             :         rtp->sl_hdr.AU_sequenceNumber = (payload[0] & 0x7);
     953             : 
     954             :         offset = 1;
     955             :         while (offset < size) {
     956             :                 switch (frag_state) {
     957             :                 case 0:
     958             :                 {
     959             :                         GF_BitStream *bs;
     960             :                         bs = gf_bs_new(payload+offset, 2, GF_BITSTREAM_READ);
     961             :                         du_size = 2 + gf_bs_read_u16(bs);
     962             :                         gf_bs_del(bs);
     963             :                         if (hdr->Marker && offset+du_size>=size) {
     964             :                                 rtp->sl_hdr.accessUnitEndFlag = 1;
     965             :                         }
     966             :                         rtp->on_sl_packet(rtp->udta, payload + offset, du_size, &rtp->sl_hdr, GF_OK);
     967             :                         rtp->sl_hdr.accessUnitStartFlag = 0;
     968             :                         offset += du_size;
     969             :                 }
     970             :                 break;
     971             :                 case 1:
     972             :                         if (rtp->inter_bs) gf_bs_del(rtp->inter_bs);
     973             : 
     974             :                         rtp->inter_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     975             :                         gf_bs_write_data(rtp->inter_bs, payload+offset, size-offset);
     976             :                         return;
     977             :                 case 2:
     978             :                         if (!rtp->inter_bs) return;
     979             :                         gf_bs_write_data(rtp->inter_bs, payload+offset, size-offset);
     980             :                         return;
     981             :                 case 3:
     982             :                         if (!rtp->inter_bs) return;
     983             :                         gf_bs_write_data(rtp->inter_bs, payload+offset, size-offset);
     984             :                         gf_bs_get_content(rtp->inter_bs, &data, &dsize);
     985             :                         gf_bs_del(rtp->inter_bs);
     986             : 
     987             :                         /*send unit header - if dims size is >0xFFFF, use our internal hack for large units*/
     988             :                         rtp->inter_bs = gf_bs_new(dhdr, 6, GF_BITSTREAM_WRITE);
     989             :                         if (dsize<=0xFFFF) {
     990             :                                 gf_bs_write_u16(rtp->inter_bs, dsize);
     991             :                                 hdr_size = 2;
     992             :                         } else {
     993             :                                 gf_bs_write_u16(rtp->inter_bs, 0);
     994             :                                 gf_bs_write_u32(rtp->inter_bs, dsize);
     995             :                                 hdr_size = 6;
     996             :                         }
     997             :                         gf_bs_del(rtp->inter_bs);
     998             :                         rtp->inter_bs = NULL;
     999             : 
    1000             :                         rtp->on_sl_packet(rtp->udta, dhdr, hdr_size, &rtp->sl_hdr, GF_OK);
    1001             :                         rtp->sl_hdr.accessUnitStartFlag = 0;
    1002             : 
    1003             :                         rtp->sl_hdr.accessUnitEndFlag = hdr->Marker;
    1004             :                         rtp->on_sl_packet(rtp->udta, data, dsize, &rtp->sl_hdr, GF_OK);
    1005             :                         gf_free(data);
    1006             :                         return;
    1007             :                 }
    1008             :         }
    1009             : 
    1010             : }
    1011             : #endif
    1012             : 
    1013             : 
    1014             : #ifndef GPAC_DISABLE_AV_PARSERS
    1015             : 
    1016          29 : static void gf_rtp_parse_ac3(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
    1017             : {
    1018             :         u8 ft;
    1019             : 
    1020          29 :         rtp->sl_hdr.compositionTimeStampFlag = 1;
    1021          29 :         rtp->sl_hdr.compositionTimeStamp = hdr->TimeStamp;
    1022          29 :         rtp->sl_hdr.randomAccessPointFlag = 1;
    1023          29 :         ft = payload[0];
    1024             :         /*nb_pck = payload[1];*/
    1025          29 :         payload += 2;
    1026          29 :         size -= 2;
    1027             : 
    1028          29 :         if (!ft) {
    1029             :                 GF_AC3Config ac3hdr;
    1030             :                 memset(&ac3hdr, 0, sizeof(GF_AC3Config));
    1031          29 :                 rtp->sl_hdr.accessUnitStartFlag = rtp->sl_hdr.accessUnitEndFlag = 1;
    1032          87 :                 while (size) {
    1033             :                         u32 offset;
    1034          29 :                         if (!gf_ac3_parser((u8*)payload, size, &offset, &ac3hdr, GF_FALSE)) {
    1035           0 :                                 return;
    1036             :                         }
    1037          29 :                         if (offset) {
    1038           0 :                                 if (offset>size) return;
    1039           0 :                                 payload+=offset;
    1040           0 :                                 size-=offset;
    1041             :                         }
    1042          29 :                         rtp->on_sl_packet(rtp->udta, payload, ac3hdr.framesize, &rtp->sl_hdr, GF_OK);
    1043          29 :                         if (size < ac3hdr.framesize) return;
    1044          29 :                         size -= ac3hdr.framesize;
    1045          29 :                         payload += ac3hdr.framesize;
    1046          29 :                         rtp->sl_hdr.compositionTimeStamp += 1536;
    1047             :                 }
    1048          29 :                 rtp->flags |= GF_RTP_NEW_AU;
    1049           0 :         } else if (ft==3) {
    1050           0 :                 rtp->sl_hdr.accessUnitStartFlag = 0;
    1051           0 :                 rtp->sl_hdr.accessUnitEndFlag = hdr->Marker ? 1 : 0;
    1052           0 :                 rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK);
    1053             :         } else {
    1054           0 :                 rtp->sl_hdr.accessUnitStartFlag = 1;
    1055           0 :                 rtp->sl_hdr.accessUnitEndFlag = 0;
    1056           0 :                 rtp->on_sl_packet(rtp->udta, payload, size, &rtp->sl_hdr, GF_OK);
    1057             :         }
    1058             : }
    1059             : #endif /*GPAC_DISABLE_AV_PARSERS*/
    1060             : 
    1061          20 : static u32 gf_rtp_get_payload_type(GF_RTPMap *map, GF_SDPMedia *media)
    1062             : {
    1063             :         u32 i, j;
    1064             : 
    1065          20 :         if (!stricmp(map->payload_name, "MP4V-ES") ) return GF_RTP_PAYT_MPEG4;
    1066          19 :         else if (!stricmp(map->payload_name, "mpeg4-generic")) return GF_RTP_PAYT_MPEG4;
    1067          12 :         else if (!stricmp(map->payload_name, "enc-mpeg4-generic")) return GF_RTP_PAYT_MPEG4;
    1068             :         /*optibase mm400 card hack*/
    1069          12 :         else if (!stricmp(map->payload_name, "enc-generic-mp4") ) {
    1070           0 :                 gf_free(map->payload_name);
    1071           0 :                 map->payload_name = gf_strdup("enc-mpeg4-generic");
    1072             :                 return GF_RTP_PAYT_MPEG4;
    1073             :         }
    1074             : 
    1075             :         /*LATM: only without multiplexing (not tested but should be straight AUs)*/
    1076          12 :         else if (!stricmp(map->payload_name, "MP4A-LATM")) {
    1077             :                 GF_SDP_FMTP *fmtp;
    1078           1 :                 i=0;
    1079           2 :                 while ((fmtp = (GF_SDP_FMTP *) gf_list_enum(media->FMTP, &i))) {
    1080             :                         GF_X_Attribute *att;
    1081           1 :                         if (fmtp->PayloadType != map->PayloadType) continue;
    1082             :                         //this is our payload. check cpresent is 0
    1083           1 :                         j=0;
    1084           4 :                         while ((att = (GF_X_Attribute *)gf_list_enum(fmtp->Attributes, &j))) {
    1085           4 :                                 if (!stricmp(att->Name, "cpresent") && atoi(att->Value)) return 0;
    1086             :                         }
    1087             :                 }
    1088             :                 return GF_RTP_PAYT_LATM;
    1089             :         }
    1090          11 :         else if (!stricmp(map->payload_name, "MPA")) return GF_RTP_PAYT_MPEG12_AUDIO;
    1091          10 :         else if (!stricmp(map->payload_name, "MPV")) return GF_RTP_PAYT_MPEG12_VIDEO;
    1092           9 :         else if (!stricmp(map->payload_name, "H263-1998") || !stricmp(map->payload_name, "H263-2000")) return GF_RTP_PAYT_H263;
    1093           8 :         else if (!stricmp(map->payload_name, "AMR")) return GF_RTP_PAYT_AMR;
    1094           7 :         else if (!stricmp(map->payload_name, "AMR-WB")) return GF_RTP_PAYT_AMR_WB;
    1095           7 :         else if (!stricmp(map->payload_name, "3gpp-tt")) return GF_RTP_PAYT_3GPP_TEXT;
    1096           6 :         else if (!stricmp(map->payload_name, "H264")) return GF_RTP_PAYT_H264_AVC;
    1097             : #if GPAC_ENABLE_3GPP_DIMS_RTP
    1098             :         else if (!stricmp(map->payload_name, "richmedia+xml")) return GF_RTP_PAYT_3GPP_DIMS;
    1099             : #endif
    1100           3 :         else if (!stricmp(map->payload_name, "ac3")) return GF_RTP_PAYT_AC3;
    1101           2 :         else if (!stricmp(map->payload_name, "H264-SVC")) return GF_RTP_PAYT_H264_SVC;
    1102           2 :         else if (!stricmp(map->payload_name, "H265")) return GF_RTP_PAYT_HEVC;
    1103           1 :         else if (!stricmp(map->payload_name, "H265-SHVC")) return GF_RTP_PAYT_LHVC;
    1104             :         else return 0;
    1105             : }
    1106             : 
    1107             : 
    1108          90 : static GF_Err payt_set_param(GF_RTPDepacketizer *rtp, char *param_name, char *param_val)
    1109             : {
    1110             :         u32 i, val;
    1111             :         char valS[3];
    1112             :         GF_BitStream *bs;
    1113             : 
    1114          90 :         if (!rtp || !param_name) return GF_BAD_PARAM;
    1115             : 
    1116             :         /*1 - mpeg4-generic / RFC 3016 payload type items*/
    1117             : 
    1118             :         /*PL (not needed when IOD is here)*/
    1119          90 :         if (!stricmp(param_name, "Profile-level-id")) {
    1120          12 :                 if (rtp->payt == GF_RTP_PAYT_H264_AVC || rtp->payt == GF_RTP_PAYT_H264_SVC) {
    1121           3 :                         sscanf(param_val, "%x", &rtp->sl_map.PL_ID);
    1122             :                 } else {
    1123           9 :                         rtp->sl_map.PL_ID = atoi(param_val);
    1124             :                 }
    1125             :         }
    1126             :         /*decoder specific info (not needed when IOD is here)*/
    1127          78 :         else if (!stricmp(param_name, "config")) {
    1128           9 :                 u32 len = (u32) strlen(param_val);
    1129             :                 //decode the buffer - the string buffer is MSB hexadecimal
    1130           9 :                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    1131           9 :                 valS[2] = 0;
    1132          86 :                 for (i=0; i<len; i+=2) {
    1133          77 :                         valS[0] = param_val[i];
    1134          77 :                         valS[1] = param_val[i+1];
    1135          77 :                         sscanf(valS, "%x", &val);
    1136          77 :                         gf_bs_write_u8(bs, val);
    1137             :                 }
    1138           9 :                 if (rtp->sl_map.config) gf_free(rtp->sl_map.config);
    1139           9 :                 rtp->sl_map.config = NULL;
    1140           9 :                 gf_bs_get_content(bs, &rtp->sl_map.config, &rtp->sl_map.configSize);
    1141           9 :                 gf_bs_del(bs);
    1142             :         }
    1143             :         /*mpeg4-generic payload type items required*/
    1144             : 
    1145             :         /*constant size (size of all AUs) */
    1146          69 :         else if (!stricmp(param_name, "ConstantSize")) {
    1147           0 :                 rtp->sl_map.ConstantSize = atoi(param_val);
    1148             :         }
    1149             :         /*constant size (size of all AUs) */
    1150          69 :         else if (!stricmp(param_name, "ConstantDuration")) {
    1151           7 :                 rtp->sl_map.ConstantDuration = atoi(param_val);
    1152             :         }
    1153             :         /*object type indication (not needed when IOD is here)*/
    1154          62 :         else if (!stricmp(param_name, "ObjectType")) {
    1155           7 :                 rtp->sl_map.CodecID = atoi(param_val);
    1156             :         }
    1157          55 :         else if (!stricmp(param_name, "StreamType"))
    1158           7 :                 rtp->sl_map.StreamType = atoi(param_val);
    1159          48 :         else if (!stricmp(param_name, "mode")) {
    1160           7 :                 strcpy(rtp->sl_map.mode, param_val);
    1161             :                 /*in case no IOD and no streamType/OTI in the file*/
    1162           7 :                 if (!stricmp(param_val, "AAC-hbr") || !stricmp(param_val, "AAC-lbr") || !stricmp(param_val, "CELP-vbr") || !stricmp(param_val, "CELP-cbr")) {
    1163           7 :                         rtp->sl_map.StreamType = GF_STREAM_AUDIO;
    1164           7 :                         rtp->sl_map.CodecID = GF_CODECID_AAC_MPEG4;
    1165             :                 }
    1166             :                 /*in case no IOD and no streamType/OTI in the file*/
    1167           0 :                 else if (!stricmp(param_val, "avc-video") ) {
    1168           0 :                         rtp->sl_map.StreamType = GF_STREAM_VISUAL;
    1169           0 :                         rtp->sl_map.CodecID = GF_CODECID_AVC;
    1170             :                 }
    1171             :         }
    1172             : 
    1173          41 :         else if (!stricmp(param_name, "DTSDeltaLength")) rtp->sl_map.DTSDeltaLength = atoi(param_val);
    1174          41 :         else if (!stricmp(param_name, "CTSDeltaLength")) rtp->sl_map.CTSDeltaLength = atoi(param_val);
    1175          48 :         else if (!stricmp(param_name, "SizeLength")) rtp->sl_map.SizeLength = atoi(param_val);
    1176          41 :         else if (!stricmp(param_name, "IndexLength")) rtp->sl_map.IndexLength = atoi(param_val);
    1177          34 :         else if (!stricmp(param_name, "IndexDeltaLength")) rtp->sl_map.IndexDeltaLength = atoi(param_val);
    1178          20 :         else if (!stricmp(param_name, "RandomAccessIndication")) rtp->sl_map.RandomAccessIndication = atoi(param_val);
    1179          20 :         else if (!stricmp(param_name, "StreamStateIndication")) rtp->sl_map.StreamStateIndication = atoi(param_val);
    1180          20 :         else if (!stricmp(param_name, "AuxiliaryDataSizeLength")) rtp->sl_map.AuxiliaryDataSizeLength = atoi(param_val);
    1181             : 
    1182             :         /*H264/AVC config - we only handle mode 0 and 1*/
    1183          20 :         else if (!stricmp(param_name, "packetization-mode"))
    1184           3 :                 rtp->h264_pck_mode = 1;
    1185             :         /*AMR config*/
    1186          17 :         else if (!stricmp(param_name, "octet-align")) {
    1187           1 :                 if (!stricmp(param_val, "1"))
    1188           1 :                         rtp->flags |= GF_RTP_AMR_ALIGN;
    1189             :         } /*ISMACryp config*/
    1190          16 :         else if (!stricmp(param_name, "ISMACrypCryptoSuite")) {
    1191           0 :                 if (!stricmp(param_val, "AES_CTR_128"))
    1192           0 :                         rtp->isma_scheme = GF_ISOM_ISMACRYP_SCHEME;
    1193             :                 else
    1194           0 :                         rtp->isma_scheme = 0;
    1195             :         }
    1196          16 :         else if (!stricmp(param_name, "ISMACrypSelectiveEncryption")) {
    1197           0 :                 if (!stricmp(param_val, "1") || !stricmp(param_val, "true"))
    1198           0 :                         rtp->flags |= GF_RTP_ISMA_SEL_ENC;
    1199             :                 else
    1200           0 :                         rtp->flags &= ~GF_RTP_ISMA_SEL_ENC;
    1201             :         }
    1202          16 :         else if (!stricmp(param_name, "ISMACrypIVLength"))
    1203           0 :                 rtp->sl_map.IV_length = atoi(param_val);
    1204          16 :         else if (!stricmp(param_name, "ISMACrypDeltaIVLength"))
    1205           0 :                 rtp->sl_map.IV_delta_length = atoi(param_val);
    1206          16 :         else if (!stricmp(param_name, "ISMACrypKeyIndicatorLength"))
    1207           0 :                 rtp->sl_map.KI_length = atoi(param_val);
    1208          16 :         else if (!stricmp(param_name, "ISMACrypKeyIndicatorPerAU")) {
    1209           0 :                 if (!stricmp(param_val, "1") || !stricmp(param_val, "true"))
    1210           0 :                         rtp->flags |= GF_RTP_ISMA_HAS_KEY_IDX;
    1211             :                 else
    1212           0 :                         rtp->flags &= ~GF_RTP_ISMA_HAS_KEY_IDX;
    1213          16 :         } else if (!stricmp(param_name, "ISMACrypKey")) {
    1214           0 :                 rtp->key = gf_strdup(param_val);
    1215             :         }
    1216             :         return GF_OK;
    1217             : }
    1218             : 
    1219          20 : static GF_Err gf_rtp_payt_setup(GF_RTPDepacketizer *rtp, GF_RTPMap *map, GF_SDPMedia *media)
    1220             : {
    1221             :         u32 i, j;
    1222             :         GF_SDP_FMTP *fmtp;
    1223             : 
    1224             :         /*reset sl map*/
    1225          20 :         memset(&rtp->sl_map, 0, sizeof(GP_RTPSLMap));
    1226             : 
    1227          20 :         if (map && !stricmp(map->payload_name, "enc-mpeg4-generic")) rtp->flags |= GF_RTP_HAS_ISMACRYP;
    1228             : 
    1229             : 
    1230             :         /*then process all FMTPs*/
    1231          20 :         if (media) {
    1232          19 :                 i=0;
    1233          53 :                 while ((fmtp = (GF_SDP_FMTP*)gf_list_enum(media->FMTP, &i))) {
    1234             :                         GF_X_Attribute *att;
    1235             :                         //we work with only one PayloadType for now
    1236          15 :                         if (map && (fmtp->PayloadType != map->PayloadType)) continue;
    1237          15 :                         j=0;
    1238         120 :                         while ((att = (GF_X_Attribute *)gf_list_enum(fmtp->Attributes, &j))) {
    1239          90 :                                 payt_set_param(rtp, att->Name, att->Value);
    1240             :                         }
    1241             :                 }
    1242             :         }
    1243             : 
    1244          20 :         switch (rtp->payt) {
    1245             : #ifndef GPAC_DISABLE_AV_PARSERS
    1246           1 :         case GF_RTP_PAYT_LATM:
    1247             :         {
    1248             :                 u32 AudioMuxVersion, AllStreamsSameTime, numSubFrames, numPrograms, numLayers, ch_cfg;
    1249             :                 GF_M4ADecSpecInfo cfg;
    1250           1 :                 char *latm_dsi = rtp->sl_map.config;
    1251           1 :                 GF_BitStream *bs = gf_bs_new(latm_dsi, rtp->sl_map.configSize, GF_BITSTREAM_READ);
    1252           1 :                 AudioMuxVersion = gf_bs_read_int(bs, 1);
    1253           1 :                 AllStreamsSameTime = gf_bs_read_int(bs, 1);
    1254           1 :                 numSubFrames = gf_bs_read_int(bs, 6);
    1255           1 :                 numPrograms = gf_bs_read_int(bs, 4);
    1256           1 :                 numLayers = gf_bs_read_int(bs, 3);
    1257             : 
    1258           1 :                 if (AudioMuxVersion || !AllStreamsSameTime || numSubFrames || numPrograms || numLayers) {
    1259           0 :                         gf_bs_del(bs);
    1260           0 :                         return GF_NOT_SUPPORTED;
    1261             :                 }
    1262             :                 memset(&cfg, 0, sizeof(cfg));
    1263           1 :                 cfg.base_object_type = gf_bs_read_int(bs, 5);
    1264           1 :                 cfg.base_sr_index = gf_bs_read_int(bs, 4);
    1265           1 :                 if (cfg.base_sr_index == 0x0F) {
    1266           0 :                         cfg.base_sr = gf_bs_read_int(bs, 24);
    1267             :                 } else {
    1268           1 :                         cfg.base_sr = GF_M4ASampleRates[cfg.base_sr_index];
    1269             :                 }
    1270           1 :                 ch_cfg = gf_bs_read_int(bs, 4);
    1271           1 :                 if (cfg.base_object_type==5 || cfg.base_object_type==29) {
    1272           0 :                         if (cfg.base_object_type==29) {
    1273           0 :                                 cfg.has_ps = 1;
    1274           0 :                                 cfg.nb_chan = 1;
    1275             :                         }
    1276           0 :                         cfg.has_sbr = 1;
    1277           0 :                         cfg.sbr_sr_index = gf_bs_read_int(bs, 4);
    1278           0 :                         if (cfg.sbr_sr_index == 0x0F) {
    1279           0 :                                 cfg.sbr_sr = gf_bs_read_int(bs, 24);
    1280             :                         } else {
    1281           0 :                                 cfg.sbr_sr = GF_M4ASampleRates[cfg.sbr_sr_index];
    1282             :                         }
    1283           0 :                         cfg.sbr_object_type = gf_bs_read_int(bs, 5);
    1284             :                 }
    1285           1 :                 gf_bs_del(bs);
    1286           1 :                 gf_free(rtp->sl_map.config);
    1287           1 :                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    1288             :                 /*write as regular AAC*/
    1289           1 :                 gf_bs_write_int(bs, cfg.base_object_type, 5);
    1290           1 :                 gf_bs_write_int(bs, cfg.base_sr_index, 4);
    1291             : 
    1292           1 :                 gf_bs_write_int(bs, ch_cfg, 4);
    1293           1 :                 gf_bs_align(bs);
    1294           1 :                 gf_bs_get_content(bs, &rtp->sl_map.config, &rtp->sl_map.configSize);
    1295           1 :                 gf_bs_del(bs);
    1296           1 :                 rtp->sl_map.StreamType = GF_STREAM_AUDIO;
    1297           1 :                 rtp->sl_map.CodecID = GF_CODECID_AAC_MPEG4;
    1298           1 :                 rtp->sl_hdr.au_duration = 1024;
    1299           1 :                 if (cfg.base_sr && map && (cfg.base_sr!=map->ClockRate)) {
    1300           0 :                         rtp->sl_hdr.au_duration *= map->ClockRate;
    1301           0 :                         rtp->sl_hdr.au_duration /= cfg.base_sr;
    1302             :                 }
    1303             : 
    1304             :                 /*assign depacketizer*/
    1305           1 :                 rtp->depacketize = gf_rtp_parse_latm;
    1306             :         }
    1307           1 :         break;
    1308             : #endif
    1309           8 :         case GF_RTP_PAYT_MPEG4:
    1310             :                 /*mark if AU header is present*/
    1311           8 :                 rtp->sl_map.auh_first_min_len = 0;
    1312           8 :                 if (rtp->flags & GF_RTP_HAS_ISMACRYP) {
    1313           0 :                         if (!rtp->isma_scheme) rtp->isma_scheme = GF_ISOM_ISMACRYP_SCHEME;
    1314           0 :                         if (!rtp->sl_map.IV_length) rtp->sl_map.IV_length = 4;
    1315             : 
    1316           0 :                         if (rtp->flags & GF_RTP_ISMA_SEL_ENC) rtp->sl_map.auh_first_min_len += 8;
    1317           0 :                         else rtp->sl_map.auh_first_min_len += 8*(rtp->sl_map.IV_length + rtp->sl_map.KI_length);
    1318             :                 }
    1319           8 :                 rtp->sl_map.auh_first_min_len += rtp->sl_map.CTSDeltaLength;
    1320           8 :                 rtp->sl_map.auh_first_min_len += rtp->sl_map.DTSDeltaLength;
    1321           8 :                 rtp->sl_map.auh_first_min_len += rtp->sl_map.SizeLength;
    1322           8 :                 rtp->sl_map.auh_first_min_len += rtp->sl_map.RandomAccessIndication;
    1323           8 :                 rtp->sl_map.auh_first_min_len += rtp->sl_map.StreamStateIndication;
    1324             :                 rtp->sl_map.auh_min_len = rtp->sl_map.auh_first_min_len;
    1325           8 :                 rtp->sl_map.auh_first_min_len += rtp->sl_map.IndexLength;
    1326           8 :                 rtp->sl_map.auh_min_len += rtp->sl_map.IndexDeltaLength;
    1327           8 :                 if (!map) {
    1328           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP] Missing required payload map\n"));
    1329             :                         return GF_NON_COMPLIANT_BITSTREAM;
    1330             :                 }
    1331             :                 /*RFC3016 flags*/
    1332           8 :                 if (!stricmp(map->payload_name, "MP4V-ES")) {
    1333           1 :                         rtp->sl_map.StreamType = GF_STREAM_VISUAL;
    1334           1 :                         rtp->sl_map.CodecID = GF_CODECID_MPEG4_PART2;
    1335             :                 }
    1336           7 :                 else if (!strnicmp(map->payload_name, "AAC", 3)) {
    1337           0 :                         rtp->sl_map.StreamType = GF_STREAM_AUDIO;
    1338           0 :                         rtp->sl_map.CodecID = GF_CODECID_AAC_MPEG4;
    1339             :                 }
    1340           7 :                 else if (!stricmp(map->payload_name, "MP4A-LATM")) {
    1341           0 :                         rtp->sl_map.StreamType = GF_STREAM_AUDIO;
    1342           0 :                         rtp->sl_map.CodecID = GF_CODECID_AAC_MPEG4;
    1343             :                 }
    1344             :                 /*MPEG-4 video, check RAPs if not indicated*/
    1345           8 :                 if ((rtp->sl_map.StreamType == GF_STREAM_VISUAL) && (rtp->sl_map.CodecID == GF_CODECID_MPEG4_PART2) && !rtp->sl_map.RandomAccessIndication) {
    1346           1 :                         rtp->flags |= GF_RTP_M4V_CHECK_RAP;
    1347             :                 }
    1348             : #ifndef GPAC_DISABLE_AV_PARSERS
    1349           8 :                 if ((rtp->sl_map.CodecID == GF_CODECID_AAC_MPEG4) && !rtp->sl_map.config && media) {
    1350             :                         GF_M4ADecSpecInfo cfg;
    1351           0 :                         GF_RTPMap *a_map = (GF_RTPMap*)gf_list_get(media->RTPMaps, 0);
    1352             : 
    1353             :                         memset(&cfg, 0, sizeof(GF_M4ADecSpecInfo));
    1354           0 :                         cfg.audioPL = rtp->sl_map.PL_ID;
    1355           0 :                         cfg.nb_chan = a_map->AudioChannels ? a_map->AudioChannels : 1;
    1356           0 :                         cfg.base_sr = a_map->ClockRate/2;
    1357           0 :                         cfg.sbr_sr = a_map->ClockRate;
    1358           0 :                         cfg.base_object_type = GF_M4A_AAC_SBR;
    1359           0 :                         cfg.sbr_object_type = GF_M4A_AAC_MAIN;
    1360           0 :                         gf_m4a_write_config(&cfg, &rtp->sl_map.config, &rtp->sl_map.configSize);
    1361             :                 }
    1362             : #endif
    1363             :                 /*assign depacketizer*/
    1364           8 :                 rtp->depacketize = gf_rtp_parse_mpeg4;
    1365           8 :                 break;
    1366             : #ifndef GPAC_DISABLE_AV_PARSERS
    1367           1 :         case GF_RTP_PAYT_MPEG12_AUDIO:
    1368           1 :                 rtp->sl_map.StreamType = GF_STREAM_AUDIO;
    1369           1 :                 rtp->sl_map.CodecID = GF_CODECID_MPEG2_PART3;
    1370             :                 /*assign depacketizer*/
    1371           1 :                 rtp->depacketize = gf_rtp_parse_mpeg12_audio;
    1372           1 :                 break;
    1373             : #endif /*GPAC_DISABLE_AV_PARSERS*/
    1374             : 
    1375           1 :         case GF_RTP_PAYT_MPEG12_VIDEO:
    1376             :                 /*we signal RAPs*/
    1377           1 :                 rtp->sl_map.RandomAccessIndication = GF_TRUE;
    1378           1 :                 rtp->sl_map.StreamType = GF_STREAM_VISUAL;
    1379             :                 /*FIXME: how to differentiate MPEG1 from MPEG2 video before any frame is received??*/
    1380           1 :                 rtp->sl_map.CodecID = GF_CODECID_MPEG1;
    1381             :                 /*assign depacketizer*/
    1382           1 :                 rtp->depacketize = gf_rtp_parse_mpeg12_video;
    1383           1 :                 break;
    1384           1 :         case GF_RTP_PAYT_AMR:
    1385             :         case GF_RTP_PAYT_AMR_WB:
    1386           1 :                 rtp->sl_map.StreamType = GF_STREAM_AUDIO;
    1387           1 :                 rtp->sl_map.CodecID = (rtp->payt == GF_RTP_PAYT_AMR) ? GF_CODECID_AMR : GF_CODECID_AMR_WB;
    1388             :                 /*assign depacketizer*/
    1389           1 :                 rtp->depacketize = gf_rtp_parse_amr;
    1390           1 :                 break;
    1391           1 :         case GF_RTP_PAYT_H263:
    1392           1 :                 if (media) {
    1393             :                         GF_X_Attribute *att;
    1394           1 :                         j=0;
    1395           5 :                         while ((att = (GF_X_Attribute *)gf_list_enum(media->Attributes, &j))) {
    1396           3 :                                 if (stricmp(att->Name, "cliprect")) continue;
    1397             :                                 /*only get the display area*/
    1398           1 :                                 sscanf(att->Value, "%u,%u,%u,%u", &rtp->y, &rtp->x, &rtp->h, &rtp->w);
    1399             :                         }
    1400             :                 }
    1401           1 :                 rtp->sl_map.StreamType = GF_STREAM_VISUAL;
    1402           1 :                 rtp->sl_map.CodecID = GF_CODECID_H263;
    1403             : 
    1404             :                 /*we signal RAPs*/
    1405           1 :                 rtp->sl_map.RandomAccessIndication = GF_TRUE;
    1406             : 
    1407             :                 /*assign depacketizer*/
    1408           1 :                 rtp->depacketize = gf_rtp_parse_h263;
    1409           1 :                 break;
    1410             : 
    1411             :         case GF_RTP_PAYT_3GPP_TEXT:
    1412             :         {
    1413             :                 char *tx3g, *a_tx3g;
    1414             :                 GF_BitStream *bs;
    1415             :                 u32 nb_desc;
    1416             :                 GF_TextConfig tcfg;
    1417             :                 memset(&tcfg, 0, sizeof(GF_TextConfig));
    1418           1 :                 tcfg.tag = GF_ODF_TEXT_CFG_TAG;
    1419           1 :                 tcfg.Base3GPPFormat = 0x10;
    1420           1 :                 tcfg.MPEGExtendedFormat = 0x10;
    1421           1 :                 tcfg.profileLevel = 0x10;
    1422           1 :                 if (!map || !media) {
    1423           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP] Missing required payload map\n"));
    1424           0 :                         return GF_NON_COMPLIANT_BITSTREAM;
    1425             :                 }
    1426           1 :                 tcfg.timescale = map->ClockRate;
    1427           1 :                 tcfg.sampleDescriptionFlags = 1;
    1428             :                 tx3g = NULL;
    1429             : 
    1430           1 :                 i=0;
    1431           3 :                 while ((fmtp = (GF_SDP_FMTP*)gf_list_enum(media->FMTP, &i))) {
    1432             :                         GF_X_Attribute *att;
    1433           1 :                         if (fmtp->PayloadType != map->PayloadType) continue;
    1434           1 :                         j=0;
    1435          11 :                         while ((att = (GF_X_Attribute *)gf_list_enum(fmtp->Attributes, &j))) {
    1436             : 
    1437          10 :                                 if (!stricmp(att->Name, "width")) tcfg.text_width = atoi(att->Value);
    1438           9 :                                 else if (!stricmp(att->Name, "height")) tcfg.text_height = atoi(att->Value);
    1439           8 :                                 else if (!stricmp(att->Name, "tx")) tcfg.horiz_offset = atoi(att->Value);
    1440           7 :                                 else if (!stricmp(att->Name, "ty")) tcfg.vert_offset = atoi(att->Value);
    1441           6 :                                 else if (!stricmp(att->Name, "layer")) tcfg.layer = atoi(att->Value);
    1442           5 :                                 else if (!stricmp(att->Name, "max-w")) tcfg.video_width = atoi(att->Value);
    1443           4 :                                 else if (!stricmp(att->Name, "max-h")) tcfg.video_height = atoi(att->Value);
    1444           2 :                                 else if (!stricmp(att->Name, "tx3g")) tx3g = att->Value;
    1445             :                         }
    1446             :                 }
    1447           1 :                 if (!tx3g) return GF_NON_COMPLIANT_BITSTREAM;
    1448             : 
    1449           1 :                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    1450           1 :                 gf_bs_write_u8(bs, tcfg.Base3GPPFormat);
    1451           1 :                 gf_bs_write_u8(bs, tcfg.MPEGExtendedFormat); /*MPEGExtendedFormat*/
    1452           1 :                 gf_bs_write_u8(bs, tcfg.profileLevel); /*profileLevel*/
    1453           1 :                 gf_bs_write_u24(bs, tcfg.timescale);
    1454           1 :                 gf_bs_write_int(bs, 0, 1);      /*no alt formats*/
    1455           1 :                 gf_bs_write_int(bs, tcfg.sampleDescriptionFlags, 2);
    1456           1 :                 gf_bs_write_int(bs, 1, 1);      /*we will write sample desc*/
    1457           1 :                 gf_bs_write_int(bs, 1, 1);      /*video info*/
    1458           1 :                 gf_bs_write_int(bs, 0, 3);      /*reserved, spec doesn't say the values*/
    1459           1 :                 gf_bs_write_u8(bs, tcfg.layer);
    1460           1 :                 gf_bs_write_u16(bs, tcfg.text_width);
    1461           1 :                 gf_bs_write_u16(bs, tcfg.text_height);
    1462             :                 /*get all tx3g (comma separated)*/
    1463             :                 nb_desc = 1;
    1464             :                 a_tx3g = tx3g;
    1465           2 :                 while ((a_tx3g = strchr(a_tx3g, ',')) ) {
    1466           0 :                         a_tx3g ++;
    1467           0 :                         nb_desc ++;
    1468             :                 }
    1469             :                 a_tx3g = tx3g;
    1470           1 :                 gf_bs_write_u8(bs, nb_desc);
    1471             :                 nb_desc = 1;
    1472           0 :                 while (1) {
    1473             :                         char *next_tx3g, szOut[1000];
    1474             :                         u32 len, s_len;
    1475           1 :                         next_tx3g = strchr(a_tx3g, ',');
    1476           1 :                         if (next_tx3g) s_len = (u32) (next_tx3g - a_tx3g - 1);
    1477           1 :                         else s_len = (u32) strlen(a_tx3g);
    1478             : 
    1479           1 :                         len = gf_base64_decode(a_tx3g, s_len, szOut, 1000);
    1480             :                         nb_desc++;
    1481           1 :                         gf_bs_write_data(bs, szOut, len);
    1482           1 :                         if (!next_tx3g) break;
    1483           0 :                         a_tx3g = strchr(a_tx3g, ',');
    1484           0 :                         if (!a_tx3g) break;
    1485           0 :                         a_tx3g += 1;
    1486           0 :                         while (a_tx3g[0] == ' ') a_tx3g += 1;
    1487             :                 }
    1488             : 
    1489             :                 /*write video cfg*/
    1490           1 :                 gf_bs_write_u16(bs, tcfg.video_width);
    1491           1 :                 gf_bs_write_u16(bs, tcfg.video_height);
    1492           1 :                 gf_bs_write_u16(bs, tcfg.horiz_offset);
    1493           1 :                 gf_bs_write_u16(bs, tcfg.vert_offset);
    1494           1 :                 gf_bs_get_content(bs, &rtp->sl_map.config, &rtp->sl_map.configSize);
    1495           1 :                 rtp->sl_map.StreamType = GF_STREAM_TEXT;
    1496           1 :                 rtp->sl_map.CodecID = GF_CODECID_TEXT_MPEG4;
    1497           1 :                 gf_bs_del(bs);
    1498             :                 /*assign depacketizer*/
    1499           1 :                 rtp->depacketize = gf_rtp_parse_ttxt;
    1500             :         }
    1501             :         break;
    1502             : #ifndef GPAC_DISABLE_AV_PARSERS
    1503           3 :         case GF_RTP_PAYT_H264_AVC:
    1504             :         case GF_RTP_PAYT_H264_SVC:
    1505             :         {
    1506             :                 GF_AVCConfig *avcc;
    1507           3 :                 if (!map || !media) {
    1508           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP] Missing required payload map\n"));
    1509             :                         return GF_NON_COMPLIANT_BITSTREAM;
    1510             :                 }
    1511             : 
    1512           3 :                 avcc = gf_odf_avc_cfg_new();
    1513           3 :                 avcc->AVCProfileIndication = (rtp->sl_map.PL_ID>>16) & 0xFF;
    1514           3 :                 avcc->profile_compatibility = (rtp->sl_map.PL_ID>>8) & 0xFF;
    1515           3 :                 avcc->AVCLevelIndication = rtp->sl_map.PL_ID & 0xFF;
    1516           3 :                 avcc->configurationVersion = 1;
    1517           3 :                 avcc->nal_unit_size = 4;
    1518           3 :                 rtp->sl_map.StreamType = 4;
    1519           3 :                 rtp->sl_map.CodecID = GF_CODECID_AVC;
    1520             :                 /*we will signal RAPs*/
    1521           3 :                 rtp->sl_map.RandomAccessIndication = GF_TRUE;
    1522             :                 /*rewrite sps and pps*/
    1523           3 :                 i=0;
    1524           9 :                 while ((fmtp = (GF_SDP_FMTP*)gf_list_enum(media->FMTP, &i))) {
    1525             :                         GF_X_Attribute *att;
    1526           3 :                         if (fmtp->PayloadType != map->PayloadType) continue;
    1527           3 :                         j=0;
    1528          15 :                         while ((att = (GF_X_Attribute *)gf_list_enum(fmtp->Attributes, &j))) {
    1529             :                                 char *nal_ptr, *sep;
    1530           9 :                                 if (stricmp(att->Name, "sprop-parameter-sets")) continue;
    1531             : 
    1532           3 :                                 nal_ptr = att->Value;
    1533           9 :                                 while (nal_ptr) {
    1534             :                                         u32 nalt, b64size, ret;
    1535             :                                         char *b64_d;
    1536             : 
    1537           6 :                                         sep = strchr(nal_ptr, ',');
    1538           6 :                                         if (sep) sep[0] = 0;
    1539             : 
    1540           6 :                                         b64size = (u32) strlen(nal_ptr);
    1541           6 :                                         b64_d = (char*)gf_malloc(sizeof(char)*b64size);
    1542           6 :                                         ret = gf_base64_decode(nal_ptr, b64size, b64_d, b64size);
    1543           6 :                                         b64_d[ret] = 0;
    1544             : 
    1545           6 :                                         nalt = b64_d[0] & 0x1F;
    1546           6 :                                         if (/*SPS*/(nalt==0x07) || /*PPS*/(nalt==0x08) || /*SSPS*/(nalt==0x0F)) {
    1547           6 :                                                 GF_NALUFFParam *sl = (GF_NALUFFParam *)gf_malloc(sizeof(GF_NALUFFParam));
    1548           6 :                                                 sl->size = ret;
    1549           6 :                                                 sl->data = (char*)gf_malloc(sizeof(char)*sl->size);
    1550           6 :                                                 memcpy(sl->data, b64_d, sizeof(char)*sl->size);
    1551           6 :                                                 if (nalt==0x07 || nalt==0x0F) {
    1552           3 :                                                         gf_list_add(avcc->sequenceParameterSets, sl);
    1553             :                                                 } else {
    1554           3 :                                                         gf_list_add(avcc->pictureParameterSets, sl);
    1555             :                                                 }
    1556             :                                         }
    1557           6 :                                         gf_free(b64_d);
    1558             : 
    1559           6 :                                         if (sep) {
    1560           3 :                                                 sep[0] = ',';
    1561           3 :                                                 nal_ptr = sep+1;
    1562             :                                         } else {
    1563             :                                                 break;
    1564             :                                         }
    1565             :                                 }
    1566             :                         }
    1567             :                 }
    1568           3 :                 if (gf_list_count(avcc->sequenceParameterSets) && gf_list_count(avcc->pictureParameterSets)) {
    1569           3 :                         gf_odf_avc_cfg_write(avcc, &rtp->sl_map.config, &rtp->sl_map.configSize);
    1570             :                 } else {
    1571           0 :                         rtp->flags |= GF_RTP_AVC_USE_ANNEX_B;
    1572             :                 }
    1573           3 :                 gf_odf_avc_cfg_del(avcc);
    1574             :         }
    1575             :                 /*assign depacketizer*/
    1576           3 :         rtp->depacketize = gf_rtp_parse_h264;
    1577           3 :         break;
    1578           1 :         case GF_RTP_PAYT_HEVC:
    1579             :         case GF_RTP_PAYT_LHVC:
    1580             : #ifndef GPAC_DISABLE_HEVC
    1581             :         {
    1582             :                 GF_HEVCConfig *hevcc;
    1583           1 :                 if (!map || !media) {
    1584           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("[RTP] Missing required payload map\n"));
    1585             :                         return GF_NON_COMPLIANT_BITSTREAM;
    1586             :                 }
    1587           1 :                 hevcc = gf_odf_hevc_cfg_new();
    1588           1 :                 hevcc->configurationVersion = 1;
    1589           1 :                 hevcc->nal_unit_size = 4;
    1590           1 :                 rtp->sl_map.StreamType = 4;
    1591           1 :                 rtp->sl_map.CodecID = GF_CODECID_HEVC;
    1592             :                 /*we will signal RAPs*/
    1593           1 :                 rtp->sl_map.RandomAccessIndication = GF_TRUE;
    1594           1 :                 i=0;
    1595           3 :                 while ((fmtp = (GF_SDP_FMTP*)gf_list_enum(media->FMTP, &i))) {
    1596             :                         GF_X_Attribute *att;
    1597           1 :                         if (fmtp->PayloadType != map->PayloadType) continue;
    1598           1 :                         j=0;
    1599           5 :                         while ((att = (GF_X_Attribute *)gf_list_enum(fmtp->Attributes, &j))) {
    1600             :                                 char *nal_ptr, *sep;
    1601             :                                 GF_NALUFFParamArray *ar;
    1602           3 :                                 if (!stricmp(att->Name, "sprop-vps")) {
    1603           1 :                                         GF_SAFEALLOC(ar, GF_NALUFFParamArray);
    1604           1 :                                         if (!ar) return GF_OUT_OF_MEM;
    1605           1 :                                         ar->nalus = gf_list_new();
    1606           1 :                                         ar->type = GF_HEVC_NALU_VID_PARAM;
    1607             :                                 }
    1608           2 :                                 else if (!stricmp(att->Name, "sprop-sps")) {
    1609           1 :                                         GF_SAFEALLOC(ar, GF_NALUFFParamArray);
    1610           1 :                                         if (!ar) return GF_OUT_OF_MEM;
    1611           1 :                                         ar->nalus = gf_list_new();
    1612           1 :                                         ar->type = GF_HEVC_NALU_SEQ_PARAM;
    1613             :                                 }
    1614           1 :                                 else if (!stricmp(att->Name, "sprop-pps")) {
    1615           1 :                                         GF_SAFEALLOC(ar, GF_NALUFFParamArray);
    1616           1 :                                         if (!ar) return GF_OUT_OF_MEM;
    1617           1 :                                         ar->nalus = gf_list_new();
    1618           1 :                                         ar->type = GF_HEVC_NALU_PIC_PARAM;
    1619             :                                 }
    1620             :                                 else
    1621           0 :                                         continue;
    1622           3 :                                 nal_ptr = att->Value;
    1623           6 :                                 while (nal_ptr) {
    1624             :                                         u32 b64size, ret;
    1625             :                                         char *b64_d;
    1626             :                                         GF_NALUFFParam *sl;
    1627             : 
    1628           3 :                                         sep = strchr(nal_ptr, ',');
    1629           3 :                                         if (sep) sep[0] = 0;
    1630             : 
    1631           3 :                                         b64size = (u32) strlen(nal_ptr);
    1632           3 :                                         b64_d = (char*)gf_malloc(sizeof(char)*b64size);
    1633           3 :                                         ret = gf_base64_decode(nal_ptr, b64size, b64_d, b64size);
    1634           3 :                                         b64_d[ret] = 0;
    1635             : 
    1636           3 :                                         sl = (GF_NALUFFParam *)gf_malloc(sizeof(GF_NALUFFParam));
    1637           3 :                                         sl->size = ret;
    1638           3 :                                         sl->data = (char*)gf_malloc(sizeof(char)*sl->size);
    1639           3 :                                         memcpy(sl->data, b64_d, sizeof(char)*sl->size);
    1640           3 :                                         gf_list_add(ar->nalus, sl);
    1641             : 
    1642           3 :                                         gf_free(b64_d);
    1643             : 
    1644           3 :                                         if (sep) {
    1645           0 :                                                 sep[0] = ',';
    1646           0 :                                                 nal_ptr = sep+1;
    1647             :                                         } else {
    1648             :                                                 break;
    1649             :                                         }
    1650             :                                 }
    1651           3 :                                 if (!hevcc->param_array) hevcc->param_array = gf_list_new();
    1652           3 :                                 gf_list_add(hevcc->param_array, ar);
    1653             :                         }
    1654             :                 }
    1655           1 :                 gf_odf_hevc_cfg_write(hevcc, &rtp->sl_map.config, &rtp->sl_map.configSize);
    1656           1 :                 gf_odf_hevc_cfg_del(hevcc);
    1657             :         }
    1658           1 :         rtp->depacketize = gf_rtp_parse_hevc;
    1659             : #else
    1660             :         return GF_NOT_SUPPORTED;
    1661             : #endif
    1662           1 :         break;
    1663             : #endif /*GPAC_DISABLE_AV_PARSERS*/
    1664             : 
    1665             : #if GPAC_ENABLE_3GPP_DIMS_RTP
    1666             :         /*todo - rewrite DIMS config*/
    1667             :         case GF_RTP_PAYT_3GPP_DIMS:
    1668             :                 rtp->sl_map.StreamType = GF_STREAM_SCENE;
    1669             :                 rtp->sl_map.CodecID = GF_CODECID_DIMS;
    1670             :                 /*we will signal RAPs*/
    1671             :                 rtp->sl_map.RandomAccessIndication = GF_TRUE;
    1672             :                 /*we map DIMS CTR to AU seq num, hence 3 bits*/
    1673             :                 rtp->sl_map.StreamStateIndication = 3;
    1674             :                 rtp->sl_map.IndexLength = 3;
    1675             :                 /*assign depacketizer*/
    1676             :                 rtp->depacketize = gf_rtp_parse_3gpp_dims;
    1677             :                 break;
    1678             : #endif
    1679             : 
    1680             : #ifndef GPAC_DISABLE_AV_PARSERS
    1681           1 :         case GF_RTP_PAYT_AC3:
    1682           1 :                 rtp->sl_map.StreamType = GF_STREAM_AUDIO;
    1683           1 :                 rtp->sl_map.CodecID = GF_CODECID_AC3;
    1684           1 :                 rtp->sl_map.RandomAccessIndication = GF_TRUE;
    1685             :                 /*assign depacketizer*/
    1686           1 :                 rtp->depacketize = gf_rtp_parse_ac3;
    1687           1 :                 break;
    1688             : #endif /*GPAC_DISABLE_AV_PARSERS*/
    1689           1 :         default:
    1690           1 :                 if (rtp->payt >= GF_RTP_PAYT_LAST_STATIC_DEFINED)
    1691             :                         return GF_NOT_SUPPORTED;
    1692           1 :                 rtp->depacketize = gf_rtp_parse_pass_through;
    1693           1 :                 return GF_OK;
    1694             :         }
    1695             :         return GF_OK;
    1696             : }
    1697             : 
    1698             : const GF_RTPStaticMap static_payloads [] =
    1699             : {
    1700             :         { GF_RTP_PAYT_PCMU, 8000, GF_STREAM_AUDIO},
    1701             :         { GF_RTP_PAYT_GSM, 8000, GF_STREAM_AUDIO},
    1702             :         { GF_RTP_PAYT_G723, 8000, GF_STREAM_AUDIO},
    1703             :         { GF_RTP_PAYT_DVI4_8K, 8000, GF_STREAM_AUDIO},
    1704             :         { GF_RTP_PAYT_DVI4_16K, 16000, GF_STREAM_AUDIO},
    1705             :         { GF_RTP_PAYT_LPC, 8000, GF_STREAM_AUDIO},
    1706             :         { GF_RTP_PAYT_PCMA, 8000, GF_STREAM_AUDIO},
    1707             :         { GF_RTP_PAYT_G722, 8000, GF_STREAM_AUDIO},
    1708             :         { GF_RTP_PAYT_L16_STEREO, 44100, GF_STREAM_AUDIO},
    1709             :         { GF_RTP_PAYT_L16_MONO, 44100, GF_STREAM_AUDIO},
    1710             :         { GF_RTP_PAYT_QCELP_BASIC, 8000, GF_STREAM_AUDIO},
    1711             :         { GF_RTP_PAYT_CN, 8000, GF_STREAM_AUDIO},
    1712             :         { GF_RTP_PAYT_MPEG12_AUDIO, 90000, GF_STREAM_AUDIO},
    1713             :         { GF_RTP_PAYT_G728, 8000, GF_STREAM_AUDIO},
    1714             :         { GF_RTP_PAYT_DVI4_11K, 11025, GF_STREAM_AUDIO},
    1715             :         { GF_RTP_PAYT_DVI4_22K, 22050, GF_STREAM_AUDIO},
    1716             :         { GF_RTP_PAYT_G729, 8000, GF_STREAM_AUDIO},
    1717             :         { GF_RTP_PAYT_CelB, 90000, GF_STREAM_VISUAL},
    1718             :         { GF_RTP_PAYT_JPEG, 90000, GF_STREAM_VISUAL},
    1719             :         { GF_RTP_PAYT_nv, 90000, GF_STREAM_VISUAL},
    1720             :         { GF_RTP_PAYT_H261, 90000, GF_STREAM_VISUAL},
    1721             :         { GF_RTP_PAYT_MPEG12_VIDEO, 90000, GF_STREAM_VISUAL},
    1722             :         { GF_RTP_PAYT_MP2T, 90000, GF_STREAM_FILE, 0, "video/mp2t"},
    1723             :         { GF_RTP_PAYT_H263, 90000, GF_STREAM_VISUAL}
    1724             : };
    1725             : 
    1726             : static const GF_RTPStaticMap *gf_rtp_is_valid_static_payt(u32 payt)
    1727             : {
    1728             :         u32 i, count = sizeof(static_payloads) / sizeof(struct rtp_static_payt);
    1729           1 :         if (payt>= GF_RTP_PAYT_LAST_STATIC_DEFINED) return NULL;
    1730          22 :         for (i=0; i<count; i++) {
    1731          23 :                 if (static_payloads[i].fmt == payt) {
    1732           1 :                         return &static_payloads[i];
    1733             :                 }
    1734             :         }
    1735             :         return NULL;
    1736             : }
    1737             : 
    1738             : 
    1739             : GF_EXPORT
    1740          21 : GF_RTPDepacketizer *gf_rtp_depacketizer_new(GF_SDPMedia *media, u32 hdr_payt, gf_rtp_packet_cbk sl_packet_cbk, void *udta)
    1741             : {
    1742             :         GF_Err e;
    1743             :         GF_RTPMap *map = NULL;
    1744             :         u32 payt;
    1745             :         GF_RTPDepacketizer *tmp;
    1746             :         u32 clock_rate;
    1747             :         const GF_RTPStaticMap *static_map = NULL;
    1748             : 
    1749             :         /*check RTP map. For now we only support 1 RTPMap*/
    1750          21 :         if (!sl_packet_cbk || (!media && !hdr_payt)) return NULL;
    1751          21 :         if (media && (gf_list_count(media->RTPMaps) > 1)) return NULL;
    1752             : 
    1753             : #ifdef GPAC_ENABEL_COVERAGE
    1754             :         if (gf_sys_is_cov_mode())
    1755             :                 gf_rtp_is_valid_static_payt(22);
    1756             : #endif
    1757             : 
    1758          21 :         if (!media) {
    1759             :                 static_map = gf_rtp_is_valid_static_payt(hdr_payt);
    1760           1 :                 if (!static_map) {
    1761           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("RTP: Invalid/unsupported static payload type %d\n", hdr_payt));
    1762             :                         return NULL;
    1763             :                 }
    1764           1 :                 clock_rate = static_map->clock_rate;
    1765             :                 payt = hdr_payt;
    1766             :         } else {
    1767             :                 /*check payload type*/
    1768          20 :                 map = (GF_RTPMap *)gf_list_get(media->RTPMaps, 0);
    1769          20 :                 if (!map) {
    1770             :                         //we deal with at most one format
    1771           0 :                         if (!media->fmt_list || strchr(media->fmt_list, ' ')) return NULL;
    1772             : 
    1773           0 :                         payt = atoi(media->fmt_list);
    1774             :                         static_map = gf_rtp_is_valid_static_payt(payt);
    1775           0 :                         if (!static_map) {
    1776           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_RTP, ("RTP: Invalid static payload type %d\n", payt));
    1777             :                                 return NULL;
    1778             :                         }
    1779           0 :                         clock_rate = static_map->clock_rate;
    1780             :                 } else {
    1781          20 :                         payt = gf_rtp_get_payload_type(map, media);
    1782          20 :                         if (!payt) return NULL;
    1783          19 :                         clock_rate = map->ClockRate;
    1784             :                 }
    1785             :         }
    1786             : 
    1787          20 :         GF_SAFEALLOC(tmp, GF_RTPDepacketizer);
    1788          20 :         if (!tmp) return NULL;
    1789          20 :         tmp->payt = payt;
    1790          20 :         tmp->static_map = static_map;
    1791             : 
    1792          20 :         e = gf_rtp_payt_setup(tmp, map, media);
    1793          20 :         if (e) {
    1794           0 :                 gf_free(tmp);
    1795           0 :                 return NULL;
    1796             :         }
    1797             : 
    1798             :         assert(tmp->depacketize);
    1799          20 :         tmp->clock_rate = clock_rate;
    1800          20 :         tmp->on_sl_packet = sl_packet_cbk;
    1801          20 :         tmp->udta = udta;
    1802          20 :         return tmp;
    1803             : }
    1804             : 
    1805             : GF_EXPORT
    1806          52 : void gf_rtp_depacketizer_reset(GF_RTPDepacketizer *rtp, Bool full_reset)
    1807             : {
    1808          52 :         if (rtp) {
    1809          51 :                 if (rtp->inter_bs) gf_bs_del(rtp->inter_bs);
    1810          51 :                 rtp->inter_bs = NULL;
    1811          51 :                 rtp->flags |= GF_RTP_NEW_AU;
    1812          51 :                 if (full_reset) {
    1813          19 :                         u32 dur = rtp->sl_hdr.au_duration;
    1814          19 :                         memset(&rtp->sl_hdr, 0, sizeof(GF_SLHeader));
    1815          19 :                         rtp->sl_hdr.au_duration = dur;
    1816             :                 }
    1817             :         }
    1818          52 : }
    1819             : 
    1820             : GF_EXPORT
    1821          20 : void gf_rtp_depacketizer_del(GF_RTPDepacketizer *rtp)
    1822             : {
    1823          20 :         if (rtp) {
    1824          20 :                 gf_rtp_depacketizer_reset(rtp, GF_FALSE);
    1825          20 :                 if (rtp->sl_map.config) gf_free(rtp->sl_map.config);
    1826          20 :                 if (rtp->key) gf_free(rtp->key);
    1827          20 :                 gf_free(rtp);
    1828             :         }
    1829          20 : }
    1830             : 
    1831             : GF_EXPORT
    1832         755 : void gf_rtp_depacketizer_process(GF_RTPDepacketizer *rtp, GF_RTPHeader *hdr, u8 *payload, u32 size)
    1833             : {
    1834             :         assert(rtp && rtp->depacketize);
    1835         755 :         rtp->sl_hdr.sender_ntp = hdr->recomputed_ntp_ts;
    1836         755 :         rtp->depacketize(rtp, hdr, payload, size);
    1837         755 : }
    1838             : 
    1839             : 
    1840             : #if 0 //unused
    1841             : void gf_rtp_depacketizer_get_slconfig(GF_RTPDepacketizer *rtp, GF_SLConfig *slc)
    1842             : {
    1843             :         memset(slc, 0, sizeof(GF_SLConfig));
    1844             :         slc->tag = GF_ODF_SLC_TAG;
    1845             : 
    1846             :         slc->AULength = rtp->sl_map.ConstantSize;
    1847             :         if (rtp->sl_map.ConstantDuration) {
    1848             :                 slc->CUDuration = slc->AUDuration = rtp->sl_map.ConstantDuration;
    1849             :         } else {
    1850             :                 slc->CUDuration = slc->AUDuration = rtp->sl_hdr.au_duration;
    1851             :         }
    1852             :         /*AUSeqNum is only signaled if streamState is used (eg for carrouselling); otherwise we ignore it*/
    1853             :         slc->AUSeqNumLength = rtp->sl_map.StreamStateIndication;
    1854             :         slc->no_dts_signaling = rtp->sl_map.DTSDeltaLength ? GF_FALSE : GF_TRUE;
    1855             : 
    1856             : 
    1857             :         /*RTP SN is on 16 bits*/
    1858             :         slc->packetSeqNumLength = 0;
    1859             :         /*RTP TS is on 32 bits*/
    1860             :         slc->timestampLength = 32;
    1861             :         slc->timeScale = slc->timestampResolution = rtp->clock_rate;
    1862             :         slc->useTimestampsFlag = 1;
    1863             : 
    1864             :         /*we override these flags because we emulate the flags through the marker bit */
    1865             :         slc->useAccessUnitEndFlag = slc->useAccessUnitStartFlag = 1;
    1866             :         slc->useRandomAccessPointFlag = rtp->sl_map.RandomAccessIndication;
    1867             :         /*checking RAP for video*/
    1868             :         if (rtp->flags & GF_RTP_M4V_CHECK_RAP) {
    1869             :                 slc->useRandomAccessPointFlag = 1;
    1870             :                 slc->hasRandomAccessUnitsOnlyFlag = 0;
    1871             :         }
    1872             : 
    1873             :         /*try to signal caroussel if not set in StreamState*/
    1874             :         if (!slc->AUSeqNumLength && rtp->sl_map.RandomAccessIndication) {
    1875             :                 switch (rtp->sl_map.StreamType) {
    1876             :                 case GF_STREAM_OD:
    1877             :                 case GF_STREAM_SCENE:
    1878             :                         slc->AUSeqNumLength = rtp->sl_map.IndexLength;
    1879             :                         break;
    1880             :                 }
    1881             :         }
    1882             : }
    1883             : #endif
    1884             : 
    1885             : 
    1886             : #endif /*GPAC_DISABLE_STREAMING*/

Generated by: LCOV version 1.13