UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
transmit.h File Reference
#include "audio/types.h"
#include "rtp/rtpenc_h264.h"
#include "types.h"
#include <cstdint>
Include dependency graph for transmit.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void audio_tx_send (struct tx *tx_session, struct rtp *rtp_session, const audio_frame2 *buffer)
 
void audio_tx_send_standard (struct tx *tx, struct rtp *rtp_session, const audio_frame2 *buffer)
 
void format_audio_header (const class audio_frame2 *frame, int channel, int buffer_idx, uint32_t *audio_hdr)
 
void format_video_header (struct video_frame *frame, int tile_idx, int buffer_idx, uint32_t *hdr)
 
int tx_get_buffer_id (struct tx *tx_session)
 
struct tx * tx_init (struct module *parent, unsigned mtu, enum tx_media_type media_type, const char *fec, const char *encryption, long long bitrate)
 
void tx_send (struct tx *tx_session, struct video_frame *frame, struct rtp *rtp_session)
 
void tx_send_h264 (struct tx *tx_session, struct video_frame *frame, struct rtp *rtp_session)
 
void tx_send_jpeg (struct tx *tx_session, struct video_frame *frame, struct rtp *rtp_session)
 

Function Documentation

◆ audio_tx_send()

void audio_tx_send ( struct tx * tx_session,
struct rtp * rtp_session,
const audio_frame2 * buffer )

Definition at line 799 of file transmit.cpp.

801{
802 if (!rtp_has_receiver(rtp_session)) {
803 return;
804 }
805
807
808 const uint32_t timestamp =
809 buffer->get_timestamp() == -1
811 : get_local_mediatime_offset() + buffer->get_timestamp();
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}
int get_channel_count() const
Definition types.cpp:260
int64_t get_timestamp() const
Definition types.cpp:340
bool rtp_has_receiver(struct rtp *session)
Definition rtp.c:4016
int mult_count
Definition transmit.cpp:150
unsigned int buffer
Definition transmit.cpp:143
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 fec_check_messages(struct tx *tx)
Definition transmit.cpp:354
uint32_t get_local_mediatime_offset(void)
Definition tv.c:73
uint32_t get_local_mediatime(void)
Definition tv.c:65

References audio_tx_send_chan(), tx::buffer, fec_check_messages(), audio_frame2::get_channel_count(), get_local_mediatime(), get_local_mediatime_offset(), audio_frame2::get_timestamp(), tx::mult_count, and rtp_has_receiver().

Referenced by audio_sender_thread(), and state_audio_mixer::worker().

Here is the call graph for this function:

◆ audio_tx_send_standard()

void audio_tx_send_standard ( struct tx * tx,
struct rtp * rtp_session,
const audio_frame2 * buffer )

audio_tx_send_standard - Send interleaved channels from the audio_frame2, as the mulaw and A-law standards (dynamic or std PT).

Definition at line 958 of file transmit.cpp.

959 {
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}
@ 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
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
static __device__ const float offset
Definition cuda_dxt.cu:139
void rtp_send_ctrl(struct rtp *session, uint32_t rtp_ts, rtcp_app_callback appcallback, time_ns_t curr_time)
Definition rtp.c:3409
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
#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
unsigned mtu
Definition transmit.cpp:137
char tmp_packet[RTP_MAX_MTU]
Definition transmit.cpp:163
uint32_t ts
Definition tfrc.c:101
static bool validate_std_audio(const audio_frame2 *buffer, int payload_size)
Definition transmit.cpp:933
uint32_t get_std_audio_local_mediatime(double samples, int rate)
Definition tv.c:185
static time_ns_t get_time_in_ns()
Definition tv.h:101
@ kHz8
Definition types.h:147
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

References AC_ALAW, AC_MP3, AC_MULAW, AC_OPUS, audio_frame2::get_channel_count(), audio_frame2::get_codec(), audio_frame2::get_data(), audio_frame2::get_data_len(), audio_frame2::get_duration(), audio_frame2::get_sample_rate(), get_std_audio_local_mediatime(), get_time_in_ns(), kHz8, tx::mtu, offset, PT_DynRTP_Type97, PT_ITU_T_G711_PCMA, PT_ITU_T_G711_PCMU, PT_MPA, remux_channel(), rtp_send_ctrl(), rtp_send_data(), tx::tmp_packet, ts, and validate_std_audio().

Referenced by audio_sender_thread().

Here is the call graph for this function:

◆ format_audio_header()

void format_audio_header ( const class audio_frame2 * frame,
int channel,
int buffer_idx,
uint32_t * audio_hdr )

◆ format_video_header()

void format_video_header ( struct video_frame * frame,
int tile_idx,
int buffer_idx,
uint32_t * hdr )

Definition at line 445 of file transmit.cpp.

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}
struct video_frame * frame
unsigned int width
Definition types.h:280
unsigned int data_len
length of the data
Definition types.h:288
unsigned int height
Definition types.h:281
enum interlacing_t interlacing
Definition types.h:307
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
double fps
Definition types.h:308
codec_t color_spec
Definition types.h:306
static uint32_t format_interl_fps_hdr_row(enum interlacing_t interlacing, double input_fps)
Definition transmit.cpp:478
uint32_t get_fourcc(codec_t codec)

References video_frame::color_spec, tile::data_len, format_interl_fps_hdr_row(), video_frame::fps, frame, get_fourcc(), tile::height, video_frame::interlacing, video_frame::tiles, and tile::width.

Referenced by rs::encode(), and tx_send_base().

Here is the call graph for this function:

◆ tx_get_buffer_id()

int tx_get_buffer_id ( struct tx * tx_session)

Returns buffer ID to be sent with next tx_send() call

Definition at line 1240 of file transmit.cpp.

1241{
1242 return tx->buffer;
1243
1244}

References tx::buffer.

◆ tx_init()

struct tx * tx_init ( struct module * parent,
unsigned mtu,
enum tx_media_type media_type,
const char * fec,
const char * encryption,
long long bitrate )

◆ tx_send()

void tx_send ( struct tx * tx_session,
struct video_frame * frame,
struct rtp * rtp_session )

Definition at line 407 of file transmit.cpp.

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}
#define TRUE
#define FALSE
unsigned int offset
Fragment offset from tile beginning (in bytes). Used only if frame is fragmented.
Definition types.h:292
enum fec_type fec_scheme
Definition transmit.cpp:148
uint32_t last_ts
Definition transmit.cpp:140
int last_frame_fragment_id
Definition transmit.cpp:141
int64_t timestamp
Definition types.h:331
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
unsigned int last_fragment
Used only if (fragment == 1). Indicates this is the last fragment.
Definition types.h:317
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
@ FEC_NONE
Definition types.h:201
@ TIMESTAMP_VALID
timestamp set by source (in 90 kHz clock)
Definition types.h:223
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].

References tx::buffer, FALSE, fec_check_messages(), FEC_NONE, tx::fec_scheme, video_frame::flags, video_frame::fragment, frame, video_frame::frame_fragment_id, get_local_mediatime(), get_local_mediatime_offset(), video_frame::last_fragment, tx::last_frame_fragment_id, tx::last_ts, tile::offset, video_frame::tile_count, video_frame::timestamp, TIMESTAMP_VALID, TRUE, ts, tx_send_base(), and vf_get_tile().

Referenced by ultragrid_rtp_video_rxtx::send_frame_async().

Here is the call graph for this function:

◆ tx_send_h264()

void tx_send_h264 ( struct tx * tx,
struct video_frame * frame,
struct rtp * rtp_session )

H.264 standard transmission

Definition at line 1057 of file transmit.cpp.

1058 {
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}
#define error_msg(...)
Definition debug.h:89
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
#define PT_DynRTP_Type96
Definition rtp_types.h:78
const unsigned char * rtpenc_get_next_nal(const unsigned char *start, long len, const unsigned char **endptr)
static void start()
Definition sdp.c:202
Struct tile is an area of video_frame.
Definition types.h:279
char * data
Raw tile data. Pointer must be at least 4B aligned.
Definition types.h:287
uint32_t get_std_video_local_mediatime(void)
Definition tv.c:204

References tile::data, tile::data_len, error_msg, FEC_NONE, tx::fec_scheme, video_frame::fragment, frame, get_std_video_local_mediatime(), tx::mtu, PT_DynRTP_Type96, rtp_send_data(), rtp_send_data_hdr(), rtpenc_get_next_nal(), start(), video_frame::tile_count, video_frame::tiles, and ts.

Referenced by h264_rtp_video_rxtx::configure_rtsp_server_video(), and h264_sdp_video_rxtx::send_frame().

Here is the call graph for this function:

◆ tx_send_jpeg()

void tx_send_jpeg ( struct tx * tx_session,
struct video_frame * frame,
struct rtp * rtp_session )

Definition at line 1168 of file transmit.cpp.

1169 {
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}
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
void exit_uv(int status)
Definition host.cpp:625
bool jpeg_get_rtp_hdr_data(uint8_t *jpeg_data, int len, struct jpeg_rtp_data *hdr_data)
bool rtp_is_ipv6(struct rtp *session)
Definition rtp.c:4022
#define PT_JPEG
Definition rtp_types.h:71
uint8_t * data
Definition jpeg_reader.h:86

References jpeg_rtp_data::data, tile::data, tile::data_len, exit_uv(), FEC_NONE, tx::fec_scheme, video_frame::fragment, frame, get_std_video_local_mediatime(), jpeg_rtp_data::height, jpeg_get_rtp_hdr_data(), LOG_LEVEL_ERROR, log_msg(), tx::mtu, PT_JPEG, jpeg_rtp_data::q, jpeg_rtp_data::quantization_tables, jpeg_rtp_data::restart_interval, rtp_is_ipv6(), rtp_send_data_hdr(), video_frame::tile_count, video_frame::tiles, ts, jpeg_rtp_data::type, and jpeg_rtp_data::width.

Referenced by h264_rtp_video_rxtx::configure_rtsp_server_video(), and h264_sdp_video_rxtx::send_frame().

Here is the call graph for this function: