MythTV master
rtcpdatapacket.h
Go to the documentation of this file.
1//
2// rtcpdatapacket.h
3// MythTV
4//
5// Created by Jean-Yves Avenard on 6/05/2014.
6// Copyright (c) 2014 Bubblestuff Pty Ltd. All rights reserved.
7//
8
9#ifndef MythTV_rtcpdatapacket_h
10#define MythTV_rtcpdatapacket_h
11
12#include <limits> // workaround QTBUG-90395
13
14#include <QHostAddress>
15#include <QByteArray>
16#include <QtEndian>
17
18#include "udppacket.h"
19
20#define RTP_VERSION 2
21#define RTCP_RR 201
22#define RTCP_SDES 202
23
38{
39public:
41 : UDPPacket(o),
45 { }
46
47 RTCPDataPacket(uint32_t timestamp, uint32_t last_timestamp,
48 uint32_t sequence, uint32_t last_sequence,
49 uint32_t lost, uint32_t lost_interval,
50 uint32_t ssrc)
51 : m_timestamp(timestamp), m_last_timestamp(last_timestamp),
52 m_sequence(sequence), m_last_sequence(last_sequence),
53 m_lost(lost), m_lost_interval(lost_interval),
54 m_ssrc(ssrc) { }
55
56 QByteArray GetData(void) const
57 {
58 QByteArray buffer;
59
60 if (m_sequence == 0)
61 {
62 // No packet received yet, send an empty RTPC RR packet
63 uchar rtcp[10];
64
65 rtcp[0] = RTP_VERSION << 6; // RTP version
66 rtcp[1] = RTCP_RR; // RTCP_RR
67 qToBigEndian((qint16)1, &rtcp[2]); // length in words - 1
68 qToBigEndian( 0, &rtcp[4]); // our own SSRC
69 buffer = QByteArray((char *)rtcp, 10);
70 }
71 else
72 {
73 static char *hostname = (char *)"MythTV";
74 uint32_t len = strlen(hostname);
75 auto *rtcp = new uchar[46 + len + 1];
76
77 rtcp[0] = (RTP_VERSION << 6) + 1; // 1 report block
78 rtcp[1] = RTCP_RR; // RTCP_RR)
79 qToBigEndian((qint16)7, &rtcp[2]); // length in words - 1
80 // our own SSRC: we use the server's SSRC + 1 to avoid conflicts
81 qToBigEndian((quint32)m_ssrc + 1, &rtcp[4]);
82 qToBigEndian((quint32)m_ssrc, &rtcp[8]);
83 // some placeholders we should really fill...
84 // RFC 1889/p 27
85
86// extended_max = stats->cycles + stats->max_seq;
87// expected = extended_max - stats->base_seq;
88// lost = expected - stats->received;
89// lost = FFMIN(lost, 0xffffff); // clamp it since it's only 24 bits...
90// expected_interval = expected - stats->expected_prior;
91// stats->expected_prior = expected;
92// received_interval = stats->received - stats->received_prior;
93// stats->received_prior = stats->received;
94// lost_interval = expected_interval - received_interval;
95// if (expected_interval == 0 || lost_interval <= 0)
96// fraction = 0;
97// else
98// fraction = (lost_interval << 8) / expected_interval;
99//
100// fraction = (fraction << 24) | lost;
101// avio_wb32(pb, fraction); /* 8 bits of fraction, 24 bits of total packets lost */
102// avio_wb32(pb, extended_max); /* max sequence received */
103// avio_wb32(pb, stats->jitter >> 4); /* jitter */
104//
105// if (s->last_rtcp_ntp_time == AV_NOPTS_VALUE) {
106// avio_wb32(pb, 0); /* last SR timestamp */
107// avio_wb32(pb, 0); /* delay since last SR */
108// } else {
109// uint32_t middle_32_bits = s->last_rtcp_ntp_time >> 16; // this is valid, right? do we need to handle 64 bit values special?
110// uint32_t delay_since_last = av_rescale(av_gettime() - s->last_rtcp_reception_time,
111// 65536, AV_TIME_BASE);
112//
113// avio_wb32(pb, middle_32_bits); /* last SR timestamp */
114// avio_wb32(pb, delay_since_last); /* delay since last SR */
115// }
116
117 qToBigEndian((quint32) 0, &rtcp[12]); /* 8 bits of fraction, 24 bits of total packets lost */
118 qToBigEndian((quint32) 0, &rtcp[16]); /* max sequence received */
119 qToBigEndian((quint32) 0, &rtcp[20]); /* jitter */
120
121 qToBigEndian((quint32) m_timestamp, &rtcp[24]); /* last SR timestamp */
122 qToBigEndian((quint32) m_last_timestamp, &rtcp[28]); /* delay since last SR timestamp */
123
124 // CNAME
125 rtcp[32] = (RTP_VERSION << 6) + 1; // 1 report block
126 rtcp[33] = RTCP_SDES; // RTCP_SDES)
127 qToBigEndian((qint16)((7 + len + 3) / 4), &rtcp[34]); /* length in words - 1 */
128 qToBigEndian((quint32)m_ssrc, &rtcp[36]);
129 qToBigEndian((quint32)m_ssrc + 1, &rtcp[40]);
130
131 buffer = QByteArray((char *)rtcp, 44);
132
133 buffer.append((char)0x01); //44
134 buffer.append((char)len); //45
135 buffer.append(hostname, len); //46
136 buffer.append((char)0); // 46 + len END
137
138 // padding
139 for (len = (7 + len) % 4; len % 4; len++)
140 {
141 buffer.append((char)0);
142 }
143 delete[] rtcp;
144 }
145 return buffer;
146 }
147
149 {
150 return m_sequence;
151 }
152
153protected:
154 uint32_t m_timestamp;
156 uint32_t m_sequence;
158 uint32_t m_lost;
159 uint32_t m_lost_interval {0};
160 uint32_t m_ssrc;
161};
162#endif
RTCP Data Packet.
uint32_t m_lost_interval
RTCPDataPacket(const RTCPDataPacket &o)
RTCPDataPacket(uint32_t timestamp, uint32_t last_timestamp, uint32_t sequence, uint32_t last_sequence, uint32_t lost, uint32_t lost_interval, uint32_t ssrc)
uint32_t m_sequence
uint32_t m_last_sequence
uint32_t m_last_timestamp
uint GetSequenceNumber(void) const
uint32_t m_timestamp
QByteArray GetData(void) const
UDP Packet.
Definition: udppacket.h:21
unsigned int uint
Definition: freesurround.h:24
string hostname
Definition: caa.py:17
#define RTP_VERSION
#define RTCP_RR
#define RTCP_SDES