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  ret = rist_logging_set(&logging_settings, s->log_level, log_cb, h, NULL, NULL);
134  if (ret < 0)
135  return risterr2ret(ret);
136 
137  if (flags & AVIO_FLAG_WRITE) {
138  h->max_packet_size = s->packet_size;
139  ret = rist_sender_create(&s->ctx, s->profile, 0, logging_settings);
140  }
141  if (ret < 0)
142  goto err;
143 
144  if (flags & AVIO_FLAG_READ) {
145  h->max_packet_size = MAX_PAYLOAD_SIZE;
146  ret = rist_receiver_create(&s->ctx, s->profile, logging_settings);
147  }
148  if (ret < 0)
149  goto err;
150 
151  ret = rist_peer_config_defaults_set(peer_config);
152  if (ret < 0)
153  goto err;
154 
155 #if FF_LIBRIST_VERSION < FF_LIBRIST_VERSION_41
156  ret = rist_parse_address(uri, (const struct rist_peer_config **)&peer_config);
157 #else
158  ret = rist_parse_address2(uri, &peer_config);
159 #endif
160  if (ret < 0)
161  goto err;
162 
163  if (((s->encryption == 128 || s->encryption == 256) && !s->secret) ||
164  ((peer_config->key_size == 128 || peer_config->key_size == 256) && !peer_config->secret[0])) {
165  av_log(h, AV_LOG_ERROR, "secret is mandatory if encryption is enabled\n");
166  librist_close(h);
167  return AVERROR(EINVAL);
168  }
169 
170  if (s->secret && peer_config->secret[0] == 0)
171  av_strlcpy(peer_config->secret, s->secret, RIST_MAX_STRING_SHORT);
172 
173  if (s->secret && (s->encryption == 128 || s->encryption == 256))
174  peer_config->key_size = s->encryption;
175 
176  if (s->buffer_size) {
177  peer_config->recovery_length_min = s->buffer_size;
178  peer_config->recovery_length_max = s->buffer_size;
179  }
180 
181  ret = rist_peer_create(s->ctx, &s->peer, &s->peer_config);
182  if (ret < 0)
183  goto err;
184 
185  ret = rist_start(s->ctx);
186  if (ret < 0)
187  goto err;
188 
189  return 0;
190 
191 err:
192  librist_close(h);
193 
194  return risterr2ret(ret);
195 }
196 
197 static int librist_read(URLContext *h, uint8_t *buf, int size)
198 {
199  RISTContext *s = h->priv_data;
200  int ret;
201 
202 #if FF_LIBRIST_VERSION < FF_LIBRIST_VERSION_41
203  const struct rist_data_block *data_block;
204  ret = rist_receiver_data_read(s->ctx, &data_block, POLLING_TIME);
205 #else
206  struct rist_data_block *data_block;
207  ret = rist_receiver_data_read2(s->ctx, &data_block, POLLING_TIME);
208 #endif
209 
210  if (ret < 0)
211  return risterr2ret(ret);
212 
213  if (ret == 0)
214  return AVERROR(EAGAIN);
215 
216  if (data_block->payload_len > MAX_PAYLOAD_SIZE) {
217 #if FF_LIBRIST_VERSION < FF_LIBRIST_VERSION_41
218  rist_receiver_data_block_free((struct rist_data_block**)&data_block);
219 #else
220  rist_receiver_data_block_free2(&data_block);
221 #endif
222  return AVERROR_EXTERNAL;
223  }
224 
225  size = data_block->payload_len;
226  memcpy(buf, data_block->payload, size);
227 #if FF_LIBRIST_VERSION < FF_LIBRIST_VERSION_41
228  rist_receiver_data_block_free((struct rist_data_block**)&data_block);
229 #else
230  rist_receiver_data_block_free2(&data_block);
231 #endif
232  return size;
233 }
234 
235 static int librist_write(URLContext *h, const uint8_t *buf, int size)
236 {
237  RISTContext *s = h->priv_data;
238  struct rist_data_block data_block = { 0 };
239  int ret;
240 
241  data_block.ts_ntp = 0;
242  data_block.payload = buf;
243  data_block.payload_len = size;
244 
245  ret = rist_sender_data_write(s->ctx, &data_block);
246  if (ret < 0)
247  return risterr2ret(ret);
248 
249  return ret;
250 }
251 
252 static const AVClass librist_class = {
253  .class_name = "librist",
254  .item_name = av_default_item_name,
255  .option = librist_options,
256  .version = LIBAVUTIL_VERSION_INT,
257 };
258 
260  .name = "rist",
261  .url_open = librist_open,
262  .url_read = librist_read,
263  .url_write = librist_write,
264  .url_close = librist_close,
265  .priv_data_size = sizeof(RISTContext),
267  .priv_data_class = &librist_class,
268 };
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:605
profile
mfxU16 profile
Definition: qsvenc.c:45
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:252
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:604
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:197
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
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:235
AVIO_FLAG_READ
#define AVIO_FLAG_READ
read-only
Definition: avio.h:603
RISTContext::logging_settings
struct rist_logging_settings logging_settings
Definition: librist.c:57
ff_librist_protocol
const URLProtocol ff_librist_protocol
Definition: librist.c:259
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