MythTV  master
mythraopconnection.h
Go to the documentation of this file.
1 #ifndef MYTHRAOPCONNECTION_H
2 #define MYTHRAOPCONNECTION_H
3 
4 #include <QObject>
5 #include <QMap>
6 #include <QHash>
7 #include <QHostAddress>
8 #include <QStringList>
9 
10 #include <openssl/rsa.h>
11 #include <openssl/pem.h>
12 #include <openssl/aes.h>
13 
14 #include "mythtvexp.h"
15 
16 #include "mythnotification.h"
17 
18 extern "C" {
19 #include "libavcodec/avcodec.h"
20 #include "libavformat/avformat.h"
21 }
22 
23 class QTcpSocket;
24 class QUdpSocket;
25 class QTimer;
26 class AudioOutput;
27 class ServerPool;
28 class RaopNetStream;
29 
30 using RawHash = QHash<QString,QString>;
31 
32 struct AudioData
33 {
34  uint8_t *data;
35  int32_t length;
36  int32_t frames;
37 };
38 
40 {
42  QList<AudioData> *data;
43 };
44 
45 class MTV_PUBLIC MythRAOPConnection : public QObject
46 {
47  Q_OBJECT
48 
49  friend class MythRAOPDevice;
50 
51  public:
52  MythRAOPConnection(QObject *parent, QTcpSocket *socket, QByteArray id,
53  int port);
54  ~MythRAOPConnection() override;
55  bool Init(void);
56  QTcpSocket *GetSocket() { return m_socket; }
57  int GetDataPort() const { return m_dataPort; }
58  bool HasAudio() { return m_audio; }
59  static QMap<QString,QString> decodeDMAP(const QByteArray &dmap);
60  static RSA *LoadKey(void);
61  static QString RSALastError(void) { return g_rsaLastError; }
62 
63  private slots:
64  void readClient(void);
65  void udpDataReady(QByteArray buf, const QHostAddress& peer, quint16 port);
66  void timeout(void);
67  void audioRetry(void);
68  void newEventClient(QTcpSocket *client);
69  void deleteEventClient();
70 
71  private:
72  void ProcessSync(const QByteArray &buf);
73  void SendResendRequest(std::chrono::milliseconds timestamp,
74  uint16_t expected, uint16_t got);
75  void ExpireResendRequests(std::chrono::milliseconds timestamp);
76  uint32_t decodeAudioPacket(uint8_t type, const QByteArray *buf,
77  QList<AudioData> *dest);
78  int ExpireAudio(std::chrono::milliseconds timestamp);
79  void ResetAudio(void);
80  void ProcessRequest(const QStringList &header,
81  const QByteArray &content);
82  static void FinishResponse(RaopNetStream *stream, QTcpSocket *socket,
83  QString &option, QString &cseq, QString &responseData);
84  void FinishAuthenticationResponse(RaopNetStream *stream, QTcpSocket *socket,
85  QString &cseq);
86 
87  static RawHash FindTags(const QStringList &lines);
88  bool CreateDecoder(void);
89  void DestroyDecoder(void);
90  bool OpenAudioDevice(void);
91  void CloseAudioDevice(void);
92  void StartAudioTimer(void);
93  void StopAudioTimer(void);
94  void CleanUp(void);
95 
96  // time sync
97  void SendTimeRequest(void);
98  void ProcessTimeResponse(const QByteArray &buf);
99  static std::chrono::milliseconds NTPToLocal(uint32_t sec, uint32_t ticks);
100  static void microsecondsToNTP(std::chrono::microseconds usec, uint32_t &ntpSec, uint32_t &ntpTicks);
101  static void timevalToNTP(timeval t, uint32_t &ntpSec, uint32_t &ntpTicks);
102 
103  // incoming data packet
104  static bool GetPacketType(const QByteArray &buf, uint8_t &type,
105  uint16_t &seq, uint64_t &timestamp);
106 
107  // utility functions
108  std::chrono::milliseconds AudioCardLatency(void);
109  static QStringList splitLines(const QByteArray &lines);
110  static QString stringFromSeconds(int timeInSeconds);
111  std::chrono::milliseconds framesToMs(uint64_t frames) const;
112  uint64_t MsToFrame(std::chrono::milliseconds millis) const;
113 
114  // notification functions
115  void SendNotification(bool update = false);
116 
117  QTimer *m_watchdogTimer {nullptr};
118  // comms socket
119  QTcpSocket *m_socket {nullptr};
120  RaopNetStream *m_textStream {nullptr};
121  QByteArray m_hardwareId;
122  QStringList m_incomingHeaders;
123  QByteArray m_incomingContent;
124  bool m_incomingPartial {false};
125  int32_t m_incomingSize {0};
126  QHostAddress m_peerAddress;
127  ServerPool *m_dataSocket {nullptr};
129  ServerPool *m_clientControlSocket {nullptr};
130  int m_clientControlPort {0};
131  ServerPool *m_clientTimingSocket {nullptr};
132  int m_clientTimingPort {0};
133  ServerPool *m_eventServer {nullptr};
134  int m_eventPort {-1};
135  QList<QTcpSocket *> m_eventClients;
136 
137  // incoming audio
138  QMap<uint16_t,std::chrono::milliseconds> m_resends;
139  // crypto
140  QByteArray m_aesIV;
141  AES_KEY m_aesKey {};
142  static RSA *g_rsa;
143  static QString g_rsaLastError;
144  // audio out
145  AudioOutput *m_audio {nullptr};
146  AVCodec *m_codec {nullptr};
147  AVCodecContext *m_codecContext {nullptr};
148  QList<int> m_audioFormat;
149  int m_channels {2};
150  int m_sampleSize {16};
151  int m_frameRate {44100};
152  int m_framesPerPacket {352};
153  QTimer *m_dequeueAudioTimer {nullptr};
154 
155  QMap<std::chrono::milliseconds, AudioPacket> m_audioQueue;
156  uint32_t m_queueLength {0};
157  bool m_streamingStarted {false};
158  bool m_allowVolumeControl {true};
159 
160  // packet index, increase after each resend packet request
161  uint16_t m_seqNum {0};
162  // audio/packet sync
163  uint16_t m_lastSequence {0};
164  std::chrono::milliseconds m_lastTimestamp {0ms};
165  std::chrono::milliseconds m_currentTimestamp {0ms};
166  uint16_t m_nextSequence {0};
167  std::chrono::milliseconds m_nextTimestamp {0ms};
168  std::chrono::milliseconds m_bufferLength {0ms};
169  std::chrono::milliseconds m_timeLastSync {0ms};
170  std::chrono::milliseconds m_cardLatency {-1ms};
171  std::chrono::milliseconds m_adjustedLatency {-1ms};
172  bool m_audioStarted {false};
173 
174  // clock sync
175  std::chrono::milliseconds m_networkLatency {0ms};
176  // Difference in ms between reference. This value will typically
177  // be huge (~50 years)and meaningless as Apple products seem to
178  // only send uptimes, not wall times.
179  std::chrono::milliseconds m_clockSkew {0ms};
180 
181  // audio retry timer
182  QTimer *m_audioTimer {nullptr};
183 
184  //Current Stream Info
185  uint32_t m_progressStart {0};
186  uint32_t m_progressCurrent {0};
187  uint32_t m_progressEnd {0};
188  QByteArray m_artwork;
190 
191  //Authentication
192  QString m_nonce;
193 
194  // Notification Center registration Id
195  int m_id;
196  bool m_firstSend {false};
197  bool m_playbackStarted {false};
198 
199  private slots:
200  void ProcessAudio(void);
201 };
202 
203 #endif // MYTHRAOPCONNECTION_H
AudioPacket::data
QList< AudioData > * data
Definition: mythraopconnection.h:42
MythRAOPConnection::g_rsa
static RSA * g_rsa
Definition: mythraopconnection.h:142
build_compdb.dest
dest
Definition: build_compdb.py:9
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
MythRAOPConnection::m_dataPort
int m_dataPort
Definition: mythraopconnection.h:128
MythRAOPConnection::m_resends
QMap< uint16_t, std::chrono::milliseconds > m_resends
Definition: mythraopconnection.h:138
MythRAOPConnection::m_eventClients
QList< QTcpSocket * > m_eventClients
Definition: mythraopconnection.h:135
MythRAOPConnection::GetSocket
QTcpSocket * GetSocket()
Definition: mythraopconnection.h:56
ServerPool
Manages a collection of sockets listening on different ports.
Definition: serverpool.h:58
mythtvexp.h
build_compdb.content
content
Definition: build_compdb.py:38
AudioData::frames
int32_t frames
Definition: mythraopconnection.h:36
RaopNetStream
Definition: mythraopconnection.cpp:51
AudioData
Definition: mythraopconnection.h:32
MythRAOPConnection::m_artwork
QByteArray m_artwork
Definition: mythraopconnection.h:188
AudioPacket
Definition: mythraopconnection.h:39
RawHash
QHash< QString, QString > RawHash
Definition: mythraopconnection.h:30
AudioPacket::seq
uint16_t seq
Definition: mythraopconnection.h:41
MythRAOPConnection::GetDataPort
int GetDataPort() const
Definition: mythraopconnection.h:57
AudioOutput
Definition: audiooutput.h:26
AudioData::data
uint8_t * data
Definition: mythraopconnection.h:34
MythRAOPDevice
Definition: mythraopdevice.h:20
hardwareprofile.i18n.t
t
Definition: i18n.py:36
MythRAOPConnection::m_hardwareId
QByteArray m_hardwareId
Definition: mythraopconnection.h:121
MythRAOPConnection::m_nonce
QString m_nonce
Definition: mythraopconnection.h:192
MythRAOPConnection::m_dmap
DMAP m_dmap
Definition: mythraopconnection.h:189
MythRAOPConnection::m_incomingContent
QByteArray m_incomingContent
Definition: mythraopconnection.h:123
MythRAOPConnection::HasAudio
bool HasAudio()
Definition: mythraopconnection.h:58
AudioData::length
int32_t length
Definition: mythraopconnection.h:35
MythRAOPConnection::m_incomingHeaders
QStringList m_incomingHeaders
Definition: mythraopconnection.h:122
mythnotification.h
MythRAOPConnection::m_peerAddress
QHostAddress m_peerAddress
Definition: mythraopconnection.h:126
MythRAOPConnection::m_id
int m_id
Definition: mythraopconnection.h:195
MythRAOPConnection::m_aesIV
QByteArray m_aesIV
Definition: mythraopconnection.h:140
MTV_PUBLIC
#define MTV_PUBLIC
Definition: mythtvexp.h:15
MythRAOPConnection::g_rsaLastError
static QString g_rsaLastError
Definition: mythraopconnection.h:143
MythRAOPConnection::RSALastError
static QString RSALastError(void)
Definition: mythraopconnection.h:61
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3
MythRAOPConnection::m_audioQueue
QMap< std::chrono::milliseconds, AudioPacket > m_audioQueue
Definition: mythraopconnection.h:155
DMAP
QMap< QString, QString > DMAP
Definition: mythnotification.h:26
MythRAOPConnection
Definition: mythraopconnection.h:45
MythRAOPConnection::m_audioFormat
QList< int > m_audioFormat
Definition: mythraopconnection.h:148