LCOV - code coverage report
Current view: top level - filters - in_sock.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 156 203 76.8 %
Date: 2021-04-29 23:48:07 Functions: 8 10 80.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2017-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / generic TCP/UDP 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             : 
      27             : #include <gpac/filters.h>
      28             : #include <gpac/constants.h>
      29             : #include <gpac/network.h>
      30             : 
      31             : #ifndef GPAC_DISABLE_STREAMING
      32             : #include <gpac/internal/ietf_dev.h>
      33             : #endif
      34             : 
      35             : typedef struct
      36             : {
      37             :         GF_FilterPid *pid;
      38             :         GF_Socket *socket;
      39             :         Bool pck_out;
      40             : #ifndef GPAC_DISABLE_STREAMING
      41             :         GF_RTPReorder *rtp_reorder;
      42             : #else
      43             :         Bool is_rtp;
      44             : #endif
      45             :         char address[GF_MAX_IP_NAME_LEN];
      46             : 
      47             :         u64 start_time;
      48             :         u64 nb_bytes;
      49             :         Bool done;
      50             : 
      51             : } GF_SockInClient;
      52             : 
      53             : typedef struct
      54             : {
      55             :         //options
      56             :         const char *src;
      57             :         u32 block_size, sockbuf;
      58             :         u32 port, maxc;
      59             :         char *ifce;
      60             :         const char *ext;
      61             :         const char *mime;
      62             :         Bool tsprobe, listen, ka, block;
      63             :         u32 timeout;
      64             : #ifndef GPAC_DISABLE_STREAMING
      65             :         u32 reorder_pck;
      66             :         u32 reorder_delay;
      67             : #endif
      68             : 
      69             :         GF_SockInClient sock_c;
      70             :         GF_List *clients;
      71             :         Bool had_clients;
      72             :         Bool is_udp;
      73             : 
      74             :         char *buffer;
      75             : 
      76             :         GF_SockGroup *active_sockets;
      77             :         u64 last_rcv_time;
      78             : } GF_SockInCtx;
      79             : 
      80             : 
      81             : 
      82           9 : static GF_Err sockin_initialize(GF_Filter *filter)
      83             : {
      84             :         char *str, *url;
      85             :         u16 port;
      86             :         u32 sock_type = 0;
      87             :         GF_Err e = GF_OK;
      88           9 :         GF_SockInCtx *ctx = (GF_SockInCtx *) gf_filter_get_udta(filter);
      89             : 
      90           9 :         if (!ctx || !ctx->src) return GF_BAD_PARAM;
      91             : 
      92           9 :         ctx->active_sockets = gf_sk_group_new();
      93           9 :         if (!ctx->active_sockets) return GF_OUT_OF_MEM;
      94             : 
      95           9 :         if (!strnicmp(ctx->src, "udp://", 6)) {
      96             :                 sock_type = GF_SOCK_TYPE_UDP;
      97           3 :                 ctx->listen = GF_FALSE;
      98           3 :                 ctx->is_udp = GF_TRUE;
      99           6 :         } else if (!strnicmp(ctx->src, "tcp://", 6)) {
     100             :                 sock_type = GF_SOCK_TYPE_TCP;
     101             : #ifdef GPAC_HAS_SOCK_UN
     102           0 :         } else if (!strnicmp(ctx->src, "tcpu://", 7) ) {
     103             :                 sock_type = GF_SOCK_TYPE_TCP_UN;
     104           0 :         } else if (!strnicmp(ctx->src, "udpu://", 7) ) {
     105             :                 sock_type = GF_SOCK_TYPE_UDP_UN;
     106           0 :                 ctx->listen = GF_FALSE;
     107             : #endif
     108             :         } else {
     109             :                 return GF_NOT_SUPPORTED;
     110             :         }
     111             : 
     112           9 :         url = strchr(ctx->src, ':');
     113           9 :         url += 3;
     114             : 
     115           9 :         ctx->sock_c.socket = gf_sk_new(sock_type);
     116           9 :         if (! ctx->sock_c.socket ) {
     117           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[SockIn] Failed to open socket for %s\n", ctx->src));
     118             :                 return GF_IO_ERR;
     119             :         }
     120           9 :         gf_sk_group_register(ctx->active_sockets, ctx->sock_c.socket);
     121             : 
     122             :         /*setup port and src*/
     123           9 :         port = ctx->port;
     124           9 :         str = strrchr(url, ':');
     125             :         /*take care of IPv6 address*/
     126           9 :         if (str && strchr(str, ']')) str = strchr(url, ':');
     127           9 :         if (str) {
     128          18 :                 port = atoi(str+1);
     129           9 :                 str[0] = 0;
     130             :         }
     131             : 
     132             :         /*do we have a source ?*/
     133           9 :         if (gf_sk_is_multicast_address(url)) {
     134           1 :                 e = gf_sk_setup_multicast(ctx->sock_c.socket, url, port, 0, 0, ctx->ifce);
     135           1 :                 ctx->listen = GF_FALSE;
     136          16 :         } else if ((sock_type==GF_SOCK_TYPE_UDP) 
     137             : #ifdef GPAC_HAS_SOCK_UN 
     138           8 :                 || (sock_type==GF_SOCK_TYPE_UDP_UN)
     139             : #endif
     140             :                 ) {
     141           2 :                 e = gf_sk_bind(ctx->sock_c.socket, ctx->ifce, port, url, port, GF_SOCK_REUSE_PORT);
     142           2 :                 ctx->listen = GF_FALSE;
     143           2 :                 if (!e)
     144           2 :                         e = gf_sk_connect(ctx->sock_c.socket, url, port, NULL);
     145           6 :         } else if (ctx->listen) {
     146           3 :                 e = gf_sk_bind(ctx->sock_c.socket, NULL, port, url, 0, GF_SOCK_REUSE_PORT);
     147           3 :                 if (!e)
     148           3 :                         e = gf_sk_listen(ctx->sock_c.socket, ctx->maxc);
     149           3 :                 if (!e) {
     150           3 :                         gf_filter_post_process_task(filter);
     151           3 :                         gf_sk_server_mode(ctx->sock_c.socket, GF_TRUE);
     152             :                 }
     153             : 
     154             :         } else {
     155           3 :                 e = gf_sk_connect(ctx->sock_c.socket, url, port, NULL);
     156             :         }
     157             : 
     158           9 :         if (str) str[0] = ':';
     159             : 
     160           9 :         if (e) {
     161           0 :                 gf_sk_del(ctx->sock_c.socket);
     162           0 :                 ctx->sock_c.socket = NULL;
     163           0 :                 return e;
     164             :         }
     165             : 
     166           9 :         gf_sk_set_buffer_size(ctx->sock_c.socket, 0, ctx->sockbuf);
     167           9 :         gf_sk_set_block_mode(ctx->sock_c.socket, !ctx->block);
     168             : 
     169             : 
     170           9 :         GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[SockIn] opening %s%s\n", ctx->src, ctx->listen ? " in server mode" : ""));
     171             : 
     172           9 :         if (ctx->block_size<2000)
     173           0 :                 ctx->block_size = 2000;
     174           9 :         ctx->buffer = gf_malloc(ctx->block_size + 1);
     175           9 :         if (!ctx->buffer) return GF_OUT_OF_MEM;
     176             :         //ext/mime given and not mpeg2, disable probe
     177           9 :         if (ctx->ext && !strstr("ts|m2t|mts|dmb|trp", ctx->ext)) ctx->tsprobe = GF_FALSE;
     178           9 :         if (ctx->mime && !strstr(ctx->mime, "mpeg-2") && !strstr(ctx->mime, "mp2t")) ctx->tsprobe = GF_FALSE;
     179             : 
     180           9 :         if (ctx->listen) {
     181           3 :                 ctx->clients = gf_list_new();
     182           3 :                 if (!ctx->clients) return GF_OUT_OF_MEM;
     183             :         }
     184             :         return GF_OK;
     185             : }
     186             : 
     187          12 : static void sockin_client_reset(GF_SockInClient *sc)
     188             : {
     189          12 :         if (sc->socket) gf_sk_del(sc->socket);
     190             : #ifndef GPAC_DISABLE_STREAMING
     191          12 :         if (sc->rtp_reorder) gf_rtp_reorderer_del(sc->rtp_reorder);
     192             : #endif
     193          12 : }
     194             : 
     195           9 : static void sockin_finalize(GF_Filter *filter)
     196             : {
     197           9 :         GF_SockInCtx *ctx = (GF_SockInCtx *) gf_filter_get_udta(filter);
     198             : 
     199           9 :         if (ctx->clients) {
     200           6 :                 while (gf_list_count(ctx->clients)) {
     201           3 :                         GF_SockInClient *sc = gf_list_pop_back(ctx->clients);
     202           3 :                         sockin_client_reset(sc);
     203           3 :                         gf_free(sc);
     204             :                 }
     205           3 :                 gf_list_del(ctx->clients);
     206             :         }
     207           9 :         sockin_client_reset(&ctx->sock_c);
     208           9 :         if (ctx->buffer) gf_free(ctx->buffer);
     209           9 :         if (ctx->active_sockets) gf_sk_group_del(ctx->active_sockets);
     210           9 : }
     211             : 
     212        2939 : static GF_FilterProbeScore sockin_probe_url(const char *url, const char *mime_type)
     213             : {
     214        2939 :         if (!strnicmp(url, "udp://", 6)) return GF_FPROBE_SUPPORTED;
     215        2936 :         if (!strnicmp(url, "tcp://", 6)) return GF_FPROBE_SUPPORTED;
     216             : #ifdef GPAC_HAS_SOCK_UN
     217        2930 :         if (!strnicmp(url, "udpu://", 7)) return GF_FPROBE_SUPPORTED;
     218        2930 :         if (!strnicmp(url, "tcpu://", 7)) return GF_FPROBE_SUPPORTED;
     219             : #endif
     220        2930 :         return GF_FPROBE_NOT_SUPPORTED;
     221             : }
     222             : 
     223             : #ifndef GPAC_DISABLE_STREAMING
     224           0 : static void sockin_rtp_destructor(GF_Filter *filter, GF_FilterPid *pid, GF_FilterPacket *pck)
     225             : {
     226             :         u32 size;
     227             :         char *data;
     228           0 :         GF_SockInClient *sc = (GF_SockInClient *) gf_filter_pid_get_udta(pid);
     229           0 :         sc->pck_out = GF_FALSE;
     230           0 :         data = (char *) gf_filter_pck_get_data(pck, &size);
     231           0 :         if (data) gf_free(data);
     232           0 : }
     233             : #endif
     234             : 
     235           0 : static Bool sockin_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
     236             : {
     237           0 :         if (!evt->base.on_pid) return GF_FALSE;
     238             : 
     239           0 :         switch (evt->base.type) {
     240             :         case GF_FEVT_PLAY:
     241             :                 return GF_TRUE;
     242             :         case GF_FEVT_STOP:
     243             :                 return GF_TRUE;
     244             :         default:
     245             :                 break;
     246             :         }
     247           0 :         return GF_FALSE;
     248             : }
     249             : 
     250         344 : static GF_Err sockin_read_client(GF_Filter *filter, GF_SockInCtx *ctx, GF_SockInClient *sock_c)
     251             : {
     252             :         u32 nb_read;
     253             :         u64 bitrate;
     254             :         GF_Err e;
     255             :         GF_FilterPacket *dst_pck;
     256             :         u8 *out_data, *in_data;
     257             : 
     258         344 :         if (!sock_c->socket)
     259             :                 return GF_EOS;
     260         344 :         if (sock_c->pck_out)
     261             :                 return GF_OK;
     262             : 
     263         344 :         if (sock_c->pid && gf_filter_pid_would_block(sock_c->pid)) {
     264             :                 return GF_OK;
     265             :         }
     266             : 
     267         338 :         if (!sock_c->start_time) sock_c->start_time = gf_sys_clock_high_res();
     268             : 
     269         338 :         e = gf_sk_receive_no_select(sock_c->socket, ctx->buffer, ctx->block_size, &nb_read);
     270         338 :         switch (e) {
     271             :         case GF_IP_NETWORK_EMPTY:
     272             :                 return GF_OK;
     273             :         case GF_OK:
     274             :                 break;
     275           6 :         case GF_IP_CONNECTION_CLOSED:
     276           6 :                 if (!sock_c->done) {
     277           6 :                         sock_c->done = GF_TRUE;
     278           6 :                         gf_filter_pid_set_eos(sock_c->pid);
     279             :                 }
     280             :                 return GF_EOS;
     281           0 :         default:
     282           0 :                 return e;
     283             :         }
     284         332 :         if (!nb_read) return GF_OK;
     285         332 :         sock_c->nb_bytes += nb_read;
     286         332 :         sock_c->done = GF_FALSE;
     287             : 
     288             :         //we allocated one more byte for that
     289         332 :         ctx->buffer[nb_read] = 0;
     290             : 
     291             :         //first run, probe data
     292         332 :         if (!sock_c->pid) {
     293           9 :                 const char *mime = ctx->mime;
     294             :                 //probe MPEG-2
     295           9 :                 if (ctx->tsprobe) {
     296             :                         /*TS over RTP signaled as udp */
     297           0 :                         if ((ctx->buffer[0] != 0x47) && ((ctx->buffer[1] & 0x7F) == 33) ) {
     298             : #ifndef GPAC_DISABLE_STREAMING
     299           0 :                                 sock_c->rtp_reorder = gf_rtp_reorderer_new(ctx->reorder_pck, ctx->reorder_delay);
     300             : #else
     301             :                                 sock_c->is_rtp = GF_TRUE;
     302             : #endif
     303           0 :                                 mime = "video/mp2t";
     304           0 :                         } else if (ctx->buffer[0] == 0x47) {
     305             :                                 mime = "video/mp2t";
     306             :                         }
     307             :                 }
     308             : 
     309           9 :                 e = gf_filter_pid_raw_new(filter, ctx->src, NULL, mime, ctx->ext, ctx->buffer, nb_read, GF_TRUE, &sock_c->pid);
     310           9 :                 if (e) return e;
     311             : 
     312             : //              if (ctx->is_udp) gf_filter_pid_set_property(sock_c->pid, GF_PROP_PID_UDP, &PROP_BOOL(GF_TRUE) );
     313             : 
     314           9 :                 gf_filter_pid_set_udta(sock_c->pid, sock_c);
     315             : 
     316             : #ifdef GPAC_ENABLE_COVERAGE
     317           9 :                 if (gf_sys_is_cov_mode()) {
     318             :                         GF_FilterEvent evt;
     319             :                         memset(&evt, 0, sizeof(GF_FilterEvent));
     320             :                         evt.base.type = GF_FEVT_PLAY;
     321             :                         evt.base.on_pid = sock_c->pid;
     322             :                         sockin_process_event(filter, &evt);
     323             :                 }
     324             : #endif
     325             : 
     326             :         }
     327             : 
     328         332 :         in_data = ctx->buffer;
     329             : 
     330             : #ifndef GPAC_DISABLE_STREAMING
     331         332 :         if (sock_c->rtp_reorder) {
     332             :                 char *pck;
     333           0 :                 u16 seq_num = ((ctx->buffer[2] << 8) & 0xFF00) | (ctx->buffer[3] & 0xFF);
     334           0 :                 gf_rtp_reorderer_add(sock_c->rtp_reorder, (void *) ctx->buffer, nb_read, seq_num);
     335             : 
     336           0 :                 pck = (char *) gf_rtp_reorderer_get(sock_c->rtp_reorder, &nb_read, GF_FALSE);
     337           0 :                 if (pck) {
     338           0 :                         dst_pck = gf_filter_pck_new_shared(sock_c->pid, pck+12, nb_read-12, sockin_rtp_destructor);
     339           0 :                         if (dst_pck) {
     340           0 :                                 gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_TRUE);
     341           0 :                                 gf_filter_pck_send(dst_pck);
     342             :                         }
     343             :                 }
     344             :                 return GF_OK;
     345             :         }
     346             : #else
     347             :         if (sock_c->is_rtp) {
     348             :                 in_data = ctx->buffer + 12;
     349             :                 nb_read -= 12;
     350             :         }
     351             : #endif
     352             : 
     353         332 :         dst_pck = gf_filter_pck_new_alloc(sock_c->pid, nb_read, &out_data);
     354         332 :         if (!dst_pck) return GF_OUT_OF_MEM;
     355             : 
     356         332 :         memcpy(out_data, in_data, nb_read);
     357             : 
     358         332 :         gf_filter_pck_set_framing(dst_pck, (sock_c->nb_bytes == nb_read)  ? GF_TRUE : GF_FALSE, GF_FALSE);
     359         332 :         gf_filter_pck_send(dst_pck);
     360             : 
     361             :         //send bitrate
     362         332 :         bitrate = ( gf_sys_clock_high_res() - sock_c->start_time );
     363         332 :         if (bitrate) {
     364         332 :                 bitrate = (sock_c->nb_bytes * 8 * 1000000) / bitrate;
     365         332 :                 gf_filter_pid_set_property(sock_c->pid, GF_PROP_PID_DOWN_RATE, &PROP_UINT((u32) bitrate) );
     366         332 :                 GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[SockIn] Receiving from %s at %d kbps\r", sock_c->address, (u32) (bitrate/10)));
     367             :         }
     368             : 
     369             :         return GF_OK;
     370             : }
     371             : 
     372        4837 : static Bool sockin_check_eos(GF_SockInCtx *ctx)
     373             : {
     374        4837 :         u64 now = gf_sys_clock_high_res();
     375        4837 :         if (!ctx->last_rcv_time) {
     376           3 :                 ctx->last_rcv_time = now;
     377           3 :                 return GF_FALSE;
     378             :         }
     379        4834 :         if (now - ctx->last_rcv_time < ctx->timeout*1000) {
     380             :                 return GF_FALSE;
     381             :         }
     382           3 :         if (ctx->sock_c.pid && !ctx->sock_c.done) {
     383           3 :                 gf_filter_pid_set_eos(ctx->sock_c.pid);
     384           3 :                 ctx->sock_c.done = GF_TRUE;
     385             :         }
     386             :         return GF_TRUE;
     387             : }
     388             : 
     389        6220 : static GF_Err sockin_process(GF_Filter *filter)
     390             : {
     391        6220 :         GF_Socket *new_conn=NULL;
     392             :         GF_Err e;
     393             :         u32 i, count;
     394        6220 :         GF_SockInCtx *ctx = (GF_SockInCtx *) gf_filter_get_udta(filter);
     395             : 
     396        6220 :         e = gf_sk_group_select(ctx->active_sockets, 10, GF_SK_SELECT_READ);
     397        6220 :         if (e==GF_IP_NETWORK_EMPTY) {
     398        5873 :                 if (ctx->is_udp) {
     399        4837 :                         if (sockin_check_eos(ctx) )
     400             :                                 return GF_EOS;
     401        1036 :                 } else if (!gf_list_count(ctx->clients)) {
     402        1035 :                         gf_filter_ask_rt_reschedule(filter, 1000);
     403        1035 :                         return GF_OK;
     404             :                 }
     405             : 
     406        4835 :                 gf_filter_ask_rt_reschedule(filter, 1000);
     407        4835 :                 return GF_OK;
     408             :         }
     409         347 :         else if (e) return e;
     410             : 
     411         347 :         if (gf_sk_group_sock_is_set(ctx->active_sockets, ctx->sock_c.socket, GF_SK_SELECT_READ)) {
     412         312 :                 if (!ctx->listen) {
     413         309 :                         return sockin_read_client(filter, ctx, &ctx->sock_c);
     414             :                 }
     415             : 
     416           3 :                 if (gf_sk_group_sock_is_set(ctx->active_sockets, ctx->sock_c.socket, GF_SK_SELECT_READ)) {
     417           3 :                         e = gf_sk_accept(ctx->sock_c.socket, &new_conn);
     418           3 :                         if ((e==GF_OK) && new_conn) {
     419             :                                 GF_SockInClient *sc;
     420           3 :                                 GF_SAFEALLOC(sc, GF_SockInClient);
     421           3 :                                 if (!sc) return GF_OUT_OF_MEM;
     422             :                                 
     423           3 :                                 sc->socket = new_conn;
     424           3 :                                 strcpy(sc->address, "unknown");
     425           3 :                                 gf_sk_get_remote_address(new_conn, sc->address);
     426           3 :                                 gf_sk_set_block_mode(new_conn, !ctx->block);
     427             : 
     428           3 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_NETWORK, ("[SockIn] Accepting new connection from %s\n", sc->address));
     429           3 :                                 gf_list_add(ctx->clients, sc);
     430           3 :                                 ctx->had_clients = GF_TRUE;
     431           3 :                                 gf_sk_group_register(ctx->active_sockets, sc->socket);
     432             :                         }
     433             :                 }
     434             :         }
     435          38 :         if (!ctx->listen) return GF_OK;
     436             : 
     437          38 :         count = gf_list_count(ctx->clients);
     438          73 :         for (i=0; i<count; i++) {
     439          38 :                 GF_SockInClient *sc = gf_list_get(ctx->clients, i);
     440             : 
     441          38 :                 if (!gf_sk_group_sock_is_set(ctx->active_sockets, sc->socket, GF_SK_SELECT_READ)) continue;
     442             : 
     443          35 :                 e = sockin_read_client(filter, ctx, sc);
     444          35 :                 if (e == GF_IP_CONNECTION_CLOSED) {
     445           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_NETWORK, ("[SockIn] Connection to %s lost, removing input\n", sc->address));
     446           0 :                         if (sc->socket)
     447           0 :                                 gf_sk_group_unregister(ctx->active_sockets, sc->socket);
     448             : 
     449           0 :                         sockin_client_reset(sc);
     450           0 :                         if (sc->pid) {
     451           0 :                                 gf_filter_pid_set_eos(sc->pid);
     452           0 :                                 gf_filter_pid_remove(sc->pid);
     453             :                         }
     454           0 :                         gf_free(sc);
     455           0 :                         gf_list_del_item(ctx->clients, sc);
     456           0 :                         i--;
     457           0 :                         count--;
     458             :                 } else {
     459          35 :                         if (e) return e;
     460             :                 }
     461             :         }
     462          35 :         if (!ctx->had_clients) {
     463             :                 //we should use socket groups and selects !
     464           0 :                 gf_filter_ask_rt_reschedule(filter, 100000);
     465           0 :                 return GF_OK;
     466             :         }
     467             : 
     468          35 :         if (!count) {
     469           0 :                 if (ctx->ka) {
     470             :                         //keep alive, ask for real-time reschedule of 100 ms - we should use socket groups and selects !
     471           0 :                         gf_filter_ask_rt_reschedule(filter, 100000);
     472             :                 } else {
     473             :                         return GF_EOS;
     474             :                 }
     475             :         }
     476             :         return GF_OK;
     477             : }
     478             : 
     479             : 
     480             : 
     481             : #define OFFS(_n)        #_n, offsetof(GF_SockInCtx, _n)
     482             : 
     483             : static const GF_FilterArgs SockInArgs[] =
     484             : {
     485             :         { OFFS(src), "address of source content - see filter help", GF_PROP_NAME, NULL, NULL, 0},
     486             :         { OFFS(block_size), "block size used to read socket", GF_PROP_UINT, "10000", NULL, GF_FS_ARG_HINT_ADVANCED},
     487             :         { OFFS(sockbuf), "socket max buffer size", GF_PROP_UINT, "65536", NULL, GF_FS_ARG_HINT_ADVANCED},
     488             :         { OFFS(port), "default port if not specified", GF_PROP_UINT, "1234", NULL, 0},
     489             :         { OFFS(ifce), "default multicast interface", GF_PROP_NAME, NULL, NULL, GF_FS_ARG_HINT_ADVANCED},
     490             :         { OFFS(listen), "indicate the input socket works in server mode", GF_PROP_BOOL, "false", NULL, 0},
     491             :         { OFFS(ka), "keep socket alive if no more connections", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
     492             :         { OFFS(maxc), "max number of concurrent connections", GF_PROP_UINT, "+I", NULL, 0},
     493             :         { OFFS(tsprobe), "probe for MPEG-2 TS data, either RTP or raw UDP. Disabled if mime or ext are given and do not match MPEG-2 TS mimes/extensions", GF_PROP_BOOL, "true", NULL, GF_FS_ARG_HINT_ADVANCED},
     494             :         { OFFS(ext), "indicate file extension of udp data", GF_PROP_STRING, NULL, NULL, 0},
     495             :         { OFFS(mime), "indicate mime type of udp data", GF_PROP_STRING, NULL, NULL, 0},
     496             :         { OFFS(block), "set blocking mode for socket(s)", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
     497             :         { OFFS(timeout), "set timeout in ms for UDP socket(s)", GF_PROP_UINT, "5000", NULL, GF_FS_ARG_HINT_ADVANCED},
     498             : 
     499             : #ifndef GPAC_DISABLE_STREAMING
     500             :         { OFFS(reorder_pck), "number of packets delay for RTP reordering (M2TS over RTP) ", GF_PROP_UINT, "100", NULL, GF_FS_ARG_HINT_ADVANCED},
     501             :         { OFFS(reorder_delay), "number of ms delay for RTP reordering (M2TS over RTP)", GF_PROP_UINT, "10", NULL, GF_FS_ARG_HINT_ADVANCED},
     502             : #endif
     503             :         {0}
     504             : };
     505             : 
     506             : static const GF_FilterCapability SockInCaps[] =
     507             : {
     508             :         CAP_UINT(GF_CAPS_OUTPUT,  GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
     509             : };
     510             : 
     511             : GF_FilterRegister SockInRegister = {
     512             :         .name = "sockin",
     513             :         GF_FS_SET_DESCRIPTION("UDP/TCP input")
     514             : #ifndef GPAC_DISABLE_DOC
     515             :         .help = "This filter handles generic TCP and UDP input sockets. It can also probe for MPEG-2 TS over RTP input. Probing of MPEG-2 TS over UDP/RTP is enabled by default but can be turned off.\n"
     516             :                 "\nData format can be specified by setting either [-ext]() or [-mime]() options. If not set, the format will be guessed by probing the first data packet\n"
     517             :                 "\n"
     518             :                 "- UDP sockets are used for source URLs formatted as `udp://NAME`\n"
     519             :                 "- TCP sockets are used for source URLs formatted as `tcp://NAME`\n"
     520             : #ifdef GPAC_HAS_SOCK_UN
     521             :                 "- UDP unix domain sockets are used for source URLs formatted as `udpu://NAME`\n"
     522             :                 "- TCP unix domain sockets are used for source URLs formatted as `tcpu://NAME`\n"
     523             :                 "\n"
     524             :                 "When ports are specified in the URL and the default option separators are used (see `gpac -h doc`), the URL must either:\n"
     525             :                 "- have a trailing '/', eg `udp://localhost:1234/[:opts]`\n"
     526             :                 "- use `gpac` separator, eg `udp://localhost:1234[:gpac:opts]`\n"
     527             : #ifdef GPAC_CONFIG_DARWIN
     528             :         "\nOn OSX with VM packet replay you will need to force multicast routing, eg: route add -net 239.255.1.4/32 -interface vboxnet0"
     529             : #endif
     530             :         ""
     531             : #else
     532             :         "Your platform does not supports unix domain sockets, udpu:// and tcpu:// schemes not supported."
     533             : #endif
     534             :         ,
     535             : #endif //GPAC_DISABLE_DOC
     536             :         .private_size = sizeof(GF_SockInCtx),
     537             :         .args = SockInArgs,
     538             :         SETCAPS(SockInCaps),
     539             :         .initialize = sockin_initialize,
     540             :         .finalize = sockin_finalize,
     541             :         .process = sockin_process,
     542             :         .process_event = sockin_process_event,
     543             :         .probe_url = sockin_probe_url
     544             : };
     545             : 
     546             : 
     547        2877 : const GF_FilterRegister *sockin_register(GF_FilterSession *session)
     548             : {
     549        2877 :         return &SockInRegister;
     550             : }
     551             : 

Generated by: LCOV version 1.13