@@ -1177,6 +1177,73 @@ void tx_send_h264(struct tx *tx, struct video_frame *frame,
11771177 }
11781178}
11791179
1180+ /* *
1181+ * send aggregate packet if possible to aggregate more NALUs (optional)
1182+ * @todo consider this also for tx_send_h264
1183+ */
1184+ static bool
1185+ send_h265_aggregate (struct rtp *rtp_session, const char pt, const uint32_t ts,
1186+ unsigned max_packet_size, const unsigned char **nal_p,
1187+ uint16_t nalsize_1st, const unsigned char *const end)
1188+ {
1189+ enum {
1190+ AP_THRESH = 100 , // aggregate just small pckts (will be copied)
1191+ };
1192+ if (nalsize_1st > AP_THRESH || end - *nal_p == nalsize_1st) {
1193+ return false ;
1194+ }
1195+ unsigned char ap_data[RTP_MAX_PACKET_LEN];
1196+ unsigned char *pkt_end = ap_data;
1197+ const unsigned char *nal = *nal_p;
1198+ const int layer_id0 = (nal[0 ] & 0x1 ) << 5 & nal[1 ] >> 3 ;
1199+ const int tid0 = nal[1 ] & 0x7 ;
1200+ const unsigned char *endptr = nullptr ;
1201+ bool emit_ap = false ;
1202+ while ((nal = rtpenc_get_next_nal (nal, end - nal, &endptr)) !=
1203+ nullptr ) {
1204+ const int layer_id = (nal[0 ] & 0x1 ) << 5 & nal[1 ] >> 3 ;
1205+ const int tid = nal[1 ] & 0x7 ;
1206+ if (layer_id != layer_id0 || tid != tid0) { // not compatible
1207+ break ;
1208+ }
1209+ const uint16_t sz = endptr - nal;
1210+ if (sz > AP_THRESH) {
1211+ break ;
1212+ }
1213+ if (ap_data - pkt_end + sz > max_packet_size) {
1214+ break ; // woultd exceed MTU
1215+ }
1216+ if (!emit_ap) { // aggregate pkt will be generated - write
1217+ // first pkt data
1218+ // AP header
1219+ *pkt_end++ = NAL_RTP_HEVC_AP << 1 | layer_id >> 5 ;
1220+ *pkt_end++ = layer_id << 3 | tid;
1221+ const uint16_t sz_n = htons (nalsize_1st);
1222+ memcpy (pkt_end, &sz_n, sizeof sz_n);
1223+ pkt_end += sizeof sz_n;
1224+ memcpy (pkt_end, *nal_p, nalsize_1st);
1225+ pkt_end += nalsize_1st;
1226+ }
1227+ emit_ap = true ;
1228+ *nal_p = nal;
1229+ const uint16_t sz_n = htons (sz);
1230+ memcpy (pkt_end, &sz_n, sizeof sz_n);
1231+ pkt_end += sizeof sz_n;
1232+ memcpy (pkt_end, nal, sz);
1233+ pkt_end += sz;
1234+ }
1235+ if (emit_ap) {
1236+ if (rtp_send_data_hdr (rtp_session, ts, pt, 1 /* m */ , 0 ,
1237+ nullptr , (char *) nullptr , 0 ,
1238+ (char *) ap_data, pkt_end - ap_data,
1239+ nullptr , 0 , 0 ) < 0 ) {
1240+ error_msg (" There was a problem sending the RTP "
1241+ " packet\n " );
1242+ }
1243+ }
1244+ return emit_ap;
1245+ }
1246+
11801247void tx_send_h265 (struct tx *tx, struct video_frame *frame,
11811248 struct rtp *rtp_session) {
11821249 assert (frame->tile_count == 1 );
@@ -1195,6 +1262,11 @@ void tx_send_h265(struct tx *tx, struct video_frame *frame,
11951262 while ((nal = rtpenc_get_next_nal (nal, end - nal, &endptr))) {
11961263 unsigned int nalsize = endptr - nal;
11971264
1265+ if (send_h265_aggregate (rtp_session, pt, ts, maxPacketSize,
1266+ &nal, nalsize, end)) {
1267+ continue ;
1268+ }
1269+
11981270 if (nalsize <= maxPacketSize) { // single NALU packet
11991271 char *payload = const_cast <char *>(
12001272 reinterpret_cast <const char *>(nal));
0 commit comments