UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
transmit.cpp
Go to the documentation of this file.
1/*
2 * FILE: transmit.cpp
3 * AUTHOR: Colin Perkins <csp@csperkins.org>
4 * Ladan Gharai
5 * Martin Benes <martinbenesh@gmail.com>
6 * Lukas Hejtmanek <xhejtman@ics.muni.cz>
7 * Petr Holub <hopet@ics.muni.cz>
8 * Milos Liska <xliska@fi.muni.cz>
9 * Jiri Matela <matela@ics.muni.cz>
10 * Dalibor Matura <255899@mail.muni.cz>
11 * Ian Wesley-Smith <iwsmith@cct.lsu.edu>
12 * David Cassany <david.cassany@i2cat.net>
13 * Ignacio Contreras <ignacio.contreras@i2cat.net>
14 * Gerard Castillo <gerard.castillo@i2cat.net>
15 * Jordi "Txor" Casas Ríos <txorlings@gmail.com>
16 * Martin Pulec <pulec@cesnet.cz>
17 *
18 * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya
19 * Copyright (c) 2001-2004 University of Southern California
20 * Copyright (c) 2005-2023 CESNET z.s.p.o.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, is permitted provided that the following conditions
24 * are met:
25 *
26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer.
28 *
29 * 2. Redistributions in binary form must reproduce the above copyright
30 * notice, this list of conditions and the following disclaimer in the
31 * documentation and/or other materials provided with the distribution.
32 *
33 * 3. All advertising materials mentioning features or use of this software
34 * must display the following acknowledgement:
35 *
36 * This product includes software developed by the University of Southern
37 * California Information Sciences Institute. This product also includes
38 * software developed by CESNET z.s.p.o.
39 *
40 * 4. Neither the name of the University, Institute, CESNET nor the names of
41 * its contributors may be used to endorse or promote products derived from
42 * this software without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
45 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
46 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
47 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
48 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
49 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
50 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
51 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
53 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
54 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
55 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 *
57 */
58
59#include <algorithm>
60#include <array>
61#include <iostream>
62#include <sstream>
63#include <vector>
64
65#include "audio/codec.h"
66#include "audio/types.h"
67#include "audio/utils.h"
68#include "control_socket.h"
70#include "debug.h"
71#include "host.h"
72#include "lib_common.h"
73#include "module.h"
74#include "rtp/fec.h"
75#include "rtp/rtp.h"
76#include "rtp/rtp_callback.h"
77#include "rtp/rtpenc_h264.h"
78#include "transmit.h"
79#include "tv.h"
80#include "types.h"
81#include "utils/jpeg_reader.h"
82#include "utils/macros.h"
83#include "utils/misc.h" // unit_evaluate
84#include "utils/random.h"
85#include "video.h"
86#include "video_codec.h"
87
88#define MOD_NAME "[transmit] "
89#define TRANSMIT_MAGIC 0xe80ab15f
90
91#define FEC_MAX_MULT 10
92
93#define CONTROL_PORT_BANDWIDTH_REPORT_INTERVAL_NS NS_IN_SEC
94
95#ifdef __APPLE__
96#define GET_STARTTIME gettimeofday(&start, NULL)
97#define GET_STOPTIME gettimeofday(&stop, NULL)
98#define GET_DELTA delta = (stop.tv_sec - start.tv_sec) * 1000000000l + (stop.tv_usec - start.tv_usec) * 1000L
99#elif defined __linux__
100#define GET_STARTTIME clock_gettime(CLOCK_REALTIME, &start)
101#define GET_STOPTIME clock_gettime(CLOCK_REALTIME, &stop)
102#define GET_DELTA delta = (stop.tv_sec - start.tv_sec) * 1000000000l + stop.tv_nsec - start.tv_nsec
103#else // Windows
104#define GET_STARTTIME {QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&start); }
105#define GET_STOPTIME { QueryPerformanceCounter(&stop); }
106#define GET_DELTA delta = (long)((double)(stop.QuadPart - start.QuadPart) * 1000 * 1000 * 1000 / freq.QuadPart);
107#endif
108
109using std::array;
110using std::vector;
111
112static void tx_update(struct tx *tx, struct video_frame *frame, int substream);
113static void tx_done(struct module *tx);
114static uint32_t format_interl_fps_hdr_row(enum interlacing_t interlacing, double input_fps);
115
116static void
117tx_send_base(struct tx *tx, struct video_frame *frame, struct rtp *rtp_session,
118 uint32_t ts, int send_m,
119 unsigned int substream,
120 int fragment_offset);
121
122
123static bool set_fec(struct tx *tx, const char *fec);
124static void fec_check_messages(struct tx *tx);
125
127 unsigned long avg_frame_size;
128 long long last_excess;
129 static constexpr int EXCESS_GAP = 4;
130};
131
132struct tx {
133 struct module mod;
134
135 uint32_t magic;
137 unsigned mtu;
138 double max_loss;
139
140 uint32_t last_ts;
142
143 unsigned int buffer:22;
144 unsigned long int sent_frames;
145 int32_t avg_len;
147
151
153
154 struct control_state *control = nullptr;
156 uint64_t last_stat_report = 0;
157
160 long long int bitrate;
162
164};
165
166static void tx_update(struct tx *tx, struct video_frame *frame, int substream)
167{
168 if(!frame) {
169 return;
170 }
171
172 uint64_t tmp_avg = tx->avg_len * tx->sent_frames + frame->tiles[substream].data_len *
174 (double) frame->fec_params.k / (frame->fec_params.k + frame->fec_params.m) :
175 1);
176 tx->sent_frames++;
177 tx->avg_len = tmp_avg / tx->sent_frames;
178 if(tx->sent_frames >= 100) {
179 if(tx->fec_scheme == FEC_LDGM && tx->max_loss > 0.0) {
180 if(abs(tx->avg_len_last - tx->avg_len) > tx->avg_len / 3) {
181 int data_len = tx->mtu - (40 + (sizeof(fec_payload_hdr_t)));
182 data_len = (data_len / 48) * 48;
183 //void *fec_state_old = tx->fec_state;
184
185 struct msg_sender *msg = (struct msg_sender *)
186 new_message(sizeof(struct msg_sender));
187 snprintf(msg->fec_cfg, sizeof(msg->fec_cfg), "LDGM percents %d %d %f",
188 data_len, tx->avg_len, tx->max_loss);
191 (struct message *) msg);
192 free_response(resp);
194 }
195 }
196 tx->avg_len = 0;
197 tx->sent_frames = 0;
198 }
199}
200
201struct tx *tx_init(struct module *parent, unsigned mtu, enum tx_media_type media_type,
202 const char *fec, const char *encryption, long long int bitrate)
203{
204 if (mtu > RTP_MAX_MTU) {
205 log_msg(LOG_LEVEL_ERROR, "Requested MTU exceeds maximal value allowed by RTP library (%d B).\n", RTP_MAX_MTU);
206 return NULL;
207 }
208
209 if (bitrate < RATE_MIN) {
210 log_msg(LOG_LEVEL_ERROR, "Invalid bitrate value %lld passed (either positive bitrate or magic values from %d supported)!\n", bitrate, RATE_MIN);
211 return NULL;
212 }
213
214 struct tx *tx = (struct tx *) calloc(1, sizeof(struct tx));
215 if (tx == nullptr) {
216 return tx;
217 }
220 tx->mod.priv_data = tx;
223
226 tx->mult_count = 1;
227 tx->max_loss = 0.0;
228 tx->mtu = mtu;
229 tx->buffer = ug_rand() & 0x3fffff;
233 if (fec) {
234 if(!set_fec(tx, fec)) {
235 module_done(&tx->mod);
236 return NULL;
237 }
238 }
239 if (strlen(encryption) > 0) {
240 tx->enc_funcs = static_cast<const struct openssl_encrypt_info *>(load_library("openssl_encrypt",
242 if (!tx->enc_funcs) {
243 fprintf(stderr, "UltraGrid was build without OpenSSL support!\n");
244 module_done(&tx->mod);
245 return NULL;
246 }
247 if (tx->enc_funcs->init(&tx->encryption,
248 encryption) != 0) {
249 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to initialize encryption\n");
250 module_done(&tx->mod);
251 return NULL;
252 }
253 }
254
255 tx->bitrate = bitrate;
256
257 if(parent)
258 tx->control = (struct control_state *) get_module(get_root_module(parent), "control");
259
260 return tx;
261}
262
263static bool set_fec(struct tx *tx, const char *fec_const)
264{
265 char *fec = strdup(fec_const);
266 bool ret = true;
267 bool req_1st_pkt_dup = true;
268
269 // handle ...[:]nodup
270 char *end = fec + MAX(strlen(fec), 5) - 5;
271 if (strcmp(end, "nodup") == 0) {
272 req_1st_pkt_dup = true;
273 *end = '\0';
274 if (end > fec) { // ':'
275 end[-1] = '\0';
276 }
277 }
278
279 const char *fec_cfg = "";
280 if(strchr(fec, ':')) {
281 char *delim = strchr(fec, ':');
282 *delim = '\0';
283 fec_cfg = delim + 1;
284 }
285
286 struct msg_sender *msg = (struct msg_sender *)
287 new_message(sizeof(struct msg_sender));
289
290 snprintf(msg->fec_cfg, sizeof(msg->fec_cfg), "flush");
291
292 tx->mult_count = 1; // default
293 if (strcasecmp(fec, "none") == 0) {
295 } else if(strcasecmp(fec, "mult") == 0) {
297 tx->mult_count = atoi(fec_cfg);
298 if (tx->mult_count <= 0 || tx->mult_count > FEC_MAX_MULT) {
299 MSG(ERROR,
300 "mult count must be between 1 and %d (%d given)!\n",
302 ret = false;
303 }
304 } else if(strcasecmp(fec, "LDGM") == 0) {
305 tx->fec_dup_1st_pkt = req_1st_pkt_dup;
307 fprintf(stderr, "LDGM is not currently supported for audio!\n");
308 ret = false;
309 } else {
310 if (strlen(fec_cfg) == 0 ||
311 (strlen(fec_cfg) > 0 &&
312 strchr(fec_cfg, '%') == nullptr)) {
313 snprintf(msg->fec_cfg, sizeof(msg->fec_cfg),
314 "LDGM cfg %s", fec_cfg);
315 } else { // delay creation until we have avarage frame size
316 tx->max_loss = atof(fec_cfg);
317 }
319 }
320 } else if(strcasecmp(fec, "RS") == 0) {
321 tx->fec_dup_1st_pkt = req_1st_pkt_dup;
322 snprintf(msg->fec_cfg, sizeof(msg->fec_cfg), "RS cfg %s",
323 fec_cfg);
325 } else if(strcasecmp(fec, "help") == 0) {
326 color_printf("Usage:\n");
327 color_printf("\t" TBOLD("-f [A:|V:]{mult:count|ldgm[:params]|"
328 "rs[:params]}[:nodup]") "\n");
329 color_printf("\nIf neither A: or V: is speciefied, FEC is set "
330 "to the video (backward compat).\n\n");
331 ret = false;
332 } else {
333 fprintf(stderr, "Unknown FEC: %s\n", fec);
334 ret = false;
335 }
336
337 if (tx->fec_dup_1st_pkt) {
338 MSG(VERBOSE, "Duplicating 1st packet of every frame for better "
339 "error resiliency.\n");
340 }
341
342 if (ret) {
344 (struct message *) msg);
345 free_response(resp);
346 } else {
347 free_message((struct message *) msg, NULL);
348 }
349
350 free(fec);
351 return ret;
352}
353
354static void fec_check_messages(struct tx *tx)
355{
356 struct message *msg;
357 while ((msg = check_message(&tx->mod))) {
358 auto *data = reinterpret_cast<struct msg_universal *>(msg);
359 const char *text = data->text;
360 if (strstr(text, MSG_UNIVERSAL_TAG_TX) != text) {
361 LOG(LOG_LEVEL_ERROR) << "[Transmit] Unexpected TX message: " << text << "\n";
362 free_message(msg, new_response(RESPONSE_BAD_REQUEST, "Unexpected message"));
363 continue;
364 }
365 text += strlen(MSG_UNIVERSAL_TAG_TX);
366 struct response *r = nullptr;
367 if (strstr(text, "fec ") == text) {
368 text += strlen("fec ");
369 if (set_fec(tx, text)) {
370 r = new_response(RESPONSE_OK, nullptr);
371 LOG(LOG_LEVEL_NOTICE) << "[Transmit] FEC set to new setting: " << text << "\n";
372 } else {
373 r = new_response(RESPONSE_INT_SERV_ERR, "cannot set FEC");
374 LOG(LOG_LEVEL_ERROR) << "[Transmit] Unable to reconfiure FEC to: " << text << "\n";
375 }
376 } else if (strstr(text, "rate ") == text) {
377 text += strlen("rate ");
378 auto new_rate = unit_evaluate(text, nullptr);
379 if (new_rate >= RATE_MIN) {
380 tx->bitrate = new_rate;
381 r = new_response(RESPONSE_OK, nullptr);
382 LOG(LOG_LEVEL_NOTICE) << "[Transmit] Bitrate set to: " << text << (new_rate > 0 ? "B" : "") << "\n";
383 } else {
384 r = new_response(RESPONSE_BAD_REQUEST, "Wrong value for bitrate");
385 LOG(LOG_LEVEL_ERROR) << "[Transmit] Wrong bitrate: " << text << "\n";
386 }
387 } else {
388 r = new_response(RESPONSE_BAD_REQUEST, "Unknown TX message");
389 LOG(LOG_LEVEL_ERROR) << "[Transmit] Unknown TX message: " << text << "\n";
390 }
391
392 free_message(msg, r);
393 }
394}
395
396static void tx_done(struct module *mod)
397{
398 struct tx *tx = (struct tx *) mod->priv_data;
399 assert(tx->magic == TRANSMIT_MAGIC);
400 free(tx);
401}
402
403/*
404 * sends one or more frames (tiles) with same TS in one RTP stream. Only one m-bit is set.
405 */
406void
407tx_send(struct tx *tx, struct video_frame *frame, struct rtp *rtp_session)
408{
409 unsigned int i;
410
411 assert(!frame->fragment || tx->fec_scheme == FEC_NONE); // currently no support for FEC with fragments
412 assert(!frame->fragment || frame->tile_count); // multiple tile are not currently supported for fragmented send
414
415 uint32_t ts =
416 (frame->flags & TIMESTAMP_VALID) == 0
419 if(frame->fragment &&
421 ts = tx->last_ts;
422 } else {
424 tx->last_ts = ts;
425 }
426
427 for(i = 0; i < frame->tile_count; ++i)
428 {
429 int last = FALSE;
430 int fragment_offset = 0;
431
432 if (i == frame->tile_count - 1) {
434 last = TRUE;
435 }
436 if(frame->fragment)
437 fragment_offset = vf_get_tile(frame, i)->offset;
438
439 tx_send_base(tx, frame, rtp_session, ts, last,
440 i, fragment_offset);
441 }
442 tx->buffer++;
443}
444
445void format_video_header(struct video_frame *frame, int tile_idx, int buffer_idx, uint32_t *video_hdr)
446{
447 uint32_t tmp;
448
449 video_hdr[3] = htonl(frame->tiles[tile_idx].width << 16 | frame->tiles[tile_idx].height);
450 video_hdr[4] = get_fourcc(frame->color_spec);
451 video_hdr[2] = htonl(frame->tiles[tile_idx].data_len);
452 tmp = tile_idx << 22;
453 tmp |= 0x3fffff & buffer_idx;
454 video_hdr[0] = htonl(tmp);
455
456 /* word 6 */
458}
459
460void format_audio_header(const audio_frame2 *frame, int channel, int buffer_idx, uint32_t *audio_hdr)
461{
462 uint32_t tmp = 0;
463 tmp = channel << 22U; /* bits 0-9 */
464 tmp |= buffer_idx; /* bits 10-31 */
465 audio_hdr[0] = htonl(tmp);
466
467 audio_hdr[2] = htonl(frame->get_data_len(channel));
468
469 /* fourth word */
470 tmp = (frame->get_bps() * 8) << 26U;
471 tmp |= frame->get_sample_rate();
472 audio_hdr[3] = htonl(tmp);
473
474 /* fifth word */
475 audio_hdr[4] = htonl(get_audio_tag(frame->get_codec()));
476}
477
478static uint32_t format_interl_fps_hdr_row(enum interlacing_t interlacing, double input_fps)
479{
480 unsigned int fpsd, fd, fps, fi;
481 uint32_t tmp;
482
483 tmp = interlacing << 29;
484 fps = round(input_fps);
485 fpsd = 1;
486 fd = 0;
487 fi = 0;
488 if (input_fps > 1.0 && fabs(input_fps - round(input_fps) / 1.001) < 0.005) { // 29.97 etc.
489 fd = 1;
490 } else if (fps < 1.0) {
491 fps = round(1.0 / input_fps);
492 fi = 1;
493 }
494
495 tmp |= fps << 19;
496 tmp |= fpsd << 15;
497 tmp |= fd << 14;
498 tmp |= fi << 13;
499 return htonl(tmp);
500}
501
502static inline void check_symbol_size(int fec_symbol_size, int payload_len)
503{
504 thread_local static bool status_printed = false;
505
506 if (status_printed && log_level < LOG_LEVEL_DEBUG2) {
507 return;
508 }
509
510 if (fec_symbol_size > payload_len) {
512 "Warning: FEC symbol size exceeds payload size! "
513 "FEC symbol size: " << fec_symbol_size
514 << "\n";
515 } else {
516 const int ll =
517 status_printed ? LOG_LEVEL_DEBUG2 : LOG_LEVEL_INFO;
518 LOG(ll) << MOD_NAME "FEC symbol size: " << fec_symbol_size
519 << ", symbols per packet: "
520 << payload_len / fec_symbol_size << ", payload size: "
521 << payload_len / fec_symbol_size * fec_symbol_size
522 << "\n";
523 }
524 status_printed = true;
525}
526
536static inline int get_video_pkt_len(int mtu,
537 int symbol_size, int *symbol_offset)
538{
539 if (symbol_size > mtu) {
540 if (symbol_size - *symbol_offset <= mtu) {
541 mtu = symbol_size - *symbol_offset;
542 *symbol_offset = 0;
543 } else {
544 *symbol_offset += mtu;
545 }
546 return mtu;
547 }
548 return mtu / symbol_size * symbol_size;
549}
550
552static vector<int> get_packet_sizes(struct video_frame *frame, int substream, int mtu) {
553 if (frame->fec_params.type != FEC_NONE) {
555 }
556
557 unsigned int symbol_size = 1;
558 int symbol_offset = 0;
560 symbol_size = vc_get_linesize(frame->tiles[substream].width, frame->color_spec);
562 assert(pf_block_size <= mtu);
563 mtu = mtu / pf_block_size * pf_block_size;
564 } else if (frame->fec_params.type != FEC_NONE) {
565 symbol_size = frame->fec_params.symbol_size;
566 }
567 vector<int> ret;
568 unsigned pos = 0;
569 do {
570 int len = symbol_size == 1
571 ? mtu
572 : get_video_pkt_len(mtu, symbol_size, &symbol_offset);
573 pos += len;
574 ret.push_back(len);
575 } while (pos < frame->tiles[substream].data_len);
576
577 if (pos > frame->tiles[substream].data_len) {
578 ret[ret.size() - 1] -=
579 (int) (pos - frame->tiles[substream].data_len);
580 }
581 return ret;
582}
583
584static void
585report_stats(struct tx *tx, struct rtp *rtp_session, long data_sent)
586{
588 return;
589 }
590
591 tx->sent_since_report += data_sent;
592
593 const time_ns_t current_time_ns = get_time_in_ns();
594 if (current_time_ns - tx->last_stat_report <
596 return;
597 }
598
599 const char *media =
600 tx->media_type == TX_MEDIA_VIDEO ? "video" : "audio";
601 std::ostringstream oss;
602 oss << "tx_send " << std::hex << rtp_my_ssrc(rtp_session) << std::dec
603 << " " << media << " " << tx->sent_since_report;
604
605 control_report_stats(tx->control, oss.str());
606 tx->last_stat_report = current_time_ns;
608}
609
613static long
614get_packet_rate(struct tx *tx, struct video_frame *frame, int substream, long packet_count)
615{
616 if (tx->bitrate == RATE_UNLIMITED) {
617 return 0;
618 }
619 double time_for_frame = 1.0 / frame->fps / frame->tile_count;
620 double interval_between_pkts = time_for_frame / tx->mult_count / packet_count;
621 // use only 75% of the time - we less likely overshot the frame time and
622 // can minimize risk of swapping packets between 2 frames (out-of-order ones)
623 interval_between_pkts = interval_between_pkts * 0.75;
624 // prevent bitrate to be "too low", here 1 Mbps at minimum
625 interval_between_pkts = std::min<double>(interval_between_pkts, tx->mtu / 1000'000.0);
626 long packet_rate_auto = interval_between_pkts * 1000'000'000L;
627
628 if (tx->bitrate == RATE_AUTO) { // adaptive (spread packets to 75% frame time)
629 return packet_rate_auto;
630 }
631 if (tx->bitrate == RATE_DYNAMIC) {
634 packet_rate_auto /= 2; // double packet rate for this frame
636 } else {
638 }
640 return packet_rate_auto;
641 }
642 long long int bitrate = tx->bitrate & ~RATE_FLAG_FIXED_RATE;
643 int avg_packet_size = frame->tiles[substream].data_len / packet_count;
644 long packet_rate = 1000'000'000L * avg_packet_size * 8 / bitrate; // fixed rate
645 if ((tx->bitrate & RATE_FLAG_FIXED_RATE) == 0) { // adaptive capped rate
646 packet_rate = std::max(packet_rate, packet_rate_auto);
647 }
648 return packet_rate;
649}
650
651static int
652get_tx_hdr_len(bool is_ipv6)
653{
654 return (is_ipv6 ? IPV6_HDR_LEN : IPV4_HDR_LEN) + UDP_HDR_LEN +
656}
657
658static void
659tx_send_base(struct tx *tx, struct video_frame *frame, struct rtp *rtp_session,
660 uint32_t ts, int send_m,
661 unsigned int substream,
662 int fragment_offset)
663{
664 assert(fragment_offset == 0); // no longer supported
665 if (!rtp_has_receiver(rtp_session)) {
666 return;
667 }
668
669 struct tile *tile = &frame->tiles[substream];
670
671 // see definition in rtp_callback.h
672 uint32_t rtp_hdr[100];
673 int rtp_hdr_len;
674 int pt = fec_pt_from_fec_type(TX_MEDIA_VIDEO, frame->fec_params.type, tx->encryption); /* A value specified in our packet format */
675#ifdef __linux__
676 struct timespec start, stop;
677#elif defined __APPLE__
678 struct timeval start, stop;
679#else // Windows
680 LARGE_INTEGER start, stop, freq;
681#endif
682 long delta, overslept = 0;
683 int hdrs_len = get_tx_hdr_len(rtp_is_ipv6(rtp_session));
684
685 assert(tx->magic == TRANSMIT_MAGIC);
686
687 tx_update(tx, frame, substream);
688
689 if (frame->fec_params.type == FEC_NONE) {
690 hdrs_len += (sizeof(video_payload_hdr_t));
691 rtp_hdr_len = sizeof(video_payload_hdr_t);
692 format_video_header(frame, substream, tx->buffer, rtp_hdr);
693 } else {
694 hdrs_len += (sizeof(fec_payload_hdr_t));
695 rtp_hdr_len = sizeof(fec_payload_hdr_t);
696 uint32_t tmp = substream << 22;
697 tmp |= 0x3fffff & tx->buffer;
698 // see definition in rtp_callback.h
699 rtp_hdr[0] = htonl(tmp);
700 rtp_hdr[2] = htonl(tile->data_len);
701 rtp_hdr[3] = htonl(
702 frame->fec_params.k << 19 |
703 frame->fec_params.m << 6 |
705 rtp_hdr[4] = htonl(frame->fec_params.seed);
706 }
707
708 if (tx->encryption) {
709 hdrs_len += sizeof(crypto_payload_hdr_t) + tx->enc_funcs->get_overhead(tx->encryption);
710 rtp_hdr[rtp_hdr_len / sizeof(uint32_t)] =
711 htonl(tx->enc_funcs->get_cipher(tx->encryption) << 24);
712 rtp_hdr_len += sizeof(crypto_payload_hdr_t);
713 }
714
715 vector<int> packet_sizes = get_packet_sizes(frame, substream, tx->mtu - hdrs_len);
716 long mult_pkt_cnt = (long) packet_sizes.size() * tx->mult_count;
717 const long packet_rate =
718 get_packet_rate(tx, frame, (int) substream, mult_pkt_cnt);
719
720 // initialize header array with values (except offset which is different among
721 // different packts)
722 void *rtp_headers = malloc((mult_pkt_cnt + 1) * rtp_hdr_len);
723 uint32_t *rtp_hdr_packet = (uint32_t *) rtp_headers;
724 for (int m = 0; m < tx->mult_count; ++m) {
725 unsigned pos = 0;
726 for (unsigned i = 0; i < packet_sizes.size(); ++i) {
727 memcpy(rtp_hdr_packet, rtp_hdr, rtp_hdr_len);
728 rtp_hdr_packet[1] = htonl(pos);
729 rtp_hdr_packet += rtp_hdr_len / sizeof(uint32_t);
730 pos += packet_sizes.at(i);
731 }
732 }
733 if (tx->fec_dup_1st_pkt) { // dup 1st pkt with RS/LDGM
734 mult_pkt_cnt += 1;
735 memcpy(rtp_hdr_packet, rtp_hdr, rtp_hdr_len);
736 rtp_hdr_packet[1] = htonl(0);
737 }
738
739 if (!tx->encryption) {
740 rtp_async_start(rtp_session, mult_pkt_cnt);
741 }
742
743 rtp_hdr_packet = (uint32_t *) rtp_headers;
744 for (long i = 0; i < mult_pkt_cnt; ++i) {
746 const int m = i == mult_pkt_cnt - 1 ? send_m : 0;
747 char *data = tile->data + ntohl(rtp_hdr_packet[1]);
748 int data_len = packet_sizes.at(i % packet_sizes.size());
749
750 char encrypted_data[RTP_MAX_PACKET_LEN + MAX_CRYPTO_EXCEED];
751 if (tx->encryption != nullptr) {
752 data_len = tx->enc_funcs->encrypt(
753 tx->encryption, data, data_len,
754 (char *) rtp_hdr_packet,
756 ? sizeof(fec_payload_hdr_t)
757 : sizeof(video_payload_hdr_t),
758 encrypted_data);
759 if (data_len <= 0) {
760 return;
761 }
762 data = encrypted_data;
763 }
764
765 rtp_send_data_hdr(rtp_session, ts, pt, m, 0, nullptr,
766 (char *) rtp_hdr_packet, rtp_hdr_len, data,
767 data_len, nullptr, 0, 0);
768 rtp_hdr_packet += rtp_hdr_len / sizeof(uint32_t);
769
770 // TRAFFIC SHAPER
771 if (m != 1) { // wait for all but last packet
772 do {
774 GET_DELTA;
775 } while (packet_rate - delta - overslept > 0);
776 overslept = -(packet_rate - delta - overslept);
777 //fprintf(stdout, "%ld ", overslept);
778 }
779 }
780
781 const long data_sent = tile->data_len + rtp_hdr_len * mult_pkt_cnt;
782 report_stats(tx, rtp_session, data_sent);
783
784 if (!tx->encryption) {
785 rtp_async_wait(rtp_session);
786 }
787 free(rtp_headers);
788}
789
790static void audio_tx_send_chan(struct tx *tx, struct rtp *rtp_session,
791 uint32_t timestamp, const audio_frame2 *buffer,
792 int channel, bool send_m);
793
794/*
795 * This multiplication scheme relies upon the fact, that our RTP/pbuf implementation is
796 * not sensitive to packet duplication. Otherwise, we can get into serious problems.
797 */
798void
799audio_tx_send(struct tx *tx, struct rtp *rtp_session,
800 const audio_frame2 *buffer)
801{
802 if (!rtp_has_receiver(rtp_session)) {
803 return;
804 }
805
807
808 const uint32_t timestamp =
809 buffer->get_timestamp() == -1
812
813 for (int iter = 0; iter < tx->mult_count; ++iter) {
814 for (int chan = 0; chan < buffer->get_channel_count(); ++chan) {
815 bool send_m = iter == tx->mult_count - 1 &&
816 chan == buffer->get_channel_count() - 1;
817 audio_tx_send_chan(tx, rtp_session, timestamp, buffer,
818 chan, send_m);
819 }
820 }
821
822 tx->buffer++;
823}
824
825static void
826audio_tx_send_chan(struct tx *tx, struct rtp *rtp_session, uint32_t timestamp,
827 const audio_frame2 *buffer, int channel, bool send_m)
828{
829 int pt = fec_pt_from_fec_type(
831 tx->encryption); /* PT set for audio in our packet format */
832 unsigned m = 0U;
833 // see definition in rtp_callback.h
834 uint32_t rtp_hdr[100];
835
836 int rtp_hdr_len = 0;
837 int hdrs_len = get_tx_hdr_len(rtp_is_ipv6(rtp_session));
838 unsigned int fec_symbol_size =
839 buffer->get_fec_params(channel).symbol_size;
840
841 const char *chan_data = buffer->get_data(channel);
842 unsigned pos = 0U;
843
844 if (buffer->get_fec_params(0).type == FEC_NONE) {
845 hdrs_len += (sizeof(audio_payload_hdr_t));
846 rtp_hdr_len = sizeof(audio_payload_hdr_t);
847 format_audio_header(buffer, channel, tx->buffer, rtp_hdr);
848 } else {
849 hdrs_len += (sizeof(fec_payload_hdr_t));
850 rtp_hdr_len = sizeof(fec_payload_hdr_t);
851 uint32_t tmp = channel << 22;
852 tmp |= 0x3fffff & tx->buffer;
853 // see definition in rtp_callback.h
854 rtp_hdr[0] = htonl(tmp);
855 rtp_hdr[2] = htonl(buffer->get_data_len(channel));
856 rtp_hdr[3] = htonl(buffer->get_fec_params(channel).k << 19 |
857 buffer->get_fec_params(channel).m << 6 |
858 buffer->get_fec_params(channel).c);
859 rtp_hdr[4] = htonl(buffer->get_fec_params(channel).seed);
860 }
861
862 if (tx->encryption) {
863 hdrs_len += sizeof(crypto_payload_hdr_t) +
865 rtp_hdr[rtp_hdr_len / sizeof(uint32_t)] =
866 htonl(tx->enc_funcs->get_cipher(tx->encryption) << 24);
867 rtp_hdr_len += sizeof(crypto_payload_hdr_t);
868 }
869
870 if (buffer->get_fec_params(0).type != FEC_NONE) {
871 check_symbol_size(fec_symbol_size, tx->mtu - hdrs_len);
872 }
873
874 long data_sent = 0;
875 const int max_len = tx->mtu - hdrs_len;
876 do {
877 const char *data = chan_data + pos;
878 int data_len = max_len;
879 if (pos + data_len >=
880 (unsigned int) buffer->get_data_len(channel)) {
881 data_len = buffer->get_data_len(channel) - pos;
882 if (send_m) {
883 m = 1;
884 }
885 }
886 rtp_hdr[1] = htonl(pos);
887 pos += data_len;
888
889 char encrypted_data[RTP_MAX_PACKET_LEN + MAX_CRYPTO_EXCEED];
890 if (tx->encryption) {
891 data_len = tx->enc_funcs->encrypt(
892 tx->encryption, const_cast<char *>(data), data_len,
893 (char *) rtp_hdr,
894 rtp_hdr_len - sizeof(crypto_payload_hdr_t),
895 encrypted_data);
896 if (data_len <= 0) {
897 return;
898 }
899 data = encrypted_data;
900 }
901
902 data_sent += data_len + rtp_hdr_len;
903
904 rtp_send_data_hdr(rtp_session, timestamp, pt, m,
905 0, /* contributing sources */
906 0, /* contributing sources length */
907 (char *) rtp_hdr, rtp_hdr_len,
908 const_cast<char *>(data), data_len, 0, 0, 0);
909
910 } while (pos < buffer->get_data_len(channel));
911
912 report_stats(tx, rtp_session, data_sent);
913
914 if (buffer->get_fec_params(0).type == FEC_NONE) {
915 return;
916 }
917 // issue a warning if R-S is inadequate
918 const int packet_count =
919 (buffer->get_data_len(channel) + max_len - 1) / max_len;
920 if (packet_count > 3) {
921 return;
922 }
923 const char *pl_suffix = packet_count == 1 ? "" : "s";
924 log_msg_once(LOG_LEVEL_WARNING, to_fourcc('t', 'x', 'a', 'F'),
926 "[audio] %d packet%s per audio channel may be too low "
927 "for Reed Solomon, consider mult instead!%s\n",
928 packet_count, pl_suffix,
929 packet_count == 3 ? " (Or increase the redundancy.)" : "");
930}
931
932static bool
933validate_std_audio(const audio_frame2 * buffer, int payload_size)
934{
935 if ((buffer->get_codec() == AC_MP3 ||
936 buffer->get_codec() == AC_OPUS) &&
937 buffer->get_channel_count() > 1) { // we cannot interleave Opus here
938 const uint32_t msg_id = to_fourcc('t', 'x', 'v', 'a');
941 "%s can currently have only 1 channel in "
942 "RFC-compliant mode! Discarding channels but the "
943 "first one...\n",
945 }
946 if (buffer->get_codec() == AC_OPUS &&
947 payload_size < (int) buffer->get_data_len(0)) {
948 MSG(ERROR, "Opus frame larger than packet! Discarding...\n");
949 return false;
950 }
951 return true;
952}
953
958void audio_tx_send_standard(struct tx* tx, struct rtp *rtp_session,
959 const audio_frame2 * buffer) {
960 //TODO to be more abstract in order to accept A-law too and other supported standards with such implementation
961 assert(buffer->get_codec() == AC_MULAW ||
962 buffer->get_codec() == AC_ALAW ||
963 buffer->get_codec() == AC_MP3 ||
964 buffer->get_codec() == AC_OPUS);
965
966 uint32_t ts;
967 static uint32_t ts_prev = 0;
968
969 enum {
970 PCMA_U_BPS = 1, // data BPS - get_bps() is 2 to expand to 16-bit
971 // format on the receiver. The semantic of 2 is
972 // the same as for other codecs like Opus to
973 // asses the decmopressed sample size.
974 };
975 const bool is_pcma_u =
976 buffer->get_codec() == AC_MULAW || buffer->get_codec() == AC_ALAW;
977 // Configure the right Payload type,
978 // 8000 Hz, 1 channel PCMU/A is the ITU-T G.711 standard
979 // Other channels or Hz goes to DynRTP-Type97
980 int pt = PT_DynRTP_Type97;
981 if (is_pcma_u && buffer->get_channel_count() == 1 &&
982 buffer->get_sample_rate() == kHz8) {
983 pt = buffer->get_codec() == AC_MULAW ? PT_ITU_T_G711_PCMU
985 }
986 if (buffer->get_codec() == AC_MP3) {
987 pt = PT_MPA;
988 }
989
990 int data_len = buffer->get_data_len(0); /* Number of samples to send */
991 int payload_size = tx->mtu - 40 - 8 - 12; /* Max size of an RTP payload field (minus IPv6, UDP and RTP header lengths) */
992
993 if (is_pcma_u) { // we may split the data into more packets, compute
994 // chunk size
995 const int frame_size = buffer->get_channel_count() * PCMA_U_BPS;
996 payload_size = payload_size / frame_size * frame_size; // align to frame size
997 // The sizes for the different channels must be the same.
998 for (int i = 1; i < buffer->get_channel_count(); i++) {
999 assert(buffer->get_data_len(0) ==
1000 buffer->get_data_len(i));
1001 }
1002 data_len *= buffer->get_channel_count();
1003 } else if (pt == PT_MPA) {
1004 payload_size -= sizeof(mpa_hdr_t);
1005 }
1006
1007 if (!validate_std_audio(buffer, payload_size)) {
1008 return;
1009 }
1010
1011 int pos = 0;
1012 do {
1013 int pkt_len = std::min(payload_size, data_len - pos);
1014
1015 if (buffer->get_codec() == AC_OPUS) {
1016 memcpy(tx->tmp_packet, buffer->get_data(0), pkt_len);
1017 } else if (buffer->get_codec() == AC_MP3) {
1018 memset(tx->tmp_packet, 0, 2);
1019 const uint16_t offset = htons(pos);
1020 memcpy(tx->tmp_packet + 2, &offset, sizeof offset);
1021 pkt_len += sizeof(mpa_hdr_t);
1022 memcpy(tx->tmp_packet + 4, buffer->get_data(0), pkt_len);
1023 } else { // interleave
1024 for (int ch = 0; ch < buffer->get_channel_count(); ch++) {
1026 tx->tmp_packet,
1027 buffer->get_data(ch) +
1028 pos / buffer->get_channel_count(),
1029 PCMA_U_BPS,
1030 pkt_len / buffer->get_channel_count(), 1,
1031 buffer->get_channel_count(), 0, ch);
1032 }
1033 }
1034
1035 // Update first sample timestamp
1036 if (buffer->get_codec() == AC_OPUS) {
1037 /* OPUS packet will be the whole contained in one packet
1038 * according to RFC 7587. For PCMA/PCMU there may be more
1039 * packets so we cannot use the whole frame duration. */
1040 ts = get_std_audio_local_mediatime(buffer->get_duration(), 48000);
1041 } else {
1042 ts = get_std_audio_local_mediatime((double) pkt_len / (double) buffer->get_channel_count() / (double) buffer->get_sample_rate(), buffer->get_sample_rate());
1043 }
1044 rtp_send_ctrl(rtp_session, ts_prev, 0, get_time_in_ns()); //send RTCP SR
1045 ts_prev = ts;
1046 // Send the packet
1047 rtp_send_data(rtp_session, ts, pt, 0, 0, /* contributing sources */
1048 0, /* contributing sources length */
1049 tx->tmp_packet, pkt_len, 0, 0, 0);
1050 pos += pkt_len;
1051 } while (pos < data_len);
1052}
1053
1057void tx_send_h264(struct tx *tx, struct video_frame *frame,
1058 struct rtp *rtp_session) {
1059 assert(frame->tile_count == 1); // std transmit doesn't handle more than one tile
1060 assert(!frame->fragment || tx->fec_scheme == FEC_NONE); // currently no support for FEC with fragments
1061 assert(!frame->fragment || frame->tile_count); // multiple tiles are not currently supported for fragmented send
1062 uint32_t ts = get_std_video_local_mediatime();
1063 struct tile *tile = &frame->tiles[0];
1064
1065 char pt = PT_DynRTP_Type96;
1066 unsigned char hdr[2];
1067 int cc = 0;
1068 uint32_t csrc = 0;
1069 int m = 0;
1070 char *extn = 0;
1071 uint16_t extn_len = 0;
1072 uint16_t extn_type = 0;
1073 const uint8_t *start = (uint8_t *) tile->data;
1074 int data_len = tile->data_len;
1075 unsigned maxPacketSize = tx->mtu - 40;
1076
1077 const unsigned char *endptr = 0;
1078 const unsigned char *nal = start;
1079
1080 while ((nal = rtpenc_get_next_nal(nal, data_len - (nal - start), &endptr))) {
1081 unsigned int nalsize = endptr - nal;
1082 bool eof = endptr == start + data_len;
1083 bool lastNALUnitFragment = false; // by default
1084 unsigned curNALOffset = 0;
1085 char *nalc = const_cast<char *>(reinterpret_cast<const char *>(nal));
1086
1087 while(!lastNALUnitFragment){
1088 // We have NAL unit data in the buffer. There are three cases to consider:
1089 // 1. There is a new NAL unit in the buffer, and it's small enough to deliver
1090 // to the RTP sink (as is).
1091 // 2. There is a new NAL unit in the buffer, but it's too large to deliver to
1092 // the RTP sink in its entirety. Deliver the first fragment of this data,
1093 // as a FU packet, with one extra preceding header byte (for the "FU header").
1094 // 3. There is a NAL unit in the buffer, and we've already delivered some
1095 // fragment(s) of this. Deliver the next fragment of this data,
1096 // as a FU packet, with two (H.264) extra preceding header bytes
1097 // (for the "NAL header" and the "FU header").
1098 if (curNALOffset == 0) { // case 1 or 2
1099 if (nalsize <= maxPacketSize) { // case 1
1100
1101 if (eof) m = 1;
1102 if (rtp_send_data(rtp_session, ts, pt, m, cc, &csrc,
1103 nalc, nalsize,
1104 extn, extn_len, extn_type) < 0) {
1105 error_msg("There was a problem sending the RTP packet\n");
1106 }
1107 lastNALUnitFragment = true;
1108 } else { // case 2
1109 // We need to send the NAL unit data as FU packets. Deliver the first
1110 // packet now. Note that we add "NAL header" and "FU header" bytes to the front
1111 // of the packet (overwriting the existing "NAL header").
1112 hdr[0] = (nal[0] & 0xE0) | 28; //FU indicator
1113 hdr[1] = 0x80 | (nal[0] & 0x1F); // FU header (with S bit)
1114
1115 if (rtp_send_data_hdr(rtp_session, ts, pt, m, cc, &csrc,
1116 (char *) hdr, 2,
1117 nalc + 1, maxPacketSize - 2,
1118 extn, extn_len, extn_type) < 0) {
1119 error_msg("There was a problem sending the RTP packet\n");
1120 }
1121 curNALOffset += maxPacketSize - 1;
1122 lastNALUnitFragment = false;
1123 nalsize -= maxPacketSize - 1;
1124 }
1125 } else { // case 3
1126 // We are sending this NAL unit data as FU packets. We've already sent the
1127 // first packet (fragment). Now, send the next fragment. Note that we add
1128 // "NAL header" and "FU header" bytes to the front. (We reuse these bytes that
1129 // we already sent for the first fragment, but clear the S bit, and add the E
1130 // bit if this is the last fragment.)
1131 hdr[1] = hdr[1] & ~0x80;// FU header (no S bit)
1132
1133 if (nalsize + 1 > maxPacketSize) {
1134 // We can't send all of the remaining data this time:
1135 if (rtp_send_data_hdr(rtp_session, ts, pt, m, cc, &csrc,
1136 (char *) hdr, 2,
1137 nalc + curNALOffset,
1138 maxPacketSize - 2, extn, extn_len,
1139 extn_type) < 0) {
1140 error_msg("There was a problem sending the RTP packet\n");
1141 }
1142 curNALOffset += maxPacketSize - 2;
1143 lastNALUnitFragment = false;
1144 nalsize -= maxPacketSize - 2;
1145
1146 } else {
1147 // This is the last fragment:
1148 if (eof) m = 1;
1149
1150 hdr[1] |= 0x40;// set the E bit in the FU header
1151
1152 if (rtp_send_data_hdr(rtp_session, ts, pt, m, cc, &csrc,
1153 (char *) hdr, 2,
1154 nalc + curNALOffset,
1155 nalsize, extn, extn_len, extn_type) < 0) {
1156 error_msg("There was a problem sending the RTP packet\n");
1157 }
1158 lastNALUnitFragment = true;
1159 }
1160 }
1161 }
1162 }
1163 if (endptr != start + data_len) {
1164 error_msg("No NAL found!\n");
1165 }
1166}
1167
1168void tx_send_jpeg(struct tx *tx, struct video_frame *frame,
1169 struct rtp *rtp_session) {
1170 uint32_t ts = 0;
1171
1172 assert(frame->tile_count == 1); // std transmit doesn't handle more than one tile
1173 assert(!frame->fragment || tx->fec_scheme == FEC_NONE); // currently no support for FEC with fragments
1174 assert(!frame->fragment || frame->tile_count); // multiple tiles are not currently supported for fragmented send
1175
1177
1178 struct tile *tile = &frame->tiles[0];
1179 char pt = PT_JPEG;
1180 struct jpeg_rtp_data d;
1181
1182 if (!jpeg_get_rtp_hdr_data((uint8_t *) frame->tiles[0].data, frame->tiles[0].data_len, &d)) {
1183 exit_uv(1);
1184 return;
1185 }
1186
1187 uint32_t jpeg_hdr[2 /* JPEG hdr */ + 1 /* RM hdr */ + 129 /* QT hdr */];
1188 int hdr_off = 0;
1189 unsigned int type_spec = 0u;
1190 jpeg_hdr[hdr_off++] = htonl(type_spec << 24u);
1191 jpeg_hdr[hdr_off++] = htonl(d.type << 24u | d.q << 16u | d.width / 8u << 8u | d.height / 8u);
1192 if (d.restart_interval != 0) {
1193 // we do not align restart interval on packet boundaries yet
1194 jpeg_hdr[hdr_off++] = htonl(d.restart_interval << 16u | 1u << 15u | 1u << 14u | 0x3fffu);
1195 }
1196 // quantization headers
1197 if (d.q == 255u) { // we must include the tables
1198 unsigned int mbz = 0u; // must be zero
1199 unsigned int precision = 0u;
1200 unsigned int qt_len = 2 * 64u;
1201 jpeg_hdr[hdr_off++] = htonl(mbz << 24u | precision << 16u | qt_len);
1202 memcpy(&jpeg_hdr[hdr_off], d.quantization_tables[0], 64);
1203 hdr_off += 64 / sizeof(uint32_t);
1204 memcpy(&jpeg_hdr[hdr_off], d.quantization_tables[1], 64);
1205 hdr_off += 64 / sizeof(uint32_t);
1206 }
1207
1208 char *data = (char *) d.data;
1209 int bytes_left = tile->data_len - ((char *) d.data - tile->data);
1210 int max_mtu = tx->mtu - ((rtp_is_ipv6(rtp_session) ? 40 : 20) + 8 + 12); // IP hdr size + UDP hdr size + RTP hdr size
1211
1212 int fragment_offset = 0;
1213 do {
1214 int hdr_len;
1215 if (fragment_offset == 0) { // include quantization header only in 1st pkt
1216 hdr_len = hdr_off * sizeof(uint32_t);
1217 } else {
1218 hdr_len = 8 + (d.restart_interval > 0 ? 4 : 0);
1219 }
1220 int data_len = max_mtu - hdr_len;
1221 int m = 0;
1222 if (bytes_left <= data_len) {
1223 data_len = bytes_left;
1224 m = 1;
1225 }
1226 jpeg_hdr[0] = htonl(type_spec << 24u | fragment_offset);
1227
1228 int ret = rtp_send_data_hdr(rtp_session, ts, pt, m, 0, 0,
1229 (char *) &jpeg_hdr, hdr_len,
1230 data, data_len, 0, 0, 0);
1231 if (ret < 0) {
1232 log_msg(LOG_LEVEL_ERROR, "Error sending RTP/JPEG packet!\n");
1233 }
1234 data += data_len;
1235 bytes_left -= data_len;
1236 fragment_offset += data_len;
1237 } while (bytes_left > 0);
1238}
1239
1241{
1242 return tx->buffer;
1243
1244}
1245
struct video_frame * frame
int void size_t * len
int vc_get_linesize(unsigned int width, codec_t codec)
This file contains definition of some common audio types.
@ AC_OPUS
Definition types.h:57
@ AC_MULAW
Definition types.h:55
@ AC_MP3
Definition types.h:59
@ AC_ALAW
Definition types.h:54
char * get_data(int channel)
Definition types.cpp:218
audio_codec_t get_codec() const
Definition types.cpp:213
int get_channel_count() const
Definition types.cpp:260
int64_t get_timestamp() const
Definition types.cpp:340
fec_desc const & get_fec_params(int channel) const
Definition types.cpp:255
size_t get_data_len(int channel) const
Definition types.cpp:228
double get_duration() const
Definition types.cpp:246
int get_sample_rate() const
Definition types.cpp:275
const char * get_name_to_audio_codec(audio_codec_t codec)
Definition codec.cpp:450
uint32_t get_audio_tag(audio_codec_t codec)
Definition codec.cpp:455
int color_printf(const char *format,...)
#define TBOLD(x)
Definition color_out.h:70
#define TRUE
#define FALSE
static void new_message(struct module *m)
bool control_stats_enabled(struct control_state *s)
void control_report_stats(struct control_state *s, const std::string &report_line)
static __device__ vec2 abs(const vec2 &v)
Definition cuda_dxt.cu:118
static __device__ vec3 round(const vec3 &v)
Definition cuda_dxt.cu:122
static __device__ const float offset
Definition cuda_dxt.cu:139
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
void log_msg_once(int level, uint32_t id, const char *msg,...)
Definition debug.cpp:137
#define error_msg(...)
Definition debug.h:89
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG_LEVEL_DEBUG2
Definition debug.h:67
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define MSG(l, fmt,...)
Definition debug.h:96
#define LOG(level)
Definition debug.h:313
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
int fec_pt_from_fec_type(enum tx_media_type media_type, enum fec_type fec_type, bool encrypted)
Definition fec.cpp:175
void module_init_default(struct module *module_data)
Definition module.c:48
void module_register(struct module *module_data, struct module *parent)
Definition module.c:82
struct module * get_module(struct module *root, const char *const_path)
Definition module.c:264
void module_done(struct module *module_data)
Definition module.c:93
struct module * get_root_module(struct module *node)
Definition module.c:203
struct module * get_parent_module(struct module *node)
Definition module.c:214
@ MODULE_CLASS_TX
Definition module.h:89
void exit_uv(int status)
Definition host.cpp:625
#define RATE_AUTO
spread packets evenly across frame time (currently 3/4)
Definition host.h:123
#define RATE_FLAG_FIXED_RATE
use the bitrate as fixed, not capped
Definition host.h:127
#define RATE_MIN
Definition host.h:125
#define RATE_UNLIMITED
Definition host.h:122
#define RATE_DYNAMIC
same as RATE_AUTO but occasional excess frame allowed
Definition host.h:124
bool jpeg_get_rtp_hdr_data(uint8_t *jpeg_data, int len, struct jpeg_rtp_data *hdr_data)
volatile int log_level
Definition debug.cpp:65
const void * load_library(const char *name, enum library_class cls, int abi_version)
@ LIBRARY_CLASS_UNDEFINED
Definition lib_common.h:74
#define to_fourcc(a, b, c, d)
Creates FourCC word.
Definition macros.h:114
#define MAX(a, b)
Definition macros.h:65
void free_message(struct message *msg, struct response *r)
struct response * new_response(int status, const char *text)
struct response * send_message_to_receiver(struct module *receiver, struct message *msg)
struct message * check_message(struct module *mod)
void free_response(struct response *r)
@ SENDER_MSG_CHANGE_FEC
Definition messaging.h:90
#define RESPONSE_OK
Definition messaging.h:57
#define RESPONSE_BAD_REQUEST
Definition messaging.h:60
#define RESPONSE_INT_SERV_ERR
Definition messaging.h:63
#define MSG_UNIVERSAL_TAG_TX
Definition messaging.h:160
long long unit_evaluate(const char *str, const char **endptr)
Definition misc.cpp:81
#define OPENSSL_ENCRYPT_ABI_VERSION
#define MAX_CRYPTO_EXCEED
int rtp_send_data_hdr(struct rtp *session, uint32_t rtp_ts, char pt, int m, int cc, const uint32_t *csrc, char *phdr, int phdr_len, char *data, int data_len, char *extn, uint16_t extn_len, uint16_t extn_type)
Definition rtp.c:2752
uint32_t rtp_my_ssrc(struct rtp *session)
Definition rtp.c:1401
void rtp_send_ctrl(struct rtp *session, uint32_t rtp_ts, rtcp_app_callback appcallback, time_ns_t curr_time)
Definition rtp.c:3409
bool rtp_has_receiver(struct rtp *session)
Definition rtp.c:4016
bool rtp_is_ipv6(struct rtp *session)
Definition rtp.c:4022
int rtp_send_data(struct rtp *session, uint32_t rtp_ts, char pt, int m, int cc, const uint32_t *csrc, char *data, int data_len, char *extn, uint16_t extn_len, uint16_t extn_type)
Definition rtp.c:2742
void rtp_async_wait(struct rtp *session)
Definition rtp.c:4032
void rtp_async_start(struct rtp *session, int nr_packets)
Definition rtp.c:4027
#define RTP_MAX_MTU
Definition rtp.h:60
@ IPV6_HDR_LEN
Definition rtp.h:65
@ IPV4_HDR_LEN
Definition rtp.h:64
@ RTP_HDR_LEN
Definition rtp.h:67
@ UDP_HDR_LEN
Definition rtp.h:66
#define RTP_MAX_PACKET_LEN
Definition rtp.h:61
struct msghdr msg
#define PT_DynRTP_Type97
Definition rtp_types.h:79
#define PT_MPA
Definition rtp_types.h:65
#define PT_ITU_T_G711_PCMU
Definition rtp_types.h:63
uint32_t mpa_hdr_t
Definition rtp_types.h:163
#define PT_ITU_T_G711_PCMA
Definition rtp_types.h:64
uint32_t audio_payload_hdr_t[5]
Definition rtp_types.h:129
uint32_t fec_payload_hdr_t[5]
Definition rtp_types.h:152
uint32_t crypto_payload_hdr_t[1]
Definition rtp_types.h:161
#define PT_DynRTP_Type96
Definition rtp_types.h:78
#define PT_JPEG
Definition rtp_types.h:71
uint32_t video_payload_hdr_t[6]
Definition rtp_types.h:107
const unsigned char * rtpenc_get_next_nal(const unsigned char *start, long len, const unsigned char **endptr)
long packet_rate
Definition run_tests.c:72
static void start()
Definition sdp.c:202
const char * parent
Definition settings.cpp:198
unsigned int k
Definition types.h:209
enum fec_type type
Definition types.h:208
unsigned int m
Definition types.h:209
unsigned int symbol_size
Definition types.h:211
unsigned int c
Definition types.h:209
unsigned int seed
Definition types.h:210
Definition fec.h:51
uint8_t * data
Definition jpeg_reader.h:86
uint8_t * quantization_tables[2]
Definition jpeg_reader.h:85
enum module_class cls
Definition module.h:115
void * priv_data
Definition module.h:126
module_deleter_t deleter
Definition module.h:118
char fec_cfg[1024]
Definition messaging.h:104
char text[8192]
Definition messaging.h:157
int(* get_overhead)(struct openssl_encrypt *encryption)
int(* encrypt)(struct openssl_encrypt *encryption, char *plaintext, int plaintext_len, char *aad, int aad_len, char *ciphertext)
enum openssl_mode(* get_cipher)(struct openssl_encrypt *encryption)
int(* init)(struct openssl_encrypt **state, const char *passphrase)
static constexpr int EXCESS_GAP
minimal gap between excessive frames
Definition transmit.cpp:129
long long last_excess
nr of frames last excessive frame was emitted
Definition transmit.cpp:128
unsigned long avg_frame_size
moving average
Definition transmit.cpp:127
char text[]
Definition messaging.cpp:68
Definition rtp.c:274
Struct tile is an area of video_frame.
Definition types.h:279
unsigned int width
Definition types.h:280
char * data
Raw tile data. Pointer must be at least 4B aligned.
Definition types.h:287
unsigned int data_len
length of the data
Definition types.h:288
unsigned int offset
Fragment offset from tile beginning (in bytes). Used only if frame is fragmented.
Definition types.h:292
unsigned int height
Definition types.h:281
unsigned mtu
Definition transmit.cpp:137
long long int bitrate
Definition transmit.cpp:160
unsigned long int sent_frames
Definition transmit.cpp:144
uint32_t magic
Definition transmit.cpp:135
struct rate_limit_dyn dyn_rate_limit_state
Definition transmit.cpp:161
enum fec_type fec_scheme
Definition transmit.cpp:148
uint32_t last_ts
Definition transmit.cpp:140
bool fec_dup_1st_pkt
Definition transmit.cpp:149
int mult_count
Definition transmit.cpp:150
size_t sent_since_report
Definition transmit.cpp:155
double max_loss
Definition transmit.cpp:138
struct module mod
Definition transmit.cpp:133
int32_t avg_len_last
Definition transmit.cpp:146
int32_t avg_len
Definition transmit.cpp:145
const struct openssl_encrypt_info * enc_funcs
Definition transmit.cpp:158
char tmp_packet[RTP_MAX_MTU]
Definition transmit.cpp:163
enum tx_media_type media_type
Definition transmit.cpp:136
int last_frame_fragment_id
Definition transmit.cpp:141
struct openssl_encrypt * encryption
Definition transmit.cpp:159
uint64_t last_stat_report
Definition transmit.cpp:156
unsigned int buffer
Definition transmit.cpp:143
int last_fragment
Definition transmit.cpp:152
struct control_state * control
Definition transmit.cpp:154
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
enum interlacing_t interlacing
Definition types.h:307
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
int64_t timestamp
Definition types.h:331
double fps
Definition types.h:308
unsigned int tile_count
Definition types.h:344
int flags
Definition types.h:329
unsigned int frame_fragment_id
Used only if (fragment == 1). ID of the frame. Fragments of same frame must have the same ID.
Definition types.h:319
unsigned int fragment
Indicates that the tile is fragmented. Normally not used (only for Bluefish444).
Definition types.h:315
struct fec_desc fec_params
Definition types.h:328
codec_t color_spec
Definition types.h:306
unsigned int last_fragment
Used only if (fragment == 1). Indicates this is the last fragment.
Definition types.h:317
uint32_t ts
Definition tfrc.c:101
void tx_send_jpeg(struct tx *tx, struct video_frame *frame, struct rtp *rtp_session)
#define FEC_MAX_MULT
Definition transmit.cpp:91
static void report_stats(struct tx *tx, struct rtp *rtp_session, long data_sent)
Definition transmit.cpp:585
#define GET_DELTA
Definition transmit.cpp:106
static void audio_tx_send_chan(struct tx *tx, struct rtp *rtp_session, uint32_t timestamp, const audio_frame2 *buffer, int channel, bool send_m)
Definition transmit.cpp:826
static void check_symbol_size(int fec_symbol_size, int payload_len)
Definition transmit.cpp:502
static bool validate_std_audio(const audio_frame2 *buffer, int payload_size)
Definition transmit.cpp:933
static int get_tx_hdr_len(bool is_ipv6)
Definition transmit.cpp:652
static bool set_fec(struct tx *tx, const char *fec)
Definition transmit.cpp:263
static void tx_update(struct tx *tx, struct video_frame *frame, int substream)
Definition transmit.cpp:166
#define TRANSMIT_MAGIC
Definition transmit.cpp:89
#define GET_STOPTIME
Definition transmit.cpp:105
static uint32_t format_interl_fps_hdr_row(enum interlacing_t interlacing, double input_fps)
Definition transmit.cpp:478
static void tx_send_base(struct tx *tx, struct video_frame *frame, struct rtp *rtp_session, uint32_t ts, int send_m, unsigned int substream, int fragment_offset)
Definition transmit.cpp:659
void format_video_header(struct video_frame *frame, int tile_idx, int buffer_idx, uint32_t *video_hdr)
Definition transmit.cpp:445
void tx_send_h264(struct tx *tx, struct video_frame *frame, struct rtp *rtp_session)
#define GET_STARTTIME
Definition transmit.cpp:104
#define CONTROL_PORT_BANDWIDTH_REPORT_INTERVAL_NS
Definition transmit.cpp:93
static void tx_done(struct module *tx)
Definition transmit.cpp:396
void audio_tx_send(struct tx *tx, struct rtp *rtp_session, const audio_frame2 *buffer)
Definition transmit.cpp:799
static long get_packet_rate(struct tx *tx, struct video_frame *frame, int substream, long packet_count)
Definition transmit.cpp:614
#define MOD_NAME
Definition transmit.cpp:88
static void fec_check_messages(struct tx *tx)
Definition transmit.cpp:354
void format_audio_header(const audio_frame2 *frame, int channel, int buffer_idx, uint32_t *audio_hdr)
Definition transmit.cpp:460
int tx_get_buffer_id(struct tx *tx)
static int get_video_pkt_len(int mtu, int symbol_size, int *symbol_offset)
Definition transmit.cpp:536
void tx_send(struct tx *tx, struct video_frame *frame, struct rtp *rtp_session)
Definition transmit.cpp:407
void audio_tx_send_standard(struct tx *tx, struct rtp *rtp_session, const audio_frame2 *buffer)
Definition transmit.cpp:958
static vector< int > get_packet_sizes(struct video_frame *frame, int substream, int mtu)
Definition transmit.cpp:552
struct tx * tx_init(struct module *parent, unsigned mtu, enum tx_media_type media_type, const char *fec, const char *encryption, long long int bitrate)
Definition transmit.cpp:201
uint32_t get_local_mediatime_offset(void)
Definition tv.c:73
uint32_t get_std_video_local_mediatime(void)
Definition tv.c:204
uint32_t get_std_audio_local_mediatime(double samples, int rate)
Definition tv.c:185
uint32_t get_local_mediatime(void)
Definition tv.c:65
long long time_ns_t
Definition tv.h:81
static time_ns_t get_time_in_ns()
Definition tv.h:101
This file contains some common data types.
tx_media_type
Definition types.h:363
@ TX_MEDIA_AUDIO
Definition types.h:364
@ TX_MEDIA_VIDEO
Definition types.h:365
fec_type
Definition types.h:200
@ FEC_LDGM
Definition types.h:203
@ FEC_MULT
Definition types.h:202
@ FEC_RS
Definition types.h:204
@ FEC_NONE
Definition types.h:201
@ TIMESTAMP_VALID
timestamp set by source (in 90 kHz clock)
Definition types.h:223
@ kHz8
Definition types.h:147
interlacing_t
Definition types.h:163
uint32_t ug_rand(void)
Definition random.c:88
void remux_channel(char *out, const char *in, int bps, int in_len, int in_stream_channels, int out_stream_channels, int pos_in_stream, int pos_out_stream)
Definition utils.cpp:352
This is an umbrella header for video functions.
bool is_codec_opaque(codec_t codec)
int get_pf_block_bytes(codec_t codec)
returns codec_info_t::block_size_bytes
uint32_t get_fourcc(codec_t codec)
int get_pf_block_pixels(codec_t codec)
returns codec_info_t::block_size_pixels
#define PIX_BLOCK_LCM
least common multiple of all pixfmt block sizes in pixels (codec_info_t::block_size/codec_info_t::bpp...
Definition video_codec.h:66
struct tile * vf_get_tile(struct video_frame *buf, int pos)
Returns pointer to n-th tile from video frame Equivalent to &video_frame::tiles[pos].