LCOV - code coverage report
Current view: top level - filters - in_pipe.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 101 131 77.1 %
Date: 2021-04-29 23:48:07 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2018-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / pipe 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             : #ifdef WIN32
      32             : 
      33             : #include <windows.h>
      34             : 
      35             : #else
      36             : 
      37             : #include <fcntl.h>
      38             : #include <unistd.h>
      39             : 
      40             : #ifdef GPAC_CONFIG_LINUX
      41             : #include <sys/types.h>
      42             : #include <sys/stat.h>
      43             : #endif
      44             : 
      45             : #ifndef __BEOS__
      46             : #include <errno.h>
      47             : #endif
      48             : 
      49             : #endif
      50             : 
      51             : 
      52             : typedef struct
      53             : {
      54             :         //options
      55             :         char *src;
      56             :         char *ext;
      57             :         char *mime;
      58             :         u32 block_size;
      59             :         Bool blk, ka, mkp;
      60             : 
      61             :         //only one output pid declared
      62             :         GF_FilterPid *pid;
      63             : 
      64             : #ifdef WIN32
      65             :         HANDLE pipe;
      66             :         HANDLE event;
      67             :         OVERLAPPED overlap;
      68             : #else
      69             :         int fd;
      70             : #endif
      71             :         u64 bytes_read;
      72             : 
      73             :         Bool is_end, pck_out, is_first, owns_pipe;
      74             :         Bool do_reconfigure;
      75             :         char *buffer;
      76             :         Bool is_stdin;
      77             : } GF_PipeInCtx;
      78             : 
      79             : static Bool pipein_process_event(GF_Filter *filter, const GF_FilterEvent *evt);
      80             : 
      81             : #ifdef WIN32
      82             : #include <io.h>
      83             : #include <fcntl.h>
      84             : #endif //WIN32
      85             : 
      86          10 : static GF_Err pipein_initialize(GF_Filter *filter)
      87             : {
      88             :         GF_Err e = GF_OK;
      89          10 :         GF_PipeInCtx *ctx = (GF_PipeInCtx *) gf_filter_get_udta(filter);
      90             :         char *frag_par = NULL;
      91             :         char *cgi_par = NULL;
      92             :         char *src;
      93             : 
      94          10 :         if (!ctx->src) return GF_BAD_PARAM;
      95             : 
      96             : #ifdef WIN32
      97             :         ctx->pipe = INVALID_HANDLE_VALUE;
      98             : #else
      99          10 :         ctx->fd = -1;
     100             : #endif
     101             : 
     102          10 :         if (!strcmp(ctx->src, "-") || !strcmp(ctx->src, "stdin")) {
     103           2 :                 ctx->is_stdin = GF_TRUE;
     104           2 :                 ctx->mkp = GF_FALSE;
     105             : #ifdef WIN32
     106             :                 _setmode(_fileno(stdin), _O_BINARY);
     107             : #endif
     108             :         }
     109           8 :         else if (strnicmp(ctx->src, "pipe:/", 6) && strstr(ctx->src, "://"))  {
     110           0 :                 gf_filter_setup_failure(filter, GF_NOT_SUPPORTED);
     111           0 :                 return GF_NOT_SUPPORTED;
     112             :         }
     113             : 
     114          10 :         if (ctx->mkp) ctx->blk = GF_TRUE;
     115             : 
     116             :         //strip any fragment identifer
     117          10 :         frag_par = strchr(ctx->src, '#');
     118          10 :         if (frag_par) frag_par[0] = 0;
     119          10 :         cgi_par = strchr(ctx->src, '?');
     120          10 :         if (cgi_par) cgi_par[0] = 0;
     121             : 
     122          10 :         src = (char *) ctx->src;
     123          10 :         if (!strnicmp(ctx->src, "pipe://", 7)) src += 7;
     124           2 :         else if (!strnicmp(ctx->src, "pipe:", 5)) src += 5;
     125             : 
     126          10 :         if (ctx->is_stdin) {
     127             :                 e = GF_OK;
     128             :                 goto setup_done;
     129             :         }
     130             : 
     131             : #ifdef WIN32
     132             :         char szNamedPipe[GF_MAX_PATH];
     133             :         if (!strncmp(src, "\\\\", 2)) {
     134             :                 strcpy(szNamedPipe, src);
     135             :         }
     136             :         else {
     137             :                 strcpy(szNamedPipe, "\\\\.\\pipe\\gpac\\");
     138             :                 strcat(szNamedPipe, src);
     139             :         }
     140             :         if (strchr(szNamedPipe, '/')) {
     141             :                 u32 i, len = (u32)strlen(szNamedPipe);
     142             :                 for (i = 0; i < len; i++) {
     143             :                         if (szNamedPipe[i] == '/')
     144             :                                 szNamedPipe[i] = '\\';
     145             :                 }
     146             :         }
     147             : 
     148             :         if (WaitNamedPipeA(szNamedPipe, 1) == FALSE) {
     149             :                 if (!ctx->mkp) {
     150             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[PipeIn] Failed to open %s: %d\n", szNamedPipe, GetLastError()));
     151             :                         e = GF_URL_ERROR;
     152             :                         goto err_exit;
     153             :                 }
     154             :                 DWORD pflags = PIPE_ACCESS_INBOUND;
     155             :                 DWORD flags = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE;
     156             :                 if (ctx->blk) flags |= PIPE_WAIT;
     157             :                 else {
     158             :                         flags |= PIPE_NOWAIT;
     159             :                         pflags |= FILE_FLAG_OVERLAPPED;
     160             :                         if (!ctx->event) ctx->event = CreateEvent(NULL, TRUE, FALSE, NULL);
     161             :                         if (!ctx->event) {
     162             :                                 e = GF_IO_ERR;
     163             :                                 goto err_exit;
     164             :                         }
     165             :                         ctx->overlap.hEvent = ctx->event;
     166             :                 }
     167             :                 ctx->pipe = CreateNamedPipe(szNamedPipe, pflags, flags, 10, ctx->block_size, ctx->block_size, 0, NULL);
     168             : 
     169             :                 if (ctx->pipe == INVALID_HANDLE_VALUE) {
     170             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[PipeIn] Failed to create named pipe %s: %d\n", szNamedPipe, GetLastError()));
     171             :                         e = GF_URL_ERROR;
     172             :                         goto err_exit;
     173             :                 }
     174             :                 if (ctx->blk) {
     175             :                         GF_LOG(GF_LOG_WARNING, GF_LOG_MMIO, ("[PipeIn] Waiting for client connection for %s, blocking\n", szNamedPipe));
     176             :                 }
     177             :                 if (!ConnectNamedPipe(ctx->pipe, ctx->blk ? NULL : &ctx->overlap) && (GetLastError() != ERROR_PIPE_CONNECTED) && (GetLastError() != ERROR_PIPE_LISTENING)) {
     178             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[PipeOut] Failed to connect named pipe %s: %d\n", szNamedPipe, GetLastError()));
     179             :                         e = GF_IO_ERR;
     180             :                         CloseHandle(ctx->pipe);
     181             :                         ctx->pipe = INVALID_HANDLE_VALUE;
     182             :                 }
     183             :                 else {
     184             :                         ctx->owns_pipe = GF_TRUE;
     185             :                 }
     186             :         }
     187             :         else {
     188             :                 ctx->pipe = CreateFile(szNamedPipe, GENERIC_READ, ctx->blk ? PIPE_WAIT : PIPE_NOWAIT, NULL, OPEN_EXISTING, 0, NULL);
     189             :                 if (ctx->pipe == INVALID_HANDLE_VALUE) {
     190             :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[PipeIn] Failed to open %s: %d\n", szNamedPipe, GetLastError()));
     191             :                         e = GF_URL_ERROR;
     192             :                 }
     193             :         }
     194             : 
     195             : err_exit:
     196             : 
     197             : #else
     198           8 :         if (!gf_file_exists(src) && ctx->mkp) {
     199             : 
     200             : #ifdef GPAC_CONFIG_DARWIN
     201             :                 mknod(src,S_IFIFO | 0666, 0);
     202             : #else
     203           1 :                 mkfifo(src, 0666);
     204             : #endif
     205           1 :                 ctx->owns_pipe = GF_TRUE;
     206             :         }
     207             : 
     208          16 :         ctx->fd = open(src, ctx->blk ? O_RDONLY : O_RDONLY|O_NONBLOCK );
     209             : 
     210           8 :         if (ctx->fd < 0) {
     211           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[PipeIn] Failed to open %s: %s\n", src, gf_errno_str(errno)));
     212             :                 e = GF_URL_ERROR;
     213             :         }
     214             : #endif
     215             : 
     216           8 : setup_done:
     217             : 
     218             :         if (e) {
     219           0 :                 if (frag_par) frag_par[0] = '#';
     220           0 :                 if (cgi_par) cgi_par[0] = '?';
     221             : 
     222           0 :                 gf_filter_setup_failure(filter, GF_URL_ERROR);
     223           0 :                 ctx->owns_pipe = GF_FALSE;
     224           0 :                 return GF_URL_ERROR;
     225             :         }
     226          10 :         GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[PipeIn] opening %s\n", src));
     227             : 
     228          10 :         ctx->is_end = GF_FALSE;
     229             : 
     230          10 :         if (frag_par) frag_par[0] = '#';
     231          10 :         if (cgi_par) cgi_par[0] = '?';
     232             : 
     233          10 :         ctx->is_first = GF_TRUE;
     234          10 :         if (!ctx->buffer)
     235          10 :                 ctx->buffer = gf_malloc(ctx->block_size +1);
     236             : 
     237          10 :         gf_filter_post_process_task(filter);
     238             : 
     239             : #ifdef GPAC_ENABLE_COVERAGE
     240          10 :         if (gf_sys_is_cov_mode()) {
     241          10 :                 pipein_process_event(NULL, NULL);
     242             :         }
     243             : #endif
     244             :         return GF_OK;
     245             : }
     246             : 
     247             : 
     248          10 : static void pipein_finalize(GF_Filter *filter)
     249             : {
     250          10 :         GF_PipeInCtx *ctx = (GF_PipeInCtx *) gf_filter_get_udta(filter);
     251             : 
     252          10 :         if (!ctx->is_stdin) {
     253             : #ifdef WIN32
     254             :                 if (ctx->pipe != INVALID_HANDLE_VALUE) CloseHandle(ctx->pipe);
     255             : #else
     256           8 :                 if (ctx->fd>=0) close(ctx->fd);
     257             : #endif
     258           8 :                 if (ctx->owns_pipe)
     259           1 :                         gf_file_delete(ctx->src);
     260             :         }
     261          10 :         if (ctx->buffer) gf_free(ctx->buffer);
     262             : 
     263          10 : }
     264             : 
     265        2939 : static GF_FilterProbeScore pipein_probe_url(const char *url, const char *mime_type)
     266             : {
     267        2939 :         if (!strnicmp(url, "pipe://", 7)) return GF_FPROBE_SUPPORTED;
     268        2931 :         else if (!strnicmp(url, "pipe:", 5)) return GF_FPROBE_SUPPORTED;
     269        2931 :         else if (!strcmp(url, "-") || !strcmp(url, "stdin")) return GF_FPROBE_SUPPORTED;
     270             : 
     271        2929 :         return GF_FPROBE_NOT_SUPPORTED;
     272             : }
     273             : 
     274          10 : static Bool pipein_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
     275             : {
     276             :         GF_PipeInCtx *ctx;
     277          10 :         if (!filter || !evt) return GF_TRUE;
     278             : 
     279           0 :         ctx = (GF_PipeInCtx *) gf_filter_get_udta(filter);
     280           0 :         if (evt->base.on_pid && (evt->base.on_pid != ctx->pid))
     281             :                 return GF_TRUE;
     282             : 
     283           0 :         switch (evt->base.type) {
     284             :         case GF_FEVT_PLAY:
     285             :                 return GF_TRUE;
     286           0 :         case GF_FEVT_STOP:
     287             :                 //stop sending data
     288           0 :                 ctx->is_end = GF_TRUE;
     289           0 :                 gf_filter_pid_set_eos(ctx->pid);
     290           0 :                 return GF_TRUE;
     291           0 :         case GF_FEVT_SOURCE_SEEK:
     292           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_MMIO, ("[PipeIn] Seek request not possible on pipes, ignoring\n"));
     293             :                 return GF_TRUE;
     294           0 :         case GF_FEVT_SOURCE_SWITCH:
     295             :                 assert(ctx->is_end);
     296           0 :                 if (evt->seek.source_switch) {
     297           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_MMIO, ("[PipeIn] source switch request not possible on pipes, ignoring\n"));
     298             :                 }
     299           0 :                 pipein_initialize(filter);
     300           0 :                 gf_filter_post_process_task(filter);
     301           0 :                 break;
     302             :         default:
     303             :                 break;
     304             :         }
     305             :         return GF_TRUE;
     306             : }
     307             : 
     308             : 
     309         277 : static void pipein_pck_destructor(GF_Filter *filter, GF_FilterPid *pid, GF_FilterPacket *pck)
     310             : {
     311         277 :         GF_PipeInCtx *ctx = (GF_PipeInCtx *) gf_filter_get_udta(filter);
     312         277 :         ctx->pck_out = GF_FALSE;
     313             :         //ready to process again
     314         277 :         gf_filter_post_process_task(filter);
     315         277 : }
     316             : 
     317        3977 : static GF_Err pipein_process(GF_Filter *filter)
     318             : {
     319             :         GF_Err e;
     320             :         u32 to_read;
     321             :         s32 nb_read;
     322             :         GF_FilterPacket *pck;
     323        3977 :         GF_PipeInCtx *ctx = (GF_PipeInCtx *) gf_filter_get_udta(filter);
     324             : 
     325        3977 :         if (ctx->is_end)
     326             :                 return GF_EOS;
     327             : 
     328             :         //until packet is released we return EOS (no processing), and ask for processing again upon release
     329        3977 :         if (ctx->pck_out)
     330             :                 return GF_EOS;
     331             : 
     332        3967 :         if (ctx->pid && gf_filter_pid_would_block(ctx->pid)) {
     333             :                 assert(0);
     334             :                 return GF_OK;
     335             :         }
     336             : 
     337        3967 :         to_read = ctx->block_size;
     338             : 
     339        3967 :         if (ctx->is_stdin) {
     340             :                 nb_read = 0;
     341          22 :                 if (feof(stdin)) {
     342           2 :                         if (!ctx->ka) {
     343           2 :                                 gf_filter_pid_set_eos(ctx->pid);
     344           2 :                                 return GF_EOS;
     345             :                         }
     346             :                 } else {
     347          40 :                         nb_read = (s32) fread(ctx->buffer, 1, to_read, stdin);
     348          20 :                         if (nb_read<0) {
     349           0 :                                 if (!ctx->ka) {
     350           0 :                                         gf_filter_pid_set_eos(ctx->pid);
     351           0 :                                         return GF_EOS;
     352             :                                 }
     353             :                         }
     354             :                 }
     355             :         } else {
     356             : 
     357        3945 :                 errno = 0;
     358             : #ifdef WIN32
     359             :                 nb_read = -1;
     360             :                 if (!ctx->blk && ctx->mkp) {
     361             :                         DWORD res = WaitForMultipleObjects(1, &ctx->event, FALSE, 1);
     362             :                         ResetEvent(ctx->event);
     363             :                         if (res == WAIT_FAILED) {
     364             :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[PipeIn] WaitForMultipleObjects failed!\n"));
     365             :                                 return GF_IO_ERR;
     366             :                         }
     367             :                         if (GetOverlappedResult(ctx->pipe, &ctx->overlap, &res, FALSE) == 0) {
     368             :                                 if (GetLastError() == ERROR_IO_INCOMPLETE) {
     369             :                                 }
     370             :                                 else {
     371             :                                         CloseHandle(ctx->pipe);
     372             :                                         ctx->pipe = INVALID_HANDLE_VALUE;
     373             :                                         if (!ctx->ka) {
     374             :                                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[PipeIn] end of stream detected\n"));
     375             :                                                 gf_filter_pid_set_eos(ctx->pid);
     376             :                                                 return GF_EOS;
     377             :                                         }
     378             :                                         GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[PipeIn] Pipe closed by remote side, reopening!\n"));
     379             :                                         return pipein_initialize(filter);
     380             :                                 }
     381             :                         }
     382             :                 }
     383             :                 if (! ReadFile(ctx->pipe, ctx->buffer, to_read, (LPDWORD) &nb_read, ctx->blk ? NULL : &ctx->overlap) ) {
     384             :                         s32 error = GetLastError();
     385             :                         if (error == ERROR_PIPE_LISTENING) return GF_OK;
     386             :                         else if ((error == ERROR_IO_PENDING) || (error== ERROR_MORE_DATA)) {
     387             :                                 //non blocking pipe with writers active
     388             :                         }
     389             :                         else if (nb_read<0) {
     390             :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[PipeIn] Failed to read, error %d\n", error));
     391             :                                 return GF_IO_ERR;
     392             :                         }
     393             :                         else if (!ctx->ka) {
     394             :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[PipeIn] end of stream detected\n"));
     395             :                                 gf_filter_pid_set_eos(ctx->pid);
     396             :                                 CloseHandle(ctx->pipe);
     397             :                                 ctx->pipe = INVALID_HANDLE_VALUE;
     398             :                                 ctx->is_end = GF_TRUE;
     399             :                                 return GF_EOS;
     400             :                         }
     401             :                         else if (error == ERROR_BROKEN_PIPE) {
     402             :                                 GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[PipeIn] Pipe closed by remote side, reopening!\n"));
     403             :                                 CloseHandle(ctx->pipe);
     404             :                                 ctx->pipe = INVALID_HANDLE_VALUE;
     405             :                                 return pipein_initialize(filter);
     406             :                         }
     407             :                         return GF_OK;
     408             :                 }
     409             : #else
     410        7890 :                 nb_read = (s32) read(ctx->fd, ctx->buffer, to_read);
     411        3945 :                 if (nb_read <= 0) {
     412        3688 :                         s32 res = errno;
     413        3688 :                         if (res == EAGAIN) {
     414             :                                 //non blocking pipe with writers active
     415           8 :                         } else if (nb_read<0) {
     416           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_MMIO, ("[PipeIn] Failed to read, error %s\n", gf_errno_str(res) ));
     417             :                                 return GF_IO_ERR;
     418           8 :                         } else if (!ctx->ka) {
     419           8 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_MMIO, ("[PipeIn] end of stream detected\n"));
     420           8 :                                 if (ctx->pid) gf_filter_pid_set_eos(ctx->pid);
     421           8 :                                 close(ctx->fd);
     422           8 :                                 ctx->fd=-1;
     423           8 :                                 ctx->is_end = GF_TRUE;
     424           8 :                                 return GF_EOS;
     425             :                         }
     426             :                         return GF_OK;
     427             :                 }
     428             : #endif
     429             :         }
     430             : 
     431         277 :         if (!nb_read)
     432             :                 return GF_OK;
     433             :         
     434         277 :         ctx->buffer[nb_read] = 0;
     435         277 :         if (!ctx->pid || ctx->do_reconfigure) {
     436          10 :                 GF_LOG(GF_LOG_INFO, GF_LOG_MMIO, ("[PipeIn] configuring stream %d probe bytes\n", nb_read));
     437          10 :                 ctx->do_reconfigure = GF_FALSE;
     438          10 :                 e = gf_filter_pid_raw_new(filter, ctx->src, NULL, ctx->mime, ctx->ext, ctx->buffer, nb_read, GF_TRUE, &ctx->pid);
     439          10 :                 if (e) {
     440           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_MMIO, ("[PipeIn] failed to configure stream: %s\n", gf_error_to_string(e) ));
     441             :                         return e;
     442             :                 }
     443          10 :                 gf_filter_pid_set_property(ctx->pid, GF_PROP_PID_FILE_CACHED, &PROP_BOOL(GF_FALSE) );
     444          10 :                 gf_filter_pid_set_property(ctx->pid, GF_PROP_PID_PLAYBACK_MODE, &PROP_UINT(GF_PLAYBACK_MODE_NONE) );
     445             :         }
     446         277 :         pck = gf_filter_pck_new_shared(ctx->pid, ctx->buffer, nb_read, pipein_pck_destructor);
     447         277 :         if (!pck) return GF_OUT_OF_MEM;
     448             : 
     449         277 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_MMIO, ("[PipeIn] sending %d bytes\n", nb_read));
     450         277 :         gf_filter_pck_set_framing(pck, ctx->is_first, ctx->is_end);
     451         277 :         gf_filter_pck_set_sap(pck, GF_FILTER_SAP_1);
     452             : 
     453         277 :         ctx->is_first = GF_FALSE;
     454         277 :         ctx->pck_out = GF_TRUE;
     455         277 :         gf_filter_pck_send(pck);
     456         277 :         ctx->bytes_read += nb_read;
     457             : 
     458         277 :         if (ctx->is_end) {
     459           0 :                 gf_filter_pid_set_eos(ctx->pid);
     460           0 :                 return GF_EOS;
     461             :         }
     462         277 :         return ctx->pck_out ? GF_EOS : GF_OK;
     463             : }
     464             : 
     465             : 
     466             : 
     467             : #define OFFS(_n)        #_n, offsetof(GF_PipeInCtx, _n)
     468             : 
     469             : static const GF_FilterArgs PipeInArgs[] =
     470             : {
     471             :         { OFFS(src), "name of source pipe", GF_PROP_NAME, NULL, NULL, 0},
     472             :         { OFFS(block_size), "buffer size used to read pipe", GF_PROP_UINT, "5000", NULL, GF_FS_ARG_HINT_ADVANCED},
     473             :         { OFFS(ext), "indicate file extension of pipe data", GF_PROP_STRING, NULL, NULL, 0},
     474             :         { OFFS(mime), "indicate mime type of pipe data", GF_PROP_STRING, NULL, NULL, 0},
     475             :         { OFFS(blk), "open pipe in block mode - see filter help", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
     476             :         { OFFS(ka), "keep-alive pipe when end of input is detected - see filter help", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
     477             :         { OFFS(mkp), "create pipe if not found - see filter help", GF_PROP_BOOL, "false", NULL, 0},
     478             :         {0}
     479             : };
     480             : 
     481             : static const GF_FilterCapability PipeInCaps[] =
     482             : {
     483             :         CAP_UINT(GF_CAPS_OUTPUT,  GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
     484             : };
     485             : 
     486             : GF_FilterRegister PipeInRegister = {
     487             :         .name = "pin",
     488             :         GF_FS_SET_DESCRIPTION("pipe input")
     489             :         GF_FS_SET_HELP( "This filter handles generic input pipes (mono-directional) in blocking or non blocking mode.\n"
     490             :                 "Warning: Input pipes cannot seek.\n"
     491             :                 "Data format of the pipe may be specified using extension (either in file name or through [-ext]()) or MIME type through [-mime]().\n"
     492             :                 "Note: Unless disabled at session level (see [-no-probe](CORE) ), file extensions are usually ignored and format probing is done on the first data block.\n"
     493             :                 "\n"
     494             :                 "# stdin pipe\n"
     495             :                 "The filter can handle reading from stdin, by using `-` or `stdin` as input file name.\n"
     496             :                 "EX gpac -i - vout\n"
     497             :                 "EX gpac -i stdin vout\n"
     498             :                 "\n"
     499             :                 "# Named pipes\n"
     500             :                 "The filter can handle reading from named pipes. The associated protocol scheme is `pipe://` when loaded as a generic input (eg, `-i pipe://URL` where URL is a relative or absolute pipe name).\n"
     501             :                 "On Windows hosts, the default pipe prefix is `\\\\.\\pipe\\gpac\\` if no prefix is set.\n"
     502             :                 "EX dst=mypipe resolves in \\\\.\\pipe\\gpac\\mypipe\n"
     503             :                 "EX dst=\\\\.\\pipe\\myapp\\mypipe resolves in \\\\.\\pipe\\myapp\\mypipe\n"
     504             :                 "Any destination name starting with `\\\\` is used as is, with `\\` translated in `/`.\n"
     505             :                 "\n"
     506             :                 "Input pipes are created by default in non-blocking mode.\n"
     507             :                 "\n"
     508             :                 "The filter can create the pipe if not found using [-mkp](). On windows hosts, this will create a pipe server.\n"
     509             :                 "On non windows hosts, the created pipe will delete the pipe file upon filter destruction.\n"
     510             :                 "\n"
     511             :                 "Input pipes can be setup to run forever using [-ka](). In this case, any potential pipe close on the writing side and end of stream will only be triggered upon session close.\n"
     512             :                 "This can be useful to pipe raw streams from different process into gpac:\n"
     513             :                 "Receiver side: `gpac -i pipe://mypipe:ext=.264:mkp:ka`\n"
     514             :                 "Sender side: `cat raw1.264 > mypipe && gpac -i raw2.264 -o pipe://mypipe:ext=.264`"
     515             :                 "\n"
     516             :                 "The pipe input can be created in blocking mode or non-blocking mode. If the filter creates the pipe, blocking mode is always enabled.\n"
     517             :         "")
     518             :         .private_size = sizeof(GF_PipeInCtx),
     519             :         .args = PipeInArgs,
     520             :         .flags = GF_FS_REG_BLOCKING,
     521             :         SETCAPS(PipeInCaps),
     522             :         .initialize = pipein_initialize,
     523             :         .finalize = pipein_finalize,
     524             :         .process = pipein_process,
     525             :         .process_event = pipein_process_event,
     526             :         .probe_url = pipein_probe_url
     527             : };
     528             : 
     529             : 
     530        2877 : const GF_FilterRegister *pipein_register(GF_FilterSession *session)
     531             : {
     532        2877 :         return &PipeInRegister;
     533             : }

Generated by: LCOV version 1.13