From 3a9682a86ead84d6f60d3f3aa01b2b4d34af983d Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 23 Apr 2013 13:47:46 -0700 Subject: Remove all traces of wifi display sink implementation and supporting code. Change-Id: I64b681b7e3df1ef0dd80c0d261cacae293d5e684 related-to-bug: 8698812 --- media/libstagefright/wifi-display/Android.mk | 76 -- .../libstagefright/wifi-display/MediaReceiver.cpp | 328 ------ media/libstagefright/wifi-display/MediaReceiver.h | 111 -- media/libstagefright/wifi-display/MediaSender.cpp | 16 - media/libstagefright/wifi-display/MediaSender.h | 1 - media/libstagefright/wifi-display/SNTPClient.cpp | 174 --- media/libstagefright/wifi-display/SNTPClient.h | 62 -- media/libstagefright/wifi-display/TimeSyncer.cpp | 338 ------ media/libstagefright/wifi-display/TimeSyncer.h | 109 -- media/libstagefright/wifi-display/nettest.cpp | 400 ------- .../wifi-display/rtp/RTPAssembler.cpp | 328 ------ .../libstagefright/wifi-display/rtp/RTPAssembler.h | 92 -- .../wifi-display/rtp/RTPReceiver.cpp | 1153 -------------------- .../libstagefright/wifi-display/rtp/RTPReceiver.h | 125 --- .../libstagefright/wifi-display/rtp/RTPSender.cpp | 11 - media/libstagefright/wifi-display/rtp/RTPSender.h | 1 - media/libstagefright/wifi-display/rtptest.cpp | 565 ---------- .../wifi-display/sink/DirectRenderer.cpp | 625 ----------- .../wifi-display/sink/DirectRenderer.h | 82 -- .../wifi-display/sink/WifiDisplaySink.cpp | 917 ---------------- .../wifi-display/sink/WifiDisplaySink.h | 196 ---- .../wifi-display/source/PlaybackSession.cpp | 85 -- .../wifi-display/source/WifiDisplaySource.cpp | 14 - .../wifi-display/source/WifiDisplaySource.h | 3 - media/libstagefright/wifi-display/udptest.cpp | 116 -- media/libstagefright/wifi-display/wfd.cpp | 125 +-- 26 files changed, 4 insertions(+), 6049 deletions(-) delete mode 100644 media/libstagefright/wifi-display/MediaReceiver.cpp delete mode 100644 media/libstagefright/wifi-display/MediaReceiver.h delete mode 100644 media/libstagefright/wifi-display/SNTPClient.cpp delete mode 100644 media/libstagefright/wifi-display/SNTPClient.h delete mode 100644 media/libstagefright/wifi-display/TimeSyncer.cpp delete mode 100644 media/libstagefright/wifi-display/TimeSyncer.h delete mode 100644 media/libstagefright/wifi-display/nettest.cpp delete mode 100644 media/libstagefright/wifi-display/rtp/RTPAssembler.cpp delete mode 100644 media/libstagefright/wifi-display/rtp/RTPAssembler.h delete mode 100644 media/libstagefright/wifi-display/rtp/RTPReceiver.cpp delete mode 100644 media/libstagefright/wifi-display/rtp/RTPReceiver.h delete mode 100644 media/libstagefright/wifi-display/rtptest.cpp delete mode 100644 media/libstagefright/wifi-display/sink/DirectRenderer.cpp delete mode 100644 media/libstagefright/wifi-display/sink/DirectRenderer.h delete mode 100644 media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp delete mode 100644 media/libstagefright/wifi-display/sink/WifiDisplaySink.h delete mode 100644 media/libstagefright/wifi-display/udptest.cpp diff --git a/media/libstagefright/wifi-display/Android.mk b/media/libstagefright/wifi-display/Android.mk index f99ef60..061ae89 100644 --- a/media/libstagefright/wifi-display/Android.mk +++ b/media/libstagefright/wifi-display/Android.mk @@ -4,17 +4,10 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ ANetworkSession.cpp \ - MediaReceiver.cpp \ MediaSender.cpp \ Parameters.cpp \ ParsedMessage.cpp \ - rtp/RTPAssembler.cpp \ - rtp/RTPReceiver.cpp \ rtp/RTPSender.cpp \ - sink/DirectRenderer.cpp \ - sink/WifiDisplaySink.cpp \ - SNTPClient.cpp \ - TimeSyncer.cpp \ source/Converter.cpp \ source/MediaPuller.cpp \ source/PlaybackSession.cpp \ @@ -67,72 +60,3 @@ LOCAL_MODULE:= wfd LOCAL_MODULE_TAGS := debug include $(BUILD_EXECUTABLE) - -################################################################################ - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - udptest.cpp \ - -LOCAL_SHARED_LIBRARIES:= \ - libbinder \ - libgui \ - libmedia \ - libstagefright \ - libstagefright_foundation \ - libstagefright_wfd \ - libutils \ - liblog \ - -LOCAL_MODULE:= udptest - -LOCAL_MODULE_TAGS := debug - -include $(BUILD_EXECUTABLE) - -################################################################################ - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - rtptest.cpp \ - -LOCAL_SHARED_LIBRARIES:= \ - libbinder \ - libgui \ - libmedia \ - libstagefright \ - libstagefright_foundation \ - libstagefright_wfd \ - libutils \ - liblog \ - -LOCAL_MODULE:= rtptest - -LOCAL_MODULE_TAGS := debug - -include $(BUILD_EXECUTABLE) - -################################################################################ - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - nettest.cpp \ - -LOCAL_SHARED_LIBRARIES:= \ - libbinder \ - libgui \ - libmedia \ - libstagefright \ - libstagefright_foundation \ - libstagefright_wfd \ - libutils \ - liblog \ - -LOCAL_MODULE:= nettest - -LOCAL_MODULE_TAGS := debug - -include $(BUILD_EXECUTABLE) diff --git a/media/libstagefright/wifi-display/MediaReceiver.cpp b/media/libstagefright/wifi-display/MediaReceiver.cpp deleted file mode 100644 index 364acb9..0000000 --- a/media/libstagefright/wifi-display/MediaReceiver.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright 2013, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "MediaReceiver" -#include - -#include "MediaReceiver.h" - -#include "ANetworkSession.h" -#include "AnotherPacketSource.h" -#include "rtp/RTPReceiver.h" - -#include -#include -#include -#include -#include - -namespace android { - -MediaReceiver::MediaReceiver( - const sp &netSession, - const sp ¬ify) - : mNetSession(netSession), - mNotify(notify), - mMode(MODE_UNDEFINED), - mGeneration(0), - mInitStatus(OK), - mInitDoneCount(0) { -} - -MediaReceiver::~MediaReceiver() { -} - -ssize_t MediaReceiver::addTrack( - RTPReceiver::TransportMode rtpMode, - RTPReceiver::TransportMode rtcpMode, - int32_t *localRTPPort) { - if (mMode != MODE_UNDEFINED) { - return INVALID_OPERATION; - } - - size_t trackIndex = mTrackInfos.size(); - - TrackInfo info; - - sp notify = new AMessage(kWhatReceiverNotify, id()); - notify->setInt32("generation", mGeneration); - notify->setSize("trackIndex", trackIndex); - - info.mReceiver = new RTPReceiver(mNetSession, notify); - looper()->registerHandler(info.mReceiver); - - info.mReceiver->registerPacketType( - 33, RTPReceiver::PACKETIZATION_TRANSPORT_STREAM); - - info.mReceiver->registerPacketType( - 96, RTPReceiver::PACKETIZATION_AAC); - - info.mReceiver->registerPacketType( - 97, RTPReceiver::PACKETIZATION_H264); - - status_t err = info.mReceiver->initAsync( - rtpMode, - rtcpMode, - localRTPPort); - - if (err != OK) { - looper()->unregisterHandler(info.mReceiver->id()); - info.mReceiver.clear(); - - return err; - } - - mTrackInfos.push_back(info); - - return trackIndex; -} - -status_t MediaReceiver::connectTrack( - size_t trackIndex, - const char *remoteHost, - int32_t remoteRTPPort, - int32_t remoteRTCPPort) { - if (trackIndex >= mTrackInfos.size()) { - return -ERANGE; - } - - TrackInfo *info = &mTrackInfos.editItemAt(trackIndex); - return info->mReceiver->connect(remoteHost, remoteRTPPort, remoteRTCPPort); -} - -status_t MediaReceiver::initAsync(Mode mode) { - if ((mode == MODE_TRANSPORT_STREAM || mode == MODE_TRANSPORT_STREAM_RAW) - && mTrackInfos.size() > 1) { - return INVALID_OPERATION; - } - - sp msg = new AMessage(kWhatInit, id()); - msg->setInt32("mode", mode); - msg->post(); - - return OK; -} - -void MediaReceiver::onMessageReceived(const sp &msg) { - switch (msg->what()) { - case kWhatInit: - { - int32_t mode; - CHECK(msg->findInt32("mode", &mode)); - - CHECK_EQ(mMode, MODE_UNDEFINED); - mMode = (Mode)mode; - - if (mInitStatus != OK || mInitDoneCount == mTrackInfos.size()) { - notifyInitDone(mInitStatus); - } - - mTSParser = new ATSParser( - ATSParser::ALIGNED_VIDEO_DATA - | ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE); - - mFormatKnownMask = 0; - break; - } - - case kWhatReceiverNotify: - { - int32_t generation; - CHECK(msg->findInt32("generation", &generation)); - if (generation != mGeneration) { - break; - } - - onReceiverNotify(msg); - break; - } - - default: - TRESPASS(); - } -} - -void MediaReceiver::onReceiverNotify(const sp &msg) { - int32_t what; - CHECK(msg->findInt32("what", &what)); - - switch (what) { - case RTPReceiver::kWhatInitDone: - { - ++mInitDoneCount; - - int32_t err; - CHECK(msg->findInt32("err", &err)); - - if (err != OK) { - mInitStatus = err; - ++mGeneration; - } - - if (mMode != MODE_UNDEFINED) { - if (mInitStatus != OK || mInitDoneCount == mTrackInfos.size()) { - notifyInitDone(mInitStatus); - } - } - break; - } - - case RTPReceiver::kWhatError: - { - int32_t err; - CHECK(msg->findInt32("err", &err)); - - notifyError(err); - break; - } - - case RTPReceiver::kWhatAccessUnit: - { - size_t trackIndex; - CHECK(msg->findSize("trackIndex", &trackIndex)); - - sp accessUnit; - CHECK(msg->findBuffer("accessUnit", &accessUnit)); - - int32_t followsDiscontinuity; - if (!msg->findInt32( - "followsDiscontinuity", &followsDiscontinuity)) { - followsDiscontinuity = 0; - } - - if (mMode == MODE_TRANSPORT_STREAM) { - if (followsDiscontinuity) { - mTSParser->signalDiscontinuity( - ATSParser::DISCONTINUITY_TIME, NULL /* extra */); - } - - for (size_t offset = 0; - offset < accessUnit->size(); offset += 188) { - status_t err = mTSParser->feedTSPacket( - accessUnit->data() + offset, 188); - - if (err != OK) { - notifyError(err); - break; - } - } - - drainPackets(0 /* trackIndex */, ATSParser::VIDEO); - drainPackets(1 /* trackIndex */, ATSParser::AUDIO); - } else { - postAccessUnit(trackIndex, accessUnit, NULL); - } - break; - } - - case RTPReceiver::kWhatPacketLost: - { - notifyPacketLost(); - break; - } - - default: - TRESPASS(); - } -} - -void MediaReceiver::drainPackets( - size_t trackIndex, ATSParser::SourceType type) { - sp source = - static_cast( - mTSParser->getSource(type).get()); - - if (source == NULL) { - return; - } - - sp format; - if (!(mFormatKnownMask & (1ul << trackIndex))) { - sp meta = source->getFormat(); - CHECK(meta != NULL); - - CHECK_EQ((status_t)OK, convertMetaDataToMessage(meta, &format)); - - mFormatKnownMask |= 1ul << trackIndex; - } - - status_t finalResult; - while (source->hasBufferAvailable(&finalResult)) { - sp accessUnit; - status_t err = source->dequeueAccessUnit(&accessUnit); - if (err == OK) { - postAccessUnit(trackIndex, accessUnit, format); - format.clear(); - } else if (err != INFO_DISCONTINUITY) { - notifyError(err); - } - } - - if (finalResult != OK) { - notifyError(finalResult); - } -} - -void MediaReceiver::notifyInitDone(status_t err) { - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatInitDone); - notify->setInt32("err", err); - notify->post(); -} - -void MediaReceiver::notifyError(status_t err) { - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatError); - notify->setInt32("err", err); - notify->post(); -} - -void MediaReceiver::notifyPacketLost() { - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatPacketLost); - notify->post(); -} - -void MediaReceiver::postAccessUnit( - size_t trackIndex, - const sp &accessUnit, - const sp &format) { - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatAccessUnit); - notify->setSize("trackIndex", trackIndex); - notify->setBuffer("accessUnit", accessUnit); - - if (format != NULL) { - notify->setMessage("format", format); - } - - notify->post(); -} - -status_t MediaReceiver::informSender( - size_t trackIndex, const sp ¶ms) { - if (trackIndex >= mTrackInfos.size()) { - return -ERANGE; - } - - TrackInfo *info = &mTrackInfos.editItemAt(trackIndex); - return info->mReceiver->informSender(params); -} - -} // namespace android - - diff --git a/media/libstagefright/wifi-display/MediaReceiver.h b/media/libstagefright/wifi-display/MediaReceiver.h deleted file mode 100644 index afbb407..0000000 --- a/media/libstagefright/wifi-display/MediaReceiver.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2013, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "ATSParser.h" -#include "rtp/RTPReceiver.h" - -namespace android { - -struct ABuffer; -struct ANetworkSession; -struct AMessage; -struct ATSParser; - -// This class facilitates receiving of media data for one or more tracks -// over RTP. Either a 1:1 track to RTP channel mapping is used or a single -// RTP channel provides the data for a transport stream that is consequently -// demuxed and its track's data provided to the observer. -struct MediaReceiver : public AHandler { - enum { - kWhatInitDone, - kWhatError, - kWhatAccessUnit, - kWhatPacketLost, - }; - - MediaReceiver( - const sp &netSession, - const sp ¬ify); - - ssize_t addTrack( - RTPReceiver::TransportMode rtpMode, - RTPReceiver::TransportMode rtcpMode, - int32_t *localRTPPort); - - status_t connectTrack( - size_t trackIndex, - const char *remoteHost, - int32_t remoteRTPPort, - int32_t remoteRTCPPort); - - enum Mode { - MODE_UNDEFINED, - MODE_TRANSPORT_STREAM, - MODE_TRANSPORT_STREAM_RAW, - MODE_ELEMENTARY_STREAMS, - }; - status_t initAsync(Mode mode); - - status_t informSender(size_t trackIndex, const sp ¶ms); - -protected: - virtual void onMessageReceived(const sp &msg); - virtual ~MediaReceiver(); - -private: - enum { - kWhatInit, - kWhatReceiverNotify, - }; - - struct TrackInfo { - sp mReceiver; - }; - - sp mNetSession; - sp mNotify; - - Mode mMode; - int32_t mGeneration; - - Vector mTrackInfos; - - status_t mInitStatus; - size_t mInitDoneCount; - - sp mTSParser; - uint32_t mFormatKnownMask; - - void onReceiverNotify(const sp &msg); - - void drainPackets(size_t trackIndex, ATSParser::SourceType type); - - void notifyInitDone(status_t err); - void notifyError(status_t err); - void notifyPacketLost(); - - void postAccessUnit( - size_t trackIndex, - const sp &accessUnit, - const sp &format); - - DISALLOW_EVIL_CONSTRUCTORS(MediaReceiver); -}; - -} // namespace android - diff --git a/media/libstagefright/wifi-display/MediaSender.cpp b/media/libstagefright/wifi-display/MediaSender.cpp index 33af66d..8a3566f 100644 --- a/media/libstagefright/wifi-display/MediaSender.cpp +++ b/media/libstagefright/wifi-display/MediaSender.cpp @@ -341,22 +341,6 @@ void MediaSender::onSenderNotify(const sp &msg) { break; } - case kWhatInformSender: - { - int64_t avgLatencyUs; - CHECK(msg->findInt64("avgLatencyUs", &avgLatencyUs)); - - int64_t maxLatencyUs; - CHECK(msg->findInt64("maxLatencyUs", &maxLatencyUs)); - - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatInformSender); - notify->setInt64("avgLatencyUs", avgLatencyUs); - notify->setInt64("maxLatencyUs", maxLatencyUs); - notify->post(); - break; - } - default: TRESPASS(); } diff --git a/media/libstagefright/wifi-display/MediaSender.h b/media/libstagefright/wifi-display/MediaSender.h index 04538ea..64722c5 100644 --- a/media/libstagefright/wifi-display/MediaSender.h +++ b/media/libstagefright/wifi-display/MediaSender.h @@ -43,7 +43,6 @@ struct MediaSender : public AHandler { kWhatInitDone, kWhatError, kWhatNetworkStall, - kWhatInformSender, }; MediaSender( diff --git a/media/libstagefright/wifi-display/SNTPClient.cpp b/media/libstagefright/wifi-display/SNTPClient.cpp deleted file mode 100644 index 5c0af6a..0000000 --- a/media/libstagefright/wifi-display/SNTPClient.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2013, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SNTPClient.h" - -#include -#include - -#include -#include -#include -#include -#include - -namespace android { - -SNTPClient::SNTPClient() { -} - -status_t SNTPClient::requestTime(const char *host) { - struct hostent *ent; - int64_t requestTimeNTP, requestTimeUs; - ssize_t n; - int64_t responseTimeUs, responseTimeNTP; - int64_t originateTimeNTP, receiveTimeNTP, transmitTimeNTP; - int64_t roundTripTimeNTP, clockOffsetNTP; - - status_t err = UNKNOWN_ERROR; - - int s = socket(AF_INET, SOCK_DGRAM, 0); - - if (s < 0) { - err = -errno; - - goto bail; - } - - ent = gethostbyname(host); - - if (ent == NULL) { - err = -ENOENT; - goto bail2; - } - - struct sockaddr_in hostAddr; - memset(hostAddr.sin_zero, 0, sizeof(hostAddr.sin_zero)); - hostAddr.sin_family = AF_INET; - hostAddr.sin_port = htons(kNTPPort); - hostAddr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr; - - uint8_t packet[kNTPPacketSize]; - memset(packet, 0, sizeof(packet)); - - packet[0] = kNTPModeClient | (kNTPVersion << 3); - - requestTimeNTP = getNowNTP(); - requestTimeUs = ALooper::GetNowUs(); - writeTimeStamp(&packet[kNTPTransmitTimeOffset], requestTimeNTP); - - n = sendto( - s, packet, sizeof(packet), 0, - (const struct sockaddr *)&hostAddr, sizeof(hostAddr)); - - if (n < 0) { - err = -errno; - goto bail2; - } - - memset(packet, 0, sizeof(packet)); - - do { - n = recv(s, packet, sizeof(packet), 0); - } while (n < 0 && errno == EINTR); - - if (n < 0) { - err = -errno; - goto bail2; - } - - responseTimeUs = ALooper::GetNowUs(); - - responseTimeNTP = requestTimeNTP + makeNTP(responseTimeUs - requestTimeUs); - - originateTimeNTP = readTimeStamp(&packet[kNTPOriginateTimeOffset]); - receiveTimeNTP = readTimeStamp(&packet[kNTPReceiveTimeOffset]); - transmitTimeNTP = readTimeStamp(&packet[kNTPTransmitTimeOffset]); - - roundTripTimeNTP = - makeNTP(responseTimeUs - requestTimeUs) - - (transmitTimeNTP - receiveTimeNTP); - - clockOffsetNTP = - ((receiveTimeNTP - originateTimeNTP) - + (transmitTimeNTP - responseTimeNTP)) / 2; - - mTimeReferenceNTP = responseTimeNTP + clockOffsetNTP; - mTimeReferenceUs = responseTimeUs; - mRoundTripTimeNTP = roundTripTimeNTP; - - err = OK; - -bail2: - close(s); - s = -1; - -bail: - return err; -} - -int64_t SNTPClient::adjustTimeUs(int64_t timeUs) const { - uint64_t nowNTP = - mTimeReferenceNTP + makeNTP(timeUs - mTimeReferenceUs); - - int64_t nowUs = - (nowNTP >> 32) * 1000000ll - + ((nowNTP & 0xffffffff) * 1000000ll) / (1ll << 32); - - nowUs -= ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll; - - return nowUs; -} - -// static -void SNTPClient::writeTimeStamp(uint8_t *dst, uint64_t ntpTime) { - *dst++ = (ntpTime >> 56) & 0xff; - *dst++ = (ntpTime >> 48) & 0xff; - *dst++ = (ntpTime >> 40) & 0xff; - *dst++ = (ntpTime >> 32) & 0xff; - *dst++ = (ntpTime >> 24) & 0xff; - *dst++ = (ntpTime >> 16) & 0xff; - *dst++ = (ntpTime >> 8) & 0xff; - *dst++ = ntpTime & 0xff; -} - -// static -uint64_t SNTPClient::readTimeStamp(const uint8_t *dst) { - return U64_AT(dst); -} - -// static -uint64_t SNTPClient::getNowNTP() { - struct timeval tv; - gettimeofday(&tv, NULL /* time zone */); - - uint64_t nowUs = tv.tv_sec * 1000000ll + tv.tv_usec; - - nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll; - - return makeNTP(nowUs); -} - -// static -uint64_t SNTPClient::makeNTP(uint64_t deltaUs) { - uint64_t hi = deltaUs / 1000000ll; - uint64_t lo = ((1ll << 32) * (deltaUs % 1000000ll)) / 1000000ll; - - return (hi << 32) | lo; -} - -} // namespace android - diff --git a/media/libstagefright/wifi-display/SNTPClient.h b/media/libstagefright/wifi-display/SNTPClient.h deleted file mode 100644 index 967d1fc..0000000 --- a/media/libstagefright/wifi-display/SNTPClient.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2013, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SNTP_CLIENT_H_ - -#define SNTP_CLIENT_H_ - -#include -#include - -namespace android { - -// Implementation of the SNTP (Simple Network Time Protocol) -struct SNTPClient { - SNTPClient(); - - status_t requestTime(const char *host); - - // given a time obtained from ALooper::GetNowUs() - // return the number of us elapsed since Jan 1 1970 00:00:00 (UTC). - int64_t adjustTimeUs(int64_t timeUs) const; - -private: - enum { - kNTPPort = 123, - kNTPPacketSize = 48, - kNTPModeClient = 3, - kNTPVersion = 3, - kNTPTransmitTimeOffset = 40, - kNTPOriginateTimeOffset = 24, - kNTPReceiveTimeOffset = 32, - }; - - uint64_t mTimeReferenceNTP; - int64_t mTimeReferenceUs; - int64_t mRoundTripTimeNTP; - - static void writeTimeStamp(uint8_t *dst, uint64_t ntpTime); - static uint64_t readTimeStamp(const uint8_t *dst); - - static uint64_t getNowNTP(); - static uint64_t makeNTP(uint64_t deltaUs); - - DISALLOW_EVIL_CONSTRUCTORS(SNTPClient); -}; - -} // namespace android - -#endif // SNTP_CLIENT_H_ diff --git a/media/libstagefright/wifi-display/TimeSyncer.cpp b/media/libstagefright/wifi-display/TimeSyncer.cpp deleted file mode 100644 index cb429bc..0000000 --- a/media/libstagefright/wifi-display/TimeSyncer.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright 2013, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NEBUG 0 -#define LOG_TAG "TimeSyncer" -#include - -#include "TimeSyncer.h" - -#include "ANetworkSession.h" - -#include -#include -#include -#include -#include -#include - -namespace android { - -TimeSyncer::TimeSyncer( - const sp &netSession, const sp ¬ify) - : mNetSession(netSession), - mNotify(notify), - mIsServer(false), - mConnected(false), - mUDPSession(0), - mSeqNo(0), - mTotalTimeUs(0.0), - mPendingT1(0ll), - mTimeoutGeneration(0) { -} - -TimeSyncer::~TimeSyncer() { -} - -void TimeSyncer::startServer(unsigned localPort) { - sp msg = new AMessage(kWhatStartServer, id()); - msg->setInt32("localPort", localPort); - msg->post(); -} - -void TimeSyncer::startClient(const char *remoteHost, unsigned remotePort) { - sp msg = new AMessage(kWhatStartClient, id()); - msg->setString("remoteHost", remoteHost); - msg->setInt32("remotePort", remotePort); - msg->post(); -} - -void TimeSyncer::onMessageReceived(const sp &msg) { - switch (msg->what()) { - case kWhatStartClient: - { - AString remoteHost; - CHECK(msg->findString("remoteHost", &remoteHost)); - - int32_t remotePort; - CHECK(msg->findInt32("remotePort", &remotePort)); - - sp notify = new AMessage(kWhatUDPNotify, id()); - - CHECK_EQ((status_t)OK, - mNetSession->createUDPSession( - 0 /* localPort */, - remoteHost.c_str(), - remotePort, - notify, - &mUDPSession)); - - postSendPacket(); - break; - } - - case kWhatStartServer: - { - mIsServer = true; - - int32_t localPort; - CHECK(msg->findInt32("localPort", &localPort)); - - sp notify = new AMessage(kWhatUDPNotify, id()); - - CHECK_EQ((status_t)OK, - mNetSession->createUDPSession( - localPort, notify, &mUDPSession)); - - break; - } - - case kWhatSendPacket: - { - if (mHistory.size() == 0) { - ALOGI("starting batch"); - } - - TimeInfo ti; - memset(&ti, 0, sizeof(ti)); - - ti.mT1 = ALooper::GetNowUs(); - - CHECK_EQ((status_t)OK, - mNetSession->sendRequest( - mUDPSession, &ti, sizeof(ti))); - - mPendingT1 = ti.mT1; - postTimeout(); - break; - } - - case kWhatTimedOut: - { - int32_t generation; - CHECK(msg->findInt32("generation", &generation)); - - if (generation != mTimeoutGeneration) { - break; - } - - ALOGI("timed out, sending another request"); - postSendPacket(); - break; - } - - case kWhatUDPNotify: - { - int32_t reason; - CHECK(msg->findInt32("reason", &reason)); - - switch (reason) { - case ANetworkSession::kWhatError: - { - int32_t sessionID; - CHECK(msg->findInt32("sessionID", &sessionID)); - - int32_t err; - CHECK(msg->findInt32("err", &err)); - - AString detail; - CHECK(msg->findString("detail", &detail)); - - ALOGE("An error occurred in session %d (%d, '%s/%s').", - sessionID, - err, - detail.c_str(), - strerror(-err)); - - mNetSession->destroySession(sessionID); - - cancelTimeout(); - - notifyError(err); - break; - } - - case ANetworkSession::kWhatDatagram: - { - int32_t sessionID; - CHECK(msg->findInt32("sessionID", &sessionID)); - - sp packet; - CHECK(msg->findBuffer("data", &packet)); - - int64_t arrivalTimeUs; - CHECK(packet->meta()->findInt64( - "arrivalTimeUs", &arrivalTimeUs)); - - CHECK_EQ(packet->size(), sizeof(TimeInfo)); - - TimeInfo *ti = (TimeInfo *)packet->data(); - - if (mIsServer) { - if (!mConnected) { - AString fromAddr; - CHECK(msg->findString("fromAddr", &fromAddr)); - - int32_t fromPort; - CHECK(msg->findInt32("fromPort", &fromPort)); - - CHECK_EQ((status_t)OK, - mNetSession->connectUDPSession( - mUDPSession, fromAddr.c_str(), fromPort)); - - mConnected = true; - } - - ti->mT2 = arrivalTimeUs; - ti->mT3 = ALooper::GetNowUs(); - - CHECK_EQ((status_t)OK, - mNetSession->sendRequest( - mUDPSession, ti, sizeof(*ti))); - } else { - if (ti->mT1 != mPendingT1) { - break; - } - - cancelTimeout(); - mPendingT1 = 0; - - ti->mT4 = arrivalTimeUs; - - // One way delay for a packet to travel from client - // to server or back (assumed to be the same either way). - int64_t delay = - (ti->mT2 - ti->mT1 + ti->mT4 - ti->mT3) / 2; - - // Offset between the client clock (T1, T4) and the - // server clock (T2, T3) timestamps. - int64_t offset = - (ti->mT2 - ti->mT1 - ti->mT4 + ti->mT3) / 2; - - mHistory.push_back(*ti); - - ALOGV("delay = %lld us,\toffset %lld us", - delay, - offset); - - if (mHistory.size() < kNumPacketsPerBatch) { - postSendPacket(1000000ll / 30); - } else { - notifyOffset(); - - ALOGI("batch done"); - - mHistory.clear(); - postSendPacket(kBatchDelayUs); - } - } - break; - } - - default: - TRESPASS(); - } - - break; - } - - default: - TRESPASS(); - } -} - -void TimeSyncer::postSendPacket(int64_t delayUs) { - (new AMessage(kWhatSendPacket, id()))->post(delayUs); -} - -void TimeSyncer::postTimeout() { - sp msg = new AMessage(kWhatTimedOut, id()); - msg->setInt32("generation", mTimeoutGeneration); - msg->post(kTimeoutDelayUs); -} - -void TimeSyncer::cancelTimeout() { - ++mTimeoutGeneration; -} - -void TimeSyncer::notifyError(status_t err) { - if (mNotify == NULL) { - looper()->stop(); - return; - } - - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatError); - notify->setInt32("err", err); - notify->post(); -} - -// static -int TimeSyncer::CompareRountripTime(const TimeInfo *ti1, const TimeInfo *ti2) { - int64_t rt1 = ti1->mT4 - ti1->mT1; - int64_t rt2 = ti2->mT4 - ti2->mT1; - - if (rt1 < rt2) { - return -1; - } else if (rt1 > rt2) { - return 1; - } - - return 0; -} - -void TimeSyncer::notifyOffset() { - mHistory.sort(CompareRountripTime); - - int64_t sum = 0ll; - size_t count = 0; - - // Only consider the third of the information associated with the best - // (smallest) roundtrip times. - for (size_t i = 0; i < mHistory.size() / 3; ++i) { - const TimeInfo *ti = &mHistory[i]; - -#if 0 - // One way delay for a packet to travel from client - // to server or back (assumed to be the same either way). - int64_t delay = - (ti->mT2 - ti->mT1 + ti->mT4 - ti->mT3) / 2; -#endif - - // Offset between the client clock (T1, T4) and the - // server clock (T2, T3) timestamps. - int64_t offset = - (ti->mT2 - ti->mT1 - ti->mT4 + ti->mT3) / 2; - - ALOGV("(%d) RT: %lld us, offset: %lld us", - i, ti->mT4 - ti->mT1, offset); - - sum += offset; - ++count; - } - - if (mNotify == NULL) { - ALOGI("avg. offset is %lld", sum / count); - return; - } - - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatTimeOffset); - notify->setInt64("offset", sum / count); - notify->post(); -} - -} // namespace android diff --git a/media/libstagefright/wifi-display/TimeSyncer.h b/media/libstagefright/wifi-display/TimeSyncer.h deleted file mode 100644 index 4e7571f..0000000 --- a/media/libstagefright/wifi-display/TimeSyncer.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2013, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TIME_SYNCER_H_ - -#define TIME_SYNCER_H_ - -#include - -namespace android { - -struct ANetworkSession; - -/* - TimeSyncer allows us to synchronize time between a client and a server. - The client sends a UDP packet containing its send-time to the server, - the server sends that packet back to the client amended with information - about when it was received as well as the time the reply was sent back. - Finally the client receives the reply and has now enough information to - compute the clock offset between client and server assuming that packet - exchange is symmetric, i.e. time for a packet client->server and - server->client is roughly equal. - This exchange is repeated a number of times and the average offset computed - over the 30% of packets that had the lowest roundtrip times. - The offset is determined every 10 secs to account for slight differences in - clock frequency. -*/ -struct TimeSyncer : public AHandler { - enum { - kWhatError, - kWhatTimeOffset, - }; - TimeSyncer( - const sp &netSession, - const sp ¬ify); - - void startServer(unsigned localPort); - void startClient(const char *remoteHost, unsigned remotePort); - -protected: - virtual ~TimeSyncer(); - - virtual void onMessageReceived(const sp &msg); - -private: - enum { - kWhatStartServer, - kWhatStartClient, - kWhatUDPNotify, - kWhatSendPacket, - kWhatTimedOut, - }; - - struct TimeInfo { - int64_t mT1; // client timestamp at send - int64_t mT2; // server timestamp at receive - int64_t mT3; // server timestamp at send - int64_t mT4; // client timestamp at receive - }; - - enum { - kNumPacketsPerBatch = 30, - }; - static const int64_t kTimeoutDelayUs = 500000ll; - static const int64_t kBatchDelayUs = 60000000ll; // every minute - - sp mNetSession; - sp mNotify; - - bool mIsServer; - bool mConnected; - int32_t mUDPSession; - uint32_t mSeqNo; - double mTotalTimeUs; - - Vector mHistory; - - int64_t mPendingT1; - int32_t mTimeoutGeneration; - - void postSendPacket(int64_t delayUs = 0ll); - - void postTimeout(); - void cancelTimeout(); - - void notifyError(status_t err); - void notifyOffset(); - - static int CompareRountripTime(const TimeInfo *ti1, const TimeInfo *ti2); - - DISALLOW_EVIL_CONSTRUCTORS(TimeSyncer); -}; - -} // namespace android - -#endif // TIME_SYNCER_H_ diff --git a/media/libstagefright/wifi-display/nettest.cpp b/media/libstagefright/wifi-display/nettest.cpp deleted file mode 100644 index 0779bf5..0000000 --- a/media/libstagefright/wifi-display/nettest.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright 2013, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NEBUG 0 -#define LOG_TAG "nettest" -#include - -#include "ANetworkSession.h" -#include "TimeSyncer.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace android { - -struct TestHandler : public AHandler { - TestHandler(const sp &netSession); - - void listen(int32_t port); - void connect(const char *host, int32_t port); - -protected: - virtual ~TestHandler(); - virtual void onMessageReceived(const sp &msg); - -private: - enum { - kTimeSyncerPort = 8123, - }; - - enum { - kWhatListen, - kWhatConnect, - kWhatTimeSyncerNotify, - kWhatNetNotify, - kWhatSendMore, - kWhatStop, - }; - - sp mNetSession; - sp mTimeSyncer; - - int32_t mServerSessionID; - int32_t mSessionID; - - int64_t mTimeOffsetUs; - bool mTimeOffsetValid; - - int32_t mCounter; - - int64_t mMaxDelayMs; - - void dumpDelay(int32_t counter, int64_t delayMs); - - DISALLOW_EVIL_CONSTRUCTORS(TestHandler); -}; - -TestHandler::TestHandler(const sp &netSession) - : mNetSession(netSession), - mServerSessionID(0), - mSessionID(0), - mTimeOffsetUs(-1ll), - mTimeOffsetValid(false), - mCounter(0), - mMaxDelayMs(-1ll) { -} - -TestHandler::~TestHandler() { -} - -void TestHandler::listen(int32_t port) { - sp msg = new AMessage(kWhatListen, id()); - msg->setInt32("port", port); - msg->post(); -} - -void TestHandler::connect(const char *host, int32_t port) { - sp msg = new AMessage(kWhatConnect, id()); - msg->setString("host", host); - msg->setInt32("port", port); - msg->post(); -} - -void TestHandler::dumpDelay(int32_t counter, int64_t delayMs) { - static const int64_t kMinDelayMs = 0; - static const int64_t kMaxDelayMs = 300; - - const char *kPattern = "########################################"; - size_t kPatternSize = strlen(kPattern); - - int n = (kPatternSize * (delayMs - kMinDelayMs)) - / (kMaxDelayMs - kMinDelayMs); - - if (n < 0) { - n = 0; - } else if ((size_t)n > kPatternSize) { - n = kPatternSize; - } - - if (delayMs > mMaxDelayMs) { - mMaxDelayMs = delayMs; - } - - ALOGI("[%d] (%4lld ms / %4lld ms) %s", - counter, - delayMs, - mMaxDelayMs, - kPattern + kPatternSize - n); -} - -void TestHandler::onMessageReceived(const sp &msg) { - switch (msg->what()) { - case kWhatListen: - { - sp notify = new AMessage(kWhatTimeSyncerNotify, id()); - mTimeSyncer = new TimeSyncer(mNetSession, notify); - looper()->registerHandler(mTimeSyncer); - - notify = new AMessage(kWhatNetNotify, id()); - - int32_t port; - CHECK(msg->findInt32("port", &port)); - - struct in_addr ifaceAddr; - ifaceAddr.s_addr = INADDR_ANY; - - CHECK_EQ((status_t)OK, - mNetSession->createTCPDatagramSession( - ifaceAddr, - port, - notify, - &mServerSessionID)); - break; - } - - case kWhatConnect: - { - sp notify = new AMessage(kWhatTimeSyncerNotify, id()); - mTimeSyncer = new TimeSyncer(mNetSession, notify); - looper()->registerHandler(mTimeSyncer); - mTimeSyncer->startServer(kTimeSyncerPort); - - AString host; - CHECK(msg->findString("host", &host)); - - int32_t port; - CHECK(msg->findInt32("port", &port)); - - notify = new AMessage(kWhatNetNotify, id()); - - CHECK_EQ((status_t)OK, - mNetSession->createTCPDatagramSession( - 0 /* localPort */, - host.c_str(), - port, - notify, - &mSessionID)); - break; - } - - case kWhatNetNotify: - { - int32_t reason; - CHECK(msg->findInt32("reason", &reason)); - - switch (reason) { - case ANetworkSession::kWhatConnected: - { - ALOGI("kWhatConnected"); - - (new AMessage(kWhatSendMore, id()))->post(); - break; - } - - case ANetworkSession::kWhatClientConnected: - { - ALOGI("kWhatClientConnected"); - - CHECK_EQ(mSessionID, 0); - CHECK(msg->findInt32("sessionID", &mSessionID)); - - AString clientIP; - CHECK(msg->findString("client-ip", &clientIP)); - - mTimeSyncer->startClient(clientIP.c_str(), kTimeSyncerPort); - break; - } - - case ANetworkSession::kWhatDatagram: - { - sp packet; - CHECK(msg->findBuffer("data", &packet)); - - CHECK_EQ(packet->size(), 12u); - - int32_t counter = U32_AT(packet->data()); - int64_t timeUs = U64_AT(packet->data() + 4); - - if (mTimeOffsetValid) { - timeUs -= mTimeOffsetUs; - int64_t nowUs = ALooper::GetNowUs(); - int64_t delayMs = (nowUs - timeUs) / 1000ll; - - dumpDelay(counter, delayMs); - } else { - ALOGI("received %d", counter); - } - break; - } - - case ANetworkSession::kWhatError: - { - ALOGE("kWhatError"); - break; - } - - default: - TRESPASS(); - } - break; - } - - case kWhatTimeSyncerNotify: - { - CHECK(msg->findInt64("offset", &mTimeOffsetUs)); - mTimeOffsetValid = true; - break; - } - - case kWhatSendMore: - { - uint8_t buffer[4 + 8]; - buffer[0] = mCounter >> 24; - buffer[1] = (mCounter >> 16) & 0xff; - buffer[2] = (mCounter >> 8) & 0xff; - buffer[3] = mCounter & 0xff; - - int64_t nowUs = ALooper::GetNowUs(); - - buffer[4] = nowUs >> 56; - buffer[5] = (nowUs >> 48) & 0xff; - buffer[6] = (nowUs >> 40) & 0xff; - buffer[7] = (nowUs >> 32) & 0xff; - buffer[8] = (nowUs >> 24) & 0xff; - buffer[9] = (nowUs >> 16) & 0xff; - buffer[10] = (nowUs >> 8) & 0xff; - buffer[11] = nowUs & 0xff; - - ++mCounter; - - CHECK_EQ((status_t)OK, - mNetSession->sendRequest( - mSessionID, - buffer, - sizeof(buffer), - true /* timeValid */, - nowUs)); - - msg->post(100000ll); - break; - } - - case kWhatStop: - { - if (mSessionID != 0) { - mNetSession->destroySession(mSessionID); - mSessionID = 0; - } - - if (mServerSessionID != 0) { - mNetSession->destroySession(mServerSessionID); - mServerSessionID = 0; - } - - looper()->stop(); - break; - } - - default: - TRESPASS(); - } -} - -} // namespace android - -static void usage(const char *me) { - fprintf(stderr, - "usage: %s -c host:port\tconnect to remote host\n" - " -l port \tlisten\n", - me); -} - -int main(int argc, char **argv) { - using namespace android; - - // srand(time(NULL)); - - ProcessState::self()->startThreadPool(); - - DataSource::RegisterDefaultSniffers(); - - int32_t connectToPort = -1; - AString connectToHost; - - int32_t listenOnPort = -1; - - int res; - while ((res = getopt(argc, argv, "hc:l:")) >= 0) { - switch (res) { - case 'c': - { - const char *colonPos = strrchr(optarg, ':'); - - if (colonPos == NULL) { - usage(argv[0]); - exit(1); - } - - connectToHost.setTo(optarg, colonPos - optarg); - - char *end; - connectToPort = strtol(colonPos + 1, &end, 10); - - if (*end != '\0' || end == colonPos + 1 - || connectToPort < 0 || connectToPort > 65535) { - fprintf(stderr, "Illegal port specified.\n"); - exit(1); - } - break; - } - - case 'l': - { - char *end; - listenOnPort = strtol(optarg, &end, 10); - - if (*end != '\0' || end == optarg - || listenOnPort < 0 || listenOnPort > 65535) { - fprintf(stderr, "Illegal port specified.\n"); - exit(1); - } - break; - } - - case '?': - case 'h': - usage(argv[0]); - exit(1); - } - } - - if ((listenOnPort < 0 && connectToPort < 0) - || (listenOnPort >= 0 && connectToPort >= 0)) { - fprintf(stderr, - "You need to select either client or server mode.\n"); - exit(1); - } - - sp netSession = new ANetworkSession; - netSession->start(); - - sp looper = new ALooper; - - sp handler = new TestHandler(netSession); - looper->registerHandler(handler); - - if (listenOnPort) { - handler->listen(listenOnPort); - } - - if (connectToPort >= 0) { - handler->connect(connectToHost.c_str(), connectToPort); - } - - looper->start(true /* runOnCallingThread */); - - return 0; -} diff --git a/media/libstagefright/wifi-display/rtp/RTPAssembler.cpp b/media/libstagefright/wifi-display/rtp/RTPAssembler.cpp deleted file mode 100644 index 7a96081..0000000 --- a/media/libstagefright/wifi-display/rtp/RTPAssembler.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright 2013, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "RTPAssembler" -#include - -#include "RTPAssembler.h" - -#include -#include -#include -#include -#include - -namespace android { - -RTPReceiver::Assembler::Assembler(const sp ¬ify) - : mNotify(notify) { -} - -void RTPReceiver::Assembler::postAccessUnit( - const sp &accessUnit, bool followsDiscontinuity) { - sp notify = mNotify->dup(); - notify->setInt32("what", RTPReceiver::kWhatAccessUnit); - notify->setBuffer("accessUnit", accessUnit); - notify->setInt32("followsDiscontinuity", followsDiscontinuity); - notify->post(); -} -//////////////////////////////////////////////////////////////////////////////// - -RTPReceiver::TSAssembler::TSAssembler(const sp ¬ify) - : Assembler(notify), - mSawDiscontinuity(false) { -} - -void RTPReceiver::TSAssembler::signalDiscontinuity() { - mSawDiscontinuity = true; -} - -status_t RTPReceiver::TSAssembler::processPacket(const sp &packet) { - int32_t rtpTime; - CHECK(packet->meta()->findInt32("rtp-time", &rtpTime)); - - packet->meta()->setInt64("timeUs", (rtpTime * 100ll) / 9); - - postAccessUnit(packet, mSawDiscontinuity); - - if (mSawDiscontinuity) { - mSawDiscontinuity = false; - } - - return OK; -} - -//////////////////////////////////////////////////////////////////////////////// - -RTPReceiver::H264Assembler::H264Assembler(const sp ¬ify) - : Assembler(notify), - mState(0), - mIndicator(0), - mNALType(0), - mAccessUnitRTPTime(0) { -} - -void RTPReceiver::H264Assembler::signalDiscontinuity() { - reset(); -} - -status_t RTPReceiver::H264Assembler::processPacket(const sp &packet) { - status_t err = internalProcessPacket(packet); - - if (err != OK) { - reset(); - } - - return err; -} - -status_t RTPReceiver::H264Assembler::internalProcessPacket( - const sp &packet) { - const uint8_t *data = packet->data(); - size_t size = packet->size(); - - switch (mState) { - case 0: - { - if (size < 1 || (data[0] & 0x80)) { - ALOGV("Malformed H264 RTP packet (empty or F-bit set)"); - return ERROR_MALFORMED; - } - - unsigned nalType = data[0] & 0x1f; - if (nalType >= 1 && nalType <= 23) { - addSingleNALUnit(packet); - ALOGV("added single NAL packet"); - } else if (nalType == 28) { - // FU-A - unsigned indicator = data[0]; - CHECK((indicator & 0x1f) == 28); - - if (size < 2) { - ALOGV("Malformed H264 FU-A packet (single byte)"); - return ERROR_MALFORMED; - } - - if (!(data[1] & 0x80)) { - ALOGV("Malformed H264 FU-A packet (no start bit)"); - return ERROR_MALFORMED; - } - - mIndicator = data[0]; - mNALType = data[1] & 0x1f; - uint32_t nri = (data[0] >> 5) & 3; - - clearAccumulator(); - - uint8_t byte = mNALType | (nri << 5); - appendToAccumulator(&byte, 1); - appendToAccumulator(data + 2, size - 2); - - int32_t rtpTime; - CHECK(packet->meta()->findInt32("rtp-time", &rtpTime)); - mAccumulator->meta()->setInt32("rtp-time", rtpTime); - - if (data[1] & 0x40) { - // Huh? End bit also set on the first buffer. - addSingleNALUnit(mAccumulator); - clearAccumulator(); - - ALOGV("added FU-A"); - break; - } - - mState = 1; - } else if (nalType == 24) { - // STAP-A - - status_t err = addSingleTimeAggregationPacket(packet); - if (err != OK) { - return err; - } - } else { - ALOGV("Malformed H264 packet (unknown type %d)", nalType); - return ERROR_UNSUPPORTED; - } - break; - } - - case 1: - { - if (size < 2 - || data[0] != mIndicator - || (data[1] & 0x1f) != mNALType - || (data[1] & 0x80)) { - ALOGV("Malformed H264 FU-A packet (indicator, " - "type or start bit mismatch)"); - - return ERROR_MALFORMED; - } - - appendToAccumulator(data + 2, size - 2); - - if (data[1] & 0x40) { - addSingleNALUnit(mAccumulator); - - clearAccumulator(); - mState = 0; - - ALOGV("added FU-A"); - } - break; - } - - default: - TRESPASS(); - } - - int32_t marker; - CHECK(packet->meta()->findInt32("M", &marker)); - - if (marker) { - flushAccessUnit(); - } - - return OK; -} - -void RTPReceiver::H264Assembler::reset() { - mNALUnits.clear(); - - clearAccumulator(); - mState = 0; -} - -void RTPReceiver::H264Assembler::clearAccumulator() { - if (mAccumulator != NULL) { - // XXX Too expensive. - mAccumulator.clear(); - } -} - -void RTPReceiver::H264Assembler::appendToAccumulator( - const void *data, size_t size) { - if (mAccumulator == NULL) { - mAccumulator = new ABuffer(size); - memcpy(mAccumulator->data(), data, size); - return; - } - - if (mAccumulator->size() + size > mAccumulator->capacity()) { - sp buf = new ABuffer(mAccumulator->size() + size); - memcpy(buf->data(), mAccumulator->data(), mAccumulator->size()); - buf->setRange(0, mAccumulator->size()); - - int32_t rtpTime; - if (mAccumulator->meta()->findInt32("rtp-time", &rtpTime)) { - buf->meta()->setInt32("rtp-time", rtpTime); - } - - mAccumulator = buf; - } - - memcpy(mAccumulator->data() + mAccumulator->size(), data, size); - mAccumulator->setRange(0, mAccumulator->size() + size); -} - -void RTPReceiver::H264Assembler::addSingleNALUnit(const sp &packet) { - if (mNALUnits.empty()) { - int32_t rtpTime; - CHECK(packet->meta()->findInt32("rtp-time", &rtpTime)); - - mAccessUnitRTPTime = rtpTime; - } - - mNALUnits.push_back(packet); -} - -void RTPReceiver::H264Assembler::flushAccessUnit() { - if (mNALUnits.empty()) { - return; - } - - size_t totalSize = 0; - for (List >::iterator it = mNALUnits.begin(); - it != mNALUnits.end(); ++it) { - totalSize += 4 + (*it)->size(); - } - - sp accessUnit = new ABuffer(totalSize); - size_t offset = 0; - for (List >::iterator it = mNALUnits.begin(); - it != mNALUnits.end(); ++it) { - const sp nalUnit = *it; - - memcpy(accessUnit->data() + offset, "\x00\x00\x00\x01", 4); - - memcpy(accessUnit->data() + offset + 4, - nalUnit->data(), - nalUnit->size()); - - offset += 4 + nalUnit->size(); - } - - mNALUnits.clear(); - - accessUnit->meta()->setInt64("timeUs", mAccessUnitRTPTime * 100ll / 9ll); - postAccessUnit(accessUnit, false /* followsDiscontinuity */); -} - -status_t RTPReceiver::H264Assembler::addSingleTimeAggregationPacket( - const sp &packet) { - const uint8_t *data = packet->data(); - size_t size = packet->size(); - - if (size < 3) { - ALOGV("Malformed H264 STAP-A packet (too small)"); - return ERROR_MALFORMED; - } - - int32_t rtpTime; - CHECK(packet->meta()->findInt32("rtp-time", &rtpTime)); - - ++data; - --size; - while (size >= 2) { - size_t nalSize = (data[0] << 8) | data[1]; - - if (size < nalSize + 2) { - ALOGV("Malformed H264 STAP-A packet (incomplete NAL unit)"); - return ERROR_MALFORMED; - } - - sp unit = new ABuffer(nalSize); - memcpy(unit->data(), &data[2], nalSize); - - unit->meta()->setInt32("rtp-time", rtpTime); - - addSingleNALUnit(unit); - - data += 2 + nalSize; - size -= 2 + nalSize; - } - - if (size != 0) { - ALOGV("Unexpected padding at end of STAP-A packet."); - } - - ALOGV("added STAP-A"); - - return OK; -} - -} // namespace android - diff --git a/media/libstagefright/wifi-display/rtp/RTPAssembler.h b/media/libstagefright/wifi-display/rtp/RTPAssembler.h deleted file mode 100644 index e456d32..0000000 --- a/media/libstagefright/wifi-display/rtp/RTPAssembler.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2013, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef RTP_ASSEMBLER_H_ - -#define RTP_ASSEMBLER_H_ - -#include "RTPReceiver.h" - -namespace android { - -// A helper class to reassemble the payload of RTP packets into access -// units depending on the packetization scheme. -struct RTPReceiver::Assembler : public RefBase { - Assembler(const sp ¬ify); - - virtual void signalDiscontinuity() = 0; - virtual status_t processPacket(const sp &packet) = 0; - -protected: - virtual ~Assembler() {} - - void postAccessUnit( - const sp &accessUnit, bool followsDiscontinuity); - -private: - sp mNotify; - - DISALLOW_EVIL_CONSTRUCTORS(Assembler); -}; - -struct RTPReceiver::TSAssembler : public RTPReceiver::Assembler { - TSAssembler(const sp ¬ify); - - virtual void signalDiscontinuity(); - virtual status_t processPacket(const sp &packet); - -private: - bool mSawDiscontinuity; - - DISALLOW_EVIL_CONSTRUCTORS(TSAssembler); -}; - -struct RTPReceiver::H264Assembler : public RTPReceiver::Assembler { - H264Assembler(const sp ¬ify); - - virtual void signalDiscontinuity(); - virtual status_t processPacket(const sp &packet); - -private: - int32_t mState; - - uint8_t mIndicator; - uint8_t mNALType; - - sp mAccumulator; - - List > mNALUnits; - int32_t mAccessUnitRTPTime; - - status_t internalProcessPacket(const sp &packet); - - void addSingleNALUnit(const sp &packet); - status_t addSingleTimeAggregationPacket(const sp &packet); - - void flushAccessUnit(); - - void clearAccumulator(); - void appendToAccumulator(const void *data, size_t size); - - void reset(); - - DISALLOW_EVIL_CONSTRUCTORS(H264Assembler); -}; - -} // namespace android - -#endif // RTP_ASSEMBLER_H_ - diff --git a/media/libstagefright/wifi-display/rtp/RTPReceiver.cpp b/media/libstagefright/wifi-display/rtp/RTPReceiver.cpp deleted file mode 100644 index 8fa1dae..0000000 --- a/media/libstagefright/wifi-display/rtp/RTPReceiver.cpp +++ /dev/null @@ -1,1153 +0,0 @@ -/* - * Copyright 2013, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "RTPReceiver" -#include - -#include "RTPAssembler.h" -#include "RTPReceiver.h" - -#include "ANetworkSession.h" - -#include -#include -#include -#include -#include -#include - -#define TRACK_PACKET_LOSS 0 - -namespace android { - -//////////////////////////////////////////////////////////////////////////////// - -struct RTPReceiver::Source : public AHandler { - Source(RTPReceiver *receiver, uint32_t ssrc); - - void onPacketReceived(uint16_t seq, const sp &buffer); - - void addReportBlock(uint32_t ssrc, const sp &buf); - -protected: - virtual ~Source(); - - virtual void onMessageReceived(const sp &msg); - -private: - enum { - kWhatRetransmit, - kWhatDeclareLost, - }; - - static const uint32_t kMinSequential = 2; - static const uint32_t kMaxDropout = 3000; - static const uint32_t kMaxMisorder = 100; - static const uint32_t kRTPSeqMod = 1u << 16; - static const int64_t kReportIntervalUs = 10000000ll; - - RTPReceiver *mReceiver; - uint32_t mSSRC; - bool mFirst; - uint16_t mMaxSeq; - uint32_t mCycles; - uint32_t mBaseSeq; - uint32_t mReceived; - uint32_t mExpectedPrior; - uint32_t mReceivedPrior; - - int64_t mFirstArrivalTimeUs; - int64_t mFirstRTPTimeUs; - - // Ordered by extended seq number. - List > mPackets; - - enum StatusBits { - STATUS_DECLARED_LOST = 1, - STATUS_REQUESTED_RETRANSMISSION = 2, - STATUS_ARRIVED_LATE = 4, - }; -#if TRACK_PACKET_LOSS - KeyedVector mLostPackets; -#endif - - void modifyPacketStatus(int32_t extSeqNo, uint32_t mask); - - int32_t mAwaitingExtSeqNo; - bool mRequestedRetransmission; - - int32_t mActivePacketType; - sp mActiveAssembler; - - int64_t mNextReportTimeUs; - - int32_t mNumDeclaredLost; - int32_t mNumDeclaredLostPrior; - - int32_t mRetransmitGeneration; - int32_t mDeclareLostGeneration; - bool mDeclareLostTimerPending; - - void queuePacket(const sp &packet); - void dequeueMore(); - - sp getNextPacket(); - void resync(); - - void postRetransmitTimer(int64_t delayUs); - void postDeclareLostTimer(int64_t delayUs); - void cancelTimers(); - - DISALLOW_EVIL_CONSTRUCTORS(Source); -}; - -//////////////////////////////////////////////////////////////////////////////// - -RTPReceiver::Source::Source(RTPReceiver *receiver, uint32_t ssrc) - : mReceiver(receiver), - mSSRC(ssrc), - mFirst(true), - mMaxSeq(0), - mCycles(0), - mBaseSeq(0), - mReceived(0), - mExpectedPrior(0), - mReceivedPrior(0), - mFirstArrivalTimeUs(-1ll), - mFirstRTPTimeUs(-1ll), - mAwaitingExtSeqNo(-1), - mRequestedRetransmission(false), - mActivePacketType(-1), - mNextReportTimeUs(-1ll), - mNumDeclaredLost(0), - mNumDeclaredLostPrior(0), - mRetransmitGeneration(0), - mDeclareLostGeneration(0), - mDeclareLostTimerPending(false) { -} - -RTPReceiver::Source::~Source() { -} - -void RTPReceiver::Source::onMessageReceived(const sp &msg) { - switch (msg->what()) { - case kWhatRetransmit: - { - int32_t generation; - CHECK(msg->findInt32("generation", &generation)); - - if (generation != mRetransmitGeneration) { - break; - } - - mRequestedRetransmission = true; - mReceiver->requestRetransmission(mSSRC, mAwaitingExtSeqNo); - - modifyPacketStatus( - mAwaitingExtSeqNo, STATUS_REQUESTED_RETRANSMISSION); - break; - } - - case kWhatDeclareLost: - { - int32_t generation; - CHECK(msg->findInt32("generation", &generation)); - - if (generation != mDeclareLostGeneration) { - break; - } - - cancelTimers(); - - ALOGV("Lost packet extSeqNo %d %s", - mAwaitingExtSeqNo, - mRequestedRetransmission ? "*" : ""); - - mRequestedRetransmission = false; - if (mActiveAssembler != NULL) { - mActiveAssembler->signalDiscontinuity(); - } - - modifyPacketStatus(mAwaitingExtSeqNo, STATUS_DECLARED_LOST); - - // resync(); - ++mAwaitingExtSeqNo; - ++mNumDeclaredLost; - - mReceiver->notifyPacketLost(); - - dequeueMore(); - break; - } - - default: - TRESPASS(); - } -} - -void RTPReceiver::Source::onPacketReceived( - uint16_t seq, const sp &buffer) { - if (mFirst) { - buffer->setInt32Data(mCycles | seq); - queuePacket(buffer); - - mFirst = false; - mBaseSeq = seq; - mMaxSeq = seq; - ++mReceived; - return; - } - - uint16_t udelta = seq - mMaxSeq; - - if (udelta < kMaxDropout) { - // In order, with permissible gap. - - if (seq < mMaxSeq) { - // Sequence number wrapped - count another 64K cycle - mCycles += kRTPSeqMod; - } - - mMaxSeq = seq; - - ++mReceived; - } else if (udelta <= kRTPSeqMod - kMaxMisorder) { - // The sequence number made a very large jump - return; - } else { - // Duplicate or reordered packet. - } - - buffer->setInt32Data(mCycles | seq); - queuePacket(buffer); -} - -void RTPReceiver::Source::queuePacket(const sp &packet) { - int32_t newExtendedSeqNo = packet->int32Data(); - - if (mFirstArrivalTimeUs < 0ll) { - mFirstArrivalTimeUs = ALooper::GetNowUs(); - - uint32_t rtpTime; - CHECK(packet->meta()->findInt32("rtp-time", (int32_t *)&rtpTime)); - - mFirstRTPTimeUs = (rtpTime * 100ll) / 9ll; - } - - if (mAwaitingExtSeqNo >= 0 && newExtendedSeqNo < mAwaitingExtSeqNo) { - // We're no longer interested in these. They're old. - ALOGV("dropping stale extSeqNo %d", newExtendedSeqNo); - - modifyPacketStatus(newExtendedSeqNo, STATUS_ARRIVED_LATE); - return; - } - - if (mPackets.empty()) { - mPackets.push_back(packet); - dequeueMore(); - return; - } - - List >::iterator firstIt = mPackets.begin(); - List >::iterator it = --mPackets.end(); - for (;;) { - int32_t extendedSeqNo = (*it)->int32Data(); - - if (extendedSeqNo == newExtendedSeqNo) { - // Duplicate packet. - return; - } - - if (extendedSeqNo < newExtendedSeqNo) { - // Insert new packet after the one at "it". - mPackets.insert(++it, packet); - break; - } - - if (it == firstIt) { - // Insert new packet before the first existing one. - mPackets.insert(it, packet); - break; - } - - --it; - } - - dequeueMore(); -} - -void RTPReceiver::Source::dequeueMore() { - int64_t nowUs = ALooper::GetNowUs(); - if (mNextReportTimeUs < 0ll || nowUs >= mNextReportTimeUs) { - if (mNextReportTimeUs >= 0ll) { - uint32_t expected = (mMaxSeq | mCycles) - mBaseSeq + 1; - - uint32_t expectedInterval = expected - mExpectedPrior; - mExpectedPrior = expected; - - uint32_t receivedInterval = mReceived - mReceivedPrior; - mReceivedPrior = mReceived; - - int64_t lostInterval = - (int64_t)expectedInterval - (int64_t)receivedInterval; - - int32_t declaredLostInterval = - mNumDeclaredLost - mNumDeclaredLostPrior; - - mNumDeclaredLostPrior = mNumDeclaredLost; - - if (declaredLostInterval > 0) { - ALOGI("lost %lld packets (%.2f %%), declared %d lost\n", - lostInterval, - 100.0f * lostInterval / expectedInterval, - declaredLostInterval); - } - } - - mNextReportTimeUs = nowUs + kReportIntervalUs; - -#if TRACK_PACKET_LOSS - for (size_t i = 0; i < mLostPackets.size(); ++i) { - int32_t key = mLostPackets.keyAt(i); - uint32_t value = mLostPackets.valueAt(i); - - AString status; - if (value & STATUS_REQUESTED_RETRANSMISSION) { - status.append("retrans "); - } - if (value & STATUS_ARRIVED_LATE) { - status.append("arrived-late "); - } - ALOGI("Packet %d declared lost %s", key, status.c_str()); - } -#endif - } - - sp packet; - while ((packet = getNextPacket()) != NULL) { - if (mDeclareLostTimerPending) { - cancelTimers(); - } - - CHECK_GE(mAwaitingExtSeqNo, 0); -#if TRACK_PACKET_LOSS - mLostPackets.removeItem(mAwaitingExtSeqNo); -#endif - - int32_t packetType; - CHECK(packet->meta()->findInt32("PT", &packetType)); - - if (packetType != mActivePacketType) { - mActiveAssembler = mReceiver->makeAssembler(packetType); - mActivePacketType = packetType; - } - - if (mActiveAssembler != NULL) { - status_t err = mActiveAssembler->processPacket(packet); - if (err != OK) { - ALOGV("assembler returned error %d", err); - } - } - - ++mAwaitingExtSeqNo; - } - - if (mDeclareLostTimerPending) { - return; - } - - if (mPackets.empty()) { - return; - } - - CHECK_GE(mAwaitingExtSeqNo, 0); - - const sp &firstPacket = *mPackets.begin(); - - uint32_t rtpTime; - CHECK(firstPacket->meta()->findInt32( - "rtp-time", (int32_t *)&rtpTime)); - - - int64_t rtpUs = (rtpTime * 100ll) / 9ll; - - int64_t maxArrivalTimeUs = - mFirstArrivalTimeUs + rtpUs - mFirstRTPTimeUs; - - nowUs = ALooper::GetNowUs(); - - CHECK_LT(mAwaitingExtSeqNo, firstPacket->int32Data()); - - ALOGV("waiting for %d, comparing against %d, %lld us left", - mAwaitingExtSeqNo, - firstPacket->int32Data(), - maxArrivalTimeUs - nowUs); - - postDeclareLostTimer(maxArrivalTimeUs + kPacketLostAfterUs); - - if (kRequestRetransmissionAfterUs > 0ll) { - postRetransmitTimer( - maxArrivalTimeUs + kRequestRetransmissionAfterUs); - } -} - -sp RTPReceiver::Source::getNextPacket() { - if (mPackets.empty()) { - return NULL; - } - - int32_t extSeqNo = (*mPackets.begin())->int32Data(); - - if (mAwaitingExtSeqNo < 0) { - mAwaitingExtSeqNo = extSeqNo; - } else if (extSeqNo != mAwaitingExtSeqNo) { - return NULL; - } - - sp packet = *mPackets.begin(); - mPackets.erase(mPackets.begin()); - - return packet; -} - -void RTPReceiver::Source::resync() { - mAwaitingExtSeqNo = -1; -} - -void RTPReceiver::Source::addReportBlock( - uint32_t ssrc, const sp &buf) { - uint32_t extMaxSeq = mMaxSeq | mCycles; - uint32_t expected = extMaxSeq - mBaseSeq + 1; - - int64_t lost = (int64_t)expected - (int64_t)mReceived; - if (lost > 0x7fffff) { - lost = 0x7fffff; - } else if (lost < -0x800000) { - lost = -0x800000; - } - - uint32_t expectedInterval = expected - mExpectedPrior; - mExpectedPrior = expected; - - uint32_t receivedInterval = mReceived - mReceivedPrior; - mReceivedPrior = mReceived; - - int64_t lostInterval = expectedInterval - receivedInterval; - - uint8_t fractionLost; - if (expectedInterval == 0 || lostInterval <=0) { - fractionLost = 0; - } else { - fractionLost = (lostInterval << 8) / expectedInterval; - } - - uint8_t *ptr = buf->data() + buf->size(); - - ptr[0] = ssrc >> 24; - ptr[1] = (ssrc >> 16) & 0xff; - ptr[2] = (ssrc >> 8) & 0xff; - ptr[3] = ssrc & 0xff; - - ptr[4] = fractionLost; - - ptr[5] = (lost >> 16) & 0xff; - ptr[6] = (lost >> 8) & 0xff; - ptr[7] = lost & 0xff; - - ptr[8] = extMaxSeq >> 24; - ptr[9] = (extMaxSeq >> 16) & 0xff; - ptr[10] = (extMaxSeq >> 8) & 0xff; - ptr[11] = extMaxSeq & 0xff; - - // XXX TODO: - - ptr[12] = 0x00; // interarrival jitter - ptr[13] = 0x00; - ptr[14] = 0x00; - ptr[15] = 0x00; - - ptr[16] = 0x00; // last SR - ptr[17] = 0x00; - ptr[18] = 0x00; - ptr[19] = 0x00; - - ptr[20] = 0x00; // delay since last SR - ptr[21] = 0x00; - ptr[22] = 0x00; - ptr[23] = 0x00; -} - -//////////////////////////////////////////////////////////////////////////////// - -RTPReceiver::RTPReceiver( - const sp &netSession, - const sp ¬ify, - uint32_t flags) - : mNetSession(netSession), - mNotify(notify), - mFlags(flags), - mRTPMode(TRANSPORT_UNDEFINED), - mRTCPMode(TRANSPORT_UNDEFINED), - mRTPSessionID(0), - mRTCPSessionID(0), - mRTPConnected(false), - mRTCPConnected(false), - mRTPClientSessionID(0), - mRTCPClientSessionID(0) { -} - -RTPReceiver::~RTPReceiver() { - if (mRTCPClientSessionID != 0) { - mNetSession->destroySession(mRTCPClientSessionID); - mRTCPClientSessionID = 0; - } - - if (mRTPClientSessionID != 0) { - mNetSession->destroySession(mRTPClientSessionID); - mRTPClientSessionID = 0; - } - - if (mRTCPSessionID != 0) { - mNetSession->destroySession(mRTCPSessionID); - mRTCPSessionID = 0; - } - - if (mRTPSessionID != 0) { - mNetSession->destroySession(mRTPSessionID); - mRTPSessionID = 0; - } -} - -status_t RTPReceiver::initAsync( - TransportMode rtpMode, - TransportMode rtcpMode, - int32_t *outLocalRTPPort) { - if (mRTPMode != TRANSPORT_UNDEFINED - || rtpMode == TRANSPORT_UNDEFINED - || rtpMode == TRANSPORT_NONE - || rtcpMode == TRANSPORT_UNDEFINED) { - return INVALID_OPERATION; - } - - CHECK_NE(rtpMode, TRANSPORT_TCP_INTERLEAVED); - CHECK_NE(rtcpMode, TRANSPORT_TCP_INTERLEAVED); - - sp rtpNotify = new AMessage(kWhatRTPNotify, id()); - - sp rtcpNotify; - if (rtcpMode != TRANSPORT_NONE) { - rtcpNotify = new AMessage(kWhatRTCPNotify, id()); - } - - CHECK_EQ(mRTPSessionID, 0); - CHECK_EQ(mRTCPSessionID, 0); - - int32_t localRTPPort; - - struct in_addr ifaceAddr; - ifaceAddr.s_addr = INADDR_ANY; - - for (;;) { - localRTPPort = PickRandomRTPPort(); - - status_t err; - if (rtpMode == TRANSPORT_UDP) { - err = mNetSession->createUDPSession( - localRTPPort, - rtpNotify, - &mRTPSessionID); - } else { - CHECK_EQ(rtpMode, TRANSPORT_TCP); - err = mNetSession->createTCPDatagramSession( - ifaceAddr, - localRTPPort, - rtpNotify, - &mRTPSessionID); - } - - if (err != OK) { - continue; - } - - if (rtcpMode == TRANSPORT_NONE) { - break; - } else if (rtcpMode == TRANSPORT_UDP) { - err = mNetSession->createUDPSession( - localRTPPort + 1, - rtcpNotify, - &mRTCPSessionID); - } else { - CHECK_EQ(rtpMode, TRANSPORT_TCP); - err = mNetSession->createTCPDatagramSession( - ifaceAddr, - localRTPPort + 1, - rtcpNotify, - &mRTCPSessionID); - } - - if (err == OK) { - break; - } - - mNetSession->destroySession(mRTPSessionID); - mRTPSessionID = 0; - } - - mRTPMode = rtpMode; - mRTCPMode = rtcpMode; - *outLocalRTPPort = localRTPPort; - - return OK; -} - -status_t RTPReceiver::connect( - const char *remoteHost, int32_t remoteRTPPort, int32_t remoteRTCPPort) { - status_t err; - - if (mRTPMode == TRANSPORT_UDP) { - CHECK(!mRTPConnected); - - err = mNetSession->connectUDPSession( - mRTPSessionID, remoteHost, remoteRTPPort); - - if (err != OK) { - notifyInitDone(err); - return err; - } - - ALOGI("connectUDPSession RTP successful."); - - mRTPConnected = true; - } - - if (mRTCPMode == TRANSPORT_UDP) { - CHECK(!mRTCPConnected); - - err = mNetSession->connectUDPSession( - mRTCPSessionID, remoteHost, remoteRTCPPort); - - if (err != OK) { - notifyInitDone(err); - return err; - } - - scheduleSendRR(); - - ALOGI("connectUDPSession RTCP successful."); - - mRTCPConnected = true; - } - - if (mRTPConnected - && (mRTCPConnected || mRTCPMode == TRANSPORT_NONE)) { - notifyInitDone(OK); - } - - return OK; -} - -status_t RTPReceiver::informSender(const sp ¶ms) { - if (!mRTCPConnected) { - return INVALID_OPERATION; - } - - int64_t avgLatencyUs; - CHECK(params->findInt64("avgLatencyUs", &avgLatencyUs)); - - int64_t maxLatencyUs; - CHECK(params->findInt64("maxLatencyUs", &maxLatencyUs)); - - sp buf = new ABuffer(28); - - uint8_t *ptr = buf->data(); - ptr[0] = 0x80 | 0; - ptr[1] = 204; // APP - ptr[2] = 0; - - CHECK((buf->size() % 4) == 0u); - ptr[3] = (buf->size() / 4) - 1; - - ptr[4] = kSourceID >> 24; // SSRC - ptr[5] = (kSourceID >> 16) & 0xff; - ptr[6] = (kSourceID >> 8) & 0xff; - ptr[7] = kSourceID & 0xff; - ptr[8] = 'l'; - ptr[9] = 'a'; - ptr[10] = 't'; - ptr[11] = 'e'; - - ptr[12] = avgLatencyUs >> 56; - ptr[13] = (avgLatencyUs >> 48) & 0xff; - ptr[14] = (avgLatencyUs >> 40) & 0xff; - ptr[15] = (avgLatencyUs >> 32) & 0xff; - ptr[16] = (avgLatencyUs >> 24) & 0xff; - ptr[17] = (avgLatencyUs >> 16) & 0xff; - ptr[18] = (avgLatencyUs >> 8) & 0xff; - ptr[19] = avgLatencyUs & 0xff; - - ptr[20] = maxLatencyUs >> 56; - ptr[21] = (maxLatencyUs >> 48) & 0xff; - ptr[22] = (maxLatencyUs >> 40) & 0xff; - ptr[23] = (maxLatencyUs >> 32) & 0xff; - ptr[24] = (maxLatencyUs >> 24) & 0xff; - ptr[25] = (maxLatencyUs >> 16) & 0xff; - ptr[26] = (maxLatencyUs >> 8) & 0xff; - ptr[27] = maxLatencyUs & 0xff; - - mNetSession->sendRequest(mRTCPSessionID, buf->data(), buf->size()); - - return OK; -} - -void RTPReceiver::onMessageReceived(const sp &msg) { - switch (msg->what()) { - case kWhatRTPNotify: - case kWhatRTCPNotify: - onNetNotify(msg->what() == kWhatRTPNotify, msg); - break; - - case kWhatSendRR: - { - onSendRR(); - break; - } - - default: - TRESPASS(); - } -} - -void RTPReceiver::onNetNotify(bool isRTP, const sp &msg) { - int32_t reason; - CHECK(msg->findInt32("reason", &reason)); - - switch (reason) { - case ANetworkSession::kWhatError: - { - int32_t sessionID; - CHECK(msg->findInt32("sessionID", &sessionID)); - - int32_t err; - CHECK(msg->findInt32("err", &err)); - - int32_t errorOccuredDuringSend; - CHECK(msg->findInt32("send", &errorOccuredDuringSend)); - - AString detail; - CHECK(msg->findString("detail", &detail)); - - ALOGE("An error occurred during %s in session %d " - "(%d, '%s' (%s)).", - errorOccuredDuringSend ? "send" : "receive", - sessionID, - err, - detail.c_str(), - strerror(-err)); - - mNetSession->destroySession(sessionID); - - if (sessionID == mRTPSessionID) { - mRTPSessionID = 0; - } else if (sessionID == mRTCPSessionID) { - mRTCPSessionID = 0; - } else if (sessionID == mRTPClientSessionID) { - mRTPClientSessionID = 0; - } else if (sessionID == mRTCPClientSessionID) { - mRTCPClientSessionID = 0; - } - - if (!mRTPConnected - || (mRTCPMode != TRANSPORT_NONE && !mRTCPConnected)) { - notifyInitDone(err); - break; - } - - notifyError(err); - break; - } - - case ANetworkSession::kWhatDatagram: - { - sp data; - CHECK(msg->findBuffer("data", &data)); - - if (isRTP) { - if (mFlags & FLAG_AUTO_CONNECT) { - AString fromAddr; - CHECK(msg->findString("fromAddr", &fromAddr)); - - int32_t fromPort; - CHECK(msg->findInt32("fromPort", &fromPort)); - - CHECK_EQ((status_t)OK, - connect( - fromAddr.c_str(), fromPort, fromPort + 1)); - - mFlags &= ~FLAG_AUTO_CONNECT; - } - - onRTPData(data); - } else { - onRTCPData(data); - } - break; - } - - case ANetworkSession::kWhatClientConnected: - { - int32_t sessionID; - CHECK(msg->findInt32("sessionID", &sessionID)); - - if (isRTP) { - CHECK_EQ(mRTPMode, TRANSPORT_TCP); - - if (mRTPClientSessionID != 0) { - // We only allow a single client connection. - mNetSession->destroySession(sessionID); - sessionID = 0; - break; - } - - mRTPClientSessionID = sessionID; - mRTPConnected = true; - } else { - CHECK_EQ(mRTCPMode, TRANSPORT_TCP); - - if (mRTCPClientSessionID != 0) { - // We only allow a single client connection. - mNetSession->destroySession(sessionID); - sessionID = 0; - break; - } - - mRTCPClientSessionID = sessionID; - mRTCPConnected = true; - } - - if (mRTPConnected - && (mRTCPConnected || mRTCPMode == TRANSPORT_NONE)) { - notifyInitDone(OK); - } - break; - } - } -} - -void RTPReceiver::notifyInitDone(status_t err) { - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatInitDone); - notify->setInt32("err", err); - notify->post(); -} - -void RTPReceiver::notifyError(status_t err) { - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatError); - notify->setInt32("err", err); - notify->post(); -} - -void RTPReceiver::notifyPacketLost() { - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatPacketLost); - notify->post(); -} - -status_t RTPReceiver::onRTPData(const sp &buffer) { - size_t size = buffer->size(); - if (size < 12) { - // Too short to be a valid RTP header. - return ERROR_MALFORMED; - } - - const uint8_t *data = buffer->data(); - - if ((data[0] >> 6) != 2) { - // Unsupported version. - return ERROR_UNSUPPORTED; - } - - if (data[0] & 0x20) { - // Padding present. - - size_t paddingLength = data[size - 1]; - - if (paddingLength + 12 > size) { - // If we removed this much padding we'd end up with something - // that's too short to be a valid RTP header. - return ERROR_MALFORMED; - } - - size -= paddingLength; - } - - int numCSRCs = data[0] & 0x0f; - - size_t payloadOffset = 12 + 4 * numCSRCs; - - if (size < payloadOffset) { - // Not enough data to fit the basic header and all the CSRC entries. - return ERROR_MALFORMED; - } - - if (data[0] & 0x10) { - // Header eXtension present. - - if (size < payloadOffset + 4) { - // Not enough data to fit the basic header, all CSRC entries - // and the first 4 bytes of the extension header. - - return ERROR_MALFORMED; - } - - const uint8_t *extensionData = &data[payloadOffset]; - - size_t extensionLength = - 4 * (extensionData[2] << 8 | extensionData[3]); - - if (size < payloadOffset + 4 + extensionLength) { - return ERROR_MALFORMED; - } - - payloadOffset += 4 + extensionLength; - } - - uint32_t srcId = U32_AT(&data[8]); - uint32_t rtpTime = U32_AT(&data[4]); - uint16_t seqNo = U16_AT(&data[2]); - - sp meta = buffer->meta(); - meta->setInt32("ssrc", srcId); - meta->setInt32("rtp-time", rtpTime); - meta->setInt32("PT", data[1] & 0x7f); - meta->setInt32("M", data[1] >> 7); - - buffer->setRange(payloadOffset, size - payloadOffset); - - ssize_t index = mSources.indexOfKey(srcId); - sp source; - if (index < 0) { - source = new Source(this, srcId); - looper()->registerHandler(source); - - mSources.add(srcId, source); - } else { - source = mSources.valueAt(index); - } - - source->onPacketReceived(seqNo, buffer); - - return OK; -} - -status_t RTPReceiver::onRTCPData(const sp &data) { - ALOGI("onRTCPData"); - return OK; -} - -void RTPReceiver::addSDES(const sp &buffer) { - uint8_t *data = buffer->data() + buffer->size(); - data[0] = 0x80 | 1; - data[1] = 202; // SDES - data[4] = kSourceID >> 24; // SSRC - data[5] = (kSourceID >> 16) & 0xff; - data[6] = (kSourceID >> 8) & 0xff; - data[7] = kSourceID & 0xff; - - size_t offset = 8; - - data[offset++] = 1; // CNAME - - AString cname = "stagefright@somewhere"; - data[offset++] = cname.size(); - - memcpy(&data[offset], cname.c_str(), cname.size()); - offset += cname.size(); - - data[offset++] = 6; // TOOL - - AString tool = "stagefright/1.0"; - data[offset++] = tool.size(); - - memcpy(&data[offset], tool.c_str(), tool.size()); - offset += tool.size(); - - data[offset++] = 0; - - if ((offset % 4) > 0) { - size_t count = 4 - (offset % 4); - switch (count) { - case 3: - data[offset++] = 0; - case 2: - data[offset++] = 0; - case 1: - data[offset++] = 0; - } - } - - size_t numWords = (offset / 4) - 1; - data[2] = numWords >> 8; - data[3] = numWords & 0xff; - - buffer->setRange(buffer->offset(), buffer->size() + offset); -} - -void RTPReceiver::scheduleSendRR() { - (new AMessage(kWhatSendRR, id()))->post(5000000ll); -} - -void RTPReceiver::onSendRR() { -#if 0 - sp buf = new ABuffer(kMaxUDPPacketSize); - buf->setRange(0, 0); - - uint8_t *ptr = buf->data(); - ptr[0] = 0x80 | 0; - ptr[1] = 201; // RR - ptr[2] = 0; - ptr[3] = 1; - ptr[4] = kSourceID >> 24; // SSRC - ptr[5] = (kSourceID >> 16) & 0xff; - ptr[6] = (kSourceID >> 8) & 0xff; - ptr[7] = kSourceID & 0xff; - - buf->setRange(0, 8); - - size_t numReportBlocks = 0; - for (size_t i = 0; i < mSources.size(); ++i) { - uint32_t ssrc = mSources.keyAt(i); - sp source = mSources.valueAt(i); - - if (numReportBlocks > 31 || buf->size() + 24 > buf->capacity()) { - // Cannot fit another report block. - break; - } - - source->addReportBlock(ssrc, buf); - ++numReportBlocks; - } - - ptr[0] |= numReportBlocks; // 5 bit - - size_t sizeInWordsMinus1 = 1 + 6 * numReportBlocks; - ptr[2] = sizeInWordsMinus1 >> 8; - ptr[3] = sizeInWordsMinus1 & 0xff; - - buf->setRange(0, (sizeInWordsMinus1 + 1) * 4); - - addSDES(buf); - - mNetSession->sendRequest(mRTCPSessionID, buf->data(), buf->size()); -#endif - - scheduleSendRR(); -} - -status_t RTPReceiver::registerPacketType( - uint8_t packetType, PacketizationMode mode) { - mPacketTypes.add(packetType, mode); - - return OK; -} - -sp RTPReceiver::makeAssembler(uint8_t packetType) { - ssize_t index = mPacketTypes.indexOfKey(packetType); - if (index < 0) { - return NULL; - } - - PacketizationMode mode = mPacketTypes.valueAt(index); - - switch (mode) { - case PACKETIZATION_NONE: - case PACKETIZATION_TRANSPORT_STREAM: - return new TSAssembler(mNotify); - - case PACKETIZATION_H264: - return new H264Assembler(mNotify); - - default: - return NULL; - } -} - -void RTPReceiver::requestRetransmission(uint32_t senderSSRC, int32_t extSeqNo) { - int32_t blp = 0; - - sp buf = new ABuffer(16); - buf->setRange(0, 0); - - uint8_t *ptr = buf->data(); - ptr[0] = 0x80 | 1; // generic NACK - ptr[1] = 205; // TSFB - ptr[2] = 0; - ptr[3] = 3; - ptr[8] = (senderSSRC >> 24) & 0xff; - ptr[9] = (senderSSRC >> 16) & 0xff; - ptr[10] = (senderSSRC >> 8) & 0xff; - ptr[11] = (senderSSRC & 0xff); - ptr[8] = (kSourceID >> 24) & 0xff; - ptr[9] = (kSourceID >> 16) & 0xff; - ptr[10] = (kSourceID >> 8) & 0xff; - ptr[11] = (kSourceID & 0xff); - ptr[12] = (extSeqNo >> 8) & 0xff; - ptr[13] = (extSeqNo & 0xff); - ptr[14] = (blp >> 8) & 0xff; - ptr[15] = (blp & 0xff); - - buf->setRange(0, 16); - - mNetSession->sendRequest(mRTCPSessionID, buf->data(), buf->size()); -} - -void RTPReceiver::Source::modifyPacketStatus(int32_t extSeqNo, uint32_t mask) { -#if TRACK_PACKET_LOSS - ssize_t index = mLostPackets.indexOfKey(extSeqNo); - if (index < 0) { - mLostPackets.add(extSeqNo, mask); - } else { - mLostPackets.editValueAt(index) |= mask; - } -#endif -} - -void RTPReceiver::Source::postRetransmitTimer(int64_t timeUs) { - int64_t delayUs = timeUs - ALooper::GetNowUs(); - sp msg = new AMessage(kWhatRetransmit, id()); - msg->setInt32("generation", mRetransmitGeneration); - msg->post(delayUs); -} - -void RTPReceiver::Source::postDeclareLostTimer(int64_t timeUs) { - CHECK(!mDeclareLostTimerPending); - mDeclareLostTimerPending = true; - - int64_t delayUs = timeUs - ALooper::GetNowUs(); - sp msg = new AMessage(kWhatDeclareLost, id()); - msg->setInt32("generation", mDeclareLostGeneration); - msg->post(delayUs); -} - -void RTPReceiver::Source::cancelTimers() { - ++mRetransmitGeneration; - ++mDeclareLostGeneration; - mDeclareLostTimerPending = false; -} - -} // namespace android - diff --git a/media/libstagefright/wifi-display/rtp/RTPReceiver.h b/media/libstagefright/wifi-display/rtp/RTPReceiver.h deleted file mode 100644 index 240ab2e..0000000 --- a/media/libstagefright/wifi-display/rtp/RTPReceiver.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2013, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef RTP_RECEIVER_H_ - -#define RTP_RECEIVER_H_ - -#include "RTPBase.h" - -#include - -namespace android { - -struct ABuffer; -struct ANetworkSession; - -// An object of this class facilitates receiving of media data on an RTP -// channel. The channel is established over a UDP or TCP connection depending -// on which "TransportMode" was chosen. In addition different RTP packetization -// schemes are supported such as "Transport Stream Packets over RTP", -// or "AVC/H.264 encapsulation as specified in RFC 3984 (non-interleaved mode)" -struct RTPReceiver : public RTPBase, public AHandler { - enum { - kWhatInitDone, - kWhatError, - kWhatAccessUnit, - kWhatPacketLost, - }; - - enum Flags { - FLAG_AUTO_CONNECT = 1, - }; - RTPReceiver( - const sp &netSession, - const sp ¬ify, - uint32_t flags = 0); - - status_t registerPacketType( - uint8_t packetType, PacketizationMode mode); - - status_t initAsync( - TransportMode rtpMode, - TransportMode rtcpMode, - int32_t *outLocalRTPPort); - - status_t connect( - const char *remoteHost, - int32_t remoteRTPPort, - int32_t remoteRTCPPort); - - status_t informSender(const sp ¶ms); - -protected: - virtual ~RTPReceiver(); - virtual void onMessageReceived(const sp &msg); - -private: - enum { - kWhatRTPNotify, - kWhatRTCPNotify, - kWhatSendRR, - }; - - enum { - kSourceID = 0xdeadbeef, - kPacketLostAfterUs = 100000, - kRequestRetransmissionAfterUs = -1, - }; - - struct Assembler; - struct H264Assembler; - struct Source; - struct TSAssembler; - - sp mNetSession; - sp mNotify; - uint32_t mFlags; - TransportMode mRTPMode; - TransportMode mRTCPMode; - int32_t mRTPSessionID; - int32_t mRTCPSessionID; - bool mRTPConnected; - bool mRTCPConnected; - - int32_t mRTPClientSessionID; // in TRANSPORT_TCP mode. - int32_t mRTCPClientSessionID; // in TRANSPORT_TCP mode. - - KeyedVector mPacketTypes; - KeyedVector > mSources; - - void onNetNotify(bool isRTP, const sp &msg); - status_t onRTPData(const sp &data); - status_t onRTCPData(const sp &data); - void onSendRR(); - - void scheduleSendRR(); - void addSDES(const sp &buffer); - - void notifyInitDone(status_t err); - void notifyError(status_t err); - void notifyPacketLost(); - - sp makeAssembler(uint8_t packetType); - - void requestRetransmission(uint32_t senderSSRC, int32_t extSeqNo); - - DISALLOW_EVIL_CONSTRUCTORS(RTPReceiver); -}; - -} // namespace android - -#endif // RTP_RECEIVER_H_ diff --git a/media/libstagefright/wifi-display/rtp/RTPSender.cpp b/media/libstagefright/wifi-display/rtp/RTPSender.cpp index 6bbe650..095fd97 100644 --- a/media/libstagefright/wifi-display/rtp/RTPSender.cpp +++ b/media/libstagefright/wifi-display/rtp/RTPSender.cpp @@ -767,17 +767,6 @@ status_t RTPSender::parseTSFB(const uint8_t *data, size_t size) { } status_t RTPSender::parseAPP(const uint8_t *data, size_t size) { - if (!memcmp("late", &data[8], 4)) { - int64_t avgLatencyUs = (int64_t)U64_AT(&data[12]); - int64_t maxLatencyUs = (int64_t)U64_AT(&data[20]); - - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatInformSender); - notify->setInt64("avgLatencyUs", avgLatencyUs); - notify->setInt64("maxLatencyUs", maxLatencyUs); - notify->post(); - } - return OK; } diff --git a/media/libstagefright/wifi-display/rtp/RTPSender.h b/media/libstagefright/wifi-display/rtp/RTPSender.h index fefcab7..7dc138a 100644 --- a/media/libstagefright/wifi-display/rtp/RTPSender.h +++ b/media/libstagefright/wifi-display/rtp/RTPSender.h @@ -37,7 +37,6 @@ struct RTPSender : public RTPBase, public AHandler { kWhatInitDone, kWhatError, kWhatNetworkStall, - kWhatInformSender, }; RTPSender( const sp &netSession, diff --git a/media/libstagefright/wifi-display/rtptest.cpp b/media/libstagefright/wifi-display/rtptest.cpp deleted file mode 100644 index 764a38b..0000000 --- a/media/libstagefright/wifi-display/rtptest.cpp +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright 2013, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NEBUG 0 -#define LOG_TAG "rtptest" -#include - -#include "ANetworkSession.h" -#include "rtp/RTPSender.h" -#include "rtp/RTPReceiver.h" -#include "TimeSyncer.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MEDIA_FILENAME "/sdcard/Frame Counter HD 30FPS_1080p.mp4" - -namespace android { - -struct PacketSource : public RefBase { - PacketSource() {} - - virtual sp getNextAccessUnit() = 0; - -protected: - virtual ~PacketSource() {} - -private: - DISALLOW_EVIL_CONSTRUCTORS(PacketSource); -}; - -struct MediaPacketSource : public PacketSource { - MediaPacketSource() - : mMaxSampleSize(1024 * 1024) { - mExtractor = new NuMediaExtractor; - CHECK_EQ((status_t)OK, - mExtractor->setDataSource(MEDIA_FILENAME)); - - bool haveVideo = false; - for (size_t i = 0; i < mExtractor->countTracks(); ++i) { - sp format; - CHECK_EQ((status_t)OK, mExtractor->getTrackFormat(i, &format)); - - AString mime; - CHECK(format->findString("mime", &mime)); - - if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str())) { - mExtractor->selectTrack(i); - haveVideo = true; - break; - } - } - - CHECK(haveVideo); - } - - virtual sp getNextAccessUnit() { - int64_t timeUs; - status_t err = mExtractor->getSampleTime(&timeUs); - - if (err != OK) { - return NULL; - } - - sp accessUnit = new ABuffer(mMaxSampleSize); - CHECK_EQ((status_t)OK, mExtractor->readSampleData(accessUnit)); - - accessUnit->meta()->setInt64("timeUs", timeUs); - - CHECK_EQ((status_t)OK, mExtractor->advance()); - - return accessUnit; - } - -protected: - virtual ~MediaPacketSource() { - } - -private: - sp mExtractor; - size_t mMaxSampleSize; - - DISALLOW_EVIL_CONSTRUCTORS(MediaPacketSource); -}; - -struct SimplePacketSource : public PacketSource { - SimplePacketSource() - : mCounter(0) { - } - - virtual sp getNextAccessUnit() { - sp buffer = new ABuffer(4); - uint8_t *dst = buffer->data(); - dst[0] = mCounter >> 24; - dst[1] = (mCounter >> 16) & 0xff; - dst[2] = (mCounter >> 8) & 0xff; - dst[3] = mCounter & 0xff; - - buffer->meta()->setInt64("timeUs", mCounter * 1000000ll / kFrameRate); - - ++mCounter; - - return buffer; - } - -protected: - virtual ~SimplePacketSource() { - } - -private: - enum { - kFrameRate = 30 - }; - - uint32_t mCounter; - - DISALLOW_EVIL_CONSTRUCTORS(SimplePacketSource); -}; - -struct TestHandler : public AHandler { - TestHandler(const sp &netSession); - - void listen(); - void connect(const char *host, int32_t port); - -protected: - virtual ~TestHandler(); - virtual void onMessageReceived(const sp &msg); - -private: - enum { - kWhatListen, - kWhatConnect, - kWhatReceiverNotify, - kWhatSenderNotify, - kWhatSendMore, - kWhatStop, - kWhatTimeSyncerNotify, - }; - -#if 1 - static const RTPBase::TransportMode kRTPMode = RTPBase::TRANSPORT_UDP; - static const RTPBase::TransportMode kRTCPMode = RTPBase::TRANSPORT_UDP; -#else - static const RTPBase::TransportMode kRTPMode = RTPBase::TRANSPORT_TCP; - static const RTPBase::TransportMode kRTCPMode = RTPBase::TRANSPORT_NONE; -#endif - -#if 1 - static const RTPBase::PacketizationMode kPacketizationMode - = RTPBase::PACKETIZATION_H264; -#else - static const RTPBase::PacketizationMode kPacketizationMode - = RTPBase::PACKETIZATION_NONE; -#endif - - sp mNetSession; - sp mSource; - sp mSender; - sp mReceiver; - - sp mTimeSyncer; - bool mTimeSyncerStarted; - - int64_t mFirstTimeRealUs; - int64_t mFirstTimeMediaUs; - - int64_t mTimeOffsetUs; - bool mTimeOffsetValid; - - status_t readMore(); - - DISALLOW_EVIL_CONSTRUCTORS(TestHandler); -}; - -TestHandler::TestHandler(const sp &netSession) - : mNetSession(netSession), - mTimeSyncerStarted(false), - mFirstTimeRealUs(-1ll), - mFirstTimeMediaUs(-1ll), - mTimeOffsetUs(-1ll), - mTimeOffsetValid(false) { -} - -TestHandler::~TestHandler() { -} - -void TestHandler::listen() { - sp msg = new AMessage(kWhatListen, id()); - msg->post(); -} - -void TestHandler::connect(const char *host, int32_t port) { - sp msg = new AMessage(kWhatConnect, id()); - msg->setString("host", host); - msg->setInt32("port", port); - msg->post(); -} - -static void dumpDelay(int64_t delayMs) { - static const int64_t kMinDelayMs = 0; - static const int64_t kMaxDelayMs = 300; - - const char *kPattern = "########################################"; - size_t kPatternSize = strlen(kPattern); - - int n = (kPatternSize * (delayMs - kMinDelayMs)) - / (kMaxDelayMs - kMinDelayMs); - - if (n < 0) { - n = 0; - } else if ((size_t)n > kPatternSize) { - n = kPatternSize; - } - - ALOGI("(%4lld ms) %s\n", - delayMs, - kPattern + kPatternSize - n); -} - -void TestHandler::onMessageReceived(const sp &msg) { - switch (msg->what()) { - case kWhatListen: - { - sp notify = new AMessage(kWhatTimeSyncerNotify, id()); - mTimeSyncer = new TimeSyncer(mNetSession, notify); - looper()->registerHandler(mTimeSyncer); - - notify = new AMessage(kWhatReceiverNotify, id()); - mReceiver = new RTPReceiver( - mNetSession, notify, RTPReceiver::FLAG_AUTO_CONNECT); - looper()->registerHandler(mReceiver); - - CHECK_EQ((status_t)OK, - mReceiver->registerPacketType(33, kPacketizationMode)); - - int32_t receiverRTPPort; - CHECK_EQ((status_t)OK, - mReceiver->initAsync( - kRTPMode, - kRTCPMode, - &receiverRTPPort)); - - printf("picked receiverRTPPort %d\n", receiverRTPPort); - -#if 0 - CHECK_EQ((status_t)OK, - mReceiver->connect( - "127.0.0.1", senderRTPPort, senderRTPPort + 1)); -#endif - break; - } - - case kWhatConnect: - { - AString host; - CHECK(msg->findString("host", &host)); - - sp notify = new AMessage(kWhatTimeSyncerNotify, id()); - mTimeSyncer = new TimeSyncer(mNetSession, notify); - looper()->registerHandler(mTimeSyncer); - mTimeSyncer->startServer(8123); - - int32_t receiverRTPPort; - CHECK(msg->findInt32("port", &receiverRTPPort)); - -#if 1 - mSource = new MediaPacketSource; -#else - mSource = new SimplePacketSource; -#endif - - notify = new AMessage(kWhatSenderNotify, id()); - mSender = new RTPSender(mNetSession, notify); - - looper()->registerHandler(mSender); - - int32_t senderRTPPort; - CHECK_EQ((status_t)OK, - mSender->initAsync( - host.c_str(), - receiverRTPPort, - kRTPMode, - kRTCPMode == RTPBase::TRANSPORT_NONE - ? -1 : receiverRTPPort + 1, - kRTCPMode, - &senderRTPPort)); - - printf("picked senderRTPPort %d\n", senderRTPPort); - break; - } - - case kWhatSenderNotify: - { - ALOGI("kWhatSenderNotify"); - - int32_t what; - CHECK(msg->findInt32("what", &what)); - - switch (what) { - case RTPSender::kWhatInitDone: - { - int32_t err; - CHECK(msg->findInt32("err", &err)); - - ALOGI("RTPSender::initAsync completed w/ err %d", err); - - if (err == OK) { - err = readMore(); - - if (err != OK) { - (new AMessage(kWhatStop, id()))->post(); - } - } - break; - } - - case RTPSender::kWhatError: - break; - } - break; - } - - case kWhatReceiverNotify: - { - ALOGV("kWhatReceiverNotify"); - - int32_t what; - CHECK(msg->findInt32("what", &what)); - - switch (what) { - case RTPReceiver::kWhatInitDone: - { - int32_t err; - CHECK(msg->findInt32("err", &err)); - - ALOGI("RTPReceiver::initAsync completed w/ err %d", err); - break; - } - - case RTPReceiver::kWhatError: - break; - - case RTPReceiver::kWhatAccessUnit: - { -#if 0 - if (!mTimeSyncerStarted) { - mTimeSyncer->startClient("172.18.41.216", 8123); - mTimeSyncerStarted = true; - } - - sp accessUnit; - CHECK(msg->findBuffer("accessUnit", &accessUnit)); - - int64_t timeUs; - CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); - - if (mTimeOffsetValid) { - timeUs -= mTimeOffsetUs; - int64_t nowUs = ALooper::GetNowUs(); - int64_t delayMs = (nowUs - timeUs) / 1000ll; - - dumpDelay(delayMs); - } -#endif - break; - } - - case RTPReceiver::kWhatPacketLost: - ALOGV("kWhatPacketLost"); - break; - - default: - TRESPASS(); - } - break; - } - - case kWhatSendMore: - { - sp accessUnit; - CHECK(msg->findBuffer("accessUnit", &accessUnit)); - - CHECK_EQ((status_t)OK, - mSender->queueBuffer( - accessUnit, - 33, - kPacketizationMode)); - - status_t err = readMore(); - - if (err != OK) { - (new AMessage(kWhatStop, id()))->post(); - } - break; - } - - case kWhatStop: - { - if (mReceiver != NULL) { - looper()->unregisterHandler(mReceiver->id()); - mReceiver.clear(); - } - - if (mSender != NULL) { - looper()->unregisterHandler(mSender->id()); - mSender.clear(); - } - - mSource.clear(); - - looper()->stop(); - break; - } - - case kWhatTimeSyncerNotify: - { - CHECK(msg->findInt64("offset", &mTimeOffsetUs)); - mTimeOffsetValid = true; - break; - } - - default: - TRESPASS(); - } -} - -status_t TestHandler::readMore() { - sp accessUnit = mSource->getNextAccessUnit(); - - if (accessUnit == NULL) { - return ERROR_END_OF_STREAM; - } - - int64_t timeUs; - CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); - - int64_t nowUs = ALooper::GetNowUs(); - int64_t whenUs; - - if (mFirstTimeRealUs < 0ll) { - mFirstTimeRealUs = whenUs = nowUs; - mFirstTimeMediaUs = timeUs; - } else { - whenUs = mFirstTimeRealUs + timeUs - mFirstTimeMediaUs; - } - - accessUnit->meta()->setInt64("timeUs", whenUs); - - sp msg = new AMessage(kWhatSendMore, id()); - msg->setBuffer("accessUnit", accessUnit); - msg->post(whenUs - nowUs); - - return OK; -} - -} // namespace android - -static void usage(const char *me) { - fprintf(stderr, - "usage: %s -c host:port\tconnect to remote host\n" - " -l \tlisten\n", - me); -} - -int main(int argc, char **argv) { - using namespace android; - - // srand(time(NULL)); - - ProcessState::self()->startThreadPool(); - - DataSource::RegisterDefaultSniffers(); - - bool listen = false; - int32_t connectToPort = -1; - AString connectToHost; - - int res; - while ((res = getopt(argc, argv, "hc:l")) >= 0) { - switch (res) { - case 'c': - { - const char *colonPos = strrchr(optarg, ':'); - - if (colonPos == NULL) { - usage(argv[0]); - exit(1); - } - - connectToHost.setTo(optarg, colonPos - optarg); - - char *end; - connectToPort = strtol(colonPos + 1, &end, 10); - - if (*end != '\0' || end == colonPos + 1 - || connectToPort < 1 || connectToPort > 65535) { - fprintf(stderr, "Illegal port specified.\n"); - exit(1); - } - break; - } - - case 'l': - { - listen = true; - break; - } - - case '?': - case 'h': - usage(argv[0]); - exit(1); - } - } - - if (!listen && connectToPort < 0) { - fprintf(stderr, - "You need to select either client or server mode.\n"); - exit(1); - } - - sp netSession = new ANetworkSession; - netSession->start(); - - sp looper = new ALooper; - - sp handler = new TestHandler(netSession); - looper->registerHandler(handler); - - if (listen) { - handler->listen(); - } - - if (connectToPort >= 0) { - handler->connect(connectToHost.c_str(), connectToPort); - } - - looper->start(true /* runOnCallingThread */); - - return 0; -} - diff --git a/media/libstagefright/wifi-display/sink/DirectRenderer.cpp b/media/libstagefright/wifi-display/sink/DirectRenderer.cpp deleted file mode 100644 index 15f9c88..0000000 --- a/media/libstagefright/wifi-display/sink/DirectRenderer.cpp +++ /dev/null @@ -1,625 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "DirectRenderer" -#include - -#include "DirectRenderer.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace android { - -/* - Drives the decoding process using a MediaCodec instance. Input buffers - queued by calls to "queueInputBuffer" are fed to the decoder as soon - as the decoder is ready for them, the client is notified about output - buffers as the decoder spits them out. -*/ -struct DirectRenderer::DecoderContext : public AHandler { - enum { - kWhatOutputBufferReady, - }; - DecoderContext(const sp ¬ify); - - status_t init( - const sp &format, - const sp &surfaceTex); - - void queueInputBuffer(const sp &accessUnit); - - status_t renderOutputBufferAndRelease(size_t index); - status_t releaseOutputBuffer(size_t index); - -protected: - virtual ~DecoderContext(); - - virtual void onMessageReceived(const sp &msg); - -private: - enum { - kWhatDecoderNotify, - }; - - sp mNotify; - sp mDecoderLooper; - sp mDecoder; - Vector > mDecoderInputBuffers; - Vector > mDecoderOutputBuffers; - List mDecoderInputBuffersAvailable; - bool mDecoderNotificationPending; - - List > mAccessUnits; - - void onDecoderNotify(); - void scheduleDecoderNotification(); - void queueDecoderInputBuffers(); - - void queueOutputBuffer( - size_t index, int64_t timeUs, const sp &buffer); - - DISALLOW_EVIL_CONSTRUCTORS(DecoderContext); -}; - -//////////////////////////////////////////////////////////////////////////////// - -/* - A "push" audio renderer. The primary function of this renderer is to use - an AudioTrack in push mode and making sure not to block the event loop - be ensuring that calls to AudioTrack::write never block. This is done by - estimating an upper bound of data that can be written to the AudioTrack - buffer without delay. -*/ -struct DirectRenderer::AudioRenderer : public AHandler { - AudioRenderer(const sp &decoderContext); - - void queueInputBuffer( - size_t index, int64_t timeUs, const sp &buffer); - -protected: - virtual ~AudioRenderer(); - virtual void onMessageReceived(const sp &msg); - -private: - enum { - kWhatPushAudio, - }; - - struct BufferInfo { - size_t mIndex; - int64_t mTimeUs; - sp mBuffer; - }; - - sp mDecoderContext; - sp mAudioTrack; - - List mInputBuffers; - bool mPushPending; - - size_t mNumFramesWritten; - - void schedulePushIfNecessary(); - void onPushAudio(); - - ssize_t writeNonBlocking(const uint8_t *data, size_t size); - - DISALLOW_EVIL_CONSTRUCTORS(AudioRenderer); -}; - -//////////////////////////////////////////////////////////////////////////////// - -DirectRenderer::DecoderContext::DecoderContext(const sp ¬ify) - : mNotify(notify), - mDecoderNotificationPending(false) { -} - -DirectRenderer::DecoderContext::~DecoderContext() { - if (mDecoder != NULL) { - mDecoder->release(); - mDecoder.clear(); - - mDecoderLooper->stop(); - mDecoderLooper.clear(); - } -} - -status_t DirectRenderer::DecoderContext::init( - const sp &format, - const sp &surfaceTex) { - CHECK(mDecoder == NULL); - - AString mime; - CHECK(format->findString("mime", &mime)); - - mDecoderLooper = new ALooper; - mDecoderLooper->setName("video codec looper"); - - mDecoderLooper->start( - false /* runOnCallingThread */, - false /* canCallJava */, - PRIORITY_DEFAULT); - - mDecoder = MediaCodec::CreateByType( - mDecoderLooper, mime.c_str(), false /* encoder */); - - CHECK(mDecoder != NULL); - - status_t err = mDecoder->configure( - format, - surfaceTex == NULL - ? NULL : new Surface(surfaceTex), - NULL /* crypto */, - 0 /* flags */); - CHECK_EQ(err, (status_t)OK); - - err = mDecoder->start(); - CHECK_EQ(err, (status_t)OK); - - err = mDecoder->getInputBuffers( - &mDecoderInputBuffers); - CHECK_EQ(err, (status_t)OK); - - err = mDecoder->getOutputBuffers( - &mDecoderOutputBuffers); - CHECK_EQ(err, (status_t)OK); - - scheduleDecoderNotification(); - - return OK; -} - -void DirectRenderer::DecoderContext::queueInputBuffer( - const sp &accessUnit) { - CHECK(mDecoder != NULL); - - mAccessUnits.push_back(accessUnit); - queueDecoderInputBuffers(); -} - -status_t DirectRenderer::DecoderContext::renderOutputBufferAndRelease( - size_t index) { - return mDecoder->renderOutputBufferAndRelease(index); -} - -status_t DirectRenderer::DecoderContext::releaseOutputBuffer(size_t index) { - return mDecoder->releaseOutputBuffer(index); -} - -void DirectRenderer::DecoderContext::queueDecoderInputBuffers() { - if (mDecoder == NULL) { - return; - } - - bool submittedMore = false; - - while (!mAccessUnits.empty() - && !mDecoderInputBuffersAvailable.empty()) { - size_t index = *mDecoderInputBuffersAvailable.begin(); - - mDecoderInputBuffersAvailable.erase( - mDecoderInputBuffersAvailable.begin()); - - sp srcBuffer = *mAccessUnits.begin(); - mAccessUnits.erase(mAccessUnits.begin()); - - const sp &dstBuffer = - mDecoderInputBuffers.itemAt(index); - - memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size()); - - int64_t timeUs; - CHECK(srcBuffer->meta()->findInt64("timeUs", &timeUs)); - - status_t err = mDecoder->queueInputBuffer( - index, - 0 /* offset */, - srcBuffer->size(), - timeUs, - 0 /* flags */); - CHECK_EQ(err, (status_t)OK); - - submittedMore = true; - } - - if (submittedMore) { - scheduleDecoderNotification(); - } -} - -void DirectRenderer::DecoderContext::onMessageReceived( - const sp &msg) { - switch (msg->what()) { - case kWhatDecoderNotify: - { - onDecoderNotify(); - break; - } - - default: - TRESPASS(); - } -} - -void DirectRenderer::DecoderContext::onDecoderNotify() { - mDecoderNotificationPending = false; - - for (;;) { - size_t index; - status_t err = mDecoder->dequeueInputBuffer(&index); - - if (err == OK) { - mDecoderInputBuffersAvailable.push_back(index); - } else if (err == -EAGAIN) { - break; - } else { - TRESPASS(); - } - } - - queueDecoderInputBuffers(); - - for (;;) { - size_t index; - size_t offset; - size_t size; - int64_t timeUs; - uint32_t flags; - status_t err = mDecoder->dequeueOutputBuffer( - &index, - &offset, - &size, - &timeUs, - &flags); - - if (err == OK) { - queueOutputBuffer( - index, timeUs, mDecoderOutputBuffers.itemAt(index)); - } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { - err = mDecoder->getOutputBuffers( - &mDecoderOutputBuffers); - CHECK_EQ(err, (status_t)OK); - } else if (err == INFO_FORMAT_CHANGED) { - // We don't care. - } else if (err == -EAGAIN) { - break; - } else { - TRESPASS(); - } - } - - scheduleDecoderNotification(); -} - -void DirectRenderer::DecoderContext::scheduleDecoderNotification() { - if (mDecoderNotificationPending) { - return; - } - - sp notify = - new AMessage(kWhatDecoderNotify, id()); - - mDecoder->requestActivityNotification(notify); - mDecoderNotificationPending = true; -} - -void DirectRenderer::DecoderContext::queueOutputBuffer( - size_t index, int64_t timeUs, const sp &buffer) { - sp msg = mNotify->dup(); - msg->setInt32("what", kWhatOutputBufferReady); - msg->setSize("index", index); - msg->setInt64("timeUs", timeUs); - msg->setBuffer("buffer", buffer); - msg->post(); -} - -//////////////////////////////////////////////////////////////////////////////// - -DirectRenderer::AudioRenderer::AudioRenderer( - const sp &decoderContext) - : mDecoderContext(decoderContext), - mPushPending(false), - mNumFramesWritten(0) { - mAudioTrack = new AudioTrack( - AUDIO_STREAM_DEFAULT, - 48000.0f, - AUDIO_FORMAT_PCM, - AUDIO_CHANNEL_OUT_STEREO, - (int)0 /* frameCount */); - - CHECK_EQ((status_t)OK, mAudioTrack->initCheck()); - - mAudioTrack->start(); -} - -DirectRenderer::AudioRenderer::~AudioRenderer() { -} - -void DirectRenderer::AudioRenderer::queueInputBuffer( - size_t index, int64_t timeUs, const sp &buffer) { - BufferInfo info; - info.mIndex = index; - info.mTimeUs = timeUs; - info.mBuffer = buffer; - - mInputBuffers.push_back(info); - schedulePushIfNecessary(); -} - -void DirectRenderer::AudioRenderer::onMessageReceived( - const sp &msg) { - switch (msg->what()) { - case kWhatPushAudio: - { - onPushAudio(); - break; - } - - default: - break; - } -} - -void DirectRenderer::AudioRenderer::schedulePushIfNecessary() { - if (mPushPending || mInputBuffers.empty()) { - return; - } - - mPushPending = true; - - uint32_t numFramesPlayed; - CHECK_EQ(mAudioTrack->getPosition(&numFramesPlayed), - (status_t)OK); - - uint32_t numFramesPendingPlayout = mNumFramesWritten - numFramesPlayed; - - // This is how long the audio sink will have data to - // play back. - const float msecsPerFrame = 1000.0f / mAudioTrack->getSampleRate(); - - int64_t delayUs = - msecsPerFrame * numFramesPendingPlayout * 1000ll; - - // Let's give it more data after about half that time - // has elapsed. - (new AMessage(kWhatPushAudio, id()))->post(delayUs / 2); -} - -void DirectRenderer::AudioRenderer::onPushAudio() { - mPushPending = false; - - while (!mInputBuffers.empty()) { - const BufferInfo &info = *mInputBuffers.begin(); - - ssize_t n = writeNonBlocking( - info.mBuffer->data(), info.mBuffer->size()); - - if (n < (ssize_t)info.mBuffer->size()) { - CHECK_GE(n, 0); - - info.mBuffer->setRange( - info.mBuffer->offset() + n, info.mBuffer->size() - n); - break; - } - - mDecoderContext->releaseOutputBuffer(info.mIndex); - - mInputBuffers.erase(mInputBuffers.begin()); - } - - schedulePushIfNecessary(); -} - -ssize_t DirectRenderer::AudioRenderer::writeNonBlocking( - const uint8_t *data, size_t size) { - uint32_t numFramesPlayed; - status_t err = mAudioTrack->getPosition(&numFramesPlayed); - if (err != OK) { - return err; - } - - ssize_t numFramesAvailableToWrite = - mAudioTrack->frameCount() - (mNumFramesWritten - numFramesPlayed); - - size_t numBytesAvailableToWrite = - numFramesAvailableToWrite * mAudioTrack->frameSize(); - - if (size > numBytesAvailableToWrite) { - size = numBytesAvailableToWrite; - } - - CHECK_EQ(mAudioTrack->write(data, size), (ssize_t)size); - - size_t numFramesWritten = size / mAudioTrack->frameSize(); - mNumFramesWritten += numFramesWritten; - - return size; -} - -//////////////////////////////////////////////////////////////////////////////// - -DirectRenderer::DirectRenderer( - const sp &bufferProducer) - : mSurfaceTex(bufferProducer), - mVideoRenderPending(false), - mNumFramesLate(0), - mNumFrames(0) { -} - -DirectRenderer::~DirectRenderer() { -} - -void DirectRenderer::onMessageReceived(const sp &msg) { - switch (msg->what()) { - case kWhatDecoderNotify: - { - onDecoderNotify(msg); - break; - } - - case kWhatRenderVideo: - { - onRenderVideo(); - break; - } - - default: - TRESPASS(); - } -} - -void DirectRenderer::setFormat(size_t trackIndex, const sp &format) { - CHECK_LT(trackIndex, 2u); - - CHECK(mDecoderContext[trackIndex] == NULL); - - sp notify = new AMessage(kWhatDecoderNotify, id()); - notify->setSize("trackIndex", trackIndex); - - mDecoderContext[trackIndex] = new DecoderContext(notify); - looper()->registerHandler(mDecoderContext[trackIndex]); - - CHECK_EQ((status_t)OK, - mDecoderContext[trackIndex]->init( - format, trackIndex == 0 ? mSurfaceTex : NULL)); - - if (trackIndex == 1) { - // Audio - mAudioRenderer = new AudioRenderer(mDecoderContext[1]); - looper()->registerHandler(mAudioRenderer); - } -} - -void DirectRenderer::queueAccessUnit( - size_t trackIndex, const sp &accessUnit) { - CHECK_LT(trackIndex, 2u); - - if (mDecoderContext[trackIndex] == NULL) { - CHECK_EQ(trackIndex, 0u); - - sp format = new AMessage; - format->setString("mime", "video/avc"); - format->setInt32("width", 640); - format->setInt32("height", 360); - - setFormat(trackIndex, format); - } - - mDecoderContext[trackIndex]->queueInputBuffer(accessUnit); -} - -void DirectRenderer::onDecoderNotify(const sp &msg) { - size_t trackIndex; - CHECK(msg->findSize("trackIndex", &trackIndex)); - - int32_t what; - CHECK(msg->findInt32("what", &what)); - - switch (what) { - case DecoderContext::kWhatOutputBufferReady: - { - size_t index; - CHECK(msg->findSize("index", &index)); - - int64_t timeUs; - CHECK(msg->findInt64("timeUs", &timeUs)); - - sp buffer; - CHECK(msg->findBuffer("buffer", &buffer)); - - queueOutputBuffer(trackIndex, index, timeUs, buffer); - break; - } - - default: - TRESPASS(); - } -} - -void DirectRenderer::queueOutputBuffer( - size_t trackIndex, - size_t index, int64_t timeUs, const sp &buffer) { - if (trackIndex == 1) { - // Audio - mAudioRenderer->queueInputBuffer(index, timeUs, buffer); - return; - } - - OutputInfo info; - info.mIndex = index; - info.mTimeUs = timeUs; - info.mBuffer = buffer; - mVideoOutputBuffers.push_back(info); - - scheduleVideoRenderIfNecessary(); -} - -void DirectRenderer::scheduleVideoRenderIfNecessary() { - if (mVideoRenderPending || mVideoOutputBuffers.empty()) { - return; - } - - mVideoRenderPending = true; - - int64_t timeUs = (*mVideoOutputBuffers.begin()).mTimeUs; - int64_t nowUs = ALooper::GetNowUs(); - - int64_t delayUs = timeUs - nowUs; - - (new AMessage(kWhatRenderVideo, id()))->post(delayUs); -} - -void DirectRenderer::onRenderVideo() { - mVideoRenderPending = false; - - int64_t nowUs = ALooper::GetNowUs(); - - while (!mVideoOutputBuffers.empty()) { - const OutputInfo &info = *mVideoOutputBuffers.begin(); - - if (info.mTimeUs > nowUs) { - break; - } - - if (info.mTimeUs + 15000ll < nowUs) { - ++mNumFramesLate; - } - ++mNumFrames; - - status_t err = - mDecoderContext[0]->renderOutputBufferAndRelease(info.mIndex); - CHECK_EQ(err, (status_t)OK); - - mVideoOutputBuffers.erase(mVideoOutputBuffers.begin()); - } - - scheduleVideoRenderIfNecessary(); -} - -} // namespace android - diff --git a/media/libstagefright/wifi-display/sink/DirectRenderer.h b/media/libstagefright/wifi-display/sink/DirectRenderer.h deleted file mode 100644 index c5a4a83..0000000 --- a/media/libstagefright/wifi-display/sink/DirectRenderer.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DIRECT_RENDERER_H_ - -#define DIRECT_RENDERER_H_ - -#include - -namespace android { - -struct ABuffer; -struct AudioTrack; -struct IGraphicBufferProducer; -struct MediaCodec; - -// Renders audio and video data queued by calls to "queueAccessUnit". -struct DirectRenderer : public AHandler { - DirectRenderer(const sp &bufferProducer); - - void setFormat(size_t trackIndex, const sp &format); - void queueAccessUnit(size_t trackIndex, const sp &accessUnit); - -protected: - virtual void onMessageReceived(const sp &msg); - virtual ~DirectRenderer(); - -private: - struct DecoderContext; - struct AudioRenderer; - - enum { - kWhatDecoderNotify, - kWhatRenderVideo, - }; - - struct OutputInfo { - size_t mIndex; - int64_t mTimeUs; - sp mBuffer; - }; - - sp mSurfaceTex; - - sp mDecoderContext[2]; - List mVideoOutputBuffers; - - bool mVideoRenderPending; - - sp mAudioRenderer; - - int32_t mNumFramesLate; - int32_t mNumFrames; - - void onDecoderNotify(const sp &msg); - - void queueOutputBuffer( - size_t trackIndex, - size_t index, int64_t timeUs, const sp &buffer); - - void scheduleVideoRenderIfNecessary(); - void onRenderVideo(); - - DISALLOW_EVIL_CONSTRUCTORS(DirectRenderer); -}; - -} // namespace android - -#endif // DIRECT_RENDERER_H_ diff --git a/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp b/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp deleted file mode 100644 index 5db2099..0000000 --- a/media/libstagefright/wifi-display/sink/WifiDisplaySink.cpp +++ /dev/null @@ -1,917 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "WifiDisplaySink" -#include - -#include "WifiDisplaySink.h" - -#include "DirectRenderer.h" -#include "MediaReceiver.h" -#include "ParsedMessage.h" -#include "TimeSyncer.h" - -#include -#include -#include -#include -#include -#include - -namespace android { - -// static -const AString WifiDisplaySink::sUserAgent = MakeUserAgent(); - -WifiDisplaySink::WifiDisplaySink( - uint32_t flags, - const sp &netSession, - const sp &bufferProducer, - const sp ¬ify) - : mState(UNDEFINED), - mFlags(flags), - mNetSession(netSession), - mSurfaceTex(bufferProducer), - mNotify(notify), - mUsingTCPTransport(false), - mUsingTCPInterleaving(false), - mSessionID(0), - mNextCSeq(1), - mIDRFrameRequestPending(false), - mTimeOffsetUs(0ll), - mTimeOffsetValid(false), - mSetupDeferred(false), - mLatencyCount(0), - mLatencySumUs(0ll), - mLatencyMaxUs(0ll), - mMaxDelayMs(-1ll) { - // We support any and all resolutions, but prefer 720p30 - mSinkSupportedVideoFormats.setNativeResolution( - VideoFormats::RESOLUTION_CEA, 5); // 1280 x 720 p30 - - mSinkSupportedVideoFormats.enableAll(); -} - -WifiDisplaySink::~WifiDisplaySink() { -} - -void WifiDisplaySink::start(const char *sourceHost, int32_t sourcePort) { - sp msg = new AMessage(kWhatStart, id()); - msg->setString("sourceHost", sourceHost); - msg->setInt32("sourcePort", sourcePort); - msg->post(); -} - -void WifiDisplaySink::start(const char *uri) { - sp msg = new AMessage(kWhatStart, id()); - msg->setString("setupURI", uri); - msg->post(); -} - -// static -bool WifiDisplaySink::ParseURL( - const char *url, AString *host, int32_t *port, AString *path, - AString *user, AString *pass) { - host->clear(); - *port = 0; - path->clear(); - user->clear(); - pass->clear(); - - if (strncasecmp("rtsp://", url, 7)) { - return false; - } - - const char *slashPos = strchr(&url[7], '/'); - - if (slashPos == NULL) { - host->setTo(&url[7]); - path->setTo("/"); - } else { - host->setTo(&url[7], slashPos - &url[7]); - path->setTo(slashPos); - } - - ssize_t atPos = host->find("@"); - - if (atPos >= 0) { - // Split of user:pass@ from hostname. - - AString userPass(*host, 0, atPos); - host->erase(0, atPos + 1); - - ssize_t colonPos = userPass.find(":"); - - if (colonPos < 0) { - *user = userPass; - } else { - user->setTo(userPass, 0, colonPos); - pass->setTo(userPass, colonPos + 1, userPass.size() - colonPos - 1); - } - } - - const char *colonPos = strchr(host->c_str(), ':'); - - if (colonPos != NULL) { - char *end; - unsigned long x = strtoul(colonPos + 1, &end, 10); - - if (end == colonPos + 1 || *end != '\0' || x >= 65536) { - return false; - } - - *port = x; - - size_t colonOffset = colonPos - host->c_str(); - size_t trailing = host->size() - colonOffset; - host->erase(colonOffset, trailing); - } else { - *port = 554; - } - - return true; -} - -void WifiDisplaySink::onMessageReceived(const sp &msg) { - switch (msg->what()) { - case kWhatStart: - { - sleep(2); // XXX - - int32_t sourcePort; - CHECK(msg->findString("sourceHost", &mRTSPHost)); - CHECK(msg->findInt32("sourcePort", &sourcePort)); - - sp notify = new AMessage(kWhatRTSPNotify, id()); - - status_t err = mNetSession->createRTSPClient( - mRTSPHost.c_str(), sourcePort, notify, &mSessionID); - CHECK_EQ(err, (status_t)OK); - - mState = CONNECTING; - break; - } - - case kWhatRTSPNotify: - { - int32_t reason; - CHECK(msg->findInt32("reason", &reason)); - - switch (reason) { - case ANetworkSession::kWhatError: - { - int32_t sessionID; - CHECK(msg->findInt32("sessionID", &sessionID)); - - int32_t err; - CHECK(msg->findInt32("err", &err)); - - AString detail; - CHECK(msg->findString("detail", &detail)); - - ALOGE("An error occurred in session %d (%d, '%s/%s').", - sessionID, - err, - detail.c_str(), - strerror(-err)); - - if (sessionID == mSessionID) { - ALOGI("Lost control connection."); - - // The control connection is dead now. - mNetSession->destroySession(mSessionID); - mSessionID = 0; - - if (mNotify == NULL) { - looper()->stop(); - } else { - sp notify = mNotify->dup(); - notify->setInt32("what", kWhatDisconnected); - notify->post(); - } - } - break; - } - - case ANetworkSession::kWhatConnected: - { - ALOGI("We're now connected."); - mState = CONNECTED; - - if (mFlags & FLAG_SPECIAL_MODE) { - sp notify = new AMessage( - kWhatTimeSyncerNotify, id()); - - mTimeSyncer = new TimeSyncer(mNetSession, notify); - looper()->registerHandler(mTimeSyncer); - - mTimeSyncer->startClient(mRTSPHost.c_str(), 8123); - } - break; - } - - case ANetworkSession::kWhatData: - { - onReceiveClientData(msg); - break; - } - - default: - TRESPASS(); - } - break; - } - - case kWhatStop: - { - looper()->stop(); - break; - } - - case kWhatMediaReceiverNotify: - { - onMediaReceiverNotify(msg); - break; - } - - case kWhatTimeSyncerNotify: - { - int32_t what; - CHECK(msg->findInt32("what", &what)); - - if (what == TimeSyncer::kWhatTimeOffset) { - CHECK(msg->findInt64("offset", &mTimeOffsetUs)); - mTimeOffsetValid = true; - - if (mSetupDeferred) { - CHECK_EQ((status_t)OK, - sendSetup( - mSessionID, - "rtsp://x.x.x.x:x/wfd1.0/streamid=0")); - - mSetupDeferred = false; - } - } - break; - } - - case kWhatReportLateness: - { - if (mLatencyCount > 0) { - int64_t avgLatencyUs = mLatencySumUs / mLatencyCount; - - ALOGV("avg. latency = %lld ms (max %lld ms)", - avgLatencyUs / 1000ll, - mLatencyMaxUs / 1000ll); - - sp params = new AMessage; - params->setInt64("avgLatencyUs", avgLatencyUs); - params->setInt64("maxLatencyUs", mLatencyMaxUs); - mMediaReceiver->informSender(0 /* trackIndex */, params); - } - - mLatencyCount = 0; - mLatencySumUs = 0ll; - mLatencyMaxUs = 0ll; - - msg->post(kReportLatenessEveryUs); - break; - } - - default: - TRESPASS(); - } -} - -void WifiDisplaySink::dumpDelay(size_t trackIndex, int64_t timeUs) { - int64_t delayMs = (ALooper::GetNowUs() - timeUs) / 1000ll; - - if (delayMs > mMaxDelayMs) { - mMaxDelayMs = delayMs; - } - - static const int64_t kMinDelayMs = 0; - static const int64_t kMaxDelayMs = 300; - - const char *kPattern = "########################################"; - size_t kPatternSize = strlen(kPattern); - - int n = (kPatternSize * (delayMs - kMinDelayMs)) - / (kMaxDelayMs - kMinDelayMs); - - if (n < 0) { - n = 0; - } else if ((size_t)n > kPatternSize) { - n = kPatternSize; - } - - ALOGI("[%lld]: (%4lld ms / %4lld ms) %s", - timeUs / 1000, - delayMs, - mMaxDelayMs, - kPattern + kPatternSize - n); -} - -void WifiDisplaySink::onMediaReceiverNotify(const sp &msg) { - int32_t what; - CHECK(msg->findInt32("what", &what)); - - switch (what) { - case MediaReceiver::kWhatInitDone: - { - status_t err; - CHECK(msg->findInt32("err", &err)); - - ALOGI("MediaReceiver initialization completed w/ err %d", err); - break; - } - - case MediaReceiver::kWhatError: - { - status_t err; - CHECK(msg->findInt32("err", &err)); - - ALOGE("MediaReceiver signaled error %d", err); - break; - } - - case MediaReceiver::kWhatAccessUnit: - { - if (mRenderer == NULL) { - mRenderer = new DirectRenderer(mSurfaceTex); - looper()->registerHandler(mRenderer); - } - - sp accessUnit; - CHECK(msg->findBuffer("accessUnit", &accessUnit)); - - int64_t timeUs; - CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); - - if (!mTimeOffsetValid && !(mFlags & FLAG_SPECIAL_MODE)) { - mTimeOffsetUs = timeUs - ALooper::GetNowUs(); - mTimeOffsetValid = true; - } - - CHECK(mTimeOffsetValid); - - // We are the timesync _client_, - // client time = server time - time offset. - timeUs -= mTimeOffsetUs; - - size_t trackIndex; - CHECK(msg->findSize("trackIndex", &trackIndex)); - - int64_t nowUs = ALooper::GetNowUs(); - int64_t delayUs = nowUs - timeUs; - - mLatencySumUs += delayUs; - if (mLatencyCount == 0 || delayUs > mLatencyMaxUs) { - mLatencyMaxUs = delayUs; - } - ++mLatencyCount; - - // dumpDelay(trackIndex, timeUs); - - timeUs += 220000ll; // Assume 220 ms of latency - accessUnit->meta()->setInt64("timeUs", timeUs); - - sp format; - if (msg->findMessage("format", &format)) { - mRenderer->setFormat(trackIndex, format); - } - - mRenderer->queueAccessUnit(trackIndex, accessUnit); - break; - } - - case MediaReceiver::kWhatPacketLost: - { -#if 0 - if (!mIDRFrameRequestPending) { - ALOGI("requesting IDR frame"); - - sendIDRFrameRequest(mSessionID); - } -#endif - break; - } - - default: - TRESPASS(); - } -} - -void WifiDisplaySink::registerResponseHandler( - int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func) { - ResponseID id; - id.mSessionID = sessionID; - id.mCSeq = cseq; - mResponseHandlers.add(id, func); -} - -status_t WifiDisplaySink::sendM2(int32_t sessionID) { - AString request = "OPTIONS * RTSP/1.0\r\n"; - AppendCommonResponse(&request, mNextCSeq); - - request.append( - "Require: org.wfa.wfd1.0\r\n" - "\r\n"); - - status_t err = - mNetSession->sendRequest(sessionID, request.c_str(), request.size()); - - if (err != OK) { - return err; - } - - registerResponseHandler( - sessionID, mNextCSeq, &WifiDisplaySink::onReceiveM2Response); - - ++mNextCSeq; - - return OK; -} - -status_t WifiDisplaySink::onReceiveM2Response( - int32_t sessionID, const sp &msg) { - int32_t statusCode; - if (!msg->getStatusCode(&statusCode)) { - return ERROR_MALFORMED; - } - - if (statusCode != 200) { - return ERROR_UNSUPPORTED; - } - - return OK; -} - -status_t WifiDisplaySink::onReceiveSetupResponse( - int32_t sessionID, const sp &msg) { - int32_t statusCode; - if (!msg->getStatusCode(&statusCode)) { - return ERROR_MALFORMED; - } - - if (statusCode != 200) { - return ERROR_UNSUPPORTED; - } - - if (!msg->findString("session", &mPlaybackSessionID)) { - return ERROR_MALFORMED; - } - - if (!ParsedMessage::GetInt32Attribute( - mPlaybackSessionID.c_str(), - "timeout", - &mPlaybackSessionTimeoutSecs)) { - mPlaybackSessionTimeoutSecs = -1; - } - - ssize_t colonPos = mPlaybackSessionID.find(";"); - if (colonPos >= 0) { - // Strip any options from the returned session id. - mPlaybackSessionID.erase( - colonPos, mPlaybackSessionID.size() - colonPos); - } - - status_t err = configureTransport(msg); - - if (err != OK) { - return err; - } - - mState = PAUSED; - - return sendPlay( - sessionID, - "rtsp://x.x.x.x:x/wfd1.0/streamid=0"); -} - -status_t WifiDisplaySink::configureTransport(const sp &msg) { - if (mUsingTCPTransport && !(mFlags & FLAG_SPECIAL_MODE)) { - // In "special" mode we still use a UDP RTCP back-channel that - // needs connecting. - return OK; - } - - AString transport; - if (!msg->findString("transport", &transport)) { - ALOGE("Missing 'transport' field in SETUP response."); - return ERROR_MALFORMED; - } - - AString sourceHost; - if (!ParsedMessage::GetAttribute( - transport.c_str(), "source", &sourceHost)) { - sourceHost = mRTSPHost; - } - - AString serverPortStr; - if (!ParsedMessage::GetAttribute( - transport.c_str(), "server_port", &serverPortStr)) { - ALOGE("Missing 'server_port' in Transport field."); - return ERROR_MALFORMED; - } - - int rtpPort, rtcpPort; - if (sscanf(serverPortStr.c_str(), "%d-%d", &rtpPort, &rtcpPort) != 2 - || rtpPort <= 0 || rtpPort > 65535 - || rtcpPort <=0 || rtcpPort > 65535 - || rtcpPort != rtpPort + 1) { - ALOGE("Invalid server_port description '%s'.", - serverPortStr.c_str()); - - return ERROR_MALFORMED; - } - - if (rtpPort & 1) { - ALOGW("Server picked an odd numbered RTP port."); - } - - return mMediaReceiver->connectTrack( - 0 /* trackIndex */, sourceHost.c_str(), rtpPort, rtcpPort); -} - -status_t WifiDisplaySink::onReceivePlayResponse( - int32_t sessionID, const sp &msg) { - int32_t statusCode; - if (!msg->getStatusCode(&statusCode)) { - return ERROR_MALFORMED; - } - - if (statusCode != 200) { - return ERROR_UNSUPPORTED; - } - - mState = PLAYING; - - (new AMessage(kWhatReportLateness, id()))->post(kReportLatenessEveryUs); - - return OK; -} - -status_t WifiDisplaySink::onReceiveIDRFrameRequestResponse( - int32_t sessionID, const sp &msg) { - CHECK(mIDRFrameRequestPending); - mIDRFrameRequestPending = false; - - return OK; -} - -void WifiDisplaySink::onReceiveClientData(const sp &msg) { - int32_t sessionID; - CHECK(msg->findInt32("sessionID", &sessionID)); - - sp obj; - CHECK(msg->findObject("data", &obj)); - - sp data = - static_cast(obj.get()); - - ALOGV("session %d received '%s'", - sessionID, data->debugString().c_str()); - - AString method; - AString uri; - data->getRequestField(0, &method); - - int32_t cseq; - if (!data->findInt32("cseq", &cseq)) { - sendErrorResponse(sessionID, "400 Bad Request", -1 /* cseq */); - return; - } - - if (method.startsWith("RTSP/")) { - // This is a response. - - ResponseID id; - id.mSessionID = sessionID; - id.mCSeq = cseq; - - ssize_t index = mResponseHandlers.indexOfKey(id); - - if (index < 0) { - ALOGW("Received unsolicited server response, cseq %d", cseq); - return; - } - - HandleRTSPResponseFunc func = mResponseHandlers.valueAt(index); - mResponseHandlers.removeItemsAt(index); - - status_t err = (this->*func)(sessionID, data); - CHECK_EQ(err, (status_t)OK); - } else { - AString version; - data->getRequestField(2, &version); - if (!(version == AString("RTSP/1.0"))) { - sendErrorResponse(sessionID, "505 RTSP Version not supported", cseq); - return; - } - - if (method == "OPTIONS") { - onOptionsRequest(sessionID, cseq, data); - } else if (method == "GET_PARAMETER") { - onGetParameterRequest(sessionID, cseq, data); - } else if (method == "SET_PARAMETER") { - onSetParameterRequest(sessionID, cseq, data); - } else { - sendErrorResponse(sessionID, "405 Method Not Allowed", cseq); - } - } -} - -void WifiDisplaySink::onOptionsRequest( - int32_t sessionID, - int32_t cseq, - const sp &data) { - AString response = "RTSP/1.0 200 OK\r\n"; - AppendCommonResponse(&response, cseq); - response.append("Public: org.wfa.wfd1.0, GET_PARAMETER, SET_PARAMETER\r\n"); - response.append("\r\n"); - - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - CHECK_EQ(err, (status_t)OK); - - err = sendM2(sessionID); - CHECK_EQ(err, (status_t)OK); -} - -void WifiDisplaySink::onGetParameterRequest( - int32_t sessionID, - int32_t cseq, - const sp &data) { - AString body; - - if (mState == CONNECTED) { - mUsingTCPTransport = false; - mUsingTCPInterleaving = false; - - char val[PROPERTY_VALUE_MAX]; - if (property_get("media.wfd-sink.tcp-mode", val, NULL)) { - if (!strcasecmp("true", val) || !strcmp("1", val)) { - ALOGI("Using TCP unicast transport."); - mUsingTCPTransport = true; - mUsingTCPInterleaving = false; - } else if (!strcasecmp("interleaved", val)) { - ALOGI("Using TCP interleaved transport."); - mUsingTCPTransport = true; - mUsingTCPInterleaving = true; - } - } else if (mFlags & FLAG_SPECIAL_MODE) { - mUsingTCPTransport = true; - } - - body = "wfd_video_formats: "; - body.append(mSinkSupportedVideoFormats.getFormatSpec()); - - body.append( - "\r\nwfd_audio_codecs: AAC 0000000F 00\r\n" - "wfd_client_rtp_ports: RTP/AVP/"); - - if (mUsingTCPTransport) { - body.append("TCP;"); - if (mUsingTCPInterleaving) { - body.append("interleaved"); - } else { - body.append("unicast 19000 0"); - } - } else { - body.append("UDP;unicast 19000 0"); - } - - body.append(" mode=play\r\n"); - } - - AString response = "RTSP/1.0 200 OK\r\n"; - AppendCommonResponse(&response, cseq); - response.append("Content-Type: text/parameters\r\n"); - response.append(StringPrintf("Content-Length: %d\r\n", body.size())); - response.append("\r\n"); - response.append(body); - - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - CHECK_EQ(err, (status_t)OK); -} - -status_t WifiDisplaySink::sendSetup(int32_t sessionID, const char *uri) { - sp notify = new AMessage(kWhatMediaReceiverNotify, id()); - - mMediaReceiverLooper = new ALooper; - mMediaReceiverLooper->setName("media_receiver"); - - mMediaReceiverLooper->start( - false /* runOnCallingThread */, - false /* canCallJava */, - PRIORITY_AUDIO); - - mMediaReceiver = new MediaReceiver(mNetSession, notify); - mMediaReceiverLooper->registerHandler(mMediaReceiver); - - RTPReceiver::TransportMode rtpMode = RTPReceiver::TRANSPORT_UDP; - if (mUsingTCPTransport) { - if (mUsingTCPInterleaving) { - rtpMode = RTPReceiver::TRANSPORT_TCP_INTERLEAVED; - } else { - rtpMode = RTPReceiver::TRANSPORT_TCP; - } - } - - int32_t localRTPPort; - status_t err = mMediaReceiver->addTrack( - rtpMode, RTPReceiver::TRANSPORT_UDP /* rtcpMode */, &localRTPPort); - - if (err == OK) { - err = mMediaReceiver->initAsync(MediaReceiver::MODE_TRANSPORT_STREAM); - } - - if (err != OK) { - mMediaReceiverLooper->unregisterHandler(mMediaReceiver->id()); - mMediaReceiver.clear(); - - mMediaReceiverLooper->stop(); - mMediaReceiverLooper.clear(); - - return err; - } - - AString request = StringPrintf("SETUP %s RTSP/1.0\r\n", uri); - - AppendCommonResponse(&request, mNextCSeq); - - if (rtpMode == RTPReceiver::TRANSPORT_TCP_INTERLEAVED) { - request.append("Transport: RTP/AVP/TCP;interleaved=0-1\r\n"); - } else if (rtpMode == RTPReceiver::TRANSPORT_TCP) { - if (mFlags & FLAG_SPECIAL_MODE) { - // This isn't quite true, since the RTP connection is through TCP - // and the RTCP connection through UDP... - request.append( - StringPrintf( - "Transport: RTP/AVP/TCP;unicast;client_port=%d-%d\r\n", - localRTPPort, localRTPPort + 1)); - } else { - request.append( - StringPrintf( - "Transport: RTP/AVP/TCP;unicast;client_port=%d\r\n", - localRTPPort)); - } - } else { - request.append( - StringPrintf( - "Transport: RTP/AVP/UDP;unicast;client_port=%d-%d\r\n", - localRTPPort, - localRTPPort + 1)); - } - - request.append("\r\n"); - - ALOGV("request = '%s'", request.c_str()); - - err = mNetSession->sendRequest(sessionID, request.c_str(), request.size()); - - if (err != OK) { - return err; - } - - registerResponseHandler( - sessionID, mNextCSeq, &WifiDisplaySink::onReceiveSetupResponse); - - ++mNextCSeq; - - return OK; -} - -status_t WifiDisplaySink::sendPlay(int32_t sessionID, const char *uri) { - AString request = StringPrintf("PLAY %s RTSP/1.0\r\n", uri); - - AppendCommonResponse(&request, mNextCSeq); - - request.append(StringPrintf("Session: %s\r\n", mPlaybackSessionID.c_str())); - request.append("\r\n"); - - status_t err = - mNetSession->sendRequest(sessionID, request.c_str(), request.size()); - - if (err != OK) { - return err; - } - - registerResponseHandler( - sessionID, mNextCSeq, &WifiDisplaySink::onReceivePlayResponse); - - ++mNextCSeq; - - return OK; -} - -status_t WifiDisplaySink::sendIDRFrameRequest(int32_t sessionID) { - CHECK(!mIDRFrameRequestPending); - - AString request = "SET_PARAMETER rtsp://localhost/wfd1.0 RTSP/1.0\r\n"; - - AppendCommonResponse(&request, mNextCSeq); - - AString content = "wfd_idr_request\r\n"; - - request.append(StringPrintf("Session: %s\r\n", mPlaybackSessionID.c_str())); - request.append(StringPrintf("Content-Length: %d\r\n", content.size())); - request.append("\r\n"); - request.append(content); - - status_t err = - mNetSession->sendRequest(sessionID, request.c_str(), request.size()); - - if (err != OK) { - return err; - } - - registerResponseHandler( - sessionID, - mNextCSeq, - &WifiDisplaySink::onReceiveIDRFrameRequestResponse); - - ++mNextCSeq; - - mIDRFrameRequestPending = true; - - return OK; -} - -void WifiDisplaySink::onSetParameterRequest( - int32_t sessionID, - int32_t cseq, - const sp &data) { - const char *content = data->getContent(); - - if (strstr(content, "wfd_trigger_method: SETUP\r\n") != NULL) { - if ((mFlags & FLAG_SPECIAL_MODE) && !mTimeOffsetValid) { - mSetupDeferred = true; - } else { - status_t err = - sendSetup( - sessionID, - "rtsp://x.x.x.x:x/wfd1.0/streamid=0"); - - CHECK_EQ(err, (status_t)OK); - } - } - - AString response = "RTSP/1.0 200 OK\r\n"; - AppendCommonResponse(&response, cseq); - response.append("\r\n"); - - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - CHECK_EQ(err, (status_t)OK); -} - -void WifiDisplaySink::sendErrorResponse( - int32_t sessionID, - const char *errorDetail, - int32_t cseq) { - AString response; - response.append("RTSP/1.0 "); - response.append(errorDetail); - response.append("\r\n"); - - AppendCommonResponse(&response, cseq); - - response.append("\r\n"); - - status_t err = mNetSession->sendRequest(sessionID, response.c_str()); - CHECK_EQ(err, (status_t)OK); -} - -// static -void WifiDisplaySink::AppendCommonResponse(AString *response, int32_t cseq) { - time_t now = time(NULL); - struct tm *now2 = gmtime(&now); - char buf[128]; - strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S %z", now2); - - response->append("Date: "); - response->append(buf); - response->append("\r\n"); - - response->append(StringPrintf("User-Agent: %s\r\n", sUserAgent.c_str())); - - if (cseq >= 0) { - response->append(StringPrintf("CSeq: %d\r\n", cseq)); - } -} - -} // namespace android diff --git a/media/libstagefright/wifi-display/sink/WifiDisplaySink.h b/media/libstagefright/wifi-display/sink/WifiDisplaySink.h deleted file mode 100644 index adb9d89..0000000 --- a/media/libstagefright/wifi-display/sink/WifiDisplaySink.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WIFI_DISPLAY_SINK_H_ - -#define WIFI_DISPLAY_SINK_H_ - -#include "ANetworkSession.h" - -#include "VideoFormats.h" - -#include -#include - -namespace android { - -struct AMessage; -struct DirectRenderer; -struct MediaReceiver; -struct ParsedMessage; -struct TimeSyncer; - -// Represents the RTSP client acting as a wifi display sink. -// Connects to a wifi display source and renders the incoming -// transport stream using a MediaPlayer instance. -struct WifiDisplaySink : public AHandler { - enum { - kWhatDisconnected, - }; - - enum Flags { - FLAG_SPECIAL_MODE = 1, - }; - - // If no notification message is specified (notify == NULL) - // the sink will stop its looper() once the session ends, - // otherwise it will post an appropriate notification but leave - // the looper() running. - WifiDisplaySink( - uint32_t flags, - const sp &netSession, - const sp &bufferProducer = NULL, - const sp ¬ify = NULL); - - void start(const char *sourceHost, int32_t sourcePort); - void start(const char *uri); - -protected: - virtual ~WifiDisplaySink(); - virtual void onMessageReceived(const sp &msg); - -private: - enum State { - UNDEFINED, - CONNECTING, - CONNECTED, - PAUSED, - PLAYING, - }; - - enum { - kWhatStart, - kWhatRTSPNotify, - kWhatStop, - kWhatMediaReceiverNotify, - kWhatTimeSyncerNotify, - kWhatReportLateness, - }; - - struct ResponseID { - int32_t mSessionID; - int32_t mCSeq; - - bool operator<(const ResponseID &other) const { - return mSessionID < other.mSessionID - || (mSessionID == other.mSessionID - && mCSeq < other.mCSeq); - } - }; - - typedef status_t (WifiDisplaySink::*HandleRTSPResponseFunc)( - int32_t sessionID, const sp &msg); - - static const int64_t kReportLatenessEveryUs = 1000000ll; - - static const AString sUserAgent; - - State mState; - uint32_t mFlags; - VideoFormats mSinkSupportedVideoFormats; - sp mNetSession; - sp mSurfaceTex; - sp mNotify; - sp mTimeSyncer; - bool mUsingTCPTransport; - bool mUsingTCPInterleaving; - AString mRTSPHost; - int32_t mSessionID; - - int32_t mNextCSeq; - - KeyedVector mResponseHandlers; - - sp mMediaReceiverLooper; - sp mMediaReceiver; - sp mRenderer; - - AString mPlaybackSessionID; - int32_t mPlaybackSessionTimeoutSecs; - - bool mIDRFrameRequestPending; - - int64_t mTimeOffsetUs; - bool mTimeOffsetValid; - - bool mSetupDeferred; - - size_t mLatencyCount; - int64_t mLatencySumUs; - int64_t mLatencyMaxUs; - - int64_t mMaxDelayMs; - - status_t sendM2(int32_t sessionID); - status_t sendSetup(int32_t sessionID, const char *uri); - status_t sendPlay(int32_t sessionID, const char *uri); - status_t sendIDRFrameRequest(int32_t sessionID); - - status_t onReceiveM2Response( - int32_t sessionID, const sp &msg); - - status_t onReceiveSetupResponse( - int32_t sessionID, const sp &msg); - - status_t configureTransport(const sp &msg); - - status_t onReceivePlayResponse( - int32_t sessionID, const sp &msg); - - status_t onReceiveIDRFrameRequestResponse( - int32_t sessionID, const sp &msg); - - void registerResponseHandler( - int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func); - - void onReceiveClientData(const sp &msg); - - void onOptionsRequest( - int32_t sessionID, - int32_t cseq, - const sp &data); - - void onGetParameterRequest( - int32_t sessionID, - int32_t cseq, - const sp &data); - - void onSetParameterRequest( - int32_t sessionID, - int32_t cseq, - const sp &data); - - void onMediaReceiverNotify(const sp &msg); - - void sendErrorResponse( - int32_t sessionID, - const char *errorDetail, - int32_t cseq); - - static void AppendCommonResponse(AString *response, int32_t cseq); - - bool ParseURL( - const char *url, AString *host, int32_t *port, AString *path, - AString *user, AString *pass); - - void dumpDelay(size_t trackIndex, int64_t timeUs); - - DISALLOW_EVIL_CONSTRUCTORS(WifiDisplaySink); -}; - -} // namespace android - -#endif // WIFI_DISPLAY_SINK_H_ diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp index cacfcca..3d7b865 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp +++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp @@ -559,8 +559,6 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived( converter->dropAFrame(); } } - } else if (what == MediaSender::kWhatInformSender) { - onSinkFeedback(msg); } else { TRESPASS(); } @@ -656,89 +654,6 @@ void WifiDisplaySource::PlaybackSession::onMessageReceived( } } -void WifiDisplaySource::PlaybackSession::onSinkFeedback(const sp &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 &videoTrack = mTracks.valueFor(mVideoTrackIndex); - sp converter = videoTrack->converter(); - - if (converter != NULL) { - int32_t videoBitrate = - Converter::GetInt32Property("media.wfd.video-bitrate", -1); - - char val[PROPERTY_VALUE_MAX]; - if (videoBitrate < 0 - && property_get("media.wfd.video-bitrate", val, NULL) - && !strcasecmp("adaptive", val)) { - videoBitrate = converter->getVideoBitrate(); - - if (avgLatencyUs > 300000ll) { - videoBitrate *= 0.6; - } else if (avgLatencyUs < 100000ll) { - videoBitrate *= 1.1; - } - } - - if (videoBitrate > 0) { - if (videoBitrate < 500000) { - videoBitrate = 500000; - } else if (videoBitrate > 10000000) { - videoBitrate = 10000000; - } - - if (videoBitrate != converter->getVideoBitrate()) { - ALOGI("setting video bitrate to %d bps", videoBitrate); - - converter->setVideoBitrate(videoBitrate); - } - } - } - - sp repeaterSource = videoTrack->repeaterSource(); - if (repeaterSource != NULL) { - double rateHz = - Converter::GetInt32Property( - "media.wfd.video-framerate", -1); - - char val[PROPERTY_VALUE_MAX]; - if (rateHz < 0.0 - && property_get("media.wfd.video-framerate", val, NULL) - && !strcasecmp("adaptive", val)) { - rateHz = repeaterSource->getFrameRate(); - - if (avgLatencyUs > 300000ll) { - rateHz *= 0.9; - } else if (avgLatencyUs < 200000ll) { - rateHz *= 1.1; - } - } - - if (rateHz > 0) { - if (rateHz < 5.0) { - rateHz = 5.0; - } else if (rateHz > 30.0) { - rateHz = 30.0; - } - - if (rateHz != repeaterSource->getFrameRate()) { - ALOGI("setting frame rate to %.2f Hz", rateHz); - - repeaterSource->setFrameRate(rateHz); - } - } - } - } -} - status_t WifiDisplaySource::PlaybackSession::setupMediaPacketizer( bool enableAudio, bool enableVideo) { DataSource::RegisterDefaultSniffers(); diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp index 4a49811..2b5bee9 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp @@ -23,7 +23,6 @@ #include "Parameters.h" #include "ParsedMessage.h" #include "rtp/RTPSender.h" -#include "TimeSyncer.h" #include #include @@ -165,14 +164,6 @@ void WifiDisplaySource::onMessageReceived(const sp &msg) { } else { err = -EINVAL; } - } - - if (err == OK) { - sp notify = new AMessage(kWhatTimeSyncerNotify, id()); - mTimeSyncer = new TimeSyncer(mNetSession, notify); - looper()->registerHandler(mTimeSyncer); - - mTimeSyncer->startServer(8123); mState = AWAITING_CLIENT_CONNECTION; } @@ -548,11 +539,6 @@ void WifiDisplaySource::onMessageReceived(const sp &msg) { break; } - case kWhatTimeSyncerNotify: - { - break; - } - default: TRESPASS(); } diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h index 3efa0b4..44d3e4d 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h @@ -30,7 +30,6 @@ namespace android { struct IHDCP; struct IRemoteDisplayClient; struct ParsedMessage; -struct TimeSyncer; // Represents the RTSP server acting as a wifi display source. // Manages incoming connections, sets up Playback sessions as necessary. @@ -83,7 +82,6 @@ private: kWhatHDCPNotify, kWhatFinishStop2, kWhatTeardownTriggerTimedOut, - kWhatTimeSyncerNotify, }; struct ResponseID { @@ -120,7 +118,6 @@ private: sp mNetSession; sp mClient; AString mMediaPath; - sp mTimeSyncer; struct in_addr mInterfaceAddr; int32_t mSessionID; diff --git a/media/libstagefright/wifi-display/udptest.cpp b/media/libstagefright/wifi-display/udptest.cpp deleted file mode 100644 index 111846d..0000000 --- a/media/libstagefright/wifi-display/udptest.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2012, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NEBUG 0 -#define LOG_TAG "udptest" -#include - -#include "ANetworkSession.h" -#include "TimeSyncer.h" - -#include -#include - -namespace android { - -} // namespace android - -static void usage(const char *me) { - fprintf(stderr, - "usage: %s -c host[:port]\tconnect to test server\n" - " -l \tcreate a test server\n", - me); -} - -int main(int argc, char **argv) { - using namespace android; - - ProcessState::self()->startThreadPool(); - - int32_t localPort = -1; - int32_t connectToPort = -1; - AString connectToHost; - - int res; - while ((res = getopt(argc, argv, "hc:l:")) >= 0) { - switch (res) { - case 'c': - { - const char *colonPos = strrchr(optarg, ':'); - - if (colonPos == NULL) { - connectToHost = optarg; - connectToPort = 49152; - } else { - connectToHost.setTo(optarg, colonPos - optarg); - - char *end; - connectToPort = strtol(colonPos + 1, &end, 10); - - if (*end != '\0' || end == colonPos + 1 - || connectToPort < 1 || connectToPort > 65535) { - fprintf(stderr, "Illegal port specified.\n"); - exit(1); - } - } - break; - } - - case 'l': - { - char *end; - localPort = strtol(optarg, &end, 10); - - if (*end != '\0' || end == optarg - || localPort < 1 || localPort > 65535) { - fprintf(stderr, "Illegal port specified.\n"); - exit(1); - } - break; - } - - case '?': - case 'h': - usage(argv[0]); - exit(1); - } - } - - if (localPort < 0 && connectToPort < 0) { - fprintf(stderr, - "You need to select either client or server mode.\n"); - exit(1); - } - - sp netSession = new ANetworkSession; - netSession->start(); - - sp looper = new ALooper; - - sp handler = new TimeSyncer(netSession, NULL /* notify */); - looper->registerHandler(handler); - - if (localPort >= 0) { - handler->startServer(localPort); - } else { - handler->startClient(connectToHost.c_str(), connectToPort); - } - - looper->start(true /* runOnCallingThread */); - - return 0; -} - diff --git a/media/libstagefright/wifi-display/wfd.cpp b/media/libstagefright/wifi-display/wfd.cpp index 9fee4d0..c947765 100644 --- a/media/libstagefright/wifi-display/wfd.cpp +++ b/media/libstagefright/wifi-display/wfd.cpp @@ -18,7 +18,6 @@ #define LOG_TAG "wfd" #include -#include "sink/WifiDisplaySink.h" #include "source/WifiDisplaySource.h" #include @@ -39,12 +38,8 @@ namespace android { static void usage(const char *me) { fprintf(stderr, "usage:\n" - " %s -c host[:port]\tconnect to wifi source\n" - " -u uri \tconnect to an rtsp uri\n" - " -l ip[:port] \tlisten on the specified port " - " -f(ilename) \tstream media " - "(create a sink)\n" - " -s(pecial) \trun in 'special' mode\n", + " %s -l iface[:port]\tcreate a wifi display source\n" + " -f(ilename) \tstream media\n", me); } @@ -214,48 +209,14 @@ int main(int argc, char **argv) { DataSource::RegisterDefaultSniffers(); - AString connectToHost; - int32_t connectToPort = -1; - AString uri; - AString listenOnAddr; int32_t listenOnPort = -1; AString path; - bool specialMode = false; - int res; - while ((res = getopt(argc, argv, "hc:l:u:f:s")) >= 0) { + while ((res = getopt(argc, argv, "hl:f:")) >= 0) { switch (res) { - case 'c': - { - const char *colonPos = strrchr(optarg, ':'); - - if (colonPos == NULL) { - connectToHost = optarg; - connectToPort = WifiDisplaySource::kWifiDisplayDefaultPort; - } else { - connectToHost.setTo(optarg, colonPos - optarg); - - char *end; - connectToPort = strtol(colonPos + 1, &end, 10); - - if (*end != '\0' || end == colonPos + 1 - || connectToPort < 1 || connectToPort > 65535) { - fprintf(stderr, "Illegal port specified.\n"); - exit(1); - } - } - break; - } - - case 'u': - { - uri = optarg; - break; - } - case 'f': { path = optarg; @@ -284,12 +245,6 @@ int main(int argc, char **argv) { break; } - case 's': - { - specialMode = true; - break; - } - case '?': case 'h': default: @@ -298,13 +253,6 @@ int main(int argc, char **argv) { } } - if (connectToPort >= 0 && listenOnPort >= 0) { - fprintf(stderr, - "You can connect to a source or create one, " - "but not both at the same time.\n"); - exit(1); - } - if (listenOnPort >= 0) { if (path.empty()) { createSource(listenOnAddr, listenOnPort); @@ -315,72 +263,7 @@ int main(int argc, char **argv) { exit(0); } - if (connectToPort < 0 && uri.empty()) { - fprintf(stderr, - "You need to select either source host or uri.\n"); - - exit(1); - } - - if (connectToPort >= 0 && !uri.empty()) { - fprintf(stderr, - "You need to either connect to a wfd host or an rtsp url, " - "not both.\n"); - exit(1); - } - - sp composerClient = new SurfaceComposerClient; - CHECK_EQ(composerClient->initCheck(), (status_t)OK); - - sp display(SurfaceComposerClient::getBuiltInDisplay( - ISurfaceComposer::eDisplayIdMain)); - DisplayInfo info; - SurfaceComposerClient::getDisplayInfo(display, &info); - ssize_t displayWidth = info.w; - ssize_t displayHeight = info.h; - - ALOGV("display is %d x %d\n", displayWidth, displayHeight); - - sp control = - composerClient->createSurface( - String8("A Surface"), - displayWidth, - displayHeight, - PIXEL_FORMAT_RGB_565, - 0); - - CHECK(control != NULL); - CHECK(control->isValid()); - - SurfaceComposerClient::openGlobalTransaction(); - CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK); - CHECK_EQ(control->show(), (status_t)OK); - SurfaceComposerClient::closeGlobalTransaction(); - - sp surface = control->getSurface(); - CHECK(surface != NULL); - - sp session = new ANetworkSession; - session->start(); - - sp looper = new ALooper; - - sp sink = new WifiDisplaySink( - specialMode ? WifiDisplaySink::FLAG_SPECIAL_MODE : 0 /* flags */, - session, - surface->getIGraphicBufferProducer()); - - looper->registerHandler(sink); - - if (connectToPort >= 0) { - sink->start(connectToHost.c_str(), connectToPort); - } else { - sink->start(uri.c_str()); - } - - looper->start(true /* runOnCallingThread */); - - composerClient->dispose(); + usage(argv[0]); return 0; } -- cgit v1.1