Loading media/libaah_rtp/aah_rx_player.cpp +8 −7 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ AAH_RXPlayer::AAH_RXPlayer() is_playing_ = false; multicast_joined_ = false; multicast_mode_ = false; transmitter_known_ = false; current_epoch_known_ = false; data_source_set_ = false; Loading @@ -46,7 +47,7 @@ AAH_RXPlayer::AAH_RXPlayer() substreams_.setCapacity(4); memset(&listen_addr_, 0, sizeof(listen_addr_)); memset(&data_source_addr_, 0, sizeof(data_source_addr_)); memset(&transmitter_addr_, 0, sizeof(transmitter_addr_)); fetchAudioFlinger(); Loading Loading @@ -112,10 +113,10 @@ status_t AAH_RXPlayer::setDataSource( a = (a << 24) | (b << 16) | (c << 8) | d; memset(&listen_addr_, 0, sizeof(listen_addr_)); listen_addr_.sin_family = AF_INET; listen_addr_.sin_port = htons(port); listen_addr_.sin_addr.s_addr = htonl(a); memset(&data_source_addr_, 0, sizeof(data_source_addr_)); data_source_addr_.sin_family = AF_INET; data_source_addr_.sin_port = htons(port); data_source_addr_.sin_addr.s_addr = htonl(a); data_source_set_ = true; return OK; Loading Loading @@ -202,9 +203,9 @@ void AAH_RXPlayer::reset_l() { CHECK(sock_fd_ < 0); CHECK(!multicast_joined_); is_playing_ = false; data_source_set_ = false; transmitter_known_ = false; memset(&listen_addr_, 0, sizeof(listen_addr_)); memset(&data_source_addr_, 0, sizeof(data_source_addr_)); data_source_set_ = false; } status_t AAH_RXPlayer::setLooping(int loop) { Loading media/libaah_rtp/aah_rx_player.h +11 −6 Original line number Diff line number Diff line Loading @@ -266,19 +266,23 @@ class AAH_RXPlayer : public MediaPlayerInterface { void processRingBuffer(); void processCommandPacket(PacketBuffer* pb); bool processGaps(); bool processRetransmitNAK(const uint8_t* data, size_t amt); void setGapStatus(GapStatus status); void cleanoutExpiredSubstreams(); void sendUnicastGroupJoin(); void sendUnicastGroupLeave(); void fetchAudioFlinger(); PipeEvent wakeup_work_thread_evt_; sp<ThreadWrapper> thread_wrapper_; Mutex api_lock_; bool is_playing_; bool data_source_set_; struct sockaddr_in listen_addr_; int sock_fd_; struct sockaddr_in data_source_addr_; bool data_source_set_; bool multicast_mode_; bool multicast_joined_; int sock_fd_; struct sockaddr_in transmitter_addr_; bool transmitter_known_; Loading @@ -291,6 +295,7 @@ class AAH_RXPlayer : public MediaPlayerInterface { Timeout next_retrans_req_timeout_; Timeout ss_cleanout_timeout_; Timeout unicast_group_report_timeout_; RXRingBuffer ring_buffer_; SubstreamVec substreams_; Loading @@ -301,13 +306,13 @@ class AAH_RXPlayer : public MediaPlayerInterface { sp<IAudioFlinger> audio_flinger_; static const uint32_t kRTPRingBufferSize; static const uint32_t kRetransRequestMagic; static const uint32_t kFastStartRequestMagic; static const uint32_t kRetransNAKMagic; static const uint32_t kGapRerequestTimeoutMsec; static const uint32_t kFastStartTimeoutMsec; static const uint32_t kRTPActivityTimeoutMsec; static const uint32_t kSSCleanoutTimeoutMsec; static const uint32_t kGrpMemberSlowReportIntervalMsec; static const uint32_t kGrpMemberFastReportIntervalMsec; static const uint32_t INVOKE_GET_MASTER_VOLUME = 3; static const uint32_t INVOKE_SET_MASTER_VOLUME = 4; Loading media/libaah_rtp/aah_rx_player_core.cpp +173 −65 Original line number Diff line number Diff line Loading @@ -28,19 +28,16 @@ #include "aah_rx_player.h" #include "aah_tx_packet.h" #include "utils.h" namespace android { const uint32_t AAH_RXPlayer::kRetransRequestMagic = FOURCC('T','r','e','q'); const uint32_t AAH_RXPlayer::kRetransNAKMagic = FOURCC('T','n','a','k'); const uint32_t AAH_RXPlayer::kFastStartRequestMagic = FOURCC('T','f','s','t'); const uint32_t AAH_RXPlayer::kGapRerequestTimeoutMsec = 75; const uint32_t AAH_RXPlayer::kFastStartTimeoutMsec = 800; const uint32_t AAH_RXPlayer::kRTPActivityTimeoutMsec = 10000; const uint32_t AAH_RXPlayer::kSSCleanoutTimeoutMsec = 1000; const uint32_t AAH_RXPlayer::kGrpMemberSlowReportIntervalMsec = 900; const uint32_t AAH_RXPlayer::kGrpMemberFastReportIntervalMsec = 200; static inline int16_t fetchInt16(uint8_t* data) { return static_cast<int16_t>(U16_AT(data)); Loading Loading @@ -82,10 +79,23 @@ void AAH_RXPlayer::stopWorkThread() { void AAH_RXPlayer::cleanupSocket() { if (sock_fd_ >= 0) { // If we are in unicast mode, send a pair of leave requests spaced by a // short delay. We send a pair to increase the probability that at // least one gets through. If both get dropped, the transmitter will // figure it out eventually via the timeout, but we'd rather not rely on // that if we can avoid it. if (!multicast_mode_) { sendUnicastGroupLeave(); usleep(20000); // 20mSec sendUnicastGroupLeave(); } // If we had joined a multicast group, make sure we leave it properly // before closing our socket. if (multicast_joined_) { int res; struct ip_mreq mreq; mreq.imr_multiaddr = listen_addr_.sin_addr; mreq.imr_multiaddr = data_source_addr_.sin_addr; mreq.imr_interface.s_addr = htonl(INADDR_ANY); res = setsockopt(sock_fd_, IPPROTO_IP, Loading @@ -101,6 +111,7 @@ void AAH_RXPlayer::cleanupSocket() { sock_fd_ = -1; } multicast_mode_ = false; resetPipeline(); } Loading @@ -123,10 +134,27 @@ bool AAH_RXPlayer::setupSocket() { long flags; int res, buf_size; socklen_t opt_size; uint32_t addr = ntohl(data_source_addr_.sin_addr.s_addr); uint16_t port = ntohs(data_source_addr_.sin_port); cleanupSocket(); CHECK(sock_fd_ < 0); // Make sure we have a valid data source before proceeding. if (!data_source_set_) { LOGE("setupSocket called with no data source set."); goto bailout; } if ((addr == INADDR_ANY) || !port) { LOGE("setupSocket called with invalid data source (%d.%d.%d.%d:%hu)", IP_PRINTF_HELPER(addr), port); goto bailout; } // Check to see if we are in multicast RX mode or not. multicast_mode_ = isMulticastSockaddr(&data_source_addr_); // Make the socket sock_fd_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock_fd_ < 0) { Loading @@ -143,12 +171,14 @@ bool AAH_RXPlayer::setupSocket() { goto bailout; } // Bind to our port // Bind to our port. If we are in multicast mode, we need to bind to the // port on which the multicast traffic will be arriving. If we are in // unicast mode, then just bind to an ephemeral port. struct sockaddr_in bind_addr; memset(&bind_addr, 0, sizeof(bind_addr)); bind_addr.sin_family = AF_INET; bind_addr.sin_addr.s_addr = INADDR_ANY; bind_addr.sin_port = listen_addr_.sin_port; bind_addr.sin_port = multicast_mode_ ? data_source_addr_.sin_port : 0; res = bind(sock_fd_, reinterpret_cast<const sockaddr*>(&bind_addr), sizeof(bind_addr)); Loading @@ -156,17 +186,12 @@ bool AAH_RXPlayer::setupSocket() { uint32_t a = ntohl(bind_addr.sin_addr.s_addr); uint16_t p = ntohs(bind_addr.sin_port); LOGE("Failed to bind socket (%d) to %d.%d.%d.%d:%hu. (errno %d)", sock_fd_, (a >> 24) & 0xFF, (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a ) & 0xFF, p, errno); sock_fd_, IP_PRINTF_HELPER(a), p, errno); goto bailout; } // Increase our socket buffer RX size buf_size = 1 << 16; // 64k res = setsockopt(sock_fd_, SOL_SOCKET, SO_RCVBUF, Loading @@ -188,10 +213,12 @@ bool AAH_RXPlayer::setupSocket() { LOGD("RX socket buffer size is now %d bytes", buf_size); } if (listen_addr_.sin_addr.s_addr) { // If we are in multicast mode, join our socket to the multicast group on // which we expect to receive traffic. if (multicast_mode_) { // Join the multicast group and we should be good to go. struct ip_mreq mreq; mreq.imr_multiaddr = listen_addr_.sin_addr; mreq.imr_multiaddr = data_source_addr_.sin_addr; mreq.imr_interface.s_addr = htonl(INADDR_ANY); res = setsockopt(sock_fd_, IPPROTO_IP, Loading @@ -201,6 +228,7 @@ bool AAH_RXPlayer::setupSocket() { LOGE("Failed to join multicast group. (errno %d)", errno); goto bailout; } multicast_joined_ = true; } Loading @@ -220,27 +248,46 @@ bool AAH_RXPlayer::threadLoop() { goto bailout; } // If we are not in multicast mode, send our first group membership report // right now. Otherwise, make sure that the timeout has been canceled so we // don't accidentally end up sending reports when we should not. if (!multicast_mode_) { sendUnicastGroupJoin(); } else { unicast_group_report_timeout_.setTimeout(-1); } while (!thread_wrapper_->exitPending()) { // Step 1: Wait until there is something to do. int gap_timeout = next_retrans_req_timeout_.msecTillTimeout(); int ring_timeout = ring_buffer_.computeInactivityTimeout(); int ss_cleanout_timeout = ss_cleanout_timeout_.msecTillTimeout(); int timeout = -1; int tmp; // Time to report unicast group membership? if (!(tmp = unicast_group_report_timeout_.msecTillTimeout())) { sendUnicastGroupJoin(); continue; } timeout = minTimeout(tmp, timeout); if (!ring_timeout) { // Ring buffer timed out? if (!(tmp = ring_buffer_.computeInactivityTimeout())) { LOGW("RTP inactivity timeout reached, resetting pipeline."); resetPipeline(); continue; } timeout = minTimeout(tmp, timeout); if (!ss_cleanout_timeout) { // Time to check for expired substreams? if (!(tmp = ss_cleanout_timeout_.msecTillTimeout())) { cleanoutExpiredSubstreams(); continue; } timeout = minTimeout(tmp, timeout); timeout = minTimeout(gap_timeout, timeout); timeout = minTimeout(ring_timeout, timeout); timeout = minTimeout(ss_cleanout_timeout, timeout); // Finally, take the next retransmit request timeout into account and // proceed. tmp = next_retrans_req_timeout_.msecTillTimeout(); timeout = minTimeout(tmp, timeout); if ((0 != timeout) && (!process_more_right_now)) { // Set up the events to wait on. Start with the wakeup pipe. Loading @@ -252,7 +299,7 @@ bool AAH_RXPlayer::threadLoop() { poll_fds[1].fd = sock_fd_; poll_fds[1].events = POLLIN; // Wait for something interesing to happen. // Wait for something interesting to happen. int poll_res = poll(poll_fds, NELEM(poll_fds), timeout); if (poll_res < 0) { LOGE("Fatal error (%d,%d) while waiting on events", Loading Loading @@ -325,12 +372,7 @@ bool AAH_RXPlayer::threadLoop() { uint32_t a = ntohl(from.sin_addr.s_addr); uint16_t p = ntohs(from.sin_port); LOGV("Dropping packet from unknown transmitter" " %u.%u.%u.%u:%hu", ((a >> 24) & 0xFF), ((a >> 16) & 0xFF), ((a >> 8) & 0xFF), ( a & 0xFF), p); " %d.%d.%d.%d:%hu", IP_PRINTK_HELPER(a), p); drop_packet = true; } else { Loading Loading @@ -408,36 +450,39 @@ bool AAH_RXPlayer::processRX(PacketBuffer* pb) { uint32_t nak_magic; uint16_t seq_no; uint32_t epoch; // Every packet either starts with an RTP header which is at least 12 bytes // long or is a retry NAK which is 14 bytes long. If there are fewer than // 12 bytes here, this cannot be a proper RTP packet. if (amt < 12) { LOGV("Dropping packet, too short to contain RTP header (%u bytes)", bool ret_val = true; // Every packet should be either a C&C NAK packet, or a TRTP packet. The // shortest possible packet is a group membership NAK, which is only 4 bytes // long. If our RXed packet is not at least 4 bytes long, then this is junk // and should be tossed. if (amt < 4) { LOGV("Dropping packet, too short to contain any valid data (%u bytes)", static_cast<uint32_t>(amt)); goto drop_packet; } // Check to see if this is the special case of a NAK packet. // Check to see if this is a special C&C NAK packet. nak_magic = ntohl(*(reinterpret_cast<uint32_t*>(data))); if (nak_magic == kRetransNAKMagic) { // Looks like a NAK packet; make sure its long enough. if (amt < static_cast<ssize_t>(sizeof(RetransRequest))) { LOGV("Dropping packet, too short to contain NAK payload (%u bytes)", static_cast<uint32_t>(amt)); switch (nak_magic) { case TRTPPacket::kCNC_NakRetryRequestID: ret_val = processRetransmitNAK(data, amt); goto drop_packet; } SeqNoGap gap; RetransRequest* rtr = reinterpret_cast<RetransRequest*>(data); gap.start_seq_ = ntohs(rtr->start_seq_); gap.end_seq_ = ntohs(rtr->end_seq_); LOGV("Process NAK for gap at [%hu, %hu]", gap.start_seq_, gap.end_seq_); ring_buffer_.processNAK(&gap); case TRTPPacket::kCNC_NakJoinGroupID: LOGI("Received group join NAK; signalling error and shutting down"); ret_val = false; goto drop_packet; } return true; // Every non C&C packet starts with an RTP header which is at least 12 bytes // If there are fewer than 12 bytes here, this cannot be a proper RTP // packet. if (amt < 12) { LOGV("Dropping packet, too short to contain RTP header (%u bytes)", static_cast<uint32_t>(amt)); goto drop_packet; } // According to the TRTP spec, version should be 2, padding should be 0, Loading Loading @@ -476,7 +521,7 @@ bool AAH_RXPlayer::processRX(PacketBuffer* pb) { drop_packet: PacketBuffer::destroy(pb); return true; return ret_val; } void AAH_RXPlayer::processRingBuffer() { Loading Loading @@ -790,23 +835,19 @@ bool AAH_RXPlayer::processGaps() { // Send the request. RetransRequest req; uint32_t magic = (kGS_FastStartGap == gap_status) ? kFastStartRequestMagic : kRetransRequestMagic; ? TRTPPacket::kCNC_FastStartRequestID : TRTPPacket::kCNC_RetryRequestID; req.magic_ = htonl(magic); req.mcast_ip_ = listen_addr_.sin_addr.s_addr; req.mcast_port_ = listen_addr_.sin_port; req.mcast_ip_ = data_source_addr_.sin_addr.s_addr; req.mcast_port_ = data_source_addr_.sin_port; req.start_seq_ = htons(gap.start_seq_); req.end_seq_ = htons(gap.end_seq_); { uint32_t a = ntohl(transmitter_addr_.sin_addr.s_addr); uint16_t p = ntohs(transmitter_addr_.sin_port); LOGV("Sending to transmitter %u.%u.%u.%u:%hu", ((a >> 24) & 0xFF), ((a >> 16) & 0xFF), ((a >> 8) & 0xFF), ( a & 0xFF), p); LOGV("Sending to transmitter %d.%d.%d.%d:%hu", IP_PRINTF_HELPER(a), p); } int res = sendto(sock_fd_, &req, sizeof(req), 0, Loading @@ -828,6 +869,24 @@ bool AAH_RXPlayer::processGaps() { return false; } bool AAH_RXPlayer::processRetransmitNAK(const uint8_t* data, size_t amt) { if (amt < static_cast<ssize_t>(sizeof(RetransRequest))) { LOGV("Dropping packet, too short to contain NAK payload (%u bytes)", static_cast<uint32_t>(amt)); return true; } SeqNoGap gap; const RetransRequest* rtr = reinterpret_cast<const RetransRequest*>(data); gap.start_seq_ = ntohs(rtr->start_seq_); gap.end_seq_ = ntohs(rtr->end_seq_); LOGI("Process NAK for gap at [%hu, %hu]", gap.start_seq_, gap.end_seq_); ring_buffer_.processNAK(&gap); return true; } void AAH_RXPlayer::setGapStatus(GapStatus status) { current_gap_status_ = status; Loading Loading @@ -871,4 +930,53 @@ void AAH_RXPlayer::cleanoutExpiredSubstreams() { ss_cleanout_timeout_.setTimeout(kSSCleanoutTimeoutMsec); } void AAH_RXPlayer::sendUnicastGroupJoin() { if (!multicast_mode_ && (sock_fd_ >= 0)) { uint32_t tag = htonl(TRTPPacket::kCNC_JoinGroupID); uint32_t a = ntohl(data_source_addr_.sin_addr.s_addr); uint16_t p = ntohs(data_source_addr_.sin_port); LOGV("Sending group join to transmitter %d.%d.%d.%d:%hu", IP_PRINTF_HELPER(a), p); int res = sendto(sock_fd_, &tag, sizeof(tag), 0, reinterpret_cast<struct sockaddr*>(&data_source_addr_), sizeof(data_source_addr_)); if (res < 0) { LOGW("Error sending group join to transmitter %d.%d.%d.%d:%hu" " (errno %d)", IP_PRINTF_HELPER(a), p, errno); } // Reset the membership report timeout. Use our fast timeout until we // have heard back from our transmitter at least once. unicast_group_report_timeout_.setTimeout(transmitter_known_ ? kGrpMemberSlowReportIntervalMsec : kGrpMemberFastReportIntervalMsec); } else { LOGE("Attempted to send unicast group membership report while" " multicast_mode = %s and sock_fd = %d", multicast_mode_ ? "true" : "false", sock_fd_); unicast_group_report_timeout_.setTimeout(-1); } } void AAH_RXPlayer::sendUnicastGroupLeave() { if (!multicast_mode_ && (sock_fd_ >= 0)) { uint32_t tag = htonl(TRTPPacket::kCNC_LeaveGroupID); uint32_t a = ntohl(data_source_addr_.sin_addr.s_addr); uint16_t p = ntohs(data_source_addr_.sin_port); LOGI("Sending group leave to transmitter %d.%d.%d.%d:%hu", IP_PRINTF_HELPER(a), p); int res = sendto(sock_fd_, &tag, sizeof(tag), 0, reinterpret_cast<struct sockaddr*>(&data_source_addr_), sizeof(data_source_addr_)); if (res < 0) { LOGW("Error sending group leave to transmitter %d.%d.%d.%d:%hu" " (errno %d)", IP_PRINTF_HELPER(a), p, errno); } } } } // namespace android media/libaah_rtp/aah_tx_group.cpp +14 −21 Original line number Diff line number Diff line Loading @@ -114,13 +114,6 @@ const size_t AAH_TXGroup::kInitialActiveTXGroupsCapacity = 4; const size_t AAH_TXGroup::kMaxAllowedPlayerClients = 4; const size_t AAH_TXGroup::kInitialPlayerClientCapacity = 2; const uint32_t AAH_TXGroup::kCNC_RetryRequestID = 'Treq'; const uint32_t AAH_TXGroup::kCNC_FastStartRequestID = 'Tfst'; const uint32_t AAH_TXGroup::kCNC_NakRetryRequestID = 'Tnak'; const uint32_t AAH_TXGroup::kCNC_JoinGroupID = 'Tjgp'; const uint32_t AAH_TXGroup::kCNC_LeaveGroupID = 'Tlgp'; const uint32_t AAH_TXGroup::kCNC_NakJoinGroupID = 'Tngp'; Mutex AAH_TXGroup::sLock; Vector < sp<AAH_TXGroup> > AAH_TXGroup::sActiveTXGroups; sp<AAH_TXGroup::CmdAndControlRXer> AAH_TXGroup::mCmdAndControlRXer; Loading Loading @@ -687,12 +680,12 @@ void AAH_TXGroup::handleRequests() { uint32_t id = U32_AT(request); size_t minSize = 0; switch(id) { case kCNC_RetryRequestID: case kCNC_FastStartRequestID: case TRTPPacket::kCNC_RetryRequestID: case TRTPPacket::kCNC_FastStartRequestID: minSize = sizeof(RetryPacket); break; case kCNC_JoinGroupID: case kCNC_LeaveGroupID: case TRTPPacket::kCNC_JoinGroupID: case TRTPPacket::kCNC_LeaveGroupID: minSize = sizeof(uint32_t); break; } Loading @@ -705,19 +698,19 @@ void AAH_TXGroup::handleRequests() { } switch(id) { case kCNC_RetryRequestID: case TRTPPacket::kCNC_RetryRequestID: handleRetryRequest(request, &srcAddr, false); break; case kCNC_FastStartRequestID: case TRTPPacket::kCNC_FastStartRequestID: handleRetryRequest(request, &srcAddr, true); break; case kCNC_JoinGroupID: case TRTPPacket::kCNC_JoinGroupID: handleJoinGroup(&srcAddr); break; case kCNC_LeaveGroupID: case TRTPPacket::kCNC_LeaveGroupID: handleLeaveGroup(&srcAddr); break; Loading Loading @@ -755,7 +748,7 @@ void AAH_TXGroup::handleRetryRequest(const uint8_t* req, // we have an empty retry buffer for this group, so NAK the entire // request RetryPacket nak = *req_overlay; nak.id = htonl(kCNC_NakRetryRequestID); nak.id = htonl(TRTPPacket::kCNC_NakRetryRequestID); if (sendto(mSocket, &nak, sizeof(nak), 0, src, sizeof(*src_addr)) < 0) { Loading Loading @@ -796,7 +789,7 @@ void AAH_TXGroup::handleRetryRequest(const uint8_t* req, if (startIndex == -1 && endIndex == -1) { // no part of the request range is found in the retry buffer RetryPacket nak = *req_overlay; nak.id = htonl(kCNC_NakRetryRequestID); nak.id = htonl(TRTPPacket::kCNC_NakRetryRequestID); if (sendto(mSocket, &nak, sizeof(nak), 0, src, sizeof(*src_addr)) < 0) { Loading @@ -810,7 +803,7 @@ void AAH_TXGroup::handleRetryRequest(const uint8_t* req, if (startIndex == -1) { // NAK a subrange at the front of the request range RetryPacket nak = *req_overlay; nak.id = htonl(kCNC_NakRetryRequestID); nak.id = htonl(TRTPPacket::kCNC_NakRetryRequestID); nak.seqEnd = htons(retryFirstSeq - 1); if (sendto(mSocket, &nak, sizeof(nak), 0, Loading @@ -824,7 +817,7 @@ void AAH_TXGroup::handleRetryRequest(const uint8_t* req, } else if (endIndex == -1) { // NAK a subrange at the back of the request range RetryPacket nak = *req_overlay; nak.id = htonl(kCNC_NakRetryRequestID); nak.id = htonl(TRTPPacket::kCNC_NakRetryRequestID); nak.seqStart = htons(retryLastSeq + 1); if (sendto(mSocket, &nak, sizeof(nak), 0, Loading Loading @@ -879,7 +872,7 @@ void AAH_TXGroup::handleJoinGroup(const struct sockaddr_in* src_addr) { // before proceeding. If not, send a NAK back so it knows to signal an // error to its application level. if (mUnicastTargets.size() >= kMaxAllowedUnicastTargets) { uint32_t nak_payload = htonl(kCNC_NakJoinGroupID); uint32_t nak_payload = htonl(TRTPPacket::kCNC_NakJoinGroupID); if (sendto(mSocket, &nak_payload, sizeof(nak_payload), 0, src, sizeof(*src_addr)) < 0) { Loading @@ -898,7 +891,7 @@ void AAH_TXGroup::handleJoinGroup(const struct sockaddr_in* src_addr) { // application level. sp<UnicastTarget> ut = new UnicastTarget(*src_addr); if ((ut == NULL) || (mUnicastTargets.add(ut) < 0)) { uint32_t nak_payload = htonl(kCNC_NakJoinGroupID); uint32_t nak_payload = htonl(TRTPPacket::kCNC_NakJoinGroupID); if (sendto(mSocket, &nak_payload, sizeof(nak_payload), 0, src, sizeof(*src_addr)) < 0) { Loading media/libaah_rtp/aah_tx_group.h +0 −10 Original line number Diff line number Diff line Loading @@ -28,9 +28,6 @@ #include "aah_tx_packet.h" #include "utils.h" #define IP_PRINTF_HELPER(a) ((a >> 24) & 0xFF), ((a >> 16) & 0xFF), \ ((a >> 8) & 0xFF), (a & 0xFF) namespace android { class AAH_TXPlayer; Loading Loading @@ -318,13 +315,6 @@ class AAH_TXGroup : public virtual RefBase { static const size_t kMaxAllowedPlayerClients; static const size_t kInitialPlayerClientCapacity; static const uint32_t kCNC_RetryRequestID; static const uint32_t kCNC_FastStartRequestID; static const uint32_t kCNC_NakRetryRequestID; static const uint32_t kCNC_JoinGroupID; static const uint32_t kCNC_LeaveGroupID; static const uint32_t kCNC_NakJoinGroupID; DISALLOW_EVIL_CONSTRUCTORS(AAH_TXGroup); }; Loading Loading
media/libaah_rtp/aah_rx_player.cpp +8 −7 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ AAH_RXPlayer::AAH_RXPlayer() is_playing_ = false; multicast_joined_ = false; multicast_mode_ = false; transmitter_known_ = false; current_epoch_known_ = false; data_source_set_ = false; Loading @@ -46,7 +47,7 @@ AAH_RXPlayer::AAH_RXPlayer() substreams_.setCapacity(4); memset(&listen_addr_, 0, sizeof(listen_addr_)); memset(&data_source_addr_, 0, sizeof(data_source_addr_)); memset(&transmitter_addr_, 0, sizeof(transmitter_addr_)); fetchAudioFlinger(); Loading Loading @@ -112,10 +113,10 @@ status_t AAH_RXPlayer::setDataSource( a = (a << 24) | (b << 16) | (c << 8) | d; memset(&listen_addr_, 0, sizeof(listen_addr_)); listen_addr_.sin_family = AF_INET; listen_addr_.sin_port = htons(port); listen_addr_.sin_addr.s_addr = htonl(a); memset(&data_source_addr_, 0, sizeof(data_source_addr_)); data_source_addr_.sin_family = AF_INET; data_source_addr_.sin_port = htons(port); data_source_addr_.sin_addr.s_addr = htonl(a); data_source_set_ = true; return OK; Loading Loading @@ -202,9 +203,9 @@ void AAH_RXPlayer::reset_l() { CHECK(sock_fd_ < 0); CHECK(!multicast_joined_); is_playing_ = false; data_source_set_ = false; transmitter_known_ = false; memset(&listen_addr_, 0, sizeof(listen_addr_)); memset(&data_source_addr_, 0, sizeof(data_source_addr_)); data_source_set_ = false; } status_t AAH_RXPlayer::setLooping(int loop) { Loading
media/libaah_rtp/aah_rx_player.h +11 −6 Original line number Diff line number Diff line Loading @@ -266,19 +266,23 @@ class AAH_RXPlayer : public MediaPlayerInterface { void processRingBuffer(); void processCommandPacket(PacketBuffer* pb); bool processGaps(); bool processRetransmitNAK(const uint8_t* data, size_t amt); void setGapStatus(GapStatus status); void cleanoutExpiredSubstreams(); void sendUnicastGroupJoin(); void sendUnicastGroupLeave(); void fetchAudioFlinger(); PipeEvent wakeup_work_thread_evt_; sp<ThreadWrapper> thread_wrapper_; Mutex api_lock_; bool is_playing_; bool data_source_set_; struct sockaddr_in listen_addr_; int sock_fd_; struct sockaddr_in data_source_addr_; bool data_source_set_; bool multicast_mode_; bool multicast_joined_; int sock_fd_; struct sockaddr_in transmitter_addr_; bool transmitter_known_; Loading @@ -291,6 +295,7 @@ class AAH_RXPlayer : public MediaPlayerInterface { Timeout next_retrans_req_timeout_; Timeout ss_cleanout_timeout_; Timeout unicast_group_report_timeout_; RXRingBuffer ring_buffer_; SubstreamVec substreams_; Loading @@ -301,13 +306,13 @@ class AAH_RXPlayer : public MediaPlayerInterface { sp<IAudioFlinger> audio_flinger_; static const uint32_t kRTPRingBufferSize; static const uint32_t kRetransRequestMagic; static const uint32_t kFastStartRequestMagic; static const uint32_t kRetransNAKMagic; static const uint32_t kGapRerequestTimeoutMsec; static const uint32_t kFastStartTimeoutMsec; static const uint32_t kRTPActivityTimeoutMsec; static const uint32_t kSSCleanoutTimeoutMsec; static const uint32_t kGrpMemberSlowReportIntervalMsec; static const uint32_t kGrpMemberFastReportIntervalMsec; static const uint32_t INVOKE_GET_MASTER_VOLUME = 3; static const uint32_t INVOKE_SET_MASTER_VOLUME = 4; Loading
media/libaah_rtp/aah_rx_player_core.cpp +173 −65 Original line number Diff line number Diff line Loading @@ -28,19 +28,16 @@ #include "aah_rx_player.h" #include "aah_tx_packet.h" #include "utils.h" namespace android { const uint32_t AAH_RXPlayer::kRetransRequestMagic = FOURCC('T','r','e','q'); const uint32_t AAH_RXPlayer::kRetransNAKMagic = FOURCC('T','n','a','k'); const uint32_t AAH_RXPlayer::kFastStartRequestMagic = FOURCC('T','f','s','t'); const uint32_t AAH_RXPlayer::kGapRerequestTimeoutMsec = 75; const uint32_t AAH_RXPlayer::kFastStartTimeoutMsec = 800; const uint32_t AAH_RXPlayer::kRTPActivityTimeoutMsec = 10000; const uint32_t AAH_RXPlayer::kSSCleanoutTimeoutMsec = 1000; const uint32_t AAH_RXPlayer::kGrpMemberSlowReportIntervalMsec = 900; const uint32_t AAH_RXPlayer::kGrpMemberFastReportIntervalMsec = 200; static inline int16_t fetchInt16(uint8_t* data) { return static_cast<int16_t>(U16_AT(data)); Loading Loading @@ -82,10 +79,23 @@ void AAH_RXPlayer::stopWorkThread() { void AAH_RXPlayer::cleanupSocket() { if (sock_fd_ >= 0) { // If we are in unicast mode, send a pair of leave requests spaced by a // short delay. We send a pair to increase the probability that at // least one gets through. If both get dropped, the transmitter will // figure it out eventually via the timeout, but we'd rather not rely on // that if we can avoid it. if (!multicast_mode_) { sendUnicastGroupLeave(); usleep(20000); // 20mSec sendUnicastGroupLeave(); } // If we had joined a multicast group, make sure we leave it properly // before closing our socket. if (multicast_joined_) { int res; struct ip_mreq mreq; mreq.imr_multiaddr = listen_addr_.sin_addr; mreq.imr_multiaddr = data_source_addr_.sin_addr; mreq.imr_interface.s_addr = htonl(INADDR_ANY); res = setsockopt(sock_fd_, IPPROTO_IP, Loading @@ -101,6 +111,7 @@ void AAH_RXPlayer::cleanupSocket() { sock_fd_ = -1; } multicast_mode_ = false; resetPipeline(); } Loading @@ -123,10 +134,27 @@ bool AAH_RXPlayer::setupSocket() { long flags; int res, buf_size; socklen_t opt_size; uint32_t addr = ntohl(data_source_addr_.sin_addr.s_addr); uint16_t port = ntohs(data_source_addr_.sin_port); cleanupSocket(); CHECK(sock_fd_ < 0); // Make sure we have a valid data source before proceeding. if (!data_source_set_) { LOGE("setupSocket called with no data source set."); goto bailout; } if ((addr == INADDR_ANY) || !port) { LOGE("setupSocket called with invalid data source (%d.%d.%d.%d:%hu)", IP_PRINTF_HELPER(addr), port); goto bailout; } // Check to see if we are in multicast RX mode or not. multicast_mode_ = isMulticastSockaddr(&data_source_addr_); // Make the socket sock_fd_ = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock_fd_ < 0) { Loading @@ -143,12 +171,14 @@ bool AAH_RXPlayer::setupSocket() { goto bailout; } // Bind to our port // Bind to our port. If we are in multicast mode, we need to bind to the // port on which the multicast traffic will be arriving. If we are in // unicast mode, then just bind to an ephemeral port. struct sockaddr_in bind_addr; memset(&bind_addr, 0, sizeof(bind_addr)); bind_addr.sin_family = AF_INET; bind_addr.sin_addr.s_addr = INADDR_ANY; bind_addr.sin_port = listen_addr_.sin_port; bind_addr.sin_port = multicast_mode_ ? data_source_addr_.sin_port : 0; res = bind(sock_fd_, reinterpret_cast<const sockaddr*>(&bind_addr), sizeof(bind_addr)); Loading @@ -156,17 +186,12 @@ bool AAH_RXPlayer::setupSocket() { uint32_t a = ntohl(bind_addr.sin_addr.s_addr); uint16_t p = ntohs(bind_addr.sin_port); LOGE("Failed to bind socket (%d) to %d.%d.%d.%d:%hu. (errno %d)", sock_fd_, (a >> 24) & 0xFF, (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a ) & 0xFF, p, errno); sock_fd_, IP_PRINTF_HELPER(a), p, errno); goto bailout; } // Increase our socket buffer RX size buf_size = 1 << 16; // 64k res = setsockopt(sock_fd_, SOL_SOCKET, SO_RCVBUF, Loading @@ -188,10 +213,12 @@ bool AAH_RXPlayer::setupSocket() { LOGD("RX socket buffer size is now %d bytes", buf_size); } if (listen_addr_.sin_addr.s_addr) { // If we are in multicast mode, join our socket to the multicast group on // which we expect to receive traffic. if (multicast_mode_) { // Join the multicast group and we should be good to go. struct ip_mreq mreq; mreq.imr_multiaddr = listen_addr_.sin_addr; mreq.imr_multiaddr = data_source_addr_.sin_addr; mreq.imr_interface.s_addr = htonl(INADDR_ANY); res = setsockopt(sock_fd_, IPPROTO_IP, Loading @@ -201,6 +228,7 @@ bool AAH_RXPlayer::setupSocket() { LOGE("Failed to join multicast group. (errno %d)", errno); goto bailout; } multicast_joined_ = true; } Loading @@ -220,27 +248,46 @@ bool AAH_RXPlayer::threadLoop() { goto bailout; } // If we are not in multicast mode, send our first group membership report // right now. Otherwise, make sure that the timeout has been canceled so we // don't accidentally end up sending reports when we should not. if (!multicast_mode_) { sendUnicastGroupJoin(); } else { unicast_group_report_timeout_.setTimeout(-1); } while (!thread_wrapper_->exitPending()) { // Step 1: Wait until there is something to do. int gap_timeout = next_retrans_req_timeout_.msecTillTimeout(); int ring_timeout = ring_buffer_.computeInactivityTimeout(); int ss_cleanout_timeout = ss_cleanout_timeout_.msecTillTimeout(); int timeout = -1; int tmp; // Time to report unicast group membership? if (!(tmp = unicast_group_report_timeout_.msecTillTimeout())) { sendUnicastGroupJoin(); continue; } timeout = minTimeout(tmp, timeout); if (!ring_timeout) { // Ring buffer timed out? if (!(tmp = ring_buffer_.computeInactivityTimeout())) { LOGW("RTP inactivity timeout reached, resetting pipeline."); resetPipeline(); continue; } timeout = minTimeout(tmp, timeout); if (!ss_cleanout_timeout) { // Time to check for expired substreams? if (!(tmp = ss_cleanout_timeout_.msecTillTimeout())) { cleanoutExpiredSubstreams(); continue; } timeout = minTimeout(tmp, timeout); timeout = minTimeout(gap_timeout, timeout); timeout = minTimeout(ring_timeout, timeout); timeout = minTimeout(ss_cleanout_timeout, timeout); // Finally, take the next retransmit request timeout into account and // proceed. tmp = next_retrans_req_timeout_.msecTillTimeout(); timeout = minTimeout(tmp, timeout); if ((0 != timeout) && (!process_more_right_now)) { // Set up the events to wait on. Start with the wakeup pipe. Loading @@ -252,7 +299,7 @@ bool AAH_RXPlayer::threadLoop() { poll_fds[1].fd = sock_fd_; poll_fds[1].events = POLLIN; // Wait for something interesing to happen. // Wait for something interesting to happen. int poll_res = poll(poll_fds, NELEM(poll_fds), timeout); if (poll_res < 0) { LOGE("Fatal error (%d,%d) while waiting on events", Loading Loading @@ -325,12 +372,7 @@ bool AAH_RXPlayer::threadLoop() { uint32_t a = ntohl(from.sin_addr.s_addr); uint16_t p = ntohs(from.sin_port); LOGV("Dropping packet from unknown transmitter" " %u.%u.%u.%u:%hu", ((a >> 24) & 0xFF), ((a >> 16) & 0xFF), ((a >> 8) & 0xFF), ( a & 0xFF), p); " %d.%d.%d.%d:%hu", IP_PRINTK_HELPER(a), p); drop_packet = true; } else { Loading Loading @@ -408,36 +450,39 @@ bool AAH_RXPlayer::processRX(PacketBuffer* pb) { uint32_t nak_magic; uint16_t seq_no; uint32_t epoch; // Every packet either starts with an RTP header which is at least 12 bytes // long or is a retry NAK which is 14 bytes long. If there are fewer than // 12 bytes here, this cannot be a proper RTP packet. if (amt < 12) { LOGV("Dropping packet, too short to contain RTP header (%u bytes)", bool ret_val = true; // Every packet should be either a C&C NAK packet, or a TRTP packet. The // shortest possible packet is a group membership NAK, which is only 4 bytes // long. If our RXed packet is not at least 4 bytes long, then this is junk // and should be tossed. if (amt < 4) { LOGV("Dropping packet, too short to contain any valid data (%u bytes)", static_cast<uint32_t>(amt)); goto drop_packet; } // Check to see if this is the special case of a NAK packet. // Check to see if this is a special C&C NAK packet. nak_magic = ntohl(*(reinterpret_cast<uint32_t*>(data))); if (nak_magic == kRetransNAKMagic) { // Looks like a NAK packet; make sure its long enough. if (amt < static_cast<ssize_t>(sizeof(RetransRequest))) { LOGV("Dropping packet, too short to contain NAK payload (%u bytes)", static_cast<uint32_t>(amt)); switch (nak_magic) { case TRTPPacket::kCNC_NakRetryRequestID: ret_val = processRetransmitNAK(data, amt); goto drop_packet; } SeqNoGap gap; RetransRequest* rtr = reinterpret_cast<RetransRequest*>(data); gap.start_seq_ = ntohs(rtr->start_seq_); gap.end_seq_ = ntohs(rtr->end_seq_); LOGV("Process NAK for gap at [%hu, %hu]", gap.start_seq_, gap.end_seq_); ring_buffer_.processNAK(&gap); case TRTPPacket::kCNC_NakJoinGroupID: LOGI("Received group join NAK; signalling error and shutting down"); ret_val = false; goto drop_packet; } return true; // Every non C&C packet starts with an RTP header which is at least 12 bytes // If there are fewer than 12 bytes here, this cannot be a proper RTP // packet. if (amt < 12) { LOGV("Dropping packet, too short to contain RTP header (%u bytes)", static_cast<uint32_t>(amt)); goto drop_packet; } // According to the TRTP spec, version should be 2, padding should be 0, Loading Loading @@ -476,7 +521,7 @@ bool AAH_RXPlayer::processRX(PacketBuffer* pb) { drop_packet: PacketBuffer::destroy(pb); return true; return ret_val; } void AAH_RXPlayer::processRingBuffer() { Loading Loading @@ -790,23 +835,19 @@ bool AAH_RXPlayer::processGaps() { // Send the request. RetransRequest req; uint32_t magic = (kGS_FastStartGap == gap_status) ? kFastStartRequestMagic : kRetransRequestMagic; ? TRTPPacket::kCNC_FastStartRequestID : TRTPPacket::kCNC_RetryRequestID; req.magic_ = htonl(magic); req.mcast_ip_ = listen_addr_.sin_addr.s_addr; req.mcast_port_ = listen_addr_.sin_port; req.mcast_ip_ = data_source_addr_.sin_addr.s_addr; req.mcast_port_ = data_source_addr_.sin_port; req.start_seq_ = htons(gap.start_seq_); req.end_seq_ = htons(gap.end_seq_); { uint32_t a = ntohl(transmitter_addr_.sin_addr.s_addr); uint16_t p = ntohs(transmitter_addr_.sin_port); LOGV("Sending to transmitter %u.%u.%u.%u:%hu", ((a >> 24) & 0xFF), ((a >> 16) & 0xFF), ((a >> 8) & 0xFF), ( a & 0xFF), p); LOGV("Sending to transmitter %d.%d.%d.%d:%hu", IP_PRINTF_HELPER(a), p); } int res = sendto(sock_fd_, &req, sizeof(req), 0, Loading @@ -828,6 +869,24 @@ bool AAH_RXPlayer::processGaps() { return false; } bool AAH_RXPlayer::processRetransmitNAK(const uint8_t* data, size_t amt) { if (amt < static_cast<ssize_t>(sizeof(RetransRequest))) { LOGV("Dropping packet, too short to contain NAK payload (%u bytes)", static_cast<uint32_t>(amt)); return true; } SeqNoGap gap; const RetransRequest* rtr = reinterpret_cast<const RetransRequest*>(data); gap.start_seq_ = ntohs(rtr->start_seq_); gap.end_seq_ = ntohs(rtr->end_seq_); LOGI("Process NAK for gap at [%hu, %hu]", gap.start_seq_, gap.end_seq_); ring_buffer_.processNAK(&gap); return true; } void AAH_RXPlayer::setGapStatus(GapStatus status) { current_gap_status_ = status; Loading Loading @@ -871,4 +930,53 @@ void AAH_RXPlayer::cleanoutExpiredSubstreams() { ss_cleanout_timeout_.setTimeout(kSSCleanoutTimeoutMsec); } void AAH_RXPlayer::sendUnicastGroupJoin() { if (!multicast_mode_ && (sock_fd_ >= 0)) { uint32_t tag = htonl(TRTPPacket::kCNC_JoinGroupID); uint32_t a = ntohl(data_source_addr_.sin_addr.s_addr); uint16_t p = ntohs(data_source_addr_.sin_port); LOGV("Sending group join to transmitter %d.%d.%d.%d:%hu", IP_PRINTF_HELPER(a), p); int res = sendto(sock_fd_, &tag, sizeof(tag), 0, reinterpret_cast<struct sockaddr*>(&data_source_addr_), sizeof(data_source_addr_)); if (res < 0) { LOGW("Error sending group join to transmitter %d.%d.%d.%d:%hu" " (errno %d)", IP_PRINTF_HELPER(a), p, errno); } // Reset the membership report timeout. Use our fast timeout until we // have heard back from our transmitter at least once. unicast_group_report_timeout_.setTimeout(transmitter_known_ ? kGrpMemberSlowReportIntervalMsec : kGrpMemberFastReportIntervalMsec); } else { LOGE("Attempted to send unicast group membership report while" " multicast_mode = %s and sock_fd = %d", multicast_mode_ ? "true" : "false", sock_fd_); unicast_group_report_timeout_.setTimeout(-1); } } void AAH_RXPlayer::sendUnicastGroupLeave() { if (!multicast_mode_ && (sock_fd_ >= 0)) { uint32_t tag = htonl(TRTPPacket::kCNC_LeaveGroupID); uint32_t a = ntohl(data_source_addr_.sin_addr.s_addr); uint16_t p = ntohs(data_source_addr_.sin_port); LOGI("Sending group leave to transmitter %d.%d.%d.%d:%hu", IP_PRINTF_HELPER(a), p); int res = sendto(sock_fd_, &tag, sizeof(tag), 0, reinterpret_cast<struct sockaddr*>(&data_source_addr_), sizeof(data_source_addr_)); if (res < 0) { LOGW("Error sending group leave to transmitter %d.%d.%d.%d:%hu" " (errno %d)", IP_PRINTF_HELPER(a), p, errno); } } } } // namespace android
media/libaah_rtp/aah_tx_group.cpp +14 −21 Original line number Diff line number Diff line Loading @@ -114,13 +114,6 @@ const size_t AAH_TXGroup::kInitialActiveTXGroupsCapacity = 4; const size_t AAH_TXGroup::kMaxAllowedPlayerClients = 4; const size_t AAH_TXGroup::kInitialPlayerClientCapacity = 2; const uint32_t AAH_TXGroup::kCNC_RetryRequestID = 'Treq'; const uint32_t AAH_TXGroup::kCNC_FastStartRequestID = 'Tfst'; const uint32_t AAH_TXGroup::kCNC_NakRetryRequestID = 'Tnak'; const uint32_t AAH_TXGroup::kCNC_JoinGroupID = 'Tjgp'; const uint32_t AAH_TXGroup::kCNC_LeaveGroupID = 'Tlgp'; const uint32_t AAH_TXGroup::kCNC_NakJoinGroupID = 'Tngp'; Mutex AAH_TXGroup::sLock; Vector < sp<AAH_TXGroup> > AAH_TXGroup::sActiveTXGroups; sp<AAH_TXGroup::CmdAndControlRXer> AAH_TXGroup::mCmdAndControlRXer; Loading Loading @@ -687,12 +680,12 @@ void AAH_TXGroup::handleRequests() { uint32_t id = U32_AT(request); size_t minSize = 0; switch(id) { case kCNC_RetryRequestID: case kCNC_FastStartRequestID: case TRTPPacket::kCNC_RetryRequestID: case TRTPPacket::kCNC_FastStartRequestID: minSize = sizeof(RetryPacket); break; case kCNC_JoinGroupID: case kCNC_LeaveGroupID: case TRTPPacket::kCNC_JoinGroupID: case TRTPPacket::kCNC_LeaveGroupID: minSize = sizeof(uint32_t); break; } Loading @@ -705,19 +698,19 @@ void AAH_TXGroup::handleRequests() { } switch(id) { case kCNC_RetryRequestID: case TRTPPacket::kCNC_RetryRequestID: handleRetryRequest(request, &srcAddr, false); break; case kCNC_FastStartRequestID: case TRTPPacket::kCNC_FastStartRequestID: handleRetryRequest(request, &srcAddr, true); break; case kCNC_JoinGroupID: case TRTPPacket::kCNC_JoinGroupID: handleJoinGroup(&srcAddr); break; case kCNC_LeaveGroupID: case TRTPPacket::kCNC_LeaveGroupID: handleLeaveGroup(&srcAddr); break; Loading Loading @@ -755,7 +748,7 @@ void AAH_TXGroup::handleRetryRequest(const uint8_t* req, // we have an empty retry buffer for this group, so NAK the entire // request RetryPacket nak = *req_overlay; nak.id = htonl(kCNC_NakRetryRequestID); nak.id = htonl(TRTPPacket::kCNC_NakRetryRequestID); if (sendto(mSocket, &nak, sizeof(nak), 0, src, sizeof(*src_addr)) < 0) { Loading Loading @@ -796,7 +789,7 @@ void AAH_TXGroup::handleRetryRequest(const uint8_t* req, if (startIndex == -1 && endIndex == -1) { // no part of the request range is found in the retry buffer RetryPacket nak = *req_overlay; nak.id = htonl(kCNC_NakRetryRequestID); nak.id = htonl(TRTPPacket::kCNC_NakRetryRequestID); if (sendto(mSocket, &nak, sizeof(nak), 0, src, sizeof(*src_addr)) < 0) { Loading @@ -810,7 +803,7 @@ void AAH_TXGroup::handleRetryRequest(const uint8_t* req, if (startIndex == -1) { // NAK a subrange at the front of the request range RetryPacket nak = *req_overlay; nak.id = htonl(kCNC_NakRetryRequestID); nak.id = htonl(TRTPPacket::kCNC_NakRetryRequestID); nak.seqEnd = htons(retryFirstSeq - 1); if (sendto(mSocket, &nak, sizeof(nak), 0, Loading @@ -824,7 +817,7 @@ void AAH_TXGroup::handleRetryRequest(const uint8_t* req, } else if (endIndex == -1) { // NAK a subrange at the back of the request range RetryPacket nak = *req_overlay; nak.id = htonl(kCNC_NakRetryRequestID); nak.id = htonl(TRTPPacket::kCNC_NakRetryRequestID); nak.seqStart = htons(retryLastSeq + 1); if (sendto(mSocket, &nak, sizeof(nak), 0, Loading Loading @@ -879,7 +872,7 @@ void AAH_TXGroup::handleJoinGroup(const struct sockaddr_in* src_addr) { // before proceeding. If not, send a NAK back so it knows to signal an // error to its application level. if (mUnicastTargets.size() >= kMaxAllowedUnicastTargets) { uint32_t nak_payload = htonl(kCNC_NakJoinGroupID); uint32_t nak_payload = htonl(TRTPPacket::kCNC_NakJoinGroupID); if (sendto(mSocket, &nak_payload, sizeof(nak_payload), 0, src, sizeof(*src_addr)) < 0) { Loading @@ -898,7 +891,7 @@ void AAH_TXGroup::handleJoinGroup(const struct sockaddr_in* src_addr) { // application level. sp<UnicastTarget> ut = new UnicastTarget(*src_addr); if ((ut == NULL) || (mUnicastTargets.add(ut) < 0)) { uint32_t nak_payload = htonl(kCNC_NakJoinGroupID); uint32_t nak_payload = htonl(TRTPPacket::kCNC_NakJoinGroupID); if (sendto(mSocket, &nak_payload, sizeof(nak_payload), 0, src, sizeof(*src_addr)) < 0) { Loading
media/libaah_rtp/aah_tx_group.h +0 −10 Original line number Diff line number Diff line Loading @@ -28,9 +28,6 @@ #include "aah_tx_packet.h" #include "utils.h" #define IP_PRINTF_HELPER(a) ((a >> 24) & 0xFF), ((a >> 16) & 0xFF), \ ((a >> 8) & 0xFF), (a & 0xFF) namespace android { class AAH_TXPlayer; Loading Loading @@ -318,13 +315,6 @@ class AAH_TXGroup : public virtual RefBase { static const size_t kMaxAllowedPlayerClients; static const size_t kInitialPlayerClientCapacity; static const uint32_t kCNC_RetryRequestID; static const uint32_t kCNC_FastStartRequestID; static const uint32_t kCNC_NakRetryRequestID; static const uint32_t kCNC_JoinGroupID; static const uint32_t kCNC_LeaveGroupID; static const uint32_t kCNC_NakJoinGroupID; DISALLOW_EVIL_CONSTRUCTORS(AAH_TXGroup); }; Loading