QXmppRtpChannel.cpp 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. /*
  2. * Copyright (C) 2008-2012 The QXmpp developers
  3. *
  4. * Author:
  5. * Jeremy Lainé
  6. *
  7. * Source:
  8. * http://code.google.com/p/qxmpp
  9. *
  10. * This file is a part of QXmpp library.
  11. *
  12. * This library is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU Lesser General Public
  14. * License as published by the Free Software Foundation; either
  15. * version 2.1 of the License, or (at your option) any later version.
  16. *
  17. * This library is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * Lesser General Public License for more details.
  21. *
  22. */
  23. #include <cmath>
  24. #include <QDataStream>
  25. #include <QMetaType>
  26. #include <QTimer>
  27. #include "QXmppCodec_p.h"
  28. #include "QXmppJingleIq.h"
  29. #include "QXmppRtpChannel.h"
  30. #ifndef M_PI
  31. #define M_PI 3.14159265358979323846264338327950288
  32. #endif
  33. //#define QXMPP_DEBUG_RTP
  34. //#define QXMPP_DEBUG_RTP_BUFFER
  35. #define SAMPLE_BYTES 2
  36. const quint8 RTP_VERSION = 0x02;
  37. /// Parses an RTP packet.
  38. ///
  39. /// \param ba
  40. bool QXmppRtpPacket::decode(const QByteArray &ba)
  41. {
  42. if (ba.isEmpty())
  43. return false;
  44. // fixed header
  45. quint8 tmp;
  46. QDataStream stream(ba);
  47. stream >> tmp;
  48. version = (tmp >> 6);
  49. const quint8 cc = (tmp >> 1) & 0xf;
  50. const int hlen = 12 + 4 * cc;
  51. if (version != RTP_VERSION || ba.size() < hlen)
  52. return false;
  53. stream >> tmp;
  54. marker = (tmp >> 7);
  55. type = tmp & 0x7f;
  56. stream >> sequence;
  57. stream >> stamp;
  58. stream >> ssrc;
  59. // contributing source IDs
  60. csrc.clear();
  61. quint32 src;
  62. for (int i = 0; i < cc; ++i) {
  63. stream >> src;
  64. csrc << src;
  65. }
  66. // retrieve payload
  67. payload = ba.right(ba.size() - hlen);
  68. return true;
  69. }
  70. /// Encodes an RTP packet.
  71. QByteArray QXmppRtpPacket::encode() const
  72. {
  73. Q_ASSERT(csrc.size() < 16);
  74. // fixed header
  75. QByteArray ba;
  76. ba.resize(payload.size() + 12 + 4 * csrc.size());
  77. QDataStream stream(&ba, QIODevice::WriteOnly);
  78. stream << quint8(((version & 0x3) << 6) |
  79. ((csrc.size() & 0xf) << 1));
  80. stream << quint8((type & 0x7f) | (marker << 7));
  81. stream << sequence;
  82. stream << stamp;
  83. stream << ssrc;
  84. // contributing source ids
  85. foreach (const quint32 &src, csrc)
  86. stream << src;
  87. stream.writeRawData(payload.constData(), payload.size());
  88. return ba;
  89. }
  90. /// Returns a string representation of the RTP header.
  91. QString QXmppRtpPacket::toString() const
  92. {
  93. return QString("RTP packet seq %1 stamp %2 marker %3 type %4 size %5").arg(
  94. QString::number(sequence),
  95. QString::number(stamp),
  96. QString::number(marker),
  97. QString::number(type),
  98. QString::number(payload.size()));
  99. }
  100. /// Creates a new RTP channel.
  101. QXmppRtpChannel::QXmppRtpChannel()
  102. : m_outgoingPayloadNumbered(false)
  103. {
  104. }
  105. /// Returns the local payload types.
  106. ///
  107. QList<QXmppJinglePayloadType> QXmppRtpChannel::localPayloadTypes()
  108. {
  109. m_outgoingPayloadNumbered = true;
  110. return m_outgoingPayloadTypes;
  111. }
  112. /// Sets the remote payload types.
  113. ///
  114. /// \param remotePayloadTypes
  115. void QXmppRtpChannel::setRemotePayloadTypes(const QList<QXmppJinglePayloadType> &remotePayloadTypes)
  116. {
  117. QList<QXmppJinglePayloadType> commonOutgoingTypes;
  118. QList<QXmppJinglePayloadType> commonIncomingTypes;
  119. foreach (const QXmppJinglePayloadType &incomingType, remotePayloadTypes) {
  120. // check we support this payload type
  121. int outgoingIndex = m_outgoingPayloadTypes.indexOf(incomingType);
  122. if (outgoingIndex < 0)
  123. continue;
  124. QXmppJinglePayloadType outgoingType = m_outgoingPayloadTypes[outgoingIndex];
  125. // be kind and try to adopt the other agent's numbering
  126. if (!m_outgoingPayloadNumbered && outgoingType.id() > 95) {
  127. outgoingType.setId(incomingType.id());
  128. }
  129. commonIncomingTypes << incomingType;
  130. commonOutgoingTypes << outgoingType;
  131. }
  132. if (commonOutgoingTypes.isEmpty()) {
  133. qWarning("QXmppRtpChannel could not negociate a common codec");
  134. return;
  135. }
  136. m_incomingPayloadTypes = commonIncomingTypes;
  137. m_outgoingPayloadTypes = commonOutgoingTypes;
  138. m_outgoingPayloadNumbered = true;
  139. // call hook
  140. payloadTypesChanged();
  141. }
  142. enum CodecId {
  143. G711u = 0,
  144. GSM = 3,
  145. G723 = 4,
  146. G711a = 8,
  147. G722 = 9,
  148. L16Stereo = 10,
  149. L16Mono = 11,
  150. G728 = 15,
  151. G729 = 18,
  152. };
  153. struct ToneInfo
  154. {
  155. QXmppRtpAudioChannel::Tone tone;
  156. quint32 incomingStart;
  157. quint32 outgoingStart;
  158. bool finished;
  159. };
  160. static QPair<int, int> toneFreqs(QXmppRtpAudioChannel::Tone tone)
  161. {
  162. switch (tone) {
  163. case QXmppRtpAudioChannel::Tone_1: return qMakePair(697, 1209);
  164. case QXmppRtpAudioChannel::Tone_2: return qMakePair(697, 1336);
  165. case QXmppRtpAudioChannel::Tone_3: return qMakePair(697, 1477);
  166. case QXmppRtpAudioChannel::Tone_A: return qMakePair(697, 1633);
  167. case QXmppRtpAudioChannel::Tone_4: return qMakePair(770, 1209);
  168. case QXmppRtpAudioChannel::Tone_5: return qMakePair(770, 1336);
  169. case QXmppRtpAudioChannel::Tone_6: return qMakePair(770, 1477);
  170. case QXmppRtpAudioChannel::Tone_B: return qMakePair(770, 1633);
  171. case QXmppRtpAudioChannel::Tone_7: return qMakePair(852, 1209);
  172. case QXmppRtpAudioChannel::Tone_8: return qMakePair(852, 1336);
  173. case QXmppRtpAudioChannel::Tone_9: return qMakePair(852, 1477);
  174. case QXmppRtpAudioChannel::Tone_C: return qMakePair(852, 1633);
  175. case QXmppRtpAudioChannel::Tone_Star: return qMakePair(941, 1209);
  176. case QXmppRtpAudioChannel::Tone_0: return qMakePair(941, 1336);
  177. case QXmppRtpAudioChannel::Tone_Pound: return qMakePair(941, 1477);
  178. case QXmppRtpAudioChannel::Tone_D: return qMakePair(941, 1633);
  179. }
  180. return qMakePair(0, 0);
  181. }
  182. QByteArray renderTone(QXmppRtpAudioChannel::Tone tone, int clockrate, quint32 clockTick, qint64 samples)
  183. {
  184. QPair<int,int> tf = toneFreqs(tone);
  185. const float clockMult = 2.0 * M_PI / float(clockrate);
  186. QByteArray chunk;
  187. chunk.reserve(samples * SAMPLE_BYTES);
  188. QDataStream output(&chunk, QIODevice::WriteOnly);
  189. output.setByteOrder(QDataStream::LittleEndian);
  190. for (quint32 i = 0; i < samples; ++i) {
  191. quint16 val = 16383.0 * (sin(clockMult * clockTick * tf.first) + sin(clockMult * clockTick * tf.second));
  192. output << val;
  193. clockTick++;
  194. }
  195. return chunk;
  196. }
  197. class QXmppRtpAudioChannelPrivate
  198. {
  199. public:
  200. QXmppRtpAudioChannelPrivate(QXmppRtpAudioChannel *qq);
  201. QXmppCodec *codecForPayloadType(const QXmppJinglePayloadType &payloadType);
  202. // signals
  203. bool signalsEmitted;
  204. qint64 writtenSinceLastEmit;
  205. // RTP
  206. QHostAddress remoteHost;
  207. quint16 remotePort;
  208. QByteArray incomingBuffer;
  209. bool incomingBuffering;
  210. QMap<int, QXmppCodec*> incomingCodecs;
  211. int incomingMinimum;
  212. int incomingMaximum;
  213. // position of the head of the incoming buffer, in bytes
  214. qint64 incomingPos;
  215. quint16 incomingSequence;
  216. QByteArray outgoingBuffer;
  217. quint16 outgoingChunk;
  218. QXmppCodec *outgoingCodec;
  219. bool outgoingMarker;
  220. bool outgoingPayloadNumbered;
  221. quint16 outgoingSequence;
  222. quint32 outgoingStamp;
  223. QTimer *outgoingTimer;
  224. QList<ToneInfo> outgoingTones;
  225. QXmppJinglePayloadType outgoingTonesType;
  226. quint32 outgoingSsrc;
  227. QXmppJinglePayloadType payloadType;
  228. private:
  229. QXmppRtpAudioChannel *q;
  230. };
  231. QXmppRtpAudioChannelPrivate::QXmppRtpAudioChannelPrivate(QXmppRtpAudioChannel *qq)
  232. : signalsEmitted(false),
  233. writtenSinceLastEmit(0),
  234. incomingBuffering(true),
  235. incomingMinimum(0),
  236. incomingMaximum(0),
  237. incomingPos(0),
  238. incomingSequence(0),
  239. outgoingCodec(0),
  240. outgoingMarker(true),
  241. outgoingPayloadNumbered(false),
  242. outgoingSequence(1),
  243. outgoingStamp(0),
  244. outgoingSsrc(0),
  245. q(qq)
  246. {
  247. qRegisterMetaType<QXmppRtpAudioChannel::Tone>("QXmppRtpAudioChannel::Tone");
  248. outgoingSsrc = qrand();
  249. }
  250. /// Returns the audio codec for the given payload type.
  251. ///
  252. QXmppCodec *QXmppRtpAudioChannelPrivate::codecForPayloadType(const QXmppJinglePayloadType &payloadType)
  253. {
  254. if (payloadType.id() == G711u)
  255. return new QXmppG711uCodec(payloadType.clockrate());
  256. else if (payloadType.id() == G711a)
  257. return new QXmppG711aCodec(payloadType.clockrate());
  258. #ifdef QXMPP_USE_SPEEX
  259. else if (payloadType.name().toLower() == "speex")
  260. return new QXmppSpeexCodec(payloadType.clockrate());
  261. #endif
  262. return 0;
  263. }
  264. /// Constructs a new RTP audio channel with the given \a parent.
  265. QXmppRtpAudioChannel::QXmppRtpAudioChannel(QObject *parent)
  266. : QIODevice(parent)
  267. {
  268. d = new QXmppRtpAudioChannelPrivate(this);
  269. QXmppLoggable *logParent = qobject_cast<QXmppLoggable*>(parent);
  270. if (logParent) {
  271. connect(this, SIGNAL(logMessage(QXmppLogger::MessageType,QString)),
  272. logParent, SIGNAL(logMessage(QXmppLogger::MessageType,QString)));
  273. }
  274. d->outgoingTimer = new QTimer(this);
  275. connect(d->outgoingTimer, SIGNAL(timeout()), this, SLOT(writeDatagram()));
  276. // set supported codecs
  277. QXmppJinglePayloadType payload;
  278. #ifdef QXMPP_USE_SPEEX
  279. payload.setId(96);
  280. payload.setChannels(1);
  281. payload.setName("speex");
  282. payload.setClockrate(8000);
  283. m_outgoingPayloadTypes << payload;
  284. #endif
  285. payload.setId(G711u);
  286. payload.setChannels(1);
  287. payload.setName("PCMU");
  288. payload.setClockrate(8000);
  289. m_outgoingPayloadTypes << payload;
  290. payload.setId(G711a);
  291. payload.setChannels(1);
  292. payload.setName("PCMA");
  293. payload.setClockrate(8000);
  294. m_outgoingPayloadTypes << payload;
  295. QMap<QString, QString> parameters;
  296. parameters.insert("events", "0-15");
  297. payload.setId(101);
  298. payload.setChannels(1);
  299. payload.setName("telephone-event");
  300. payload.setClockrate(8000);
  301. payload.setParameters(parameters);
  302. m_outgoingPayloadTypes << payload;
  303. }
  304. /// Destroys an RTP audio channel.
  305. ///
  306. QXmppRtpAudioChannel::~QXmppRtpAudioChannel()
  307. {
  308. foreach (QXmppCodec *codec, d->incomingCodecs)
  309. delete codec;
  310. if (d->outgoingCodec)
  311. delete d->outgoingCodec;
  312. delete d;
  313. }
  314. /// Returns the number of bytes that are available for reading.
  315. qint64 QXmppRtpAudioChannel::bytesAvailable() const
  316. {
  317. return QIODevice::bytesAvailable() + d->incomingBuffer.size();
  318. }
  319. /// Closes the RTP audio channel.
  320. void QXmppRtpAudioChannel::close()
  321. {
  322. d->outgoingTimer->stop();
  323. QIODevice::close();
  324. }
  325. /// Processes an incoming RTP packet.
  326. ///
  327. /// \param ba
  328. void QXmppRtpAudioChannel::datagramReceived(const QByteArray &ba)
  329. {
  330. QXmppRtpPacket packet;
  331. if (!packet.decode(ba))
  332. return;
  333. #ifdef QXMPP_DEBUG_RTP
  334. logReceived(packet.toString());
  335. #endif
  336. // check sequence number
  337. #if 0
  338. if (d->incomingSequence && packet.sequence != d->incomingSequence + 1)
  339. warning(QString("RTP packet seq %1 is out of order, previous was %2")
  340. .arg(QString::number(packet.sequence))
  341. .arg(QString::number(d->incomingSequence)));
  342. #endif
  343. d->incomingSequence = packet.sequence;
  344. // get or create codec
  345. QXmppCodec *codec = 0;
  346. if (!d->incomingCodecs.contains(packet.type)) {
  347. foreach (const QXmppJinglePayloadType &payload, m_incomingPayloadTypes) {
  348. if (packet.type == payload.id()) {
  349. codec = d->codecForPayloadType(payload);
  350. break;
  351. }
  352. }
  353. if (codec)
  354. d->incomingCodecs.insert(packet.type, codec);
  355. else
  356. warning(QString("Could not find codec for RTP type %1").arg(QString::number(packet.type)));
  357. } else {
  358. codec = d->incomingCodecs.value(packet.type);
  359. }
  360. if (!codec)
  361. return;
  362. // determine packet's position in the buffer (in bytes)
  363. qint64 packetOffset = 0;
  364. if (!d->incomingBuffer.isEmpty()) {
  365. packetOffset = packet.stamp * SAMPLE_BYTES - d->incomingPos;
  366. if (packetOffset < 0) {
  367. #ifdef QXMPP_DEBUG_RTP_BUFFER
  368. warning(QString("RTP packet stamp %1 is too old, buffer start is %2")
  369. .arg(QString::number(packet.stamp))
  370. .arg(QString::number(d->incomingPos)));
  371. #endif
  372. return;
  373. }
  374. } else {
  375. d->incomingPos = packet.stamp * SAMPLE_BYTES + (d->incomingPos % SAMPLE_BYTES);
  376. }
  377. // allocate space for new packet
  378. // FIXME: this is wrong, we want the decoded data size!
  379. qint64 packetLength = packet.payload.size();
  380. if (packetOffset + packetLength > d->incomingBuffer.size())
  381. d->incomingBuffer += QByteArray(packetOffset + packetLength - d->incomingBuffer.size(), 0);
  382. QDataStream input(packet.payload);
  383. QDataStream output(&d->incomingBuffer, QIODevice::WriteOnly);
  384. output.device()->seek(packetOffset);
  385. output.setByteOrder(QDataStream::LittleEndian);
  386. codec->decode(input, output);
  387. // check whether we are running late
  388. if (d->incomingBuffer.size() > d->incomingMaximum)
  389. {
  390. qint64 droppedSize = d->incomingBuffer.size() - d->incomingMinimum;
  391. const int remainder = droppedSize % SAMPLE_BYTES;
  392. if (remainder)
  393. droppedSize -= remainder;
  394. #ifdef QXMPP_DEBUG_RTP_BUFFER
  395. warning(QString("Incoming RTP buffer is too full, dropping %1 bytes")
  396. .arg(QString::number(droppedSize)));
  397. #endif
  398. d->incomingBuffer.remove(0, droppedSize);
  399. d->incomingPos += droppedSize;
  400. }
  401. // check whether we have filled the initial buffer
  402. if (d->incomingBuffer.size() >= d->incomingMinimum)
  403. d->incomingBuffering = false;
  404. if (!d->incomingBuffering)
  405. emit readyRead();
  406. }
  407. void QXmppRtpAudioChannel::emitSignals()
  408. {
  409. emit bytesWritten(d->writtenSinceLastEmit);
  410. d->writtenSinceLastEmit = 0;
  411. d->signalsEmitted = false;
  412. }
  413. /// Returns true, as the RTP channel is a sequential device.
  414. ///
  415. bool QXmppRtpAudioChannel::isSequential() const
  416. {
  417. return true;
  418. }
  419. /// Returns the mode in which the channel has been opened.
  420. QIODevice::OpenMode QXmppRtpAudioChannel::openMode() const
  421. {
  422. return QIODevice::openMode();
  423. }
  424. /// Returns the RTP channel's payload type.
  425. ///
  426. /// You can use this to determine the QAudioFormat to use with your
  427. /// QAudioInput/QAudioOutput.
  428. QXmppJinglePayloadType QXmppRtpAudioChannel::payloadType() const
  429. {
  430. return d->payloadType;
  431. }
  432. /// \cond
  433. qint64 QXmppRtpAudioChannel::readData(char * data, qint64 maxSize)
  434. {
  435. // if we are filling the buffer, return empty samples
  436. if (d->incomingBuffering)
  437. {
  438. // FIXME: if we are asked for a non-integer number of samples,
  439. // we will return junk on next read as we don't increment d->incomingPos
  440. memset(data, 0, maxSize);
  441. return maxSize;
  442. }
  443. qint64 readSize = qMin(maxSize, qint64(d->incomingBuffer.size()));
  444. memcpy(data, d->incomingBuffer.constData(), readSize);
  445. d->incomingBuffer.remove(0, readSize);
  446. if (readSize < maxSize)
  447. {
  448. #ifdef QXMPP_DEBUG_RTP
  449. debug(QString("QXmppRtpAudioChannel::readData missing %1 bytes").arg(QString::number(maxSize - readSize)));
  450. #endif
  451. memset(data + readSize, 0, maxSize - readSize);
  452. }
  453. // add local DTMF echo
  454. if (!d->outgoingTones.isEmpty()) {
  455. const int headOffset = d->incomingPos % SAMPLE_BYTES;
  456. const int samples = (headOffset + maxSize + SAMPLE_BYTES - 1) / SAMPLE_BYTES;
  457. const QByteArray chunk = renderTone(
  458. d->outgoingTones[0].tone,
  459. d->payloadType.clockrate(),
  460. d->incomingPos / SAMPLE_BYTES - d->outgoingTones[0].incomingStart,
  461. samples);
  462. memcpy(data, chunk.constData() + headOffset, maxSize);
  463. }
  464. d->incomingPos += maxSize;
  465. return maxSize;
  466. }
  467. void QXmppRtpAudioChannel::payloadTypesChanged()
  468. {
  469. // delete incoming codecs
  470. foreach (QXmppCodec *codec, d->incomingCodecs)
  471. delete codec;
  472. d->incomingCodecs.clear();
  473. // delete outgoing codec
  474. if (d->outgoingCodec) {
  475. delete d->outgoingCodec;
  476. d->outgoingCodec = 0;
  477. }
  478. // create outgoing codec
  479. foreach (const QXmppJinglePayloadType &outgoingType, m_outgoingPayloadTypes) {
  480. // check for telephony events
  481. if (outgoingType.name() == "telephone-event") {
  482. d->outgoingTonesType = outgoingType;
  483. }
  484. else if (!d->outgoingCodec) {
  485. QXmppCodec *codec = d->codecForPayloadType(outgoingType);
  486. if (codec) {
  487. d->payloadType = outgoingType;
  488. d->outgoingCodec = codec;
  489. }
  490. }
  491. }
  492. // size in bytes of an decoded packet
  493. d->outgoingChunk = SAMPLE_BYTES * d->payloadType.ptime() * d->payloadType.clockrate() / 1000;
  494. d->outgoingTimer->setInterval(d->payloadType.ptime());
  495. d->incomingMinimum = d->outgoingChunk * 5;
  496. d->incomingMaximum = d->outgoingChunk * 15;
  497. open(QIODevice::ReadWrite | QIODevice::Unbuffered);
  498. }
  499. /// \endcond
  500. /// Returns the position in the received audio data.
  501. qint64 QXmppRtpAudioChannel::pos() const
  502. {
  503. return d->incomingPos;
  504. }
  505. /// Seeks in the received audio data.
  506. ///
  507. /// Seeking backwards will result in empty samples being added at the start
  508. /// of the buffer.
  509. ///
  510. /// \param pos
  511. bool QXmppRtpAudioChannel::seek(qint64 pos)
  512. {
  513. qint64 delta = pos - d->incomingPos;
  514. if (delta < 0)
  515. d->incomingBuffer.prepend(QByteArray(-delta, 0));
  516. else
  517. d->incomingBuffer.remove(0, delta);
  518. d->incomingPos = pos;
  519. return true;
  520. }
  521. /// Starts sending the specified DTMF tone.
  522. ///
  523. /// \param tone
  524. void QXmppRtpAudioChannel::startTone(QXmppRtpAudioChannel::Tone tone)
  525. {
  526. ToneInfo info;
  527. info.tone = tone;
  528. info.incomingStart = d->incomingPos / SAMPLE_BYTES;
  529. info.outgoingStart = d->outgoingStamp;
  530. info.finished = false;
  531. d->outgoingTones << info;
  532. }
  533. /// Stops sending the specified DTMF tone.
  534. ///
  535. /// \param tone
  536. void QXmppRtpAudioChannel::stopTone(QXmppRtpAudioChannel::Tone tone)
  537. {
  538. for (int i = 0; i < d->outgoingTones.size(); ++i) {
  539. if (d->outgoingTones[i].tone == tone) {
  540. d->outgoingTones[i].finished = true;
  541. break;
  542. }
  543. }
  544. }
  545. /// \cond
  546. qint64 QXmppRtpAudioChannel::writeData(const char * data, qint64 maxSize)
  547. {
  548. if (!d->outgoingCodec) {
  549. warning("QXmppRtpAudioChannel::writeData before codec was set");
  550. return -1;
  551. }
  552. d->outgoingBuffer += QByteArray::fromRawData(data, maxSize);
  553. // start sending audio chunks
  554. if (!d->outgoingTimer->isActive())
  555. d->outgoingTimer->start();
  556. return maxSize;
  557. }
  558. /// \endcond
  559. void QXmppRtpAudioChannel::writeDatagram()
  560. {
  561. // read audio chunk
  562. QByteArray chunk;
  563. if (d->outgoingBuffer.size() < d->outgoingChunk) {
  564. #ifdef QXMPP_DEBUG_RTP_BUFFER
  565. warning("Outgoing RTP buffer is starved");
  566. #endif
  567. chunk = QByteArray(d->outgoingChunk, 0);
  568. } else {
  569. chunk = d->outgoingBuffer.left(d->outgoingChunk);
  570. d->outgoingBuffer.remove(0, d->outgoingChunk);
  571. }
  572. bool sendAudio = true;
  573. if (!d->outgoingTones.isEmpty()) {
  574. const quint32 packetTicks = (d->payloadType.clockrate() * d->payloadType.ptime()) / 1000;
  575. const ToneInfo info = d->outgoingTones[0];
  576. if (d->outgoingTonesType.id()) {
  577. // send RFC 2833 DTMF
  578. QXmppRtpPacket packet;
  579. packet.version = RTP_VERSION;
  580. packet.marker = (info.outgoingStart == d->outgoingStamp);
  581. packet.type = d->outgoingTonesType.id();
  582. packet.sequence = d->outgoingSequence;
  583. packet.stamp = info.outgoingStart;
  584. packet.ssrc = d->outgoingSsrc;
  585. QDataStream output(&packet.payload, QIODevice::WriteOnly);
  586. output << quint8(info.tone);
  587. output << quint8(info.finished ? 0x80 : 0x00);
  588. output << quint16(d->outgoingStamp + packetTicks - info.outgoingStart);
  589. #ifdef QXMPP_DEBUG_RTP
  590. logSent(packet.toString());
  591. #endif
  592. emit sendDatagram(packet.encode());
  593. d->outgoingSequence++;
  594. d->outgoingStamp += packetTicks;
  595. sendAudio = false;
  596. } else {
  597. // generate in-band DTMF
  598. chunk = renderTone(info.tone, d->payloadType.clockrate(), d->outgoingStamp - info.outgoingStart, packetTicks);
  599. }
  600. // if the tone is finished, remove it
  601. if (info.finished)
  602. d->outgoingTones.removeFirst();
  603. }
  604. if (sendAudio) {
  605. // send audio data
  606. QXmppRtpPacket packet;
  607. packet.version = RTP_VERSION;
  608. if (d->outgoingMarker)
  609. {
  610. packet.marker = true;
  611. d->outgoingMarker = false;
  612. } else {
  613. packet.marker = false;
  614. }
  615. packet.type = d->payloadType.id();
  616. packet.sequence = d->outgoingSequence;
  617. packet.stamp = d->outgoingStamp;
  618. packet.ssrc = d->outgoingSsrc;
  619. // encode audio chunk
  620. QDataStream input(chunk);
  621. input.setByteOrder(QDataStream::LittleEndian);
  622. QDataStream output(&packet.payload, QIODevice::WriteOnly);
  623. const qint64 packetTicks = d->outgoingCodec->encode(input, output);
  624. #ifdef QXMPP_DEBUG_RTP
  625. logSent(packet.toString());
  626. #endif
  627. emit sendDatagram(packet.encode());
  628. d->outgoingSequence++;
  629. d->outgoingStamp += packetTicks;
  630. }
  631. // queue signals
  632. d->writtenSinceLastEmit += chunk.size();
  633. if (!d->signalsEmitted && !signalsBlocked()) {
  634. d->signalsEmitted = true;
  635. QMetaObject::invokeMethod(this, "emitSignals", Qt::QueuedConnection);
  636. }
  637. }
  638. /** Constructs a null video frame.
  639. */
  640. QXmppVideoFrame::QXmppVideoFrame()
  641. : m_bytesPerLine(0),
  642. m_height(0),
  643. m_mappedBytes(0),
  644. m_pixelFormat(Format_Invalid),
  645. m_width(0)
  646. {
  647. }
  648. /** Constructs a video frame of the given pixel format and size in pixels.
  649. *
  650. * @param bytes
  651. * @param size
  652. * @param bytesPerLine
  653. * @param format
  654. */
  655. QXmppVideoFrame::QXmppVideoFrame(int bytes, const QSize &size, int bytesPerLine, PixelFormat format)
  656. : m_bytesPerLine(bytesPerLine),
  657. m_height(size.height()),
  658. m_mappedBytes(bytes),
  659. m_pixelFormat(format),
  660. m_width(size.width())
  661. {
  662. m_data.resize(bytes);
  663. }
  664. /// Returns a pointer to the start of the frame data buffer.
  665. uchar *QXmppVideoFrame::bits()
  666. {
  667. return (uchar*)m_data.data();
  668. }
  669. /// Returns a pointer to the start of the frame data buffer.
  670. const uchar *QXmppVideoFrame::bits() const
  671. {
  672. return (const uchar*)m_data.constData();
  673. }
  674. /// Returns the number of bytes in a scan line.
  675. int QXmppVideoFrame::bytesPerLine() const
  676. {
  677. return m_bytesPerLine;
  678. }
  679. /// Returns the height of a video frame.
  680. int QXmppVideoFrame::height() const
  681. {
  682. return m_height;
  683. }
  684. /// Returns true if the frame is valid.
  685. bool QXmppVideoFrame::isValid() const
  686. {
  687. return m_pixelFormat != Format_Invalid &&
  688. m_height > 0 && m_width > 0 &&
  689. m_mappedBytes > 0;
  690. }
  691. /// Returns the number of bytes occupied by the mapped frame data.
  692. int QXmppVideoFrame::mappedBytes() const
  693. {
  694. return m_mappedBytes;
  695. }
  696. /// Returns the color format of a video frame.
  697. QXmppVideoFrame::PixelFormat QXmppVideoFrame::pixelFormat() const
  698. {
  699. return m_pixelFormat;
  700. }
  701. /// Returns the size of a video frame.
  702. QSize QXmppVideoFrame::size() const
  703. {
  704. return QSize(m_width, m_height);
  705. }
  706. /// Returns the width of a video frame.
  707. int QXmppVideoFrame::width() const
  708. {
  709. return m_width;
  710. }
  711. class QXmppRtpVideoChannelPrivate
  712. {
  713. public:
  714. QXmppRtpVideoChannelPrivate();
  715. QMap<int, QXmppVideoDecoder*> decoders;
  716. QXmppVideoEncoder *encoder;
  717. QList<QXmppVideoFrame> frames;
  718. // local
  719. QXmppVideoFormat outgoingFormat;
  720. quint8 outgoingId;
  721. quint16 outgoingSequence;
  722. quint32 outgoingStamp;
  723. quint32 outgoingSsrc;
  724. };
  725. QXmppRtpVideoChannelPrivate::QXmppRtpVideoChannelPrivate()
  726. : encoder(0),
  727. outgoingId(0),
  728. outgoingSequence(1),
  729. outgoingStamp(0),
  730. outgoingSsrc(0)
  731. {
  732. outgoingSsrc = qrand();
  733. }
  734. /// Constructs a new RTP video channel with the given \a parent.
  735. QXmppRtpVideoChannel::QXmppRtpVideoChannel(QObject *parent)
  736. : QXmppLoggable(parent)
  737. {
  738. d = new QXmppRtpVideoChannelPrivate;
  739. d->outgoingFormat.setFrameRate(15.0);
  740. d->outgoingFormat.setFrameSize(QSize(320, 240));
  741. d->outgoingFormat.setPixelFormat(QXmppVideoFrame::Format_YUYV);
  742. // set supported codecs
  743. QXmppVideoEncoder *encoder;
  744. QXmppJinglePayloadType payload;
  745. Q_UNUSED(encoder);
  746. Q_UNUSED(payload);
  747. #ifdef QXMPP_USE_VPX
  748. encoder = new QXmppVpxEncoder;
  749. encoder->setFormat(d->outgoingFormat);
  750. payload.setId(96);
  751. payload.setName("vp8");
  752. payload.setClockrate(90000);
  753. payload.setParameters(encoder->parameters());
  754. m_outgoingPayloadTypes << payload;
  755. delete encoder;
  756. #endif
  757. #ifdef QXMPP_USE_THEORA
  758. encoder = new QXmppTheoraEncoder;
  759. encoder->setFormat(d->outgoingFormat);
  760. payload.setId(97);
  761. payload.setName("theora");
  762. payload.setClockrate(90000);
  763. payload.setParameters(encoder->parameters());
  764. m_outgoingPayloadTypes << payload;
  765. delete encoder;
  766. #endif
  767. }
  768. QXmppRtpVideoChannel::~QXmppRtpVideoChannel()
  769. {
  770. foreach (QXmppVideoDecoder *decoder, d->decoders)
  771. delete decoder;
  772. if (d->encoder)
  773. delete d->encoder;
  774. delete d;
  775. }
  776. /// Closes the RTP video channel.
  777. void QXmppRtpVideoChannel::close()
  778. {
  779. }
  780. /// Processes an incoming RTP video packet.
  781. ///
  782. /// \param ba
  783. void QXmppRtpVideoChannel::datagramReceived(const QByteArray &ba)
  784. {
  785. QXmppRtpPacket packet;
  786. if (!packet.decode(ba))
  787. return;
  788. #ifdef QXMPP_DEBUG_RTP
  789. logReceived(packet.toString());
  790. #endif
  791. // get codec
  792. QXmppVideoDecoder *decoder = d->decoders.value(packet.type);
  793. if (!decoder)
  794. return;
  795. d->frames << decoder->handlePacket(packet);
  796. }
  797. /// Returns the video format used by the encoder.
  798. QXmppVideoFormat QXmppRtpVideoChannel::decoderFormat() const
  799. {
  800. if (d->decoders.isEmpty())
  801. return QXmppVideoFormat();
  802. const int key = d->decoders.keys().first();
  803. return d->decoders.value(key)->format();
  804. }
  805. /// Returns the video format used by the encoder.
  806. QXmppVideoFormat QXmppRtpVideoChannel::encoderFormat() const
  807. {
  808. return d->outgoingFormat;
  809. }
  810. /// Sets the video format used by the encoder.
  811. void QXmppRtpVideoChannel::setEncoderFormat(const QXmppVideoFormat &format)
  812. {
  813. if (d->encoder && !d->encoder->setFormat(format))
  814. return;
  815. d->outgoingFormat = format;
  816. }
  817. /// Returns the mode in which the channel has been opened.
  818. QIODevice::OpenMode QXmppRtpVideoChannel::openMode() const
  819. {
  820. QIODevice::OpenMode mode = QIODevice::NotOpen;
  821. if (!d->decoders.isEmpty())
  822. mode |= QIODevice::ReadOnly;
  823. if (d->encoder)
  824. mode |= QIODevice::WriteOnly;
  825. return mode;
  826. }
  827. /// \cond
  828. void QXmppRtpVideoChannel::payloadTypesChanged()
  829. {
  830. // refresh decoders
  831. foreach (QXmppVideoDecoder *decoder, d->decoders)
  832. delete decoder;
  833. d->decoders.clear();
  834. foreach (const QXmppJinglePayloadType &payload, m_incomingPayloadTypes) {
  835. QXmppVideoDecoder *decoder = 0;
  836. if (false)
  837. {}
  838. #ifdef QXMPP_USE_THEORA
  839. else if (payload.name().toLower() == "theora")
  840. decoder = new QXmppTheoraDecoder;
  841. #endif
  842. #ifdef QXMPP_USE_VPX
  843. else if (payload.name().toLower() == "vp8")
  844. decoder = new QXmppVpxDecoder;
  845. #endif
  846. if (decoder) {
  847. decoder->setParameters(payload.parameters());
  848. d->decoders.insert(payload.id(), decoder);
  849. }
  850. }
  851. // refresh encoder
  852. if (d->encoder) {
  853. delete d->encoder;
  854. d->encoder = 0;
  855. }
  856. foreach (const QXmppJinglePayloadType &payload, m_outgoingPayloadTypes) {
  857. QXmppVideoEncoder *encoder = 0;
  858. if (false)
  859. {}
  860. #ifdef QXMPP_USE_THEORA
  861. else if (payload.name().toLower() == "theora")
  862. encoder = new QXmppTheoraEncoder;
  863. #endif
  864. #ifdef QXMPP_USE_VPX
  865. else if (payload.name().toLower() == "vp8") {
  866. encoder = new QXmppVpxEncoder;
  867. }
  868. #endif
  869. if (encoder) {
  870. encoder->setFormat(d->outgoingFormat);
  871. d->encoder = encoder;
  872. d->outgoingId = payload.id();
  873. break;
  874. }
  875. }
  876. }
  877. /// \endcond
  878. /// Decodes buffered RTP packets and returns a list of video frames.
  879. QList<QXmppVideoFrame> QXmppRtpVideoChannel::readFrames()
  880. {
  881. const QList<QXmppVideoFrame> frames = d->frames;
  882. d->frames.clear();
  883. return frames;
  884. }
  885. /// Encodes a video \a frame and sends RTP packets.
  886. void QXmppRtpVideoChannel::writeFrame(const QXmppVideoFrame &frame)
  887. {
  888. if (!d->encoder) {
  889. warning("QXmppRtpVideoChannel::writeFrame before codec was set");
  890. return;
  891. }
  892. QXmppRtpPacket packet;
  893. packet.version = RTP_VERSION;
  894. packet.marker = false;
  895. packet.type = d->outgoingId;
  896. packet.ssrc = d->outgoingSsrc;
  897. foreach (const QByteArray &payload, d->encoder->handleFrame(frame)) {
  898. packet.sequence = d->outgoingSequence++;
  899. packet.stamp = d->outgoingStamp;
  900. packet.payload = payload;
  901. #ifdef QXMPP_DEBUG_RTP
  902. logSent(packet.toString());
  903. #endif
  904. emit sendDatagram(packet.encode());
  905. }
  906. d->outgoingStamp += 1;
  907. }