summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/wifi-display/source/Sender.cpp
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2012-11-12 13:08:44 -0800
committerAndreas Huber <andih@google.com>2012-11-13 13:21:36 -0800
commit83c9bd167600b3ff77008a6c06c05bb1f189d4ca (patch)
tree627825a9a372a21c82dfc9df9c2184cf598cd251 /media/libstagefright/wifi-display/source/Sender.cpp
parent86ee26bf99d8937d6dfd3aaee7965368e1612a62 (diff)
downloadframeworks_av-83c9bd167600b3ff77008a6c06c05bb1f189d4ca.zip
frameworks_av-83c9bd167600b3ff77008a6c06c05bb1f189d4ca.tar.gz
frameworks_av-83c9bd167600b3ff77008a6c06c05bb1f189d4ca.tar.bz2
Various improvements of wifi display code
- manually prepend SPS/PPS if encoder doesn't support it - latency improvements - support for "our" method of optional RTP retransmission - improvements to the wfd commandline tool for testing - make it easier to turn on/off suspension of the video pipeline on idle - fixes an issue where an error during encryption would cause a SEGV - add HDCP descriptor if necessary Squashed commit of the following: commit 1115be0ebb3b885b4f1b7dba56761ca013d0ec4a Author: Andreas Huber <andih@google.com> Date: Fri Nov 9 11:32:23 2012 -0800 Better shutdown of wfd -l sessions. Change-Id: Id898a14ae21efd3b065b00a729830063d39195a7 commit 0e7d106dfe4eb6e2640b0b66c65deaba265f7ff0 Author: Andreas Huber <andih@google.com> Date: Thu Nov 8 16:38:55 2012 -0800 No more sending delay, create rtp packets upfront. Change-Id: I809a225f664fdb485c7d9a49a27886601a6a26b2 commit d399e8571b77353d59afb57508dfd2a82c1ef93a Author: Andreas Huber <andih@google.com> Date: Thu Nov 8 14:19:43 2012 -0800 Restore AudioSource buffer size, factor out TimeSeries, make suspending video optional. Change-Id: Ifdfe4d447b901e714abf52856b4641d1d55a5d41 commit f8b649f0b8f917d59f4b8a2e8e6d7db61a684a78 Author: Andreas Huber <andih@google.com> Date: Thu Nov 8 09:34:06 2012 -0800 Pull 480 frames at a time from AudioSource/AudioRecord Change-Id: I1e215abd329faec3da026631122c0f4c800c0ac4 commit 1bc13452eb35eebbba00f5da93fa86535be5db59 Author: Andreas Huber <andih@google.com> Date: Thu Nov 8 08:50:30 2012 -0800 fixed bitrate traffic simulation Change-Id: Ic5efb7cbb0b5d3b4917bc77b8ba73d447249e695 commit 016cdff18e74bdc631a5679e97192645ed095aa2 Author: Andreas Huber <andih@google.com> Date: Wed Nov 7 14:00:03 2012 -0800 resurrected "our" style of retransmission. Change-Id: I34d757aba67428437cb39b8293a9651750ad20d9 commit 384cf1a3c8fb4ec410bdf8fa5722c298e6028f3e Author: Andreas Huber <andih@google.com> Date: Tue Nov 6 09:38:55 2012 -0800 Changes to make wfd work on manta. Change-Id: I7a4e00cf16581fe2146edd1b359af195774090e4 commit 9628f24b22b35f28630d99dda3614babf51bc07e Author: Andreas Huber <andih@google.com> Date: Wed Nov 7 09:15:44 2012 -0800 Patch up rtp timestamps to more accurately measure network jitter. Change-Id: I9502a4615575f97f98a215a13131a89a6ae93c6d commit 7c891a1a24f08bbd50f55be13f7d05f43e807eb8 Author: Andreas Huber <andih@google.com> Date: Tue Nov 6 09:37:24 2012 -0800 Additions to the "wfd" tool to create a local wfd source. Change-Id: I99558653a70fdc703f9d13990b3ce1c4d3ae227a Change-Id: Ia94c63fc390f597014531073485f0cfc53b3418a
Diffstat (limited to 'media/libstagefright/wifi-display/source/Sender.cpp')
-rw-r--r--media/libstagefright/wifi-display/source/Sender.cpp415
1 files changed, 153 insertions, 262 deletions
diff --git a/media/libstagefright/wifi-display/source/Sender.cpp b/media/libstagefright/wifi-display/source/Sender.cpp
index ea12424..9048691 100644
--- a/media/libstagefright/wifi-display/source/Sender.cpp
+++ b/media/libstagefright/wifi-display/source/Sender.cpp
@@ -21,6 +21,7 @@
#include "Sender.h"
#include "ANetworkSession.h"
+#include "TimeSeries.h"
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -29,79 +30,8 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/Utils.h>
-#include <math.h>
-
-#define DEBUG_JITTER 0
-
namespace android {
-////////////////////////////////////////////////////////////////////////////////
-
-#if DEBUG_JITTER
-struct TimeSeries {
- TimeSeries();
-
- void add(double val);
-
- double mean() const;
- double sdev() const;
-
-private:
- enum {
- kHistorySize = 20
- };
- double mValues[kHistorySize];
-
- size_t mCount;
- double mSum;
-};
-
-TimeSeries::TimeSeries()
- : mCount(0),
- mSum(0.0) {
-}
-
-void TimeSeries::add(double val) {
- if (mCount < kHistorySize) {
- mValues[mCount++] = val;
- mSum += val;
- } else {
- mSum -= mValues[0];
- memmove(&mValues[0], &mValues[1], (kHistorySize - 1) * sizeof(double));
- mValues[kHistorySize - 1] = val;
- mSum += val;
- }
-}
-
-double TimeSeries::mean() const {
- if (mCount < 1) {
- return 0.0;
- }
-
- return mSum / mCount;
-}
-
-double TimeSeries::sdev() const {
- if (mCount < 1) {
- return 0.0;
- }
-
- double m = mean();
-
- double sum = 0.0;
- for (size_t i = 0; i < mCount; ++i) {
- double tmp = mValues[i] - m;
- tmp *= tmp;
-
- sum += tmp;
- }
-
- return sqrt(sum / mCount);
-}
-#endif // DEBUG_JITTER
-
-////////////////////////////////////////////////////////////////////////////////
-
static size_t kMaxRTPPacketSize = 1500;
static size_t kMaxNumTSPacketsPerRTPPacket = (kMaxRTPPacketSize - 12) / 188;
@@ -110,14 +40,13 @@ Sender::Sender(
const sp<AMessage> &notify)
: mNetSession(netSession),
mNotify(notify),
- mTSQueue(new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188)),
mTransportMode(TRANSPORT_UDP),
mRTPChannel(0),
mRTCPChannel(0),
mRTPPort(0),
mRTPSessionID(0),
mRTCPSessionID(0),
-#if ENABLE_RETRANSMISSION
+#if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX
mRTPRetransmissionSessionID(0),
mRTCPRetransmissionSessionID(0),
#endif
@@ -128,7 +57,7 @@ Sender::Sender(
mFirstOutputBufferReadyTimeUs(-1ll),
mFirstOutputBufferSentTimeUs(-1ll),
mRTPSeqNo(0),
-#if ENABLE_RETRANSMISSION
+#if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX
mRTPRetransmissionSeqNo(0),
#endif
mLastNTPTime(0),
@@ -148,15 +77,13 @@ Sender::Sender(
,mLogFile(NULL)
#endif
{
- mTSQueue->setRange(0, 12);
-
#if LOG_TRANSPORT_STREAM
mLogFile = fopen("/system/etc/log.ts", "wb");
#endif
}
Sender::~Sender() {
-#if ENABLE_RETRANSMISSION
+#if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX
if (mRTCPRetransmissionSessionID != 0) {
mNetSession->destroySession(mRTCPRetransmissionSessionID);
}
@@ -217,7 +144,7 @@ status_t Sender::init(
sp<AMessage> rtpNotify = new AMessage(kWhatRTPNotify, id());
sp<AMessage> rtcpNotify = new AMessage(kWhatRTCPNotify, id());
-#if ENABLE_RETRANSMISSION
+#if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX
sp<AMessage> rtpRetransmissionNotify =
new AMessage(kWhatRTPRetransmissionNotify, id());
@@ -264,7 +191,7 @@ status_t Sender::init(
}
}
-#if ENABLE_RETRANSMISSION
+#if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX
if (mTransportMode == TRANSPORT_UDP) {
int32_t rtpRetransmissionSession;
@@ -358,44 +285,67 @@ int32_t Sender::getRTPPort() const {
}
void Sender::queuePackets(
- int64_t timeUs, const sp<ABuffer> &packets) {
- bool isVideo = false;
+ int64_t timeUs, const sp<ABuffer> &tsPackets) {
+ const size_t numTSPackets = tsPackets->size() / 188;
+
+ const size_t numRTPPackets =
+ (numTSPackets + kMaxNumTSPacketsPerRTPPacket - 1)
+ / kMaxNumTSPacketsPerRTPPacket;
+
+ sp<ABuffer> udpPackets = new ABuffer(
+ numRTPPackets * (12 + kMaxNumTSPacketsPerRTPPacket * 188));
+
+ udpPackets->meta()->setInt64("timeUs", timeUs);
+
+ size_t dstOffset = 0;
+ for (size_t i = 0; i < numTSPackets; ++i) {
+ if ((i % kMaxNumTSPacketsPerRTPPacket) == 0) {
+ static const bool kMarkerBit = false;
+
+ uint8_t *rtp = udpPackets->data() + dstOffset;
+ rtp[0] = 0x80;
+ rtp[1] = 33 | (kMarkerBit ? (1 << 7) : 0); // M-bit
+ rtp[2] = (mRTPSeqNo >> 8) & 0xff;
+ rtp[3] = mRTPSeqNo & 0xff;
+ rtp[4] = 0x00; // rtp time to be filled in later.
+ rtp[5] = 0x00;
+ rtp[6] = 0x00;
+ rtp[7] = 0x00;
+ rtp[8] = kSourceID >> 24;
+ rtp[9] = (kSourceID >> 16) & 0xff;
+ rtp[10] = (kSourceID >> 8) & 0xff;
+ rtp[11] = kSourceID & 0xff;
+
+ ++mRTPSeqNo;
+
+ dstOffset += 12;
+ }
+
+ memcpy(udpPackets->data() + dstOffset,
+ tsPackets->data() + 188 * i,
+ 188);
- int32_t dummy;
- if (packets->meta()->findInt32("isVideo", &dummy)) {
- isVideo = true;
+ dstOffset += 188;
}
- int64_t delayUs;
- int64_t whenUs;
+ udpPackets->setRange(0, dstOffset);
- if (mFirstOutputBufferReadyTimeUs < 0ll) {
- mFirstOutputBufferReadyTimeUs = timeUs;
- mFirstOutputBufferSentTimeUs = whenUs = ALooper::GetNowUs();
- delayUs = 0ll;
- } else {
- int64_t nowUs = ALooper::GetNowUs();
-
- whenUs = (timeUs - mFirstOutputBufferReadyTimeUs)
- + mFirstOutputBufferSentTimeUs;
+ sp<AMessage> msg = new AMessage(kWhatDrainQueue, id());
+ msg->setBuffer("udpPackets", udpPackets);
+ msg->post();
- delayUs = whenUs - nowUs;
+#if LOG_TRANSPORT_STREAM
+ if (mLogFile != NULL) {
+ fwrite(tsPackets->data(), 1, tsPackets->size(), mLogFile);
}
-
- sp<AMessage> msg = new AMessage(kWhatQueuePackets, id());
- msg->setBuffer("packets", packets);
-
- packets->meta()->setInt64("timeUs", timeUs);
- packets->meta()->setInt64("whenUs", whenUs);
- packets->meta()->setInt64("delayUs", delayUs);
- msg->post(delayUs > 0 ? delayUs : 0);
+#endif
}
void Sender::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatRTPNotify:
case kWhatRTCPNotify:
-#if ENABLE_RETRANSMISSION
+#if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX
case kWhatRTPRetransmissionNotify:
case kWhatRTCPRetransmissionNotify:
#endif
@@ -419,7 +369,7 @@ void Sender::onMessageReceived(const sp<AMessage> &msg) {
CHECK(msg->findString("detail", &detail));
if ((msg->what() == kWhatRTPNotify
-#if ENABLE_RETRANSMISSION
+#if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX
|| msg->what() == kWhatRTPRetransmissionNotify
#endif
) && !errorOccuredDuringSend) {
@@ -443,7 +393,7 @@ void Sender::onMessageReceived(const sp<AMessage> &msg) {
} else if (sessionID == mRTCPSessionID) {
mRTCPSessionID = 0;
}
-#if ENABLE_RETRANSMISSION
+#if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX
else if (sessionID == mRTPRetransmissionSessionID) {
mRTPRetransmissionSessionID = 0;
} else if (sessionID == mRTCPRetransmissionSessionID) {
@@ -465,7 +415,7 @@ void Sender::onMessageReceived(const sp<AMessage> &msg) {
status_t err;
if (msg->what() == kWhatRTCPNotify
-#if ENABLE_RETRANSMISSION
+#if ENABLE_RETRANSMISSION && RETRANSMISSION_ACCORDING_TO_RFC_XXXX
|| msg->what() == kWhatRTCPRetransmissionNotify
#endif
)
@@ -507,12 +457,12 @@ void Sender::onMessageReceived(const sp<AMessage> &msg) {
break;
}
- case kWhatQueuePackets:
+ case kWhatDrainQueue:
{
- sp<ABuffer> packets;
- CHECK(msg->findBuffer("packets", &packets));
+ sp<ABuffer> udpPackets;
+ CHECK(msg->findBuffer("udpPackets", &udpPackets));
- onQueuePackets(packets);
+ onDrainQueue(udpPackets);
break;
}
@@ -532,156 +482,6 @@ void Sender::onMessageReceived(const sp<AMessage> &msg) {
}
}
-void Sender::onQueuePackets(const sp<ABuffer> &packets) {
-#if DEBUG_JITTER
- int32_t dummy;
- if (packets->meta()->findInt32("isVideo", &dummy)) {
- static int64_t lastTimeUs = 0ll;
- int64_t nowUs = ALooper::GetNowUs();
-
- static TimeSeries series;
- series.add((double)(nowUs - lastTimeUs));
-
- ALOGI("deltaTimeUs = %lld us, mean %.2f, sdev %.2f",
- nowUs - lastTimeUs, series.mean(), series.sdev());
-
- lastTimeUs = nowUs;
- }
-#endif
-
- int64_t startTimeUs = ALooper::GetNowUs();
-
- for (size_t offset = 0;
- offset < packets->size(); offset += 188) {
- bool lastTSPacket = (offset + 188 >= packets->size());
-
- appendTSData(
- packets->data() + offset,
- 188,
- true /* timeDiscontinuity */,
- lastTSPacket /* flush */);
- }
-
-#if 0
- int64_t netTimeUs = ALooper::GetNowUs() - startTimeUs;
-
- int64_t whenUs;
- CHECK(packets->meta()->findInt64("whenUs", &whenUs));
-
- int64_t delayUs;
- CHECK(packets->meta()->findInt64("delayUs", &delayUs));
-
- bool isVideo = false;
- int32_t dummy;
- if (packets->meta()->findInt32("isVideo", &dummy)) {
- isVideo = true;
- }
-
- int64_t nowUs = ALooper::GetNowUs();
-
- if (nowUs - whenUs > 2000) {
- ALOGI("[%s] delayUs = %lld us, delta = %lld us",
- isVideo ? "video" : "audio", delayUs, nowUs - netTimeUs - whenUs);
- }
-#endif
-
-#if LOG_TRANSPORT_STREAM
- if (mLogFile != NULL) {
- fwrite(packets->data(), 1, packets->size(), mLogFile);
- }
-#endif
-}
-
-ssize_t Sender::appendTSData(
- const void *data, size_t size, bool timeDiscontinuity, bool flush) {
- CHECK_EQ(size, 188);
-
- CHECK_LE(mTSQueue->size() + size, mTSQueue->capacity());
-
- memcpy(mTSQueue->data() + mTSQueue->size(), data, size);
- mTSQueue->setRange(0, mTSQueue->size() + size);
-
- if (flush || mTSQueue->size() == mTSQueue->capacity()) {
- // flush
-
- int64_t nowUs = ALooper::GetNowUs();
-
-#if TRACK_BANDWIDTH
- if (mFirstPacketTimeUs < 0ll) {
- mFirstPacketTimeUs = nowUs;
- }
-#endif
-
- // 90kHz time scale
- uint32_t rtpTime = (nowUs * 9ll) / 100ll;
-
- uint8_t *rtp = mTSQueue->data();
- rtp[0] = 0x80;
- rtp[1] = 33 | (timeDiscontinuity ? (1 << 7) : 0); // M-bit
- rtp[2] = (mRTPSeqNo >> 8) & 0xff;
- rtp[3] = mRTPSeqNo & 0xff;
- rtp[4] = rtpTime >> 24;
- rtp[5] = (rtpTime >> 16) & 0xff;
- rtp[6] = (rtpTime >> 8) & 0xff;
- rtp[7] = rtpTime & 0xff;
- rtp[8] = kSourceID >> 24;
- rtp[9] = (kSourceID >> 16) & 0xff;
- rtp[10] = (kSourceID >> 8) & 0xff;
- rtp[11] = kSourceID & 0xff;
-
- ++mRTPSeqNo;
- ++mNumRTPSent;
- mNumRTPOctetsSent += mTSQueue->size() - 12;
-
- mLastRTPTime = rtpTime;
- mLastNTPTime = GetNowNTP();
-
- if (mTransportMode == TRANSPORT_TCP_INTERLEAVED) {
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatBinaryData);
-
- sp<ABuffer> data = new ABuffer(mTSQueue->size());
- memcpy(data->data(), rtp, mTSQueue->size());
-
- notify->setInt32("channel", mRTPChannel);
- notify->setBuffer("data", data);
- notify->post();
- } else {
- sendPacket(mRTPSessionID, rtp, mTSQueue->size());
-
-#if TRACK_BANDWIDTH
- mTotalBytesSent += mTSQueue->size();
- int64_t delayUs = ALooper::GetNowUs() - mFirstPacketTimeUs;
-
- if (delayUs > 0ll) {
- ALOGI("approx. net bandwidth used: %.2f Mbit/sec",
- mTotalBytesSent * 8.0 / delayUs);
- }
-#endif
- }
-
-#if ENABLE_RETRANSMISSION
- mTSQueue->setInt32Data(mRTPSeqNo - 1);
-
- mHistory.push_back(mTSQueue);
- ++mHistoryLength;
-
- if (mHistoryLength > kMaxHistoryLength) {
- mTSQueue = *mHistory.begin();
- mHistory.erase(mHistory.begin());
-
- --mHistoryLength;
- } else {
- mTSQueue = new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188);
- }
-#endif
-
- mTSQueue->setRange(0, 12);
- }
-
- return size;
-}
-
void Sender::scheduleSendSR() {
if (mSendSRPending || mRTCPSessionID == 0) {
return;
@@ -851,6 +651,7 @@ status_t Sender::parseTSFB(
if (retransmit) {
ALOGI("retransmitting seqNo %d", bufferSeqNo);
+#if RETRANSMISSION_ACCORDING_TO_RFC_XXXX
sp<ABuffer> retransRTP = new ABuffer(2 + buffer->size());
uint8_t *rtp = retransRTP->data();
memcpy(rtp, buffer->data(), 12);
@@ -865,6 +666,10 @@ status_t Sender::parseTSFB(
sendPacket(
mRTPRetransmissionSessionID,
retransRTP->data(), retransRTP->size());
+#else
+ sendPacket(
+ mRTPSessionID, buffer->data(), buffer->size());
+#endif
if (bufferSeqNo == seqNo) {
foundSeqNo = true;
@@ -975,5 +780,91 @@ void Sender::notifySessionDead() {
notify->post();
}
+void Sender::onDrainQueue(const sp<ABuffer> &udpPackets) {
+ static const size_t kFullRTPPacketSize =
+ 12 + 188 * kMaxNumTSPacketsPerRTPPacket;
+
+ size_t srcOffset = 0;
+ while (srcOffset < udpPackets->size()) {
+ uint8_t *rtp = udpPackets->data() + srcOffset;
+
+ size_t rtpPacketSize = udpPackets->size() - srcOffset;
+ if (rtpPacketSize > kFullRTPPacketSize) {
+ rtpPacketSize = kFullRTPPacketSize;
+ }
+
+ int64_t nowUs = ALooper::GetNowUs();
+ mLastNTPTime = GetNowNTP();
+
+ // 90kHz time scale
+ uint32_t rtpTime = (nowUs * 9ll) / 100ll;
+
+ rtp[4] = rtpTime >> 24;
+ rtp[5] = (rtpTime >> 16) & 0xff;
+ rtp[6] = (rtpTime >> 8) & 0xff;
+ rtp[7] = rtpTime & 0xff;
+
+ ++mNumRTPSent;
+ mNumRTPOctetsSent += rtpPacketSize - 12;
+
+ mLastRTPTime = rtpTime;
+
+ if (mTransportMode == TRANSPORT_TCP_INTERLEAVED) {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatBinaryData);
+
+ sp<ABuffer> data = new ABuffer(rtpPacketSize);
+ memcpy(data->data(), rtp, rtpPacketSize);
+
+ notify->setInt32("channel", mRTPChannel);
+ notify->setBuffer("data", data);
+ notify->post();
+ } else {
+ sendPacket(mRTPSessionID, rtp, rtpPacketSize);
+
+#if TRACK_BANDWIDTH
+ mTotalBytesSent += rtpPacketSize->size();
+ int64_t delayUs = ALooper::GetNowUs() - mFirstPacketTimeUs;
+
+ if (delayUs > 0ll) {
+ ALOGI("approx. net bandwidth used: %.2f Mbit/sec",
+ mTotalBytesSent * 8.0 / delayUs);
+ }
+#endif
+ }
+
+#if ENABLE_RETRANSMISSION
+ addToHistory(rtp, rtpPacketSize);
+#endif
+
+ srcOffset += rtpPacketSize;
+ }
+
+#if 0
+ int64_t timeUs;
+ CHECK(udpPackets->meta()->findInt64("timeUs", &timeUs));
+
+ ALOGI("dTimeUs = %lld us", ALooper::GetNowUs() - timeUs);
+#endif
+}
+
+#if ENABLE_RETRANSMISSION
+void Sender::addToHistory(const uint8_t *rtp, size_t rtpPacketSize) {
+ sp<ABuffer> packet = new ABuffer(rtpPacketSize);
+ memcpy(packet->data(), rtp, rtpPacketSize);
+
+ unsigned rtpSeqNo = U16_AT(&rtp[2]);
+ packet->setInt32Data(rtpSeqNo);
+
+ mHistory.push_back(packet);
+ ++mHistoryLength;
+
+ if (mHistoryLength > kMaxHistoryLength) {
+ mHistory.erase(mHistory.begin());
+ --mHistoryLength;
+ }
+}
+#endif
+
} // namespace android