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