summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/wifi-display/source
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2013-03-25 15:46:52 -0700
committerAndreas Huber <andih@google.com>2013-03-25 16:20:26 -0700
commit2aea9552aeba92bbaf9e56c666049ea2d14057b5 (patch)
treefc3cdb049837a7bdd7452620b9b596aad2c831d3 /media/libstagefright/wifi-display/source
parentf90debb467a0daf5288e7d8684642ef1119c4bad (diff)
downloadframeworks_av-2aea9552aeba92bbaf9e56c666049ea2d14057b5.zip
frameworks_av-2aea9552aeba92bbaf9e56c666049ea2d14057b5.tar.gz
frameworks_av-2aea9552aeba92bbaf9e56c666049ea2d14057b5.tar.bz2
In "special" mode we now establish a UDP RTCP channel in addition to the
TCP RTP channel and provide feedback on the latency of arriving packets from the sink back to the source. This information is then used to throttle video bitrate. Change-Id: Ic589a3cb65e4893a3ff67de947da6063d32a1c6e
Diffstat (limited to 'media/libstagefright/wifi-display/source')
-rw-r--r--media/libstagefright/wifi-display/source/Converter.cpp17
-rw-r--r--media/libstagefright/wifi-display/source/Converter.h3
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.cpp52
-rw-r--r--media/libstagefright/wifi-display/source/PlaybackSession.h9
-rw-r--r--media/libstagefright/wifi-display/source/WifiDisplaySource.cpp18
5 files changed, 88 insertions, 11 deletions
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp
index bb8c387..d41e1e6 100644
--- a/media/libstagefright/wifi-display/source/Converter.cpp
+++ b/media/libstagefright/wifi-display/source/Converter.cpp
@@ -622,6 +622,7 @@ status_t Converter::feedEncoderInputBuffers() {
}
status_t Converter::doMoreWork() {
+#if 0
if (mIsVideo) {
int32_t videoBitrate = getBitrate("media.wfd.video-bitrate", 5000000);
if (videoBitrate != mPrevVideoBitrate) {
@@ -633,6 +634,7 @@ status_t Converter::doMoreWork() {
mPrevVideoBitrate = videoBitrate;
}
}
+#endif
status_t err;
@@ -708,4 +710,19 @@ void Converter::dropAFrame() {
(new AMessage(kWhatDropAFrame, id()))->post();
}
+int32_t Converter::getVideoBitrate() const {
+ return mPrevVideoBitrate;
+}
+
+void Converter::setVideoBitrate(int32_t bitRate) {
+ if (mIsVideo && mEncoder != NULL && bitRate != mPrevVideoBitrate) {
+ sp<AMessage> params = new AMessage;
+ params->setInt32("videoBitrate", bitRate);
+
+ mEncoder->setParameters(params);
+
+ mPrevVideoBitrate = bitRate;
+ }
+}
+
} // namespace android
diff --git a/media/libstagefright/wifi-display/source/Converter.h b/media/libstagefright/wifi-display/source/Converter.h
index a418f69..538f10a 100644
--- a/media/libstagefright/wifi-display/source/Converter.h
+++ b/media/libstagefright/wifi-display/source/Converter.h
@@ -70,6 +70,9 @@ struct Converter : public AHandler {
void shutdownAsync();
+ int32_t getVideoBitrate() const;
+ void setVideoBitrate(int32_t bitrate);
+
protected:
virtual ~Converter();
virtual void onMessageReceived(const sp<AMessage> &msg);
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index a3b6542..68aa9cb 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -362,8 +362,11 @@ WifiDisplaySource::PlaybackSession::PlaybackSession(
}
status_t WifiDisplaySource::PlaybackSession::init(
- const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
- RTPSender::TransportMode transportMode,
+ const char *clientIP,
+ int32_t clientRtp,
+ RTPSender::TransportMode rtpMode,
+ int32_t clientRtcp,
+ RTPSender::TransportMode rtcpMode,
bool enableAudio,
bool usePCMAudio,
bool enableVideo,
@@ -385,10 +388,11 @@ status_t WifiDisplaySource::PlaybackSession::init(
if (err == OK) {
err = mMediaSender->initAsync(
-1 /* trackIndex */,
- transportMode,
clientIP,
clientRtp,
+ rtpMode,
clientRtcp,
+ rtcpMode,
&mLocalRTPPort);
}
@@ -548,6 +552,8 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
converter->dropAFrame();
}
}
+ } else if (what == MediaSender::kWhatInformSender) {
+ onSinkFeedback(msg);
} else {
TRESPASS();
}
@@ -643,6 +649,46 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived(
}
}
+void WifiDisplaySource::PlaybackSession::onSinkFeedback(const sp<AMessage> &msg) {
+ int64_t avgLatencyUs;
+ CHECK(msg->findInt64("avgLatencyUs", &avgLatencyUs));
+
+ int64_t maxLatencyUs;
+ CHECK(msg->findInt64("maxLatencyUs", &maxLatencyUs));
+
+ ALOGI("sink reports avg. latency of %lld ms (max %lld ms)",
+ avgLatencyUs / 1000ll,
+ maxLatencyUs / 1000ll);
+
+ if (mVideoTrackIndex >= 0) {
+ const sp<Track> &videoTrack = mTracks.valueFor(mVideoTrackIndex);
+ sp<Converter> converter = videoTrack->converter();
+ if (converter != NULL) {
+ int32_t videoBitrate = converter->getVideoBitrate();
+
+ if (avgLatencyUs > 300000ll) {
+ videoBitrate *= 0.6;
+
+ if (videoBitrate < 500000) {
+ videoBitrate = 500000; // cap at 500kbit/sec
+ }
+ } else if (avgLatencyUs < 100000ll) {
+ videoBitrate *= 1.1;
+
+ if (videoBitrate > 10000000) {
+ videoBitrate = 10000000; // cap at 10Mbit/sec
+ }
+ }
+
+ if (videoBitrate != converter->getVideoBitrate()) {
+ ALOGI("setting video bitrate to %d bps", videoBitrate);
+
+ converter->setVideoBitrate(videoBitrate);
+ }
+ }
+ }
+}
+
status_t WifiDisplaySource::PlaybackSession::setupMediaPacketizer(
bool enableAudio, bool enableVideo) {
DataSource::RegisterDefaultSniffers();
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h
index da207e2..39086a1 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.h
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.h
@@ -44,8 +44,11 @@ struct WifiDisplaySource::PlaybackSession : public AHandler {
const char *path = NULL);
status_t init(
- const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
- RTPSender::TransportMode transportMode,
+ const char *clientIP,
+ int32_t clientRtp,
+ RTPSender::TransportMode rtpMode,
+ int32_t clientRtcp,
+ RTPSender::TransportMode rtcpMode,
bool enableAudio,
bool usePCMAudio,
bool enableVideo,
@@ -149,6 +152,8 @@ private:
void schedulePullExtractor();
void onPullExtractor();
+ void onSinkFeedback(const sp<AMessage> &msg);
+
DISALLOW_EVIL_CONSTRUCTORS(PlaybackSession);
};
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index 5167cb3..f2e659a 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -1159,7 +1159,7 @@ status_t WifiDisplaySource::onSetupRequest(
return ERROR_MALFORMED;
}
- RTPSender::TransportMode transportMode = RTPSender::TRANSPORT_UDP;
+ RTPSender::TransportMode rtpMode = RTPSender::TRANSPORT_UDP;
int clientRtp, clientRtcp;
if (transport.startsWith("RTP/AVP/TCP;")) {
@@ -1168,7 +1168,7 @@ status_t WifiDisplaySource::onSetupRequest(
transport.c_str(), "interleaved", &interleaved)
&& sscanf(interleaved.c_str(), "%d-%d",
&clientRtp, &clientRtcp) == 2) {
- transportMode = RTPSender::TRANSPORT_TCP_INTERLEAVED;
+ rtpMode = RTPSender::TRANSPORT_TCP_INTERLEAVED;
} else {
bool badRequest = false;
@@ -1190,7 +1190,7 @@ status_t WifiDisplaySource::onSetupRequest(
return ERROR_MALFORMED;
}
- transportMode = RTPSender::TRANSPORT_TCP;
+ rtpMode = RTPSender::TRANSPORT_TCP;
}
} else if (transport.startsWith("RTP/AVP;unicast;")
|| transport.startsWith("RTP/AVP/UDP;unicast;")) {
@@ -1249,11 +1249,17 @@ status_t WifiDisplaySource::onSetupRequest(
return ERROR_MALFORMED;
}
+ RTPSender::TransportMode rtcpMode = RTPSender::TRANSPORT_UDP;
+ if (clientRtcp < 0) {
+ rtcpMode = RTPSender::TRANSPORT_NONE;
+ }
+
status_t err = playbackSession->init(
mClientInfo.mRemoteIP.c_str(),
clientRtp,
+ rtpMode,
clientRtcp,
- transportMode,
+ rtcpMode,
mSinkSupportsAudio,
mUsingPCMAudio,
mSinkSupportsVideo,
@@ -1282,7 +1288,7 @@ status_t WifiDisplaySource::onSetupRequest(
AString response = "RTSP/1.0 200 OK\r\n";
AppendCommonResponse(&response, cseq, playbackSessionID);
- if (transportMode == RTPSender::TRANSPORT_TCP_INTERLEAVED) {
+ if (rtpMode == RTPSender::TRANSPORT_TCP_INTERLEAVED) {
response.append(
StringPrintf(
"Transport: RTP/AVP/TCP;interleaved=%d-%d;",
@@ -1291,7 +1297,7 @@ status_t WifiDisplaySource::onSetupRequest(
int32_t serverRtp = playbackSession->getRTPPort();
AString transportString = "UDP";
- if (transportMode == RTPSender::TRANSPORT_TCP) {
+ if (rtpMode == RTPSender::TRANSPORT_TCP) {
transportString = "TCP";
}