From patchwork Sun Nov 22 16:21:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yakov Okshtein X-Patchwork-Id: 23960 Delivered-To: andriy.gelman@gmail.com Received: by 2002:a25:c00a:0:0:0:0:0 with SMTP id c10csp2594630ybf; Sun, 22 Nov 2020 08:28:58 -0800 (PST) X-Google-Smtp-Source: ABdhPJyeYcy0nPFibkAlIX+q29uoQZ36Bs5wSTXQAy1E23+SRlqR2NmR5+J2n8oCUBowCGw6RYUf X-Received: by 2002:a5d:690a:: with SMTP id t10mr8170627wru.203.1606062538153; Sun, 22 Nov 2020 08:28:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1606062538; cv=none; d=google.com; s=arc-20160816; b=f7fFzVkwhwXY/+ggahhODCX0zB/UJWlw80uZ6oFeSENPqQQ7N/krKfSjUbM44kyT13 pOSm+GkyrNDxdar1Nxh6y5ZXCNRqJaXzTykCqLxBmDW4uMEUtFKWdm6wb4cV84P8BUJE gLxYqbuT4S2wqv9gtOkssBd/6uHqIvaE54jMZP3PIqV4BkzvqLF1BPvc2TBLkMyCLsp3 RLGMf/QXsqVP+iWzE6ppLgKEUoinK+yxZgX47/TDNNbmkP4yqmfabNdj2WcoPwXbwGgq IyhCRD4UEWkWxpK2bR4vKMJB9LNYA2vpbeioM1pdCpXwAIXXx91gBNdQYClYOuqjzMpT DeFg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject:to :message-id:date:from:mime-version:dkim-signature:delivered-to; bh=ASKBImNbCYFu5JQVwfd5IbRnvP2Wn01Za4CNZBYme7s=; b=VintEQiE+VHprUqH5OxPTq+P6TJl41wEv6UqzKJsXLYixkdrjQCE54CCLMoFrUmP1v PL0D3fuWfEcdyyMnWlqD0f1OwQUDYJwrtzgqxvMRlNEw45+EpEFVSxA75IonBtvHU9uH 4fDnbbXcZLo0A27q0IuTHzrJ62rJPuLacwz3O2YEk3U2sjSYe3pPZZebrmlF46de8h36 nC/2FCDyhtiYK8bmXVcMFUVkonkV04L0VKH9YThFpIJ/2ciI8l1lnYNn2W2/Nu4JDiYY PV4B7diZo9fWeMUc3g19RgMkeSyxptJY6kOkRXVoikw501eOoSv0QMIvlY+mgkGsGKqg K/Pg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=bVYkbbLu; 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=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id t130si8694628wmf.69.2020.11.22.08.28.56; Sun, 22 Nov 2020 08:28:58 -0800 (PST) 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=@gmail.com header.s=20161025 header.b=bVYkbbLu; 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=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 070A568B844; Sun, 22 Nov 2020 18:28:55 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f47.google.com (mail-wr1-f47.google.com [209.85.221.47]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8AED968B844 for ; Sun, 22 Nov 2020 18:28:48 +0200 (EET) Received: by mail-wr1-f47.google.com with SMTP id k2so16139304wrx.2 for ; Sun, 22 Nov 2020 08:28:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:reply-to:from:date:message-id:subject:to; bh=XHjyM1GObAAKiwMIzQvu7TaRYn2BmHoXbMv0lsvHP+s=; b=bVYkbbLuhz9MQWfQsrcSw9BSISLSOHeQy7FxeEuAAZLZguE4KzJBqEGvLnzcM2ykNv 8B1M5Po/KeRRHNrdGteX6oS5J2nP6/uHvi6oG/lqHH1mDGqvwNFC/g2CPIgYOibOID9j yPKZOik3O2dwP7X36tpdmUhIKJpWKUKVHcDD4zP3t/787npeEWh3VQZNTDSEBkDBECh6 tnB03s3l1UnDt6AriD9svlgCcrIec/kftHM964OagLdgiX01gHiCrvGEWpwloRgHue/r bn4E26lb7+TdinB7gqKoMc6GoLBcycLzz79SzdVX0g53DOmBpdaftyMvqemqCiyovVWh DXWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:reply-to:from:date:message-id :subject:to; bh=XHjyM1GObAAKiwMIzQvu7TaRYn2BmHoXbMv0lsvHP+s=; b=qQOk6bzIi5XPLs2xEDTiqks9LhVv1bjXh45xPnyaU+/bWbGxSLymQ7OAMAy9oB9oc6 6WTV6M+9+yifBqmxFCP8xWTNK7gDoLZS4kx8Q2hx+bf9nR4SQEkwkkpXEs098q3EapdL yvdwd+IEuWdSzoqkNoO0blQe/vWW58bnPDqgZk/Wjxy8y/PujBA264psysRmwtwet6b7 CiQACVjFURJvSphK1HgcisL0QQIT5MfZaVop06vPLXocA2nee8VFvVNP9+54WI03UwXV 4kXo6MwdVuGjO2+yl46QRvcCvgtEJcWUbP8ESJ78hH9uNtCvnT3M3wU5gW/5QrKjG6Uo tGQw== X-Gm-Message-State: AOAM530H+muk7VQqz8luhTXF6STg7qIxhbencg7VBuhIMgTp7n+4VY8X sX5F/cG2g3m5rrIm5qYTf6a6GWW8DmDkCuXS1pkt/MZKsAs= X-Received: by 2002:a05:6000:11c2:: with SMTP id i2mr24768785wrx.21.1606062115054; Sun, 22 Nov 2020 08:21:55 -0800 (PST) MIME-Version: 1.0 From: Yakov Okshtein Date: Sun, 22 Nov 2020 11:21:39 -0500 Message-ID: To: ffmpeg-devel@ffmpeg.org X-Content-Filtered-By: Mailman/MimeDel 2.1.20 Subject: [FFmpeg-devel] Add RTSP range header X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: RGFqAZlrXgHU Hi all, While working to get historical video off a DVR, I found the lack of a customizable Range: header for RTSP video frustrating (as, apparently, have others on StackOverflow and the Trac wiki, #6659). One user mentionedhaving made a custom patch, but didn't post it; so, I decided to make one. It's my first submission to ffmpeg. I read the submission guidelines and hope I didn't miss anything. Thanks all! Yakov Subject: [PATCH] Add optional Range and Rate-Control header to RTSP PLAY command Some DVR/NVRs send historical video specified by the Range: header, and can send files faster than real-time by the presence of the Rate-Control: no header. This patch adds optional -range and -rate_control CLI arguments, and if present, uses those values to override the defaults. Closes #6659 --- libavformat/rtsp.c | 2 ++ libavformat/rtsp.h | 10 ++++++++++ libavformat/rtspdec.c | 15 +++++++++++---- libavformat/rtspenc.c | 9 +++++++-- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 0be405aba1..ca0b92251c 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -101,6 +101,8 @@ const AVOption ff_rtsp_options[] = { #endif COMMON_OPTS(), { "user_agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC }, + { "range", "override Range header", OFFSET(range), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC }, + { "rate_control", "override Rate-Control header", OFFSET(rate_control), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC }, #if FF_API_OLD_RTSP_OPTIONS { "user-agent", "override User-Agent header (deprecated, use user_agent)", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC }, #endif diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 251ed86d19..0778515045 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -409,6 +409,16 @@ typedef struct RTSPState { */ char *user_agent; + /** + * Range header override; string. + */ + char *range; + + /** + * Rate-Control header; optional string. + */ + char *rate_control; + char default_lang[4]; int buffer_size; int pkt_size; diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 28b35d1993..0a0de21b82 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -541,11 +541,18 @@ static int rtsp_read_play(AVFormatContext *s) if (rt->state == RTSP_STATE_PAUSED) { cmd[0] = 0; } else { - snprintf(cmd, sizeof(cmd), - "Range: npt=%"PRId64".%03"PRId64"-\r\n", - rt->seek_timestamp / AV_TIME_BASE, - rt->seek_timestamp / (AV_TIME_BASE / 1000) % 1000); + if (rt->range != NULL) { + snprintf(cmd, sizeof(cmd), "Range: %s\r\n", rt->range); + } else { + snprintf(cmd, sizeof(cmd), + "Range: npt=%"PRId64".%03"PRId64"-\r\n", + rt->seek_timestamp / AV_TIME_BASE, + rt->seek_timestamp / (AV_TIME_BASE / 1000) % 1000); + } } + if (rt->rate_control != NULL) { + snprintf(cmd, sizeof(cmd), "Rate-Control: %s\r\n", rt->rate_control); + } ff_rtsp_send_cmd(s, "PLAY", rt->control_uri, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) { return ff_rtsp_averror(reply->status_code, -1); diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index d50544456d..1b7281cc67 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -113,8 +113,13 @@ static int rtsp_write_record(AVFormatContext *s) RTSPMessageHeader reply1, *reply = &reply1; char cmd[1024]; - snprintf(cmd, sizeof(cmd), - "Range: npt=0.000-\r\n"); + if (rt->range != NULL) { + snprintf(cmd, sizeof(cmd), + "Range: %s\r\n", rt->range); + } else { + snprintf(cmd, sizeof(cmd), + "Range: npt=0.0000-\r\n"); + } ff_rtsp_send_cmd(s, "RECORD", rt->control_uri, cmd, reply, NULL); if (reply->status_code != RTSP_STATUS_OK) return ff_rtsp_averror(reply->status_code, -1);