@@ -60,6 +60,8 @@ typedef struct RTPContext {
6060 char * sources ;
6161 char * block ;
6262 char * fec_options_str ;
63+ int64_t bitrate ; /* number of bits to send per second */
64+ int64_t burst_bits ;
6365} RTPContext ;
6466
6567#define OFFSET (x ) offsetof(RTPContext, x)
@@ -78,6 +80,8 @@ static const AVOption options[] = {
7880 { "sources" , "Source list" , OFFSET (sources ), AV_OPT_TYPE_STRING , { .str = NULL }, .flags = D |E },
7981 { "block" , "Block list" , OFFSET (block ), AV_OPT_TYPE_STRING , { .str = NULL }, .flags = D |E },
8082 { "fec" , "FEC" , OFFSET (fec_options_str ), AV_OPT_TYPE_STRING , { .str = NULL }, .flags = E },
83+ { "bitrate" , "Bits to send per second" , OFFSET (bitrate ), AV_OPT_TYPE_INT64 , { .i64 = 0 }, 0 , INT64_MAX , .flags = E },
84+ { "burst_bits" , "Max length of bursts in bits (when using bitrate)" , OFFSET (burst_bits ), AV_OPT_TYPE_INT64 , { .i64 = 0 }, 0 , INT64_MAX , .flags = E },
8185 { NULL }
8286};
8387
@@ -229,6 +233,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
229233 const char * p ;
230234 int i , max_retry_count = 3 ;
231235 int rtcpflags ;
236+ AVDictionary * udp_proto_options = NULL ;
232237
233238 av_url_split (NULL , 0 , NULL , 0 , hostname , sizeof (hostname ), & rtp_port ,
234239 path , sizeof (path ), uri );
@@ -281,6 +286,30 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
281286 }
282287 }
283288
289+ // AVOptions to be passed to the UDP protocol
290+ if (s -> bitrate ) {
291+ int ret = av_dict_set_int (& udp_proto_options , "bitrate" ,
292+ s -> bitrate , 0 );
293+ if (ret < 0 || !udp_proto_options ) {
294+ av_log (h , AV_LOG_ERROR , "Failed to set the bitrate option for the "
295+ "UDP protocol to value %" PRId64 " "
296+ "(error: %s)\n" ,
297+ s -> bitrate , av_err2str (ret ));
298+ goto fail ;
299+ }
300+ }
301+ if (s -> burst_bits ) {
302+ int ret = av_dict_set_int (& udp_proto_options ,
303+ "burst_bits" , s -> burst_bits , 0 );
304+ if (ret < 0 || !udp_proto_options ) {
305+ av_log (h , AV_LOG_ERROR , "Failed to set the burst_bits option for the "
306+ "UDP protocol to value %" PRId64 " "
307+ "(error: %s)\n" ,
308+ s -> burst_bits , av_err2str (ret ));
309+ goto fail ;
310+ }
311+ }
312+
284313 if (s -> fec_options_str ) {
285314 p = s -> fec_options_str ;
286315
@@ -311,8 +340,15 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
311340 hostname , rtp_port , s -> local_rtpport ,
312341 sources , block );
313342 if (ffurl_open_whitelist (& s -> rtp_hd , buf , flags , & h -> interrupt_callback ,
314- NULL , h -> protocol_whitelist , h -> protocol_blacklist , h ) < 0 )
343+ & udp_proto_options , h -> protocol_whitelist , h -> protocol_blacklist , h ) < 0 )
315344 goto fail ;
345+
346+ if (udp_proto_options && av_dict_count (udp_proto_options )) {
347+ av_log (h , AV_LOG_WARNING , "Failed to set %d AVOptions for the "
348+ "underlying UDP protocol!\n" ,
349+ av_dict_count (udp_proto_options ));
350+ }
351+
316352 s -> local_rtpport = ff_udp_get_local_port (s -> rtp_hd );
317353 if (s -> local_rtpport == 65535 ) {
318354 s -> local_rtpport = -1 ;
@@ -369,6 +405,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags)
369405 ffurl_close (s -> rtcp_hd );
370406 ffurl_closep (& s -> fec_hd );
371407 av_free (fec_protocol );
408+ av_dict_free (& udp_proto_options );
372409 av_dict_free (& fec_opts );
373410 return AVERROR (EIO );
374411}
0 commit comments