Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2010 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
Andreas Huber | 6e3fa44 | 2010-09-21 13:13:15 -0700 | [diff] [blame] | 17 | //#define LOG_NDEBUG 0 |
| 18 | #define LOG_TAG "ARTPSource" |
| 19 | #include <utils/Log.h> |
| 20 | |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 21 | #include "ARTPSource.h" |
| 22 | |
Andreas Huber | 57648e4 | 2010-08-04 10:14:30 -0700 | [diff] [blame] | 23 | #include "AAMRAssembler.h" |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 24 | #include "AAVCAssembler.h" |
Andreas Huber | 57648e4 | 2010-08-04 10:14:30 -0700 | [diff] [blame] | 25 | #include "AH263Assembler.h" |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 26 | #include "AMPEG4AudioAssembler.h" |
Andreas Huber | a979ad6 | 2010-08-19 10:56:15 -0700 | [diff] [blame] | 27 | #include "AMPEG4ElementaryAssembler.h" |
Andreas Huber | b672373 | 2011-02-22 16:25:00 -0800 | [diff] [blame] | 28 | #include "ARawAudioAssembler.h" |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 29 | #include "ASessionDescription.h" |
| 30 | |
| 31 | #include <media/stagefright/foundation/ABuffer.h> |
| 32 | #include <media/stagefright/foundation/ADebug.h> |
| 33 | #include <media/stagefright/foundation/AMessage.h> |
| 34 | |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 35 | namespace android { |
| 36 | |
Andreas Huber | 57648e4 | 2010-08-04 10:14:30 -0700 | [diff] [blame] | 37 | static const uint32_t kSourceID = 0xdeadbeef; |
| 38 | |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 39 | ARTPSource::ARTPSource( |
| 40 | uint32_t id, |
| 41 | const sp<ASessionDescription> &sessionDesc, size_t index, |
| 42 | const sp<AMessage> ¬ify) |
| 43 | : mID(id), |
| 44 | mHighestSeqNumber(0), |
| 45 | mNumBuffersReceived(0), |
Andreas Huber | 57648e4 | 2010-08-04 10:14:30 -0700 | [diff] [blame] | 46 | mLastNTPTime(0), |
| 47 | mLastNTPTimeUpdateUs(0), |
| 48 | mIssueFIRRequests(false), |
| 49 | mLastFIRRequestUs(-1), |
Andreas Huber | b2934b1 | 2011-02-08 10:18:41 -0800 | [diff] [blame] | 50 | mNextFIRSeqNo((rand() * 256.0) / RAND_MAX), |
| 51 | mNotify(notify) { |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 52 | unsigned long PT; |
| 53 | AString desc; |
| 54 | AString params; |
| 55 | sessionDesc->getFormatType(index, &PT, &desc, ¶ms); |
| 56 | |
| 57 | if (!strncmp(desc.c_str(), "H264/", 5)) { |
| 58 | mAssembler = new AAVCAssembler(notify); |
Andreas Huber | 57648e4 | 2010-08-04 10:14:30 -0700 | [diff] [blame] | 59 | mIssueFIRRequests = true; |
| 60 | } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) { |
Andreas Huber | b0d25a0 | 2010-10-27 13:59:59 -0700 | [diff] [blame] | 61 | mAssembler = new AMPEG4AudioAssembler(notify, params); |
Andreas Huber | 57648e4 | 2010-08-04 10:14:30 -0700 | [diff] [blame] | 62 | } else if (!strncmp(desc.c_str(), "H263-1998/", 10) |
| 63 | || !strncmp(desc.c_str(), "H263-2000/", 10)) { |
| 64 | mAssembler = new AH263Assembler(notify); |
Andreas Huber | 3eaa300 | 2010-08-05 09:22:25 -0700 | [diff] [blame] | 65 | mIssueFIRRequests = true; |
Andreas Huber | 57648e4 | 2010-08-04 10:14:30 -0700 | [diff] [blame] | 66 | } else if (!strncmp(desc.c_str(), "AMR/", 4)) { |
| 67 | mAssembler = new AAMRAssembler(notify, false /* isWide */, params); |
| 68 | } else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) { |
| 69 | mAssembler = new AAMRAssembler(notify, true /* isWide */, params); |
Andreas Huber | e536f80 | 2010-08-31 14:25:36 -0700 | [diff] [blame] | 70 | } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8) |
Andreas Huber | 0407269 | 2011-02-15 10:39:48 -0800 | [diff] [blame] | 71 | || !strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) { |
Andreas Huber | e536f80 | 2010-08-31 14:25:36 -0700 | [diff] [blame] | 72 | mAssembler = new AMPEG4ElementaryAssembler(notify, desc, params); |
Andreas Huber | a979ad6 | 2010-08-19 10:56:15 -0700 | [diff] [blame] | 73 | mIssueFIRRequests = true; |
Andreas Huber | b672373 | 2011-02-22 16:25:00 -0800 | [diff] [blame] | 74 | } else if (ARawAudioAssembler::Supports(desc.c_str())) { |
| 75 | mAssembler = new ARawAudioAssembler(notify, desc.c_str(), params); |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 76 | } else { |
| 77 | TRESPASS(); |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | static uint32_t AbsDiff(uint32_t seq1, uint32_t seq2) { |
| 82 | return seq1 > seq2 ? seq1 - seq2 : seq2 - seq1; |
| 83 | } |
| 84 | |
| 85 | void ARTPSource::processRTPPacket(const sp<ABuffer> &buffer) { |
Andreas Huber | b2934b1 | 2011-02-08 10:18:41 -0800 | [diff] [blame] | 86 | if (queuePacket(buffer) && mAssembler != NULL) { |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 87 | mAssembler->onPacketReceived(this); |
| 88 | } |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 89 | } |
| 90 | |
| 91 | void ARTPSource::timeUpdate(uint32_t rtpTime, uint64_t ntpTime) { |
Andreas Huber | 57648e4 | 2010-08-04 10:14:30 -0700 | [diff] [blame] | 92 | mLastNTPTime = ntpTime; |
| 93 | mLastNTPTimeUpdateUs = ALooper::GetNowUs(); |
| 94 | |
Andreas Huber | b2934b1 | 2011-02-08 10:18:41 -0800 | [diff] [blame] | 95 | sp<AMessage> notify = mNotify->dup(); |
| 96 | notify->setInt32("time-update", true); |
| 97 | notify->setInt32("rtp-time", rtpTime); |
| 98 | notify->setInt64("ntp-time", ntpTime); |
| 99 | notify->post(); |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) { |
| 103 | uint32_t seqNum = (uint32_t)buffer->int32Data(); |
| 104 | |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 105 | if (mNumBuffersReceived++ == 0) { |
| 106 | mHighestSeqNumber = seqNum; |
| 107 | mQueue.push_back(buffer); |
| 108 | return true; |
| 109 | } |
| 110 | |
| 111 | // Only the lower 16-bit of the sequence numbers are transmitted, |
| 112 | // derive the high-order bits by choosing the candidate closest |
| 113 | // to the highest sequence number (extended to 32 bits) received so far. |
| 114 | |
| 115 | uint32_t seq1 = seqNum | (mHighestSeqNumber & 0xffff0000); |
| 116 | uint32_t seq2 = seqNum | ((mHighestSeqNumber & 0xffff0000) + 0x10000); |
| 117 | uint32_t seq3 = seqNum | ((mHighestSeqNumber & 0xffff0000) - 0x10000); |
| 118 | uint32_t diff1 = AbsDiff(seq1, mHighestSeqNumber); |
| 119 | uint32_t diff2 = AbsDiff(seq2, mHighestSeqNumber); |
| 120 | uint32_t diff3 = AbsDiff(seq3, mHighestSeqNumber); |
| 121 | |
| 122 | if (diff1 < diff2) { |
| 123 | if (diff1 < diff3) { |
| 124 | // diff1 < diff2 ^ diff1 < diff3 |
| 125 | seqNum = seq1; |
| 126 | } else { |
| 127 | // diff3 <= diff1 < diff2 |
| 128 | seqNum = seq3; |
| 129 | } |
| 130 | } else if (diff2 < diff3) { |
| 131 | // diff2 <= diff1 ^ diff2 < diff3 |
| 132 | seqNum = seq2; |
| 133 | } else { |
| 134 | // diff3 <= diff2 <= diff1 |
| 135 | seqNum = seq3; |
| 136 | } |
| 137 | |
| 138 | if (seqNum > mHighestSeqNumber) { |
| 139 | mHighestSeqNumber = seqNum; |
| 140 | } |
| 141 | |
| 142 | buffer->setInt32Data(seqNum); |
| 143 | |
| 144 | List<sp<ABuffer> >::iterator it = mQueue.begin(); |
| 145 | while (it != mQueue.end() && (uint32_t)(*it)->int32Data() < seqNum) { |
| 146 | ++it; |
| 147 | } |
| 148 | |
| 149 | if (it != mQueue.end() && (uint32_t)(*it)->int32Data() == seqNum) { |
Andreas Huber | 6e3fa44 | 2010-09-21 13:13:15 -0700 | [diff] [blame] | 150 | LOGW("Discarding duplicate buffer"); |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 151 | return false; |
| 152 | } |
| 153 | |
| 154 | mQueue.insert(it, buffer); |
| 155 | |
| 156 | return true; |
| 157 | } |
| 158 | |
Andreas Huber | 57648e4 | 2010-08-04 10:14:30 -0700 | [diff] [blame] | 159 | void ARTPSource::byeReceived() { |
| 160 | mAssembler->onByeReceived(); |
| 161 | } |
| 162 | |
| 163 | void ARTPSource::addFIR(const sp<ABuffer> &buffer) { |
| 164 | if (!mIssueFIRRequests) { |
| 165 | return; |
| 166 | } |
| 167 | |
| 168 | int64_t nowUs = ALooper::GetNowUs(); |
| 169 | if (mLastFIRRequestUs >= 0 && mLastFIRRequestUs + 5000000ll > nowUs) { |
| 170 | // Send FIR requests at most every 5 secs. |
| 171 | return; |
| 172 | } |
| 173 | |
| 174 | mLastFIRRequestUs = nowUs; |
| 175 | |
| 176 | if (buffer->size() + 20 > buffer->capacity()) { |
Andreas Huber | 6e3fa44 | 2010-09-21 13:13:15 -0700 | [diff] [blame] | 177 | LOGW("RTCP buffer too small to accomodate FIR."); |
Andreas Huber | 57648e4 | 2010-08-04 10:14:30 -0700 | [diff] [blame] | 178 | return; |
| 179 | } |
| 180 | |
| 181 | uint8_t *data = buffer->data() + buffer->size(); |
| 182 | |
| 183 | data[0] = 0x80 | 4; |
| 184 | data[1] = 206; // PSFB |
| 185 | data[2] = 0; |
| 186 | data[3] = 4; |
| 187 | data[4] = kSourceID >> 24; |
| 188 | data[5] = (kSourceID >> 16) & 0xff; |
| 189 | data[6] = (kSourceID >> 8) & 0xff; |
| 190 | data[7] = kSourceID & 0xff; |
| 191 | |
| 192 | data[8] = 0x00; // SSRC of media source (unused) |
| 193 | data[9] = 0x00; |
| 194 | data[10] = 0x00; |
| 195 | data[11] = 0x00; |
| 196 | |
| 197 | data[12] = mID >> 24; |
| 198 | data[13] = (mID >> 16) & 0xff; |
| 199 | data[14] = (mID >> 8) & 0xff; |
| 200 | data[15] = mID & 0xff; |
| 201 | |
| 202 | data[16] = mNextFIRSeqNo++; // Seq Nr. |
| 203 | |
| 204 | data[17] = 0x00; // Reserved |
| 205 | data[18] = 0x00; |
| 206 | data[19] = 0x00; |
| 207 | |
| 208 | buffer->setRange(buffer->offset(), buffer->size() + 20); |
| 209 | |
Andreas Huber | 6e3fa44 | 2010-09-21 13:13:15 -0700 | [diff] [blame] | 210 | LOGV("Added FIR request."); |
Andreas Huber | 57648e4 | 2010-08-04 10:14:30 -0700 | [diff] [blame] | 211 | } |
| 212 | |
| 213 | void ARTPSource::addReceiverReport(const sp<ABuffer> &buffer) { |
| 214 | if (buffer->size() + 32 > buffer->capacity()) { |
Andreas Huber | 6e3fa44 | 2010-09-21 13:13:15 -0700 | [diff] [blame] | 215 | LOGW("RTCP buffer too small to accomodate RR."); |
Andreas Huber | 57648e4 | 2010-08-04 10:14:30 -0700 | [diff] [blame] | 216 | return; |
| 217 | } |
| 218 | |
| 219 | uint8_t *data = buffer->data() + buffer->size(); |
| 220 | |
| 221 | data[0] = 0x80 | 1; |
| 222 | data[1] = 201; // RR |
| 223 | data[2] = 0; |
| 224 | data[3] = 7; |
| 225 | data[4] = kSourceID >> 24; |
| 226 | data[5] = (kSourceID >> 16) & 0xff; |
| 227 | data[6] = (kSourceID >> 8) & 0xff; |
| 228 | data[7] = kSourceID & 0xff; |
| 229 | |
| 230 | data[8] = mID >> 24; |
| 231 | data[9] = (mID >> 16) & 0xff; |
| 232 | data[10] = (mID >> 8) & 0xff; |
| 233 | data[11] = mID & 0xff; |
| 234 | |
| 235 | data[12] = 0x00; // fraction lost |
| 236 | |
| 237 | data[13] = 0x00; // cumulative lost |
| 238 | data[14] = 0x00; |
| 239 | data[15] = 0x00; |
| 240 | |
| 241 | data[16] = mHighestSeqNumber >> 24; |
| 242 | data[17] = (mHighestSeqNumber >> 16) & 0xff; |
| 243 | data[18] = (mHighestSeqNumber >> 8) & 0xff; |
| 244 | data[19] = mHighestSeqNumber & 0xff; |
| 245 | |
| 246 | data[20] = 0x00; // Interarrival jitter |
| 247 | data[21] = 0x00; |
| 248 | data[22] = 0x00; |
| 249 | data[23] = 0x00; |
| 250 | |
| 251 | uint32_t LSR = 0; |
| 252 | uint32_t DLSR = 0; |
| 253 | if (mLastNTPTime != 0) { |
| 254 | LSR = (mLastNTPTime >> 16) & 0xffffffff; |
| 255 | |
| 256 | DLSR = (uint32_t) |
| 257 | ((ALooper::GetNowUs() - mLastNTPTimeUpdateUs) * 65536.0 / 1E6); |
| 258 | } |
| 259 | |
| 260 | data[24] = LSR >> 24; |
| 261 | data[25] = (LSR >> 16) & 0xff; |
| 262 | data[26] = (LSR >> 8) & 0xff; |
| 263 | data[27] = LSR & 0xff; |
| 264 | |
| 265 | data[28] = DLSR >> 24; |
| 266 | data[29] = (DLSR >> 16) & 0xff; |
| 267 | data[30] = (DLSR >> 8) & 0xff; |
| 268 | data[31] = DLSR & 0xff; |
| 269 | |
| 270 | buffer->setRange(buffer->offset(), buffer->size() + 32); |
| 271 | } |
| 272 | |
Andreas Huber | 7a747b8 | 2010-06-07 15:19:40 -0700 | [diff] [blame] | 273 | } // namespace android |
| 274 | |
| 275 | |