[FFmpeg-devel] Add RTSP range header
Yakov Okshtein
flyashi at gmail.com
Mon Nov 23 03:51:51 EET 2020
Whoops, looks like Gmail sent the .patch file attachment as
application/octet-stream ... I must say, the ffmpeg binary is much more
lenient in its input than the ffmpeg-devel mailing list :)
Let me try again with Thunderbird, and a .txt file.
Thanks all,
Yakov
On 11/22/20 11:21 AM, Yakov Okshtein wrote:
> 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
-------------- next part --------------
From 1c0a5ce96eef83bb3ed55a4dfa6e825668055cdb Mon Sep 17 00:00:00 2001
From: Yakov Okshtein <flyashi at gmail.com>
Date: Sun, 22 Nov 2020 16:06:46 +0000
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);
--
2.25.1
More information about the ffmpeg-devel
mailing list