From patchwork Tue May 18 16:03:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Zhili X-Patchwork-Id: 27831 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:b214:0:0:0:0:0 with SMTP id b20csp516159iof; Tue, 18 May 2021 09:03:51 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw0NH5zXYJvwE8GRdL9CO6NUkRAXSRgozxtOOSZzqj6pz54AuD+JjAWZFIiroizuqcCz7yr X-Received: by 2002:a17:907:7629:: with SMTP id jy9mr6954325ejc.34.1621353831376; Tue, 18 May 2021 09:03:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1621353831; cv=none; d=google.com; s=arc-20160816; b=t4/4poHfPWeqhNiTmCEwjjp4RdfbcBrrkZkZjaOXb0O1AMesAy5qKJx37ph55KPS0f nDusuMy78QXLdmIlPBSlZ5KlECEr7Ah3lT2iTtw2oiE2n8AGx0pNxKvdVcm/sL01QEMH 5rZB5gG+iZmr3j2jyUU3M3lUC0rAOUkQktuMzi2zcw9XqxdwAEe1cK+SdRUxwxCFZhHv mRRKqYVArlIcOrIuEjBOkNn4aS/3fNRv2aeWswx1XsV4hn6HzEWONX7CLyMGc9zkHdOZ OvtgHkIlhAJ0USXzIgSRXGoWWcwSWRMaf60TdmgGfSFWk9e1Enr93qK9X9AE2prTlYY5 47oQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:date:to:from:message-id :dkim-signature:delivered-to; bh=l1BtwzUUUdY+KJF89ZMSt0Ym2b4gK5Za1v8eeDrxFJI=; b=d9OxeyJaZA/aKCe7AuxMg9JTPAMFXvlB4V+RK/TeM9a8ONvyR2d0sDEKOdHCELCpLS cYIGsfsrCySrV7DDz97zVuXrcs0NpTS1R0Vqu/BSztLNsx/46yH4zDyZ0sgzWCLJ0ERI BhlQ7Jx6mB/+WDIwu2uGcaikOGHm+I0x5PYn0ma/HaUqubHu/hIyU3edSzK7urCipEu4 NCw8nj6T3J1cF0NGoUV7yzTGSbSwIdWuv1wL5+UQ+vBudxJ5x5vBi0XPEhDv3n+lFCzz 2r0P8MWgsGvSJu3J4tyQcc+Pyvo9rOlgEohWpcj82HPagZCu0jL+uCKnDPQCGCsmJ+9t dnDw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@foxmail.com header.s=s201512 header.b=xTEqDYPy; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=foxmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id y3si17052387ejo.374.2021.05.18.09.03.47; Tue, 18 May 2021 09:03:51 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@foxmail.com header.s=s201512 header.b=xTEqDYPy; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=foxmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id F223C689B62; Tue, 18 May 2021 19:03:41 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from out162-62-57-137.mail.qq.com (out162-62-57-137.mail.qq.com [162.62.57.137]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id C58D3680A7A for ; Tue, 18 May 2021 19:03:34 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foxmail.com; s=s201512; t=1621353810; bh=xF/8GRfhPSWNW+rui4PDP3o29ebg4Qr2AEEC0KPua+I=; h=From:To:Cc:Subject:Date; b=xTEqDYPyz4akbCru1rnfQBJBBlz3taMwRF9JwNDJRVos8r8j7pKdYcIKF04+nmdKr OHmCbjWm/fYwkEHsTh/ZNIgxzNLEqVKWDOycW6i6DDbcedvTtOCPCqRx9dfw36poC0 x2IpymQVv/JODvOHZQoljKDKV0jtvkfEmDIUMnDo= Received: from localhost.localdomain ([119.123.135.161]) by newxmesmtplogicsvrszc8.qq.com (NewEsmtp) with SMTP id DD146F4; Wed, 19 May 2021 00:03:29 +0800 X-QQ-mid: xmsmtpt1621353809ts9c8q1bc Message-ID: X-QQ-XMAILINFO: OH/+daVgfqZe2ovmMcTRzU0mWWXM1iTD/CMvPtEpagM9cBqFFnIcL+/rCtXalp f08hYNrXWIew77r5GNmzZZwOqBSPYf+gvOyD53mMzFTrE4kIqq8tdkBUDjxrImRCCU6ADuWm2MPO AmfTTQJl7GO6d3jLNZvcvvz78jf1xqnO3j9rLEHnEfWdq3ng5MCCtm+w/Tcs+uZJmn4nUez1nZgk fD+XG1iMn+r6WakuGg6Va/7qHI59ycPxrlNUqgibz1K4KNznco/vVOGu8X1ZGlpVjfjG81/7pxfm LGBcCGT7YgRGFoziWs0WOkVO8kRZuzocbZ9JWoLwDXJPUFrwhhxIKpcmo07EZQr1J/E/9LwcoNcp pyo/rflB3VKqp7YIftNPM3+sCu5RqhucKticr7lM9SMaf2pgVXtCYORdfzV752Ovr9IalOGN7bmP uCmYSdv+b2o8ZD2xrVnqE4TyrNwYO+6UBSLse4we7MBrl1VDROQkxARdGBEdUZx4Jl99YvlUPT8Q hG0rJ8Huo+h2cbljPzvoaCpd7Wqqwtn1uC379BxZOMGF3s4jeGEki1rcZdR2z4UWkovt2H3TQKVZ lAfyfPsclrUX1GnC+K9CMpwnDQhzqeQR1WWOKJSHiO2hw83FeCfRHEmm5lVd4312PD2z3VeTHGdF gvMkGygXrble6YrlmuY6jJp7MhYfA8oiwSwJLvvhcoclIsAGBXXOIcbbz7yfXOipBH0uJ03cKIi7 4P+128DLSOrwPNiA6uDjnEtTjQpFxavdg7aJM7S0KrvQmTa4ioxxI8EzJAsBmjvlZYIapyaVccs0 gPxXC9DfpBhQ== From: Zhao Zhili To: ffmpeg-devel@ffmpeg.org Date: Wed, 19 May 2021 00:03:20 +0800 X-OQ-MSGID: <20210518160321.27698-1-quinkblack@foxmail.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/2] avformat/libsrt: support bidirectional transmission X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Zhao Zhili Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 9cycjY/2mspI --- There is no good use case yet. Patch 2/2 is only used for test. libavformat/libsrt.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/libavformat/libsrt.c b/libavformat/libsrt.c index c1e96f700e..a05921d9f0 100644 --- a/libavformat/libsrt.c +++ b/libavformat/libsrt.c @@ -163,10 +163,17 @@ static int libsrt_socket_nonblock(int socket, int enable) return srt_setsockopt(socket, 0, SRTO_RCVSYN, &blocking, sizeof(blocking)); } -static int libsrt_epoll_create(URLContext *h, int fd, int write) +static int libsrt_epoll_create(URLContext *h, int fd, int flags) { - int modes = SRT_EPOLL_ERR | (write ? SRT_EPOLL_OUT : SRT_EPOLL_IN); - int eid = srt_epoll_create(); + int modes; + int eid; + + modes = SRT_EPOLL_ERR; + if (flags & AVIO_FLAG_WRITE) + modes |= SRT_EPOLL_OUT; + if (flags & AVIO_FLAG_READ) + modes |= SRT_EPOLL_IN; + eid = srt_epoll_create(); if (eid < 0) return libsrt_neterrno(h); if (srt_epoll_add_usock(eid, fd, &modes) < 0) { @@ -178,14 +185,26 @@ static int libsrt_epoll_create(URLContext *h, int fd, int write) static int libsrt_network_wait_fd(URLContext *h, int eid, int write) { - int ret, len = 1, errlen = 1; + int ret, len = 1, errlen; SRTSOCKET ready[1]; SRTSOCKET error[1]; + SRTSOCKET *error_ptr; + int *errlen_ptr; + if ((h->flags & AVIO_FLAG_READ_WRITE) == AVIO_FLAG_READ_WRITE) { + // cannot detect error in this case + errlen = 0; + error_ptr = NULL; + errlen_ptr = NULL; + } else { + errlen = 1; + error_ptr = error; + errlen_ptr = &errlen; + } if (write) { - ret = srt_epoll_wait(eid, error, &errlen, ready, &len, POLLING_TIME, 0, 0, 0, 0); + ret = srt_epoll_wait(eid, error_ptr, errlen_ptr, ready, &len, POLLING_TIME, 0, 0, 0, 0); } else { - ret = srt_epoll_wait(eid, ready, &len, error, &errlen, POLLING_TIME, 0, 0, 0, 0); + ret = srt_epoll_wait(eid, ready, &len, error_ptr, errlen_ptr, POLLING_TIME, 0, 0, 0, 0); } if (ret < 0) { if (srt_getlasterror(NULL) == SRT_ETIMEOUT) @@ -435,7 +454,7 @@ static int libsrt_setup(URLContext *h, const char *uri, int flags) if (libsrt_socket_nonblock(fd, 1) < 0) av_log(h, AV_LOG_DEBUG, "libsrt_socket_nonblock failed\n"); - ret = write_eid = libsrt_epoll_create(h, fd, 1); + ret = write_eid = libsrt_epoll_create(h, fd, AVIO_FLAG_WRITE); if (ret < 0) goto fail1; if (s->mode == SRT_MODE_LISTENER) { @@ -479,7 +498,7 @@ static int libsrt_setup(URLContext *h, const char *uri, int flags) h->max_packet_size = packet_size; } - ret = eid = libsrt_epoll_create(h, fd, flags & AVIO_FLAG_WRITE); + ret = eid = libsrt_epoll_create(h, fd, flags); if (eid < 0) goto fail1; From patchwork Tue May 18 16:03:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Zhili X-Patchwork-Id: 27832 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a6b:b214:0:0:0:0:0 with SMTP id b20csp516361iof; Tue, 18 May 2021 09:04:03 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw1DCpntF0z0iRqDLr3vp2TD2QDY2Y2DctRxiRZzrjlSbzeJpgM5XUnt2OYn3tq6XJtP2dL X-Received: by 2002:aa7:d913:: with SMTP id a19mr7950985edr.173.1621353843308; Tue, 18 May 2021 09:04:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1621353843; cv=none; d=google.com; s=arc-20160816; b=xyRQE7LaR+3rRWTCQIjjPviK+ozfERtFet9nA1BSSx9JdW0PRrP49+K0fUHfzyliR9 V1MbHlWzhLhiLF/zxPgLc9i6SHNQwbR16jLfosGAKt+yKwscW+af5fyf6TesBEnrPG/k gmiGZcAqmuN9R7dJI8mUy7xOAAwWeg6Ri/PltGVEJT9kDkRXL8N4IX5MDr5Pf+vVzLkj KonA5D+RC6L4IuQzgrWGDnN/31FPELlq8LC6Dx2+r14OqkFYUyELk3OOu5tP4tNtmAFz FLomg14em8xuwQt2kaRVVEyg4izwiJz5PlyQs2bNC31AJwkSpCBEukZwoM+V6ryjKLW1 QIjQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to:date :to:from:message-id:dkim-signature:delivered-to; bh=HaL5R4vOucuADzFpt5vL25NjpVckS7Bf0VCtDF8Zz8A=; b=vqDd4+x2qARvOgCBZkjoLN11JbshPD07jK5Jajp5ZrWb50aSBgAHV5cyqgcBJnbR7Z Du2rW84AUt7pIced9TBmd/DOwz7CbKoANr8Ggdr5CeXLhUXFneqfr96qEDbHnFFc2aUi UXYqDXmxElPNEeOThe8dbkmlxfqqUNULOTTCmWa1gfMf9wCzadamif1gaxRhdUEguulW e0AIf8Av3ZsJv+uULnmbYrQ6ob4+aYpnSqrZRTGodAICMe2HSfERQszp6auojKaNL+69 lzpLjqAjmH5r0PXh5UJZJOikS8FbO6ZWVf3TRmK+Mr7xZT5qZS5Aeu9eJ2cfhlfK8jza wLhw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@foxmail.com header.s=s201512 header.b=h1Dtw94B; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=foxmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id gn42si12306633ejc.93.2021.05.18.09.04.02; Tue, 18 May 2021 09:04:03 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@foxmail.com header.s=s201512 header.b=h1Dtw94B; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=foxmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 08915689BDB; Tue, 18 May 2021 19:03:47 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from out203-205-221-149.mail.qq.com (out203-205-221-149.mail.qq.com [203.205.221.149]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E34D4689900 for ; Tue, 18 May 2021 19:03:39 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foxmail.com; s=s201512; t=1621353813; bh=WiISu032rV/HdfstxBYkSqXV86kqhKnsDJFCKENBA68=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=h1Dtw94BWTpWFudNHkeXaepzPRF6wFYdnsO34GnnCw3uh3ZV/tUdT63Orez7ezqs7 QbKHA7B1j+KulRXS225kAI5oMrTfBuyvt/qbogqPvoK8H4dr7NgG+QaodYDyLYwnZa uJscdnjUNRnUWMOhKjaH58h/PMn3TSIkfIYfaH4c= Received: from localhost.localdomain ([119.123.135.161]) by newxmesmtplogicsvrszc8.qq.com (NewEsmtp) with SMTP id DD146F4; Wed, 19 May 2021 00:03:29 +0800 X-QQ-mid: xmsmtpt1621353810tr2j32b43 Message-ID: X-QQ-XMAILINFO: NzOHSugmTg7X3tnXBHf6Cz7P+NYvl43j7WKEx6m3gCwlmQpbSDghQ0CPJGKcJh F0MC+i5s4y0LROKXVL0QJVr7RwnVxRNOcLgF36JUz2wViKXTW4Kil9LaZDehRODLmBTOZA1z9MuY T96ebgYE3uB4Ihmmzi5szB938DvYBfmFrmV+pr9fNkKrmpAO7PSXRkGnUH/sAPRqtb9zgHnVWs2Q KsszzlT2Hb/XhQ2Gzb9sed49ht9Y2yp32GW+D7bh21zS0VRcQ2jHjfGLdgYINna8dtuj8iBt91Kj dliuO6CfTiyqZhMzITMuYfqcWS5WCeWanFoOlEP2q8lcFQ78WYS8dycFJhgQkUJZbjmlrgPYb8TO SaVS0qnouTRg0YEogiqMJKvxc9g34Jp1H4hrDNj3WjiCt7rbUITccoX9svYQma00LiuzI5MXVjqt ePKdTGhzVtq1fVfCsHxAqcMcYxkSI9AFn+EDty4q6H9U4S+go1OQeWdTP1Hna9Hw2IPoQn1HK2Yd uZ6A55UChfpUVspzuqS3H7i6FtPHuX6g5KCrGvQ6+dnDpxt1Qq+F2JTxRjgCSAgt1UlC8ODa8568 D3xFXwLcdFfKUBLSqpo3PcynYMyLT0wmUsu6XkGUsff11AuQf+rGGNuhxLBiltPmKZCRHiL9wCwW ShU8bBolN/OI5w8bKpvPScJvEWy0xKe+Fei78D1RAVjpOREnFHV5/OHC7T2QQoImQa3T7nzixOrJ cFM6CDyAikxBJNbjdUnk3l53n40WSbzRTuQpDTzCupqS/al3fq3ppb8WrmhLhvLSiVw4YN/oWC1P F8DhcIJ0jxdvKTxr4cjL1XWOJWQL4qSjQub0a+R0KJ+tRfyqvZw7GG2yWBkcoiP94= From: Zhao Zhili To: ffmpeg-devel@ffmpeg.org Date: Wed, 19 May 2021 00:03:21 +0800 X-OQ-MSGID: <20210518160321.27698-2-quinkblack@foxmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210518160321.27698-1-quinkblack@foxmail.com> References: <20210518160321.27698-1-quinkblack@foxmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [ONLY FOR TEST PATCH 2/2] avformat/rtmp: add rtmp over srt X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Zhao Zhili Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: khmaU7ykJ+p9 --- Test with: ./ffplay -listen 1 rtmpsrt://127.0.0.1:8888 ./ffmpeg -re -i bunny.mp4 -c copy -f flv rtmpsrt://127.0.0.1:8888 configure | 2 + libavformat/Makefile | 2 + libavformat/protocols.c | 2 + libavformat/rtmpproto.c | 11 ++- libavformat/rtmpsrt.c | 167 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 libavformat/rtmpsrt.c diff --git a/configure b/configure index 82367fd30d..76cd56477a 100755 --- a/configure +++ b/configure @@ -3476,6 +3476,7 @@ ffrtmpcrypt_protocol_deps_any="gcrypt gmp openssl mbedtls" ffrtmpcrypt_protocol_select="tcp_protocol" ffrtmphttp_protocol_conflict="librtmp_protocol" ffrtmphttp_protocol_select="http_protocol" +ffrtmpsrt_protocol_select="libsrt_protocol" ftp_protocol_select="tcp_protocol" gopher_protocol_select="tcp_protocol" gophers_protocol_select="tls_protocol" @@ -3502,6 +3503,7 @@ rtmpte_protocol_select="ffrtmpcrypt_protocol ffrtmphttp_protocol" rtmpte_protocol_suggest="zlib" rtmpts_protocol_select="ffrtmphttp_protocol https_protocol" rtmpts_protocol_suggest="zlib" +rtmpsrt_protocol_select="ffrtmpsrt_protocol" rtp_protocol_select="udp_protocol" schannel_conflict="openssl gnutls libtls mbedtls" sctp_protocol_deps="struct_sctp_event_subscribe struct_msghdr_msg_flags" diff --git a/libavformat/Makefile b/libavformat/Makefile index 85b5d8e7eb..7770fb2f8c 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -618,6 +618,7 @@ OBJS-$(CONFIG_CRYPTO_PROTOCOL) += crypto.o OBJS-$(CONFIG_DATA_PROTOCOL) += data_uri.o OBJS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpcrypt.o rtmpdigest.o rtmpdh.o OBJS-$(CONFIG_FFRTMPHTTP_PROTOCOL) += rtmphttp.o +OBJS-$(CONFIG_FFRTMPSRT_PROTOCOL) += rtmpsrt.o OBJS-$(CONFIG_FILE_PROTOCOL) += file.o OBJS-$(CONFIG_FTP_PROTOCOL) += ftp.o urldecode.o OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o @@ -638,6 +639,7 @@ OBJS-$(CONFIG_RTMPS_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o OBJS-$(CONFIG_RTMPT_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o OBJS-$(CONFIG_RTMPTE_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o OBJS-$(CONFIG_RTMPTS_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o +OBJS-$(CONFIG_RTMPSRT_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o OBJS-$(CONFIG_RTP_PROTOCOL) += rtpproto.o ip.o OBJS-$(CONFIG_SCTP_PROTOCOL) += sctp.o OBJS-$(CONFIG_SRTP_PROTOCOL) += srtpproto.o srtp.o diff --git a/libavformat/protocols.c b/libavformat/protocols.c index 4b6b1c8e98..3f848338b0 100644 --- a/libavformat/protocols.c +++ b/libavformat/protocols.c @@ -31,6 +31,7 @@ extern const URLProtocol ff_crypto_protocol; extern const URLProtocol ff_data_protocol; extern const URLProtocol ff_ffrtmpcrypt_protocol; extern const URLProtocol ff_ffrtmphttp_protocol; +extern const URLProtocol ff_ffrtmpsrt_protocol; extern const URLProtocol ff_file_protocol; extern const URLProtocol ff_ftp_protocol; extern const URLProtocol ff_gopher_protocol; @@ -51,6 +52,7 @@ extern const URLProtocol ff_rtmps_protocol; extern const URLProtocol ff_rtmpt_protocol; extern const URLProtocol ff_rtmpte_protocol; extern const URLProtocol ff_rtmpts_protocol; +extern const URLProtocol ff_rtmpsrt_protocol; extern const URLProtocol ff_rtp_protocol; extern const URLProtocol ff_sctp_protocol; extern const URLProtocol ff_srtp_protocol; diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 5a540e3240..50e41662e8 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -128,6 +128,7 @@ typedef struct RTMPContext { char auth_params[500]; int do_reconnect; int auth_tried; + int rtmp_over_srt; } RTMPContext; #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing @@ -2624,7 +2625,7 @@ static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **o } } - if (rt->listen && strcmp(proto, "rtmp")) { + if (rt->listen && strcmp(proto, "rtmp") && strcmp(proto, "rtmpsrt")) { av_log(s, AV_LOG_ERROR, "rtmp_listen not available for %s\n", proto); return AVERROR(EINVAL); @@ -2647,6 +2648,12 @@ static int rtmp_open(URLContext *s, const char *uri, int flags, AVDictionary **o /* open the encrypted connection */ ff_url_join(buf, sizeof(buf), "ffrtmpcrypt", NULL, hostname, port, NULL); rt->encrypted = 1; + } else if (!strcmp(proto, "rtmpsrt") || rt->rtmp_over_srt) { + if (rt->listen) + av_dict_set(opts, "mode", "listener", 1); + else + av_dict_set(opts, "mode", "caller", 1); + ff_url_join(buf, sizeof(buf), "ffrtmpsrt", NULL, hostname, port, "%s", path); } else { /* open the tcp connection */ if (port < 0) @@ -3116,6 +3123,7 @@ static const AVOption rtmp_options[] = { {"rtmp_listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" }, {"listen", "Listen for incoming rtmp connections", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtmp_listen" }, {"timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies -rtmp_listen 1", OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC, "rtmp_listen" }, + {"rtmp_srt", "Force RTMP over SRT", OFFSET(rtmp_over_srt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DEC|ENC}, { NULL }, }; @@ -3153,3 +3161,4 @@ RTMP_PROTOCOL(rtmps, RTMPS) RTMP_PROTOCOL(rtmpt, RTMPT) RTMP_PROTOCOL(rtmpte, RTMPTE) RTMP_PROTOCOL(rtmpts, RTMPTS) +RTMP_PROTOCOL(rtmpsrt, RTMPSRT) diff --git a/libavformat/rtmpsrt.c b/libavformat/rtmpsrt.c new file mode 100644 index 0000000000..0325973db9 --- /dev/null +++ b/libavformat/rtmpsrt.c @@ -0,0 +1,167 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "libavutil/intfloat.h" +#include "libavutil/opt.h" +#include "libavutil/time.h" +#include "internal.h" +#include "url.h" + +typedef struct RTMP_SrtContext { + const AVClass *class; + URLContext *stream; + char buf[1500]; + int buf_len; + int buf_index; + char *streamid; +} RTMP_SrtContext; + +static int rtmp_srt_open(URLContext *h, const char *uri, int flags, AVDictionary **opts) +{ + RTMP_SrtContext *s = h->priv_data; + char buf[512]; + char host[256]; + int port; + char path[1024]; + char *streamid; + char *p; + + av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, path, sizeof(path), uri); + + if (s->streamid) { + streamid = av_strdup(s->streamid); + } else { + // rtmp path: /${app}/{stream}?txSecret=${txSecret}&txTime=${txTime} + // streamid=#!::h=${rtmp-push-domain},r=${app}/${stream},txSecret=${txSecret},txTime=${txTime} + for (p = path; *p; p++) { + if (*p == '&' || *p == '?') + *p = ','; + } + if (path[0] == '/') + p = path + 1; + else + p = path; + streamid = av_asprintf("#!::h=%s,r=%s", host, p); + } + av_log(h, AV_LOG_DEBUG, "streamid %s\n", streamid ? streamid : ""); + av_dict_set(opts, "streamid", streamid, AV_DICT_DONT_STRDUP_VAL); + + av_dict_set(opts, "tlpktdrop", "0", 1); + av_dict_set(opts, "payload_size", "max_size", 1); + + ff_url_join(buf, sizeof(buf), "srt", NULL, host, port, NULL); + return ffurl_open_whitelist( + &s->stream, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback, opts, + h->protocol_whitelist, h->protocol_blacklist, h); +} + +static int read_from_buf(RTMP_SrtContext *s, unsigned char *buf, int size) +{ + int min = FFMIN(s->buf_len, size); + memcpy(buf, s->buf + s->buf_index, min); + if (min == s->buf_len) { + s->buf_len = 0; + s->buf_index = 0; + } else { + s->buf_len -= min; + s->buf_index += min; + } + return min; +} + +static int rtmp_srt_read(URLContext *h, unsigned char *buf, int size) +{ + int ret; + RTMP_SrtContext *s = h->priv_data; + if (s->buf_len > 0) { + return read_from_buf(s, buf, size); + } + + if (h->flags & AVIO_FLAG_NONBLOCK) + s->stream->flags |= AVIO_FLAG_NONBLOCK; + else + s->stream->flags &= ~AVIO_FLAG_NONBLOCK; + ret = ffurl_read(s->stream, s->buf, s->stream->max_packet_size); + if (ret < 0) { + return ret; + } + s->buf_len = ret; + s->buf_index = 0; + return read_from_buf(s, buf, size); +} + +static int rtmp_srt_write(URLContext *h, const unsigned char *buf, int size) +{ + int ret; + int n; + int len = 0; + RTMP_SrtContext *s = h->priv_data; + + if (h->flags & AVIO_FLAG_NONBLOCK) + s->stream->flags |= AVIO_FLAG_NONBLOCK; + else + s->stream->flags &= ~AVIO_FLAG_NONBLOCK; + while (size > 0) { + n = size > s->stream->max_packet_size ? s->stream->max_packet_size : size; + ret = ffurl_write(s->stream, buf + len, n); + if (ret < 0) { + return ret; + } + len += ret; + size -= ret; + } + + return len; +} + +static int rtmp_srt_close(URLContext *h) +{ + RTMP_SrtContext *s = h->priv_data; + return ffurl_closep(&s->stream); +} + +#define OFFSET(x) offsetof(RTMP_SrtContext, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +#define ENC AV_OPT_FLAG_ENCODING_PARAM + +static const AVOption ffrtmpsrt_options[] = { + // There is a streamid option in ffmpeg_opt. When libsrt is used by rtmp, + // the streamid option was passed to ffmpeg_opt and leads to error. + { "rtmpsrt_streamid", "A string of up to 512 characters that an Initiator can pass to a Responder", OFFSET(streamid), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = DEC|ENC }, + { NULL }, +}; + +static const AVClass ffrtmpsrt_class = { + .class_name = "ffrtmpsrt", + .item_name = av_default_item_name, + .option = ffrtmpsrt_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const URLProtocol ff_ffrtmpsrt_protocol = { + .name = "ffrtmpsrt", + .url_open2 = rtmp_srt_open, + .url_read = rtmp_srt_read, + .url_write = rtmp_srt_write, + .url_close = rtmp_srt_close, + .priv_data_size = sizeof(RTMP_SrtContext), + .flags = URL_PROTOCOL_FLAG_NETWORK, + .priv_data_class= &ffrtmpsrt_class, + .default_whitelist = "srt", +};