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 _NetStream;
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() { 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(uint64_t timestamp,
74  uint16_t expected, uint16_t got);
75  void ExpireResendRequests(uint64_t timestamp);
76  uint32_t decodeAudioPacket(uint8_t type, const QByteArray *buf,
77  QList<AudioData> *dest);
78  int ExpireAudio(uint64_t timestamp);
79  void ResetAudio(void);
80  void ProcessRequest(const QStringList &header,
81  const QByteArray &content);
82  static void FinishResponse(_NetStream *stream, QTcpSocket *socket,
83  QString &option, QString &cseq, QString &responseData);
84  void FinishAuthenticationResponse(_NetStream *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 uint64_t NTPToLocal(uint32_t sec, uint32_t ticks);
100 
101  // incoming data packet
102  static bool GetPacketType(const QByteArray &buf, uint8_t &type,
103  uint16_t &seq, uint64_t &timestamp);
104 
105  // utility functions
106  int64_t AudioCardLatency(void);
107  static QStringList splitLines(const QByteArray &lines);
108  static QString stringFromSeconds(int timeInSeconds);
109  uint64_t framesToMs(uint64_t frames);
110 
111  // notification functions
112  void SendNotification(bool update = false);
113 
114  QTimer *m_watchdogTimer {nullptr};
115  // comms socket
116  QTcpSocket *m_socket {nullptr};
117  _NetStream *m_textStream {nullptr};
118  QByteArray m_hardwareId;
119  QStringList m_incomingHeaders;
120  QByteArray m_incomingContent;
121  bool m_incomingPartial {false};
122  int32_t m_incomingSize {0};
123  QHostAddress m_peerAddress;
124  ServerPool *m_dataSocket {nullptr};
126  ServerPool *m_clientControlSocket {nullptr};
127  int m_clientControlPort {0};
128  ServerPool *m_clientTimingSocket {nullptr};
129  int m_clientTimingPort {0};
130  ServerPool *m_eventServer {nullptr};
131  int m_eventPort {-1};
132  QList<QTcpSocket *> m_eventClients;
133 
134  // incoming audio
135  QMap<uint16_t,uint64_t> m_resends;
136  // crypto
137  QByteArray m_AESIV;
138  AES_KEY m_aesKey;
139  static RSA *g_rsa;
140  static QString g_rsaLastError;
141  // audio out
142  AudioOutput *m_audio {nullptr};
143  AVCodec *m_codec {nullptr};
144  AVCodecContext *m_codeccontext {nullptr};
145  QList<int> m_audioFormat;
146  int m_channels {2};
147  int m_sampleSize {16};
148  int m_frameRate {44100};
149  int m_framesPerPacket {352};
150  QTimer *m_dequeueAudioTimer {nullptr};
151 
152  QMap<uint64_t, AudioPacket> m_audioQueue;
153  uint32_t m_queueLength {0};
154  bool m_streamingStarted {false};
155  bool m_allowVolumeControl {true};
156 
157  // packet index, increase after each resend packet request
158  uint16_t m_seqNum {0};
159  // audio/packet sync
160  uint16_t m_lastSequence {0};
161  uint64_t m_lastTimestamp {0};
162  uint64_t m_currentTimestamp {0};
163  uint16_t m_nextSequence {0};
164  uint64_t m_nextTimestamp {0};
165  int64_t m_bufferLength {0};
166  uint64_t m_timeLastSync {0};
167  int64_t m_cardLatency {-1};
168  int64_t m_adjustedLatency {-1};
169  bool m_audioStarted {false};
170 
171  // clock sync
172  uint64_t m_masterTimeStamp {0};
173  uint64_t m_deviceTimeStamp {0};
174  uint64_t m_networkLatency {0};
175  // difference in ms between reference
176  int64_t m_clockSkew {0};
177 
178  // audio retry timer
179  QTimer *m_audioTimer {nullptr};
180 
181  //Current Stream Info
182  uint32_t m_progressStart {0};
183  uint32_t m_progressCurrent {0};
184  uint32_t m_progressEnd {0};
185  QByteArray m_artwork;
187 
188  //Authentication
189  QString m_nonce;
190 
191  // Notification Center registration Id
192  int m_id;
193  bool m_firstsend {false};
194  bool m_playbackStarted {false};
195 
196  private slots:
197  void ProcessAudio(void);
198 };
199 
200 #endif // MYTHRAOPCONNECTION_H
QHash< QString, QString > RawHash
QStringList m_incomingHeaders
unsigned int slots[4]
Definition: element.c:38
static QString RSALastError(void)
QList< AudioData > * data
QMap< QString, QString > DMAP
QMap< uint16_t, uint64_t > m_resends
QMap< uint64_t, AudioPacket > m_audioQueue
#define MTV_PUBLIC
Definition: mythtvexp.h:15
QTcpSocket * GetSocket()
unsigned short uint16_t
Definition: iso6937tables.h:1
QHostAddress m_peerAddress
Manages a collection of sockets listening on different ports.
Definition: serverpool.h:59
static QString g_rsaLastError
QList< QTcpSocket * > m_eventClients
const char * frames[3]
Definition: element.c:46
uint8_t * data
QList< int > m_audioFormat