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 
42 #define FF_LIBRIST_MAKE_VERSION(major, minor, patch) \
43  ((patch) + ((minor)* 0x100) + ((major) *0x10000))
44 #define FF_LIBRIST_VERSION FF_LIBRIST_MAKE_VERSION(LIBRIST_API_VERSION_MAJOR, LIBRIST_API_VERSION_MINOR, LIBRIST_API_VERSION_PATCH)
45 #define FF_LIBRIST_VERSION_41 FF_LIBRIST_MAKE_VERSION(4, 1, 0)
46 
47 typedef struct RISTContext {
48  const AVClass *class;
49 
50  int profile;
53  int log_level;
55  char *secret;
56 
57  struct rist_logging_settings logging_settings;
58  struct rist_peer_config peer_config;
59 
60  struct rist_peer *peer;
61  struct rist_ctx *ctx;
62 } RISTContext;
63 
64 #define D AV_OPT_FLAG_DECODING_PARAM
65 #define E AV_OPT_FLAG_ENCODING_PARAM
66 #define OFFSET(x) offsetof(RISTContext, x)
67 static const AVOption librist_options[] = {
68  { "rist_profile","set profile", OFFSET(profile), AV_OPT_TYPE_INT, {.i64=RIST_PROFILE_MAIN}, 0, 2, .flags = D|E, "profile" },
69  { "simple", NULL, 0, AV_OPT_TYPE_CONST, {.i64=RIST_PROFILE_SIMPLE}, 0, 0, .flags = D|E, "profile" },
70  { "main", NULL, 0, AV_OPT_TYPE_CONST, {.i64=RIST_PROFILE_MAIN}, 0, 0, .flags = D|E, "profile" },
71  { "advanced", NULL, 0, AV_OPT_TYPE_CONST, {.i64=RIST_PROFILE_ADVANCED}, 0, 0, .flags = D|E, "profile" },
72  { "buffer_size", "set buffer_size in ms", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64=0}, 0, 30000, .flags = D|E },
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 #if FF_LIBRIST_VERSION < FF_LIBRIST_VERSION_41
157  ret = rist_parse_address(uri, (const struct rist_peer_config **)&peer_config);
158 #else
159  ret = rist_parse_address2(uri, &peer_config);
160 #endif
161  if (ret < 0)
162  goto err;
163 
164  if (((s->encryption == 128 || s->encryption == 256) && !s->secret) ||
165  ((peer_config->key_size == 128 || peer_config->key_size == 256) && !peer_config->secret[0])) {
166  av_log(h, AV_LOG_ERROR, "secret is mandatory if encryption is enabled\n");
167  librist_close(h);
168  return AVERROR(EINVAL);
169  }
170 
171  if (s->secret && peer_config->secret[0] == 0)
172  av_strlcpy(peer_config->secret, s->secret, RIST_MAX_STRING_SHORT);
173 
174  if (s->secret && (s->encryption == 128 || s->encryption == 256))
175  peer_config->key_size = s->encryption;
176 
177  if (s->buffer_size) {
178  peer_config->recovery_length_min = s->buffer_size;
179  peer_config->recovery_length_max = s->buffer_size;
180  }
181 
182  ret = rist_peer_create(s->ctx, &s->peer, &s->peer_config);
183  if (ret < 0)
184  goto err;
185 
186  ret = rist_start(s->ctx);
187  if (ret < 0)
188  goto err;
189 
190  return 0;
191 
192 err:
193  librist_close(h);
194 
195  return risterr2ret(ret);
196 }
197 
198 static int librist_read(URLContext *h, uint8_t *buf, int size)
199 {
200  RISTContext *s = h->priv_data;
201  int ret;
202 
203 #if FF_LIBRIST_VERSION < FF_LIBRIST_VERSION_41
204  const struct rist_data_block *data_block;
205  ret = rist_receiver_data_read(s->ctx, &data_block, POLLING_TIME);
206 #else
207  struct rist_data_block *data_block;
208  ret = rist_receiver_data_read2(s->ctx, &data_block, POLLING_TIME);
209 #endif
210 
211  if (ret < 0)
212  return risterr2ret(ret);
213 
214  if (ret == 0)
215  return AVERROR(EAGAIN);
216 
217  if (data_block->payload_len > MAX_PAYLOAD_SIZE) {
218 #if FF_LIBRIST_VERSION < FF_LIBRIST_VERSION_41
219  rist_receiver_data_block_free((struct rist_data_block**)&data_block);
220 #else
221  rist_receiver_data_block_free2(&data_block);
222 #endif
223  return AVERROR_EXTERNAL;
224  }
225 
226  size = data_block->payload_len;
227  memcpy(buf, data_block->payload, size);
228 #if FF_LIBRIST_VERSION < FF_LIBRIST_VERSION_41
229  rist_receiver_data_block_free((struct rist_data_block**)&data_block);
230 #else
231  rist_receiver_data_block_free2(&data_block);
232 #endif
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:186
level
uint8_t level
Definition: svq3.c:204
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:34
AV_LOG_QUIET
#define AV_LOG_QUIET
Print no output.
Definition: log.h:162
AVIO_FLAG_READ_WRITE
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition: avio.h:623
AVOption
AVOption.
Definition: opt.h:247
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
URLProtocol
Definition: url.h:54
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:58
risterr2ret
static int risterr2ret(int err)
Definition: librist.c:80
E
#define E
Definition: librist.c:65
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
s
#define s(width, name)
Definition: cbs_vp9.c:257
RISTContext::packet_size
int packet_size
Definition: librist.c:52
RISTContext::profile
int profile
Definition: librist.c:50
AVIO_FLAG_WRITE
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:622
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
OFFSET
#define OFFSET(x)
Definition: librist.c:66
RISTContext::encryption
int encryption
Definition: librist.c:54
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:66
NULL
#define NULL
Definition: coverity.c:32
librist_read
static int librist_read(URLContext *h, uint8_t *buf, int size)
Definition: librist.c:198
librist_options
static const AVOption librist_options[]
Definition: librist.c:67
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
parseutils.h
time.h
RISTContext::peer
struct rist_peer * peer
Definition: librist.c:60
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:55
D
#define D
Definition: librist.c:64
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:191
URLContext
Definition: url.h:38
RISTContext::log_level
int log_level
Definition: librist.c:53
url.h
profile
int profile
Definition: mxfenc.c:2003
RISTContext
Definition: librist.c:47
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:71
avformat.h
network.h
librist_close
static int librist_close(URLContext *h)
Definition: librist.c:109
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:224
RISTContext::buffer_size
int buffer_size
Definition: librist.c:51
librist_write
static int librist_write(URLContext *h, const uint8_t *buf, int size)
Definition: librist.c:236
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:621
RISTContext::logging_settings
struct rist_logging_settings logging_settings
Definition: librist.c:57
ff_librist_protocol
const URLProtocol ff_librist_protocol
Definition: librist.c:260
RISTContext::secret
char * secret
Definition: librist.c:55
POLLING_TIME
#define POLLING_TIME
Definition: network.h:249
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
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:83
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
librist_open
static int librist_open(URLContext *h, const char *uri, int flags)
Definition: librist.c:123
h
h
Definition: vp9dsp_template.c:2038
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:228
RISTContext::ctx
struct rist_ctx * ctx
Definition: librist.c:61
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Definition: opt.h:233