88#define MOD_NAME "[transmit] "
89#define TRANSMIT_MAGIC 0xe80ab15f
91#define FEC_MAX_MULT 10
93#define CONTROL_PORT_BANDWIDTH_REPORT_INTERVAL_NS NS_IN_SEC
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
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);
118 uint32_t
ts,
int send_m,
119 unsigned int substream,
120 int fragment_offset);
182 data_len = (data_len / 48) * 48;
187 snprintf(
msg->fec_cfg,
sizeof(
msg->fec_cfg),
"LDGM percents %d %d %f",
214 struct tx *
tx = (
struct tx *) calloc(1,
sizeof(
struct tx));
243 fprintf(stderr,
"UltraGrid was build without OpenSSL support!\n");
265 char *
fec = strdup(fec_const);
267 bool req_1st_pkt_dup =
true;
270 char *end =
fec +
MAX(strlen(
fec), 5) - 5;
271 if (strcmp(end,
"nodup") == 0) {
272 req_1st_pkt_dup =
true;
279 const char *fec_cfg =
"";
280 if(strchr(
fec,
':')) {
281 char *delim = strchr(
fec,
':');
290 snprintf(
msg->fec_cfg,
sizeof(
msg->fec_cfg),
"flush");
293 if (strcasecmp(
fec,
"none") == 0) {
295 }
else if(strcasecmp(
fec,
"mult") == 0) {
300 "mult count must be between 1 and %d (%d given)!\n",
304 }
else if(strcasecmp(
fec,
"LDGM") == 0) {
307 fprintf(stderr,
"LDGM is not currently supported for audio!\n");
312 strchr(
fec_cfg,
'%') ==
nullptr)) {
313 snprintf(
msg->fec_cfg,
sizeof(
msg->fec_cfg),
320 }
else if(strcasecmp(
fec,
"RS") == 0) {
322 snprintf(
msg->fec_cfg,
sizeof(
msg->fec_cfg),
"RS cfg %s",
325 }
else if(strcasecmp(
fec,
"help") == 0) {
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");
333 fprintf(stderr,
"Unknown FEC: %s\n",
fec);
338 MSG(VERBOSE,
"Duplicating 1st packet of every frame for better "
339 "error resiliency.\n");
359 const char *text = data->
text;
368 text += strlen(
"fec ");
376 }
else if (strstr(
text,
"rate ") ==
text) {
377 text += strlen(
"rate ");
430 int fragment_offset = 0;
452 tmp = tile_idx << 22;
453 tmp |= 0x3fffff & buffer_idx;
454 video_hdr[0] = htonl(tmp);
463 tmp = channel << 22U;
465 audio_hdr[0] = htonl(tmp);
467 audio_hdr[2] = htonl(
frame->get_data_len(channel));
470 tmp = (
frame->get_bps() * 8) << 26U;
471 tmp |=
frame->get_sample_rate();
472 audio_hdr[3] = htonl(tmp);
480 unsigned int fpsd, fd, fps, fi;
483 tmp = interlacing << 29;
484 fps =
round(input_fps);
488 if (input_fps > 1.0 && fabs(input_fps -
round(input_fps) / 1.001) < 0.005) {
490 }
else if (fps < 1.0) {
491 fps =
round(1.0 / input_fps);
504 thread_local static bool status_printed =
false;
510 if (fec_symbol_size > payload_len) {
512 "Warning: FEC symbol size exceeds payload size! "
513 "FEC symbol size: " << fec_symbol_size
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
524 status_printed =
true;
537 int symbol_size,
int *symbol_offset)
539 if (symbol_size >
mtu) {
540 if (symbol_size - *symbol_offset <=
mtu) {
541 mtu = symbol_size - *symbol_offset;
544 *symbol_offset +=
mtu;
548 return mtu / symbol_size * symbol_size;
557 unsigned int symbol_size = 1;
558 int symbol_offset = 0;
562 assert(pf_block_size <=
mtu);
563 mtu =
mtu / pf_block_size * pf_block_size;
570 int len = symbol_size == 1
575 }
while (pos < frame->tiles[substream].data_len);
578 ret[ret.size() - 1] -=
601 std::ostringstream oss;
602 oss <<
"tx_send " << std::hex <<
rtp_my_ssrc(rtp_session) << std::dec
620 double interval_between_pkts = time_for_frame /
tx->
mult_count / packet_count;
623 interval_between_pkts = interval_between_pkts * 0.75;
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;
629 return packet_rate_auto;
634 packet_rate_auto /= 2;
640 return packet_rate_auto;
660 uint32_t
ts,
int send_m,
661 unsigned int substream,
664 assert(fragment_offset == 0);
672 uint32_t rtp_hdr[100];
676 struct timespec
start, stop;
677#elif defined __APPLE__
678 struct timeval
start, stop;
680 LARGE_INTEGER
start, stop, freq;
682 long delta, overslept = 0;
696 uint32_t tmp = substream << 22;
699 rtp_hdr[0] = htonl(tmp);
710 rtp_hdr[rtp_hdr_len /
sizeof(uint32_t)] =
716 long mult_pkt_cnt = (long) packet_sizes.size() *
tx->
mult_count;
722 void *rtp_headers = malloc((mult_pkt_cnt + 1) * rtp_hdr_len);
723 uint32_t *rtp_hdr_packet = (uint32_t *) rtp_headers;
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);
735 memcpy(rtp_hdr_packet, rtp_hdr, rtp_hdr_len);
736 rtp_hdr_packet[1] = htonl(0);
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());
754 (
char *) rtp_hdr_packet,
762 data = encrypted_data;
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);
781 const long data_sent =
tile->
data_len + rtp_hdr_len * mult_pkt_cnt;
792 int channel,
bool send_m);
808 const uint32_t timestamp =
834 uint32_t rtp_hdr[100];
838 unsigned int fec_symbol_size =
841 const char *chan_data = buffer->
get_data(channel);
851 uint32_t tmp = channel << 22;
854 rtp_hdr[0] = htonl(tmp);
865 rtp_hdr[rtp_hdr_len /
sizeof(uint32_t)] =
875 const int max_len =
tx->
mtu - hdrs_len;
877 const char *data = chan_data + pos;
878 int data_len = max_len;
879 if (pos + data_len >=
886 rtp_hdr[1] = htonl(pos);
899 data = encrypted_data;
902 data_sent += data_len + rtp_hdr_len;
907 (
char *) rtp_hdr, rtp_hdr_len,
908 const_cast<char *
>(data), data_len, 0, 0, 0);
910 }
while (pos < buffer->get_data_len(channel));
918 const int packet_count =
919 (buffer->
get_data_len(channel) + max_len - 1) / max_len;
920 if (packet_count > 3) {
923 const char *pl_suffix = packet_count == 1 ?
"" :
"s";
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.)" :
"");
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 "
948 MSG(ERROR,
"Opus frame larger than packet! Discarding...\n");
967 static uint32_t ts_prev = 0;
975 const bool is_pcma_u =
991 int payload_size =
tx->
mtu - 40 - 8 - 12;
996 payload_size = payload_size / frame_size * frame_size;
1003 }
else if (pt ==
PT_MPA) {
1013 int pkt_len = std::min(payload_size, data_len - pos);
1019 const uint16_t
offset = htons(pos);
1051 }
while (pos < data_len);
1058 struct rtp *rtp_session) {
1066 unsigned char hdr[2];
1071 uint16_t extn_len = 0;
1072 uint16_t extn_type = 0;
1075 unsigned maxPacketSize =
tx->
mtu - 40;
1077 const unsigned char *endptr = 0;
1078 const unsigned char *nal =
start;
1081 unsigned int nalsize = endptr - nal;
1083 bool lastNALUnitFragment =
false;
1084 unsigned curNALOffset = 0;
1085 char *nalc =
const_cast<char *
>(
reinterpret_cast<const char *
>(nal));
1087 while(!lastNALUnitFragment){
1098 if (curNALOffset == 0) {
1099 if (nalsize <= maxPacketSize) {
1104 extn, extn_len, extn_type) < 0) {
1105 error_msg(
"There was a problem sending the RTP packet\n");
1107 lastNALUnitFragment =
true;
1112 hdr[0] = (nal[0] & 0xE0) | 28;
1113 hdr[1] = 0x80 | (nal[0] & 0x1F);
1117 nalc + 1, maxPacketSize - 2,
1118 extn, extn_len, extn_type) < 0) {
1119 error_msg(
"There was a problem sending the RTP packet\n");
1121 curNALOffset += maxPacketSize - 1;
1122 lastNALUnitFragment =
false;
1123 nalsize -= maxPacketSize - 1;
1131 hdr[1] = hdr[1] & ~0x80;
1133 if (nalsize + 1 > maxPacketSize) {
1137 nalc + curNALOffset,
1138 maxPacketSize - 2, extn, extn_len,
1140 error_msg(
"There was a problem sending the RTP packet\n");
1142 curNALOffset += maxPacketSize - 2;
1143 lastNALUnitFragment =
false;
1144 nalsize -= maxPacketSize - 2;
1154 nalc + curNALOffset,
1155 nalsize, extn, extn_len, extn_type) < 0) {
1156 error_msg(
"There was a problem sending the RTP packet\n");
1158 lastNALUnitFragment =
true;
1169 struct rtp *rtp_session) {
1187 uint32_t jpeg_hdr[2 + 1 + 129 ];
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);
1194 jpeg_hdr[hdr_off++] = htonl(d.
restart_interval << 16u | 1u << 15u | 1u << 14u | 0x3fffu);
1198 unsigned int mbz = 0u;
1199 unsigned int precision = 0u;
1200 unsigned int qt_len = 2 * 64u;
1201 jpeg_hdr[hdr_off++] = htonl(mbz << 24u | precision << 16u | qt_len);
1203 hdr_off += 64 /
sizeof(uint32_t);
1205 hdr_off += 64 /
sizeof(uint32_t);
1212 int fragment_offset = 0;
1215 if (fragment_offset == 0) {
1216 hdr_len = hdr_off *
sizeof(uint32_t);
1220 int data_len = max_mtu - hdr_len;
1222 if (bytes_left <= data_len) {
1223 data_len = bytes_left;
1226 jpeg_hdr[0] = htonl(type_spec << 24u | fragment_offset);
1229 (
char *) &jpeg_hdr, hdr_len,
1230 data, data_len, 0, 0, 0);
1235 bytes_left -= data_len;
1236 fragment_offset += data_len;
1237 }
while (bytes_left > 0);
struct video_frame * frame
int vc_get_linesize(unsigned int width, codec_t codec)
This file contains definition of some common audio types.
char * get_data(int channel)
audio_codec_t get_codec() const
int get_channel_count() const
int64_t get_timestamp() const
fec_desc const & get_fec_params(int channel) const
size_t get_data_len(int channel) const
double get_duration() const
int get_sample_rate() const
const char * get_name_to_audio_codec(audio_codec_t codec)
uint32_t get_audio_tag(audio_codec_t codec)
int color_printf(const char *format,...)
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)
static __device__ vec3 round(const vec3 &v)
static __device__ const float offset
void log_msg(int level, const char *format,...)
void log_msg_once(int level, uint32_t id, const char *msg,...)
#define LOG_LEVEL_NOTICE
information that may be interesting
#define LOG_LEVEL_INFO
normal reporting
#define LOG_LEVEL_ERROR
general errors
#define LOG_LEVEL_WARNING
less severe errors
int fec_pt_from_fec_type(enum tx_media_type media_type, enum fec_type fec_type, bool encrypted)
void module_init_default(struct module *module_data)
void module_register(struct module *module_data, struct module *parent)
struct module * get_module(struct module *root, const char *const_path)
void module_done(struct module *module_data)
struct module * get_root_module(struct module *node)
struct module * get_parent_module(struct module *node)
#define RATE_AUTO
spread packets evenly across frame time (currently 3/4)
#define RATE_FLAG_FIXED_RATE
use the bitrate as fixed, not capped
#define RATE_DYNAMIC
same as RATE_AUTO but occasional excess frame allowed
bool jpeg_get_rtp_hdr_data(uint8_t *jpeg_data, int len, struct jpeg_rtp_data *hdr_data)
const void * load_library(const char *name, enum library_class cls, int abi_version)
@ LIBRARY_CLASS_UNDEFINED
#define to_fourcc(a, b, c, d)
Creates FourCC word.
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)
#define RESPONSE_BAD_REQUEST
#define RESPONSE_INT_SERV_ERR
#define MSG_UNIVERSAL_TAG_TX
long long unit_evaluate(const char *str, const char **endptr)
#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)
uint32_t rtp_my_ssrc(struct rtp *session)
void rtp_send_ctrl(struct rtp *session, uint32_t rtp_ts, rtcp_app_callback appcallback, time_ns_t curr_time)
bool rtp_has_receiver(struct rtp *session)
bool rtp_is_ipv6(struct rtp *session)
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)
void rtp_async_wait(struct rtp *session)
void rtp_async_start(struct rtp *session, int nr_packets)
#define RTP_MAX_PACKET_LEN
#define PT_ITU_T_G711_PCMU
#define PT_ITU_T_G711_PCMA
uint32_t audio_payload_hdr_t[5]
uint32_t fec_payload_hdr_t[5]
uint32_t crypto_payload_hdr_t[1]
uint32_t video_payload_hdr_t[6]
const unsigned char * rtpenc_get_next_nal(const unsigned char *start, long len, const unsigned char **endptr)
uint8_t * quantization_tables[2]
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
long long last_excess
nr of frames last excessive frame was emitted
unsigned long avg_frame_size
moving average
Struct tile is an area of video_frame.
char * data
Raw tile data. Pointer must be at least 4B aligned.
unsigned int data_len
length of the data
unsigned int offset
Fragment offset from tile beginning (in bytes). Used only if frame is fragmented.
unsigned long int sent_frames
struct rate_limit_dyn dyn_rate_limit_state
const struct openssl_encrypt_info * enc_funcs
char tmp_packet[RTP_MAX_MTU]
enum tx_media_type media_type
int last_frame_fragment_id
struct openssl_encrypt * encryption
uint64_t last_stat_report
struct control_state * control
Struct video_frame represents a video frame and contains video description.
enum interlacing_t interlacing
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
unsigned int frame_fragment_id
Used only if (fragment == 1). ID of the frame. Fragments of same frame must have the same ID.
unsigned int fragment
Indicates that the tile is fragmented. Normally not used (only for Bluefish444).
struct fec_desc fec_params
unsigned int last_fragment
Used only if (fragment == 1). Indicates this is the last fragment.
void tx_send_jpeg(struct tx *tx, struct video_frame *frame, struct rtp *rtp_session)
static void report_stats(struct tx *tx, struct rtp *rtp_session, long data_sent)
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)
static void check_symbol_size(int fec_symbol_size, int payload_len)
static bool validate_std_audio(const audio_frame2 *buffer, int payload_size)
static int get_tx_hdr_len(bool is_ipv6)
static bool set_fec(struct tx *tx, const char *fec)
static void tx_update(struct tx *tx, struct video_frame *frame, int substream)
static uint32_t format_interl_fps_hdr_row(enum interlacing_t interlacing, double input_fps)
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)
void format_video_header(struct video_frame *frame, int tile_idx, int buffer_idx, uint32_t *video_hdr)
void tx_send_h264(struct tx *tx, struct video_frame *frame, struct rtp *rtp_session)
#define CONTROL_PORT_BANDWIDTH_REPORT_INTERVAL_NS
static void tx_done(struct module *tx)
void audio_tx_send(struct tx *tx, struct rtp *rtp_session, const audio_frame2 *buffer)
static long get_packet_rate(struct tx *tx, struct video_frame *frame, int substream, long packet_count)
static void fec_check_messages(struct tx *tx)
void format_audio_header(const audio_frame2 *frame, int channel, int buffer_idx, uint32_t *audio_hdr)
int tx_get_buffer_id(struct tx *tx)
static int get_video_pkt_len(int mtu, int symbol_size, int *symbol_offset)
void tx_send(struct tx *tx, struct video_frame *frame, struct rtp *rtp_session)
void audio_tx_send_standard(struct tx *tx, struct rtp *rtp_session, const audio_frame2 *buffer)
static vector< int > get_packet_sizes(struct video_frame *frame, int substream, int mtu)
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)
uint32_t get_local_mediatime_offset(void)
uint32_t get_std_video_local_mediatime(void)
uint32_t get_std_audio_local_mediatime(double samples, int rate)
uint32_t get_local_mediatime(void)
static time_ns_t get_time_in_ns()
This file contains some common data types.
@ TIMESTAMP_VALID
timestamp set by source (in 90 kHz clock)
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)
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...
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].