FFmpeg
librist.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /**
20  * @file
21  * Reliable Internet Streaming Transport protocol
22  */
23 
24 #include "libavutil/avassert.h"
25 #include "libavutil/avstring.h"
26 #include "libavutil/opt.h"
27 #include "libavutil/parseutils.h"
28 #include "libavutil/time.h"
29 
30 #include "avformat.h"
31 #include "internal.h"
32 #include "network.h"
33 #include "os_support.h"
34 #include "url.h"
35 
36 #include <librist/librist.h>
37 #include <librist/version.h>
38 
39 // RIST_MAX_PACKET_SIZE - 28 minimum protocol overhead
40 #define MAX_PAYLOAD_SIZE (10000-28)
41 #define FIFO_SIZE_DEFAULT 8192
42 
43 typedef struct RISTContext {
44  const AVClass *class;
45 
46  int profile;
49  int log_level;
51  int fifo_size;
53  char *secret;
54 
55  struct rist_logging_settings logging_settings;
56  struct rist_peer_config peer_config;
57 
58  struct rist_peer *peer;
59  struct rist_ctx *ctx;
60 } RISTContext;
61 
62 #define D AV_OPT_FLAG_DECODING_PARAM
63 #define E AV_OPT_FLAG_ENCODING_PARAM
64 #define OFFSET(x) offsetof(RISTContext, x)
65 static const AVOption librist_options[] = {
66  { "rist_profile","set profile", OFFSET(profile), AV_OPT_TYPE_INT, {.i64=RIST_PROFILE_MAIN}, 0, 2, .flags = D|E, .unit = "profile" },
67  { "simple", NULL, 0, AV_OPT_TYPE_CONST, {.i64=RIST_PROFILE_SIMPLE}, 0, 0, .flags = D|E, .unit = "profile" },
68  { "main", NULL, 0, AV_OPT_TYPE_CONST, {.i64=RIST_PROFILE_MAIN}, 0, 0, .flags = D|E, .unit = "profile" },
69  { "advanced", NULL, 0, AV_OPT_TYPE_CONST, {.i64=RIST_PROFILE_ADVANCED}, 0, 0, .flags = D|E, .unit = "profile" },
70  { "buffer_size", "set buffer_size in ms", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64=0}, 0, 30000, .flags = D|E },
71  { "fifo_size", "set fifo buffer size, must be a power of 2", OFFSET(fifo_size), AV_OPT_TYPE_INT, {.i64=FIFO_SIZE_DEFAULT}, 32, 262144, .flags = D|E },
72  { "overrun_nonfatal", "survive in case of receiving fifo buffer overrun", OFFSET(overrun_nonfatal), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, D },
73  { "pkt_size", "set packet size", OFFSET(packet_size), AV_OPT_TYPE_INT, {.i64=1316}, 1, MAX_PAYLOAD_SIZE, .flags = D|E },
74  { "log_level", "set loglevel", OFFSET(log_level), AV_OPT_TYPE_INT, {.i64=RIST_LOG_INFO}, -1, INT_MAX, .flags = D|E },
75  { "secret", "set encryption secret",OFFSET(secret), AV_OPT_TYPE_STRING,{.str=NULL}, 0, 0, .flags = D|E },
76  { "encryption","set encryption type",OFFSET(encryption), AV_OPT_TYPE_INT ,{.i64=0}, 0, INT_MAX, .flags = D|E },
77  { NULL }
78 };
79 
80 static int risterr2ret(int err)
81 {
82  switch (err) {
83  case RIST_ERR_MALLOC:
84  return AVERROR(ENOMEM);
85  default:
86  return AVERROR_EXTERNAL;
87  }
88 }
89 
90 static int log_cb(void *arg, enum rist_log_level log_level, const char *msg)
91 {
92  int level;
93 
94  switch (log_level) {
95  case RIST_LOG_ERROR: level = AV_LOG_ERROR; break;
96  case RIST_LOG_WARN: level = AV_LOG_WARNING; break;
97  case RIST_LOG_NOTICE: level = AV_LOG_INFO; break;
98  case RIST_LOG_INFO: level = AV_LOG_VERBOSE; break;
99  case RIST_LOG_DEBUG: level = AV_LOG_DEBUG; break;
100  case RIST_LOG_DISABLE: level = AV_LOG_QUIET; break;
101  default: level = AV_LOG_WARNING;
102  }
103 
104  av_log(arg, level, "%s", msg);
105 
106  return 0;
107 }
108 
110 {
111  RISTContext *s = h->priv_data;
112  int ret = 0;
113 
114  s->peer = NULL;
115 
116  if (s->ctx)
117  ret = rist_destroy(s->ctx);
118  s->ctx = NULL;
119 
120  return risterr2ret(ret);
121 }
122 
123 static int librist_open(URLContext *h, const char *uri, int flags)
124 {
125  RISTContext *s = h->priv_data;
126  struct rist_logging_settings *logging_settings = &s->logging_settings;
127  struct rist_peer_config *peer_config = &s->peer_config;
128  int ret;
129 
131  return AVERROR(EINVAL);
132 
133  s->logging_settings = (struct rist_logging_settings)LOGGING_SETTINGS_INITIALIZER;
134  ret = rist_logging_set(&logging_settings, s->log_level, log_cb, h, NULL, NULL);
135  if (ret < 0)
136  return risterr2ret(ret);
137 
138  if (flags & AVIO_FLAG_WRITE) {
139  h->max_packet_size = s->packet_size;
140  ret = rist_sender_create(&s->ctx, s->profile, 0, logging_settings);
141  }
142  if (ret < 0)
143  goto err;
144 
145  if (flags & AVIO_FLAG_READ) {
146  h->max_packet_size = MAX_PAYLOAD_SIZE;
147  ret = rist_receiver_create(&s->ctx, s->profile, logging_settings);
148  }
149  if (ret < 0)
150  goto err;
151 
152  ret = rist_peer_config_defaults_set(peer_config);
153  if (ret < 0)
154  goto err;
155 
156  ret = rist_parse_address2(uri, &peer_config);
157  if (ret < 0)
158  goto err;
159 
160  if (flags & AVIO_FLAG_READ) {
161  ret = rist_receiver_set_output_fifo_size(s->ctx, s->fifo_size);
162  if (ret != 0)
163  goto err;
164  }
165 
166  if (((s->encryption == 128 || s->encryption == 256) && !s->secret) ||
167  ((peer_config->key_size == 128 || peer_config->key_size == 256) && !peer_config->secret[0])) {
168  av_log(h, AV_LOG_ERROR, "secret is mandatory if encryption is enabled\n");
169  librist_close(h);
170  return AVERROR(EINVAL);
171  }
172 
173  if (s->secret && peer_config->secret[0] == 0)
174  av_strlcpy(peer_config->secret, s->secret, RIST_MAX_STRING_SHORT);
175 
176  if (s->secret && (s->encryption == 128 || s->encryption == 256))
177  peer_config->key_size = s->encryption;
178 
179  if (s->buffer_size) {
180  peer_config->recovery_length_min = s->buffer_size;
181  peer_config->recovery_length_max = s->buffer_size;
182  }
183 
184  ret = rist_peer_create(s->ctx, &s->peer, &s->peer_config);
185  if (ret < 0)
186  goto err;
187 
188  ret = rist_start(s->ctx);
189  if (ret < 0)
190  goto err;
191 
192  return 0;
193 
194 err:
195  librist_close(h);
196 
197  return risterr2ret(ret);
198 }
199 
200 static int librist_read(URLContext *h, uint8_t *buf, int size)
201 {
202  RISTContext *s = h->priv_data;
203  int ret;
204 
205  struct rist_data_block *data_block;
206  ret = rist_receiver_data_read2(s->ctx, &data_block, POLLING_TIME);
207 
208  if (ret < 0)
209  return risterr2ret(ret);
210 
211  if (ret == 0)
212  return AVERROR(EAGAIN);
213 
214  if (data_block->payload_len > MAX_PAYLOAD_SIZE) {
215  rist_receiver_data_block_free2(&data_block);
216  return AVERROR_EXTERNAL;
217  }
218 
219  if (data_block->flags & RIST_DATA_FLAGS_OVERFLOW) {
220  if (!s->overrun_nonfatal) {
221  av_log(h, AV_LOG_ERROR, "Fifo buffer overrun. "
222  "To avoid, increase fifo_size option. "
223  "To survive in such case, use overrun_nonfatal option\n");
224  size = AVERROR(EIO);
225  goto out_free;
226  }
227  }
228 
229  size = data_block->payload_len;
230  memcpy(buf, data_block->payload, size);
231 out_free:
232  rist_receiver_data_block_free2(&data_block);
233  return size;
234 }
235 
236 static int librist_write(URLContext *h, const uint8_t *buf, int size)
237 {
238  RISTContext *s = h->priv_data;
239  struct rist_data_block data_block = { 0 };
240  int ret;
241 
242  data_block.ts_ntp = 0;
243  data_block.payload = buf;
244  data_block.payload_len = size;
245 
246  ret = rist_sender_data_write(s->ctx, &data_block);
247  if (ret < 0)
248  return risterr2ret(ret);
249 
250  return ret;
251 }
252 
253 static const AVClass librist_class = {
254  .class_name = "librist",
255  .item_name = av_default_item_name,
256  .option = librist_options,
257  .version = LIBAVUTIL_VERSION_INT,
258 };
259 
261  .name = "rist",
262  .url_open = librist_open,
263  .url_read = librist_read,
264  .url_write = librist_write,
265  .url_close = librist_close,
266  .priv_data_size = sizeof(RISTContext),
268  .priv_data_class = &librist_class,
269 };
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:215
level
uint8_t level
Definition: svq3.c:205
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
log_cb
static int log_cb(void *arg, enum rist_log_level log_level, const char *msg)
Definition: librist.c:90
URL_PROTOCOL_FLAG_NETWORK
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:33
AV_LOG_QUIET
#define AV_LOG_QUIET
Print no output.
Definition: log.h:191
AVIO_FLAG_READ_WRITE
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition: avio.h:619
RISTContext::fifo_size
int fifo_size
Definition: librist.c:51
AVOption
AVOption.
Definition: opt.h:429
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:225
URLProtocol
Definition: url.h:51
os_support.h
librist_class
static const AVClass librist_class
Definition: librist.c:253
RISTContext::peer_config
struct rist_peer_config peer_config
Definition: librist.c:56
risterr2ret
static int risterr2ret(int err)
Definition: librist.c:80
E
#define E
Definition: librist.c:63
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
s
#define s(width, name)
Definition: cbs_vp9.c:198
RISTContext::packet_size
int packet_size
Definition: librist.c:48
RISTContext::profile
int profile
Definition: librist.c:46
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:618
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
OFFSET
#define OFFSET(x)
Definition: librist.c:64
RISTContext::encryption
int encryption
Definition: librist.c:50
arg
const char * arg
Definition: jacosubdec.c:67
internal.h
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
NULL
#define NULL
Definition: coverity.c:32
librist_read
static int librist_read(URLContext *h, uint8_t *buf, int size)
Definition: librist.c:200
librist_options
static const AVOption librist_options[]
Definition: librist.c:65
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
parseutils.h
time.h
RISTContext::overrun_nonfatal
int overrun_nonfatal
Definition: librist.c:52
RISTContext::peer
struct rist_peer * peer
Definition: librist.c:58
MAX_PAYLOAD_SIZE
#define MAX_PAYLOAD_SIZE
Definition: librist.c:40
size
int size
Definition: twinvq_data.h:10344
URLProtocol::name
const char * name
Definition: url.h:52
D
#define D
Definition: librist.c:62
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:220
URLContext
Definition: url.h:35
RISTContext::log_level
int log_level
Definition: librist.c:49
url.h
profile
int profile
Definition: mxfenc.c:2233
RISTContext
Definition: librist.c:43
ret
ret
Definition: filter_design.txt:187
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:80
avformat.h
network.h
librist_close
static int librist_close(URLContext *h)
Definition: librist.c:109
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
RISTContext::buffer_size
int buffer_size
Definition: librist.c:47
librist_write
static int librist_write(URLContext *h, const uint8_t *buf, int size)
Definition: librist.c:236
FIFO_SIZE_DEFAULT
#define FIFO_SIZE_DEFAULT
Definition: librist.c:41
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:617
RISTContext::logging_settings
struct rist_logging_settings logging_settings
Definition: librist.c:55
ff_librist_protocol
const URLProtocol ff_librist_protocol
Definition: librist.c:260
RISTContext::secret
char * secret
Definition: librist.c:53
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
POLLING_TIME
#define POLLING_TIME
Definition: network.h:249
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
av_strlcpy
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:85
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
librist_open
static int librist_open(URLContext *h, const char *uri, int flags)
Definition: librist.c:123
h
h
Definition: vp9dsp_template.c:2070
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
RISTContext::ctx
struct rist_ctx * ctx
Definition: librist.c:59
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:299
fifo_size
size_t fifo_size
Definition: dts2pts.c:371