LCOV - code coverage report
Current view: top level - filters - in_rtp_stream.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 302 385 78.4 %
Date: 2021-04-29 23:48:07 Functions: 14 15 93.3 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / RTP/RTSP input filter
       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 "in_rtp.h"
      27             : 
      28             : 
      29             : #ifndef GPAC_DISABLE_STREAMING
      30             : 
      31           6 : void rtpin_stream_ack_connect(GF_RTPInStream *stream, GF_Err e)
      32             : {
      33             :         /*in case the channel has been disconnected while SETUP was issued&processed. We also could
      34             :         clean up the command stack*/
      35             :         if (!stream->opid) return;
      36             : 
      37             :         if (e != GF_OK || !stream->rtp_ch) return;
      38             : }
      39             : 
      40          32 : GF_Err rtpin_stream_init(GF_RTPInStream *stream, Bool ResetOnly)
      41             : {
      42          32 :         gf_rtp_depacketizer_reset(stream->depacketizer, !ResetOnly);
      43             : 
      44          32 :         if (!ResetOnly) {
      45             :                 GF_Err e;
      46             :                 const char *ip_ifce = NULL;
      47          20 :                 if (!stream->rtpin->interleave) {
      48          19 :                         ip_ifce = stream->rtpin->ifce;
      49             :                 }
      50          20 :                 if (stream->rtp_ch->rtp)
      51           0 :                         gf_sk_group_unregister(stream->rtpin->sockgroup, stream->rtp_ch->rtp);
      52          20 :                 if (stream->rtp_ch->rtcp)
      53           0 :                         gf_sk_group_unregister(stream->rtpin->sockgroup, stream->rtp_ch->rtcp);
      54             : 
      55          20 :                 e = gf_rtp_initialize(stream->rtp_ch, stream->rtpin->block_size, GF_FALSE, 0, stream->rtpin->reorder_len, stream->rtpin->reorder_delay, (char *)ip_ifce);
      56          20 :                 if (e) return e;
      57             : 
      58          20 :                 if (stream->rtp_ch->rtp)
      59          19 :                         gf_sk_group_register(stream->rtpin->sockgroup, stream->rtp_ch->rtp);
      60          20 :                 if (stream->rtp_ch->rtcp)
      61          19 :                         gf_sk_group_register(stream->rtpin->sockgroup, stream->rtp_ch->rtcp);
      62             : 
      63             :         }
      64             :         //just reset the sockets
      65          32 :         gf_rtp_reset_buffers(stream->rtp_ch);
      66          32 :         return GF_OK;
      67             : }
      68             : 
      69          14 : void rtpin_stream_reset_queue(GF_RTPInStream *stream)
      70             : {
      71          14 :         if (!stream->pck_queue) return;
      72          20 :         while (gf_list_count(stream->pck_queue)) {
      73           6 :                 GF_FilterPacket *pck = gf_list_pop_back(stream->pck_queue);
      74           6 :                 gf_filter_pck_discard(pck);
      75             :         }
      76             : }
      77             : 
      78          21 : void rtpin_stream_del(GF_RTPInStream *stream)
      79             : {
      80          21 :         if (stream->rtsp) {
      81           6 :                 if (stream->status == RTP_Running) {
      82           0 :                         rtpin_rtsp_teardown(stream->rtsp, stream);
      83           0 :                         stream->status = RTP_Disconnected;
      84             :                 }
      85           6 :                 rtpin_remove_stream(stream->rtpin, stream);
      86             :         } else {
      87          15 :                 rtpin_find_stream(stream->rtpin, stream->opid, 0, NULL, GF_TRUE);
      88             :         }
      89             : 
      90          21 :         if (stream->depacketizer) gf_rtp_depacketizer_del(stream->depacketizer);
      91          21 :         if (stream->rtp_ch) gf_rtp_del(stream->rtp_ch);
      92          21 :         if (stream->control) gf_free(stream->control);
      93          21 :         if (stream->session_id) gf_free(stream->session_id);
      94          21 :         if (stream->buffer) gf_free(stream->buffer);
      95          21 :         if (stream->pck_queue) {
      96           7 :                 rtpin_stream_reset_queue(stream);
      97           7 :                 gf_list_del(stream->pck_queue);
      98             :         }
      99          21 :         gf_free(stream);
     100          21 : }
     101             : 
     102         395 : static void rtpin_stream_queue_pck(GF_RTPInStream *stream, GF_FilterPacket *pck, u64 cts)
     103             : {
     104             :         //get all packets in queue, dispatch all packets with a cts less than the cts of the packet being queued
     105             :         //if this is teh first packet in the RTP packet
     106             :         //This is only used for MPEG4, and we are sure we only have [AU(n),AU(n+i)..], [AU(n+j), AU(n+k) ...]
     107             :         //with i,j,k >0
     108         746 :         while (stream->first_in_rtp_pck) {
     109             :                 u64 prev_cts;
     110         426 :                 GF_FilterPacket *prev = gf_list_get(stream->pck_queue, 0);
     111         426 :                 if (!prev) break;
     112         351 :                 prev_cts = gf_filter_pck_get_cts(prev);
     113         351 :                 if (prev_cts>cts) break;
     114         351 :                 gf_list_rem(stream->pck_queue, 0);
     115         351 :                 gf_filter_pck_send(prev);
     116             :         }
     117         395 :         stream->first_in_rtp_pck = GF_FALSE;
     118         395 :         gf_list_add(stream->pck_queue, pck);
     119         395 : }
     120             : 
     121        1468 : static void rtp_sl_packet_cbk(void *udta, u8 *payload, u32 size, GF_SLHeader *hdr, GF_Err e)
     122             : {
     123             :         u64 cts, dts;
     124             :         s64 diff;
     125             :         GF_FilterPacket *pck;
     126             :         u8 *pck_data;
     127             :         GF_RTPInStream *stream = (GF_RTPInStream *)udta;
     128             : 
     129             : 
     130        1468 :         if (!stream->rtcp_init) {
     131          39 :                 if (!stream->rtcp_check_start) {
     132           2 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[RTP] No RTCP packet received yet, synchronization might be wrong for a while\n"));
     133           2 :                         stream->rtcp_check_start = gf_sys_clock();
     134             :                 }
     135          37 :                 else if (gf_sys_clock() - stream->rtcp_check_start <= stream->rtpin->rtcp_timeout) {
     136          37 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_RTP, ("[RTP] No RTCP packet received yet, synchronization might be wrong for a while\n"));
     137             :                 } else {
     138           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_RTP, ("[RTP] Timeout for RTCP: no SR recevied after %d ms - sync may be broken\n", stream->rtpin->rtcp_timeout));
     139           0 :                         stream->rtcp_init = GF_TRUE;
     140             :                 }
     141             :         }
     142             : 
     143        1468 :         if (stream->rtpin->first_packet_drop && (hdr->packetSequenceNumber >= stream->rtpin->first_packet_drop) ) {
     144           0 :                 if (! ( (hdr->packetSequenceNumber - stream->rtpin->first_packet_drop) % stream->rtpin->frequency_drop) )
     145           0 :                         return;
     146             :         }
     147             : 
     148        1468 :         cts = hdr->compositionTimeStamp;
     149        1468 :         dts = hdr->decodingTimeStamp;
     150             : 
     151        1468 :         hdr->seekFlag = 0;
     152        1468 :         hdr->compositionTimeStamp += stream->ts_adjust;
     153        1468 :         if (stream->first_rtp_ts) {
     154             :                 assert(hdr->compositionTimeStamp >= stream->first_rtp_ts - 1);
     155        1115 :                 hdr->compositionTimeStamp -= stream->first_rtp_ts - 1;
     156             :         }
     157             : 
     158        1468 :         if (hdr->decodingTimeStamp) {
     159         559 :                 hdr->decodingTimeStamp += stream->ts_adjust;
     160         559 :                 if (stream->first_rtp_ts) {
     161             :                         assert(hdr->decodingTimeStamp >= stream->first_rtp_ts - 1);
     162         258 :                         hdr->decodingTimeStamp -= stream->first_rtp_ts - 1;
     163             :                 }
     164             :         }
     165             : 
     166        1468 :         pck = gf_filter_pck_new_alloc(stream->opid, size, &pck_data);
     167        1468 :         if (!pck) return;
     168             :         
     169        1468 :         memcpy(pck_data, payload, size);
     170        1468 :         if (hdr->decodingTimeStampFlag)
     171           0 :                 gf_filter_pck_set_dts(pck, hdr->decodingTimeStamp);
     172             : 
     173        1468 :         gf_filter_pck_set_cts(pck, hdr->compositionTimeStamp);
     174             : 
     175        1468 :         diff = (s64) hdr->compositionTimeStamp - (s64) stream->prev_cts;
     176        1468 :         if ((stream->rtpin->max_sleep>0) && stream->prev_cts && diff) {
     177         729 :                 if (diff<0) diff = -diff;
     178         729 :                 if (!stream->min_dur_rtp || (diff < stream->min_dur_rtp)) {
     179          19 :                         u64 dur = diff;
     180          19 :                         dur *= 1000;
     181          19 :                         dur /= stream->rtp_ch->TimeScale;
     182          19 :                         stream->min_dur_rtp = (u32) dur;
     183          19 :                         if (dur > stream->rtpin->max_sleep) dur = stream->rtpin->max_sleep;
     184          19 :                         if (!stream->rtpin->min_frame_dur_ms || ( (u32) dur < stream->rtpin->min_frame_dur_ms)) {
     185          19 :                                 stream->rtpin->min_frame_dur_ms = (u32) dur;
     186             :                         }
     187             :                 }
     188             :         }
     189        1468 :         stream->prev_cts = (u32) hdr->compositionTimeStamp;
     190             : 
     191        1468 :         gf_filter_pck_set_sap(pck, hdr->randomAccessPointFlag ? GF_FILTER_SAP_1  :GF_FILTER_SAP_NONE);
     192        1468 :         if (hdr->au_duration)
     193          88 :                 gf_filter_pck_set_duration(pck, hdr->au_duration);
     194             : 
     195        1468 :         if (hdr->samplerate && (hdr->samplerate != stream->sr)) {
     196           1 :                 stream->sr = hdr->samplerate;
     197           1 :                 gf_filter_pid_set_property(stream->opid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT(stream->sr));
     198             :         }
     199        1468 :         if (hdr->channels && (hdr->channels != stream->nb_ch)) {
     200           1 :                 stream->nb_ch = hdr->channels;
     201           1 :                 gf_filter_pid_set_property(stream->opid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT(stream->nb_ch));
     202             :         }
     203        1468 :         gf_filter_pck_set_framing(pck, hdr->accessUnitStartFlag, hdr->accessUnitEndFlag);
     204             : 
     205        1468 :         if (stream->rtp_ch->packet_loss)
     206           0 :                 gf_filter_pck_set_corrupted(pck, 1);
     207             : 
     208             : #if 0 //not yet implemented
     209             :         if (hdr->seekFlag)
     210             :                 gf_filter_pck_set_seek_flag(pck, GF_TRUE);
     211             : #endif
     212             : 
     213        1468 :         if (stream->depacketizer->sl_map.IndexDeltaLength) {
     214         395 :                 rtpin_stream_queue_pck(stream, pck, hdr->compositionTimeStamp);
     215             :         } else {
     216        1073 :                 gf_filter_pck_send(pck);
     217             :         }
     218             : 
     219        1468 :         hdr->compositionTimeStamp = cts;
     220        1468 :         hdr->decodingTimeStamp = dts;
     221             : }
     222             : 
     223           0 : GF_RTPInStream *rtpin_stream_new_satip(GF_RTPIn *rtp, const char *server_ip)
     224             : {
     225             :         GF_RTSPTransport trans;
     226             :         GF_RTPInStream *tmp;
     227           0 :         GF_SAFEALLOC(tmp, GF_RTPInStream);
     228           0 :         if (!tmp) return NULL;
     229           0 :         tmp->rtpin = rtp;
     230           0 :         tmp->buffer = gf_malloc(sizeof(char) * rtp->block_size);
     231             : 
     232             :         /*create an RTP channel*/
     233           0 :         tmp->rtp_ch = gf_rtp_new();
     234           0 :         tmp->control = gf_strdup("*");
     235             : 
     236             :         memset(&trans, 0, sizeof(GF_RTSPTransport));
     237           0 :         trans.Profile = "RTP/AVP";
     238           0 :         trans.source = (char *) server_ip;
     239           0 :         trans.IsUnicast = GF_TRUE;
     240             :         trans.client_port_first = 0;
     241             :         trans.client_port_last = 0;
     242             :         trans.port_first = 0;
     243             :         trans.port_last = 0;
     244             : 
     245           0 :         if (gf_rtp_setup_transport(tmp->rtp_ch, &trans, NULL) != GF_OK) {
     246           0 :                 rtpin_stream_del(tmp);
     247           0 :                 return NULL;
     248             :         }
     249             : 
     250           0 :         gf_rtp_setup_payload(tmp->rtp_ch, 33, 90000);
     251             : 
     252           0 :         if (rtp->disable_rtcp) tmp->flags |= RTP_ENABLE_RTCP;
     253             : 
     254             :         /*setup NAT keep-alive*/
     255           0 :         gf_rtp_enable_nat_keepalive(tmp->rtp_ch, rtp->nat_keepalive ? rtp->nat_keepalive : 30000);
     256             : 
     257           0 :         tmp->range_start = 0;
     258           0 :         tmp->range_end = 0;
     259             : 
     260           0 :         return tmp;
     261             : }
     262             : 
     263           1 : GF_RTPInStream *rtpin_stream_new_standalone(GF_RTPIn *rtp, const char *flow_ip, u32 port)
     264             : {
     265             :         GF_RTSPTransport trans;
     266             :         GF_RTPInStream *tmp;
     267           1 :         GF_SAFEALLOC(tmp, GF_RTPInStream);
     268           1 :         if (!tmp) return NULL;
     269           1 :         tmp->rtpin = rtp;
     270           1 :         tmp->buffer = gf_malloc(sizeof(char) * rtp->block_size);
     271             : 
     272             :         /*create an RTP channel*/
     273           1 :         tmp->rtp_ch = gf_rtp_new();
     274             : 
     275             :         memset(&trans, 0, sizeof(GF_RTSPTransport));
     276           1 :         trans.Profile = "RTP/AVP";
     277           1 :         trans.source = (char *) flow_ip;
     278           1 :         trans.IsUnicast = gf_sk_is_multicast_address(flow_ip);
     279           1 :         trans.client_port_first = port;
     280           1 :         trans.client_port_last = port+1;
     281           1 :         trans.port_first = port;
     282           1 :         trans.port_last = port+1;
     283             : 
     284           1 :         if (gf_rtp_setup_transport(tmp->rtp_ch, &trans, NULL) != GF_OK) {
     285           0 :                 rtpin_stream_del(tmp);
     286           0 :                 return NULL;
     287             :         }
     288             : 
     289             : //      gf_rtp_setup_payload(tmp->rtp_ch, 33, 90000);
     290             : 
     291           1 :         if (rtp->disable_rtcp) tmp->flags |= RTP_ENABLE_RTCP;
     292             : 
     293             :         /*setup NAT keep-alive*/
     294           1 :         gf_rtp_enable_nat_keepalive(tmp->rtp_ch, rtp->nat_keepalive ? rtp->nat_keepalive : 30000);
     295           1 :         tmp->range_start = 0;
     296           1 :         tmp->range_end = 0;
     297           1 :         return tmp;
     298             : }
     299             : 
     300          20 : GF_RTPInStream *rtpin_stream_new(GF_RTPIn *rtp, GF_SDPMedia *media, GF_SDPInfo *sdp, GF_RTPInStream *input_stream)
     301             : {
     302             :         GF_RTSPRange *range;
     303             :         GF_RTPInStream *tmp;
     304             :         GF_RTPMap *map;
     305             :         u32 i, ESID, ODID;
     306             :         Bool force_bcast = GF_FALSE;
     307             :         Double Start, End;
     308             :         u16 rvc_predef = 0;
     309             :         char *rvc_config_att = NULL;
     310             :         GF_X_Attribute *att;
     311             :         char *ctrl;
     312             :         GF_SDPConnection *conn;
     313             :         GF_RTSPTransport trans;
     314             :         u32 mid, prev_stream, base_stream;
     315             : 
     316             :         //extract all relevant info from the GF_SDPMedia
     317             :         Start = 0.0;
     318             :         End = -1.0;
     319             :         ODID = 0;
     320             :         ESID = 0;
     321             :         ctrl = NULL;
     322             :         range = NULL;
     323          20 :         mid = prev_stream = base_stream = 0;
     324          20 :         i=0;
     325          70 :         while ((att = (GF_X_Attribute*)gf_list_enum(media->Attributes, &i))) {
     326          30 :                 if (!stricmp(att->Name, "control")) ctrl = att->Value;
     327          24 :                 else if (!stricmp(att->Name, "gpac-broadcast")) force_bcast = GF_TRUE;
     328          39 :                 else if (!stricmp(att->Name, "mpeg4-esid") && att->Value) ESID = atoi(att->Value);
     329           9 :                 else if (!stricmp(att->Name, "mpeg4-odid") && att->Value) ODID = atoi(att->Value);
     330           9 :                 else if (!stricmp(att->Name, "range") && !range) range = gf_rtsp_range_parse(att->Value);
     331           9 :                 else if (!stricmp(att->Name, "rvc-config-predef") && att->Value) {
     332           0 :                         rvc_predef = atoi(att->Value);
     333           9 :                 } else if (!stricmp(att->Name, "rvc-config")) {
     334           0 :                         rvc_config_att = att->Value;
     335           9 :                 } else if (!stricmp(att->Name, "mid")) {
     336           0 :                         sscanf(att->Value, "L%d", &mid);
     337           9 :                 } else if (!stricmp(att->Name, "depend")) {
     338             :                         char buf[3000];
     339             :                         memset(buf, 0, 3000);
     340           0 :                         sscanf(att->Value, "%*d lay L%d %*s %2999s", &base_stream, buf);
     341           0 :                         if (!strlen(buf))
     342           0 :                                 sscanf(att->Value, "%*d lay %2999s", buf);
     343           0 :                         sscanf(buf, "L%d", &prev_stream);
     344             :                 }
     345             :         }
     346             : 
     347          20 :         if (range) {
     348           0 :                 Start = range->start;
     349           0 :                 End = range->end;
     350           0 :                 gf_rtsp_range_del(range);
     351             :         }
     352             : 
     353             :         /*check connection*/
     354          20 :         conn = sdp->c_connection;
     355          20 :         if (conn && (!conn->host || !strcmp(conn->host, "0.0.0.0"))) conn = NULL;
     356             : 
     357          14 :         if (!conn) conn = (GF_SDPConnection*)gf_list_get(media->Connections, 0);
     358          20 :         if (conn && (!conn->host || !strcmp(conn->host, "0.0.0.0"))) conn = NULL;
     359             : 
     360          20 :         if (!conn) {
     361             :                 /*RTSP RFC recommends an empty "c= " line but some server don't send it. Use session info (o=)*/
     362           6 :                 if (!sdp->o_net_type || !sdp->o_add_type || strcmp(sdp->o_net_type, "IN")) return NULL;
     363           6 :                 if (strcmp(sdp->o_add_type, "IP4") && strcmp(sdp->o_add_type, "IP6")) return NULL;
     364             :         } else {
     365          14 :                 if (strcmp(conn->net_type, "IN")) return NULL;
     366          14 :                 if (strcmp(conn->add_type, "IP4") && strcmp(conn->add_type, "IP6")) return NULL;
     367             :         }
     368             :         /*do we support transport*/
     369          20 :         if (strcmp(media->Profile, "RTP/AVP") && strcmp(media->Profile, "RTP/AVP/TCP")
     370           0 :                 && strcmp(media->Profile, "RTP/SAVP") && strcmp(media->Profile, "RTP/SAVP/TCP")
     371             :            ) return NULL;
     372             : 
     373             :         /*check RTP map. For now we only support 1 RTPMap*/
     374          20 :         if (gf_list_count(media->RTPMaps) > 1) return NULL;
     375             : 
     376             :         /*check payload type*/
     377          20 :         map = (GF_RTPMap*)gf_list_get(media->RTPMaps, 0);
     378          20 :         if (!map) {
     379           0 :                 if (!media->fmt_list) return NULL;
     380           0 :                 if (strchr(media->fmt_list, ' ')) return NULL;
     381             :         }
     382             : 
     383             :         /*this is an ESD-URL setup, we likely have namespace conflicts so overwrite given ES_ID
     384             :         by the app one (client side), but keep control (server side) if provided*/
     385          20 :         if (input_stream) {
     386           0 :                 ESID = input_stream->ES_ID;
     387           0 :                 if (!ctrl) ctrl = input_stream->control;
     388             :                 tmp = input_stream;
     389             :         } else {
     390          20 :                 tmp = rtpin_find_stream(rtp, NULL, ESID, NULL, GF_FALSE);
     391          20 :                 if (tmp) return NULL;
     392             : 
     393          20 :                 GF_SAFEALLOC(tmp, GF_RTPInStream);
     394          20 :                 if (!tmp) return NULL;
     395          20 :                 tmp->rtpin = rtp;
     396          20 :                 tmp->buffer = gf_malloc(sizeof(char) * rtp->block_size);
     397             :         }
     398             : 
     399             :         /*create an RTP channel*/
     400          20 :         tmp->rtp_ch = gf_rtp_new();
     401          20 :         if (ctrl) tmp->control = gf_strdup(ctrl);
     402          20 :         tmp->ES_ID = ESID;
     403          20 :         tmp->OD_ID = ODID;
     404          20 :         tmp->mid = mid;
     405          20 :         tmp->prev_stream = prev_stream;
     406          20 :         tmp->base_stream = base_stream;
     407             : 
     408             :         memset(&trans, 0, sizeof(GF_RTSPTransport));
     409          20 :         trans.Profile = media->Profile;
     410          20 :         trans.source = conn ? conn->host : sdp->o_address;
     411          20 :         trans.IsUnicast = gf_sk_is_multicast_address(trans.source) ? GF_FALSE : GF_TRUE;
     412          20 :         if (!trans.IsUnicast) {
     413           0 :                 trans.port_first = media->PortNumber;
     414           0 :                 trans.port_last = media->PortNumber + 1;
     415           0 :                 trans.TTL = conn ? conn->TTL : 0;
     416             :         } else {
     417          20 :                 trans.client_port_first = media->PortNumber;
     418          20 :                 trans.client_port_last = media->PortNumber + 1;
     419          20 :                 trans.port_first = trans.client_port_first;
     420          20 :                 trans.port_last = trans.client_port_last;
     421             :         }
     422             : 
     423          20 :         if (gf_rtp_setup_transport(tmp->rtp_ch, &trans, NULL) != GF_OK) {
     424           0 :                 rtpin_stream_del(tmp);
     425           0 :                 return NULL;
     426             :         }
     427             :         /*setup depacketizer*/
     428          20 :         tmp->depacketizer = gf_rtp_depacketizer_new(media, 0, rtp_sl_packet_cbk, tmp);
     429          20 :         if (!tmp->depacketizer) {
     430           1 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_RTP, ("[RTP] Failed to create RTP depacketizer for payload type %d/%s - ignoring stream)\n", map ? map->PayloadType : 0, media->fmt_list ? media->fmt_list : ""));
     431           1 :                 rtpin_stream_del(tmp);
     432           1 :                 return NULL;
     433             :         }
     434             :         /*setup channel*/
     435          19 :         gf_rtp_setup_payload(tmp->rtp_ch, map ? map->PayloadType : tmp->depacketizer->payt, tmp->depacketizer->clock_rate);
     436             : 
     437          19 :         if (tmp->depacketizer->sl_map.IndexDeltaLength) {
     438           7 :                 tmp->pck_queue = gf_list_new();
     439             :         }
     440             : 
     441             : //      tmp->status = NM_Disconnected;
     442             : 
     443          19 :         if (!rtp->disable_rtcp) tmp->flags |= RTP_ENABLE_RTCP;
     444             : 
     445             :         /*setup NAT keep-alive*/
     446          19 :         if (rtp->nat_keepalive) gf_rtp_enable_nat_keepalive(tmp->rtp_ch, rtp->nat_keepalive);
     447             : 
     448          19 :         tmp->range_start = Start;
     449          19 :         tmp->range_end = End;
     450          19 :         if (End != -1.0) tmp->flags |= RTP_HAS_RANGE;
     451             : 
     452          19 :         if (force_bcast) tmp->flags |= RTP_FORCE_BROADCAST;
     453             : 
     454          19 :         if (rvc_predef) {
     455           0 :                 tmp->depacketizer->sl_map.rvc_predef = rvc_predef ;
     456          19 :         } else if (rvc_config_att) {
     457             :                 char *rvc_data=NULL;
     458             :                 u32 rvc_size=0;
     459             :                 Bool is_gz = GF_FALSE;
     460           0 :                 if (!strncmp(rvc_config_att, "data:application/rvc-config+xml", 32) && strstr(rvc_config_att, "base64") ) {
     461           0 :                         char *data = strchr(rvc_config_att, ',');
     462           0 :                         if (data) {
     463           0 :                                 rvc_size = (u32) strlen(data) * 3 / 4 + 1;
     464           0 :                                 rvc_data = (char*)gf_malloc(sizeof(char) * rvc_size);
     465           0 :                                 rvc_size = gf_base64_decode(data, (u32) strlen(data), rvc_data, rvc_size);
     466           0 :                                 rvc_data[rvc_size] = 0;
     467             :                         }
     468           0 :                         if (!strncmp(rvc_config_att, "data:application/rvc-config+xml+gz", 35)) is_gz = GF_TRUE;
     469           0 :                 } else if (!strnicmp(rvc_config_att, "http://", 7) || !strnicmp(rvc_config_att, "https://", 8) ) {
     470             :                         return NULL;
     471             :                 }
     472           0 :                 if (rvc_data) {
     473           0 :                         if (is_gz) {
     474             : #ifdef GPAC_DISABLE_ZLIB
     475             :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("Error: no zlib support - RVC not supported in RTP\n"));
     476             :                                 gf_free(rvc_data);
     477             :                                 return NULL;
     478             : #else
     479           0 :                                 gf_gz_decompress_payload(rvc_data, rvc_size, &tmp->depacketizer->sl_map.rvc_config, &tmp->depacketizer->sl_map.rvc_config_size);
     480           0 :                                 gf_free(rvc_data);
     481             : #endif
     482             :                         } else {
     483           0 :                                 tmp->depacketizer->sl_map.rvc_config = rvc_data;
     484           0 :                                 tmp->depacketizer->sl_map.rvc_config_size = rvc_size;
     485             :                         }
     486             :                 }
     487             :         }
     488             : 
     489             :         return tmp;
     490             : }
     491             : 
     492          52 : static void rtpin_stream_update_stats(GF_RTPInStream *stream)
     493             : {
     494             :         u32 time;
     495             :         Float bps;
     496          52 :         if (!stream->rtp_ch) return;
     497             : 
     498          52 :         gf_filter_pid_set_info_str(stream->opid, "nets:loss", &PROP_FLOAT( gf_rtp_get_loss(stream->rtp_ch) ) );
     499          52 :         if (stream->rtsp && (stream->flags & RTP_INTERLEAVED)) {
     500           3 :                 gf_filter_pid_set_info_str(stream->opid, "nets:interleaved", &PROP_UINT( gf_rtsp_get_session_port(stream->rtsp->session) ) );
     501           3 :                 gf_filter_pid_set_info_str(stream->opid, "nets:rtpid", &PROP_UINT( gf_rtp_get_low_interleave_id(stream->rtp_ch) ) );
     502           3 :                 gf_filter_pid_set_info_str(stream->opid, "nets:rctpid", &PROP_UINT( gf_rtp_get_hight_interleave_id(stream->rtp_ch) ) );
     503             : 
     504             :         } else {
     505          49 :                 gf_filter_pid_set_info_str(stream->opid, "nets:rtpp", &PROP_UINT( stream->rtp_ch->net_info.client_port_first ) );
     506          49 :                 gf_filter_pid_set_info_str(stream->opid, "nets:rtcpp", &PROP_UINT( stream->rtp_ch->net_info.client_port_last ) );
     507             :         }
     508          52 :         if (stream->stat_stop_time) {
     509           1 :                 time = stream->stat_stop_time - stream->stat_start_time;
     510             :         } else {
     511          51 :                 time = gf_sys_clock() - stream->stat_start_time;
     512             :         }
     513          52 :         if (!time) return;
     514             : 
     515          52 :         bps = 8.0f * stream->rtp_bytes;
     516          52 :         bps *= 1000;
     517          52 :         bps /= time;
     518          52 :         gf_filter_pid_set_info_str(stream->opid, "nets:bw_down", &PROP_UINT( (u32) bps ) );
     519             : 
     520          52 :         bps = 8.0f * stream->rtcp_bytes;
     521          52 :         bps *= 1000;
     522          52 :         bps /= time;
     523          52 :         gf_filter_pid_set_info_str(stream->opid, "nets:ctrl_bw_down", &PROP_UINT( (u32) bps ) );
     524             : 
     525          52 :         bps = 8.0f * gf_rtp_get_tcp_bytes_sent(stream->rtp_ch);
     526          52 :         bps *= 1000;
     527          52 :         bps /= time;
     528          52 :         gf_filter_pid_set_info_str(stream->opid, "nets:ctrl_bw_up", &PROP_UINT( (u32) bps ) );
     529             : }
     530             : 
     531             : 
     532         755 : void rtpin_stream_on_rtp_pck(GF_RTPInStream *stream, char *pck, u32 size)
     533             : {
     534             :         GF_Err e;
     535             :         GF_RTPHeader hdr;
     536             :         u32 PayloadStart;
     537         755 :         stream->rtp_bytes += size;
     538         755 :         stream->first_in_rtp_pck = GF_TRUE;
     539             : 
     540             :         /*first decode RTP*/
     541         755 :         e = gf_rtp_decode_rtp(stream->rtp_ch, pck, size, &hdr, &PayloadStart);
     542             : 
     543             :         /*corrupted or NULL data*/
     544         755 :         if (e || (PayloadStart >= size)) {
     545             :                 //gf_service_send_packet(stream->rtpin->service, stream->opid, NULL, 0, NULL, GF_CORRUPTED_DATA);
     546           0 :                 return;
     547             :         }
     548         755 :         if (!stream->opid && !stream->depacketizer) {
     549           1 :                 stream->depacketizer = gf_rtp_depacketizer_new(NULL, hdr.PayloadType, rtp_sl_packet_cbk, stream);
     550           1 :                 if (!stream->depacketizer) {
     551             :                         return;
     552             :                 }
     553           1 :                 stream->rtp_ch->PayloadType = hdr.PayloadType;
     554           1 :                 stream->rtp_ch->TimeScale = stream->depacketizer->clock_rate;
     555           1 :                 rtpin_declare_pid(stream, GF_FALSE, 0, NULL);
     556             :         }
     557         755 :         if (!stream->depacketizer) {
     558             :                 return;
     559             :         }
     560             : 
     561             :         /*first we only work with one payload type...*/
     562         755 :         if (hdr.PayloadType != stream->rtp_ch->PayloadType) {
     563           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_RTP, ("[RTP] Mismatched in packet payload type %d vs channel payload type %d, only one payload type per channel is currently supported\n", hdr.PayloadType, stream->rtp_ch->PayloadType));
     564             :         }
     565             : 
     566             :         //pure RTP, remap all streams to 0, adjust sync later
     567         755 :         if (!stream->rtsp) {
     568         671 :                 if (!stream->first_rtp_ts || (hdr.TimeStamp < stream->first_rtp_ts-1) )
     569          14 :                         stream->first_rtp_ts = 1 + hdr.TimeStamp;
     570             :         }
     571             : 
     572             :         /*if we must notify some timing, do it now. */
     573         755 :         if (stream->check_rtp_time) {
     574             :                 Double ch_time;
     575             : 
     576             :                 /*it may happen that we still receive packets from a previous "play" request. If this is the case,
     577             :                 filter until we reach the indicated rtptime*/
     578           6 :                 if (stream->rtp_ch->rtp_time
     579           6 :                         && (stream->rtp_ch->rtp_first_SN > hdr.SequenceNumber)
     580           0 :                         && (stream->rtp_ch->rtp_time > hdr.TimeStamp)
     581             :                    ) {
     582           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_RTP, ("[RTP] Rejecting too early packet (TS %d vs signaled rtp time %d - diff %d ms)\n",
     583             :                                                             hdr.TimeStamp, stream->rtp_ch->rtp_time, ((hdr.TimeStamp - stream->rtp_ch->rtp_time)*1000) / stream->rtp_ch->TimeScale));
     584             :                         return;
     585             :                 }
     586             : 
     587           6 :                 ch_time = gf_rtp_get_current_time(stream->rtp_ch);
     588             : 
     589             :                 /*this is the first packet on the channel (no PAUSE)*/
     590           6 :                 if (stream->check_rtp_time == RTP_SET_TIME_RTP) {
     591             :                         Double media_time = 0;
     592           6 :                         if (stream->rtsp) {
     593           6 :                                 media_time = stream->current_start + ch_time;
     594             :                         }
     595           6 :                         gf_filter_pid_set_property_str(stream->opid, "time:timestamp", &PROP_LONGUINT(hdr.TimeStamp) );
     596           6 :                         gf_filter_pid_set_property_str(stream->opid, "time:media", &PROP_DOUBLE(media_time) );
     597             : 
     598           6 :                         GF_LOG(GF_LOG_INFO, GF_LOG_RTP, ("[RTP] Mapping RTP Time seq %d TS %d Media Time %g - rtp info seq %d TS %d\n",
     599             :                                                          hdr.SequenceNumber, hdr.TimeStamp, stream->current_start + ch_time, stream->rtp_ch->rtp_first_SN, stream->rtp_ch->rtp_time
     600             :                                                         ));
     601             : 
     602             :                         /*skip RTCP clock init when RTSP is used*/
     603           6 :                         if (stream->rtsp) stream->rtcp_init = GF_TRUE;
     604             : 
     605           6 :                         if (stream->depacketizer->payt==GF_RTP_PAYT_H264_AVC) stream->depacketizer->flags |= GF_RTP_AVC_WAIT_RAP;
     606             :                 }
     607             :                 /*this is RESUME on channel, filter packet based on time (darwin seems to send
     608             :                 couple of packet before)
     609             :                 do not fetch if we're below 10 ms or <0, because this means we already have
     610             :                 this packet - as the PAUSE is issued with the RTP currentTime*/
     611           0 :                 else if (ch_time <= 0.021) {
     612             :                         return;
     613             :                 }
     614           6 :                 stream->check_rtp_time = RTP_SET_TIME_NONE;
     615             :         }
     616             : 
     617         755 :         gf_rtp_depacketizer_process(stream->depacketizer, &hdr, pck + PayloadStart, size - PayloadStart);
     618             : 
     619             :         /*last check: signal EOS if we're close to end range in case the server do not send RTCP BYE*/
     620         755 :         if ((stream->flags & RTP_HAS_RANGE) && !(stream->flags & RTP_EOS) ) {
     621             :                 /*also check last CTS*/
     622          81 :                 Double ts = (Double) ((u32) stream->depacketizer->sl_hdr.compositionTimeStamp - hdr.TimeStamp);
     623          81 :                 ts /= gf_rtp_get_clockrate(stream->rtp_ch);
     624          81 :                 if (ABSDIFF(stream->range_end, (ts + stream->current_start + gf_rtp_get_current_time(stream->rtp_ch)) ) < 0.2) {
     625           0 :                         stream->flags |= RTP_EOS;
     626           0 :                         stream->stat_stop_time = gf_sys_clock();
     627           0 :                         gf_filter_pid_set_eos(stream->opid);
     628             :                 }
     629             :         }
     630             : 
     631         755 :         if (stream->rtpin->stats) {
     632         755 :                 u32 now = gf_sys_clock();
     633         755 :                 if (stream->last_stats_time + stream->rtpin->stats < now) {
     634          52 :                         stream->last_stats_time = now;
     635          52 :                         rtpin_stream_update_stats(stream);
     636             :                 }
     637             :         }
     638             : }
     639             : 
     640          18 : static void rtpin_adjust_sync(GF_RTPIn *ctx)
     641             : {
     642          18 :         u32 i, count = gf_list_count(ctx->streams);
     643             :         u64 max_ntp_us = 0;
     644             : 
     645          18 :         for (i=0; i<count; i++) {
     646          19 :                 GF_RTPInStream *stream = gf_list_get(ctx->streams, i);
     647          19 :                 if (!stream->rtcp_init) return;
     648             : 
     649          18 :                 if (max_ntp_us < stream->init_ntp_us) {
     650             :                         max_ntp_us = stream->init_ntp_us;
     651             :                 }
     652             :         }
     653             : 
     654          17 :         for (i=0; i<count; i++) {
     655             :                 s64 ntp_diff_us;
     656          17 :                 GF_RTPInStream *stream = gf_list_get(ctx->streams, i);
     657             : 
     658             :                 ntp_diff_us = max_ntp_us;
     659          17 :                 ntp_diff_us -= stream->init_ntp_us;
     660          17 :                 ntp_diff_us *= stream->rtp_ch->TimeScale;
     661          17 :                 ntp_diff_us /= 1000000;
     662          17 :                 stream->ts_adjust = ntp_diff_us;
     663             :         }
     664             : }
     665             : 
     666          32 : static void rtpin_stream_on_rtcp_pck(GF_RTPInStream *stream, char *pck, u32 size)
     667             : {
     668             :         Bool has_sr;
     669             :         GF_Err e;
     670             : 
     671          33 :         if (stream->status == RTP_Connected) return;
     672             :         //not configured yes
     673          32 :         if (!stream->rtp_ch->TimeScale) return;
     674          31 :         stream->rtcp_bytes += size;
     675             : 
     676          31 :         e = gf_rtp_decode_rtcp(stream->rtp_ch, pck, size, &has_sr);
     677          31 :         if (e<0) return;
     678             : 
     679             :         /*update sync if on pure RTP*/
     680          31 :         if (!stream->rtcp_init && has_sr) {
     681             :                 u64 ntp_clock_us, rtp_diff_us;
     682             : 
     683          18 :                 ntp_clock_us = stream->rtp_ch->last_SR_NTP_frac;
     684          18 :                 ntp_clock_us *= 1000000;
     685          18 :                 ntp_clock_us /= 0xFFFFFFFF;
     686          18 :                 ntp_clock_us += 1000000 * (u64) stream->rtp_ch->last_SR_NTP_sec;
     687             : 
     688             :                 //ntp time at origin: ntp(now) - ntp(first_pck) = rtpts(now) - rtpts(orig) -> ntp_first = ntp - rtp_diff
     689          18 :                 rtp_diff_us = stream->rtp_ch->last_SR_rtp_time - (stream->first_rtp_ts - 1);
     690          18 :                 rtp_diff_us *= 1000000;
     691          18 :                 rtp_diff_us /= stream->rtp_ch->TimeScale;
     692             : 
     693          18 :                 stream->init_ntp_us = ntp_clock_us - rtp_diff_us;
     694             : 
     695             : 
     696          18 :                 GF_LOG(GF_LOG_INFO, GF_LOG_RTP, ("[RTCP] At %d Using Sender Report to map RTP TS %d to NTP clock "LLU" us - NTP origin "LLU"\n", gf_sys_clock(), stream->rtp_ch->last_SR_rtp_time, ntp_clock_us, stream->init_ntp_us));
     697             : 
     698          18 :                 stream->rtcp_init = GF_TRUE;
     699             : 
     700          18 :                 if (stream->rtpin->rtcpsync)
     701          18 :                         rtpin_adjust_sync(stream->rtpin);
     702             :         }
     703             : 
     704          31 :         if (e == GF_EOS) {
     705          13 :                 stream->flags |= RTP_EOS;
     706             :         }
     707             : }
     708             : 
     709          14 : GF_Err rtpin_rtsp_data_cbk(GF_RTSPSession *sess, void *cbk, u8 *buffer, u32 bufferSize, Bool IsRTCP)
     710             : {
     711             :         GF_RTPInStream *stream = (GF_RTPInStream *) cbk;
     712          14 :         if (!stream || stream->rtpin->done) return GF_OK;
     713          14 :         if (IsRTCP) {
     714           1 :                 rtpin_stream_on_rtcp_pck(stream, buffer, bufferSize);
     715             :         } else {
     716          13 :                 rtpin_stream_on_rtp_pck(stream, buffer, bufferSize);
     717             :         }
     718             :         return GF_OK;
     719             : }
     720             : 
     721             : 
     722             : 
     723     5794080 : u32 rtpin_stream_read(GF_RTPInStream *stream)
     724             : {
     725             :         u32 size, tot_size = 0;
     726             : 
     727     5794080 :         if (!stream->rtp_ch) return 0;
     728     5794080 :         if (gf_sk_group_sock_is_set(stream->rtpin->sockgroup, stream->rtp_ch->rtcp, GF_SK_SELECT_READ)) {
     729          31 :                 size = gf_rtp_read_rtcp(stream->rtp_ch, stream->buffer, stream->rtpin->block_size);
     730          31 :                 if (size) {
     731             :                         tot_size += size;
     732          31 :                         rtpin_stream_on_rtcp_pck(stream, stream->buffer, size);
     733             :                 }
     734             :         }
     735             : 
     736     5794080 :         if (gf_sk_group_sock_is_set(stream->rtpin->sockgroup, stream->rtp_ch->rtp, GF_SK_SELECT_READ)) {
     737         742 :                 size = gf_rtp_read_rtp(stream->rtp_ch, stream->buffer, stream->rtpin->block_size);
     738         742 :                 if (size) {
     739         723 :                         tot_size += size;
     740         723 :                         stream->rtpin->udp_timeout = 0;
     741         723 :                         rtpin_stream_on_rtp_pck(stream, stream->buffer, size);
     742             :                 }
     743             :         }
     744     5794080 :         if (!tot_size) return 0;
     745             : 
     746             :         /*and send the report*/
     747         742 :         if (stream->flags & RTP_ENABLE_RTCP) gf_rtp_send_rtcp_report(stream->rtp_ch);
     748             : 
     749             :         /*detect timeout*/
     750         742 :         if (stream->rtpin->udp_timeout) {
     751          18 :                 if (!stream->last_udp_time) {
     752          18 :                         stream->last_udp_time = gf_sys_clock();
     753           0 :                 } else if (stream->rtp_ch->net_info.IsUnicast) {
     754           0 :                         u32 diff = gf_sys_clock() - stream->last_udp_time;
     755           0 :                         if (diff >= stream->rtpin->udp_timeout) {
     756             :                                 char szMessage[1024];
     757           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_RTP, ("[RTP] UDP Timeout after %d ms\n", diff));
     758           0 :                                 sprintf(szMessage, "No data received in %d ms%s", diff, stream->rtpin->autortsp ? ", retrying using TCP" : "");
     759           0 :                                 rtpin_send_message(stream->rtpin, GF_IP_UDP_TIMEOUT, szMessage);
     760           0 :                                 if (stream->rtpin->autortsp)
     761           0 :                                         stream->rtpin->retry_tcp = GF_TRUE;
     762             :                         }
     763             :                 }
     764             :         }
     765             :         return tot_size;
     766             : }
     767             : 
     768             : #endif /*GPAC_DISABLE_STREAMING*/

Generated by: LCOV version 1.13