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 17 //#define LOG_NDEBUG 0 18 #define LOG_TAG "AMPEG4ElementaryAssembler" 19 #include <utils/Log.h> 20 21 #include "AMPEG4ElementaryAssembler.h" 22 23 #include "ARTPSource.h" 24 #include "ASessionDescription.h" 25 26 #include <media/stagefright/foundation/ABitReader.h> 27 #include <media/stagefright/foundation/ABuffer.h> 28 #include <media/stagefright/foundation/ADebug.h> 29 #include <media/stagefright/foundation/AMessage.h> 30 #include <media/stagefright/foundation/hexdump.h> 31 #include <media/stagefright/Utils.h> 32 33 #include <ctype.h> 34 #include <stdint.h> 35 36 namespace android { 37 38 static bool GetAttribute(const char *s, const char *key, AString *value) { 39 value->clear(); 40 41 size_t keyLen = strlen(key); 42 43 for (;;) { 44 while (isspace(*s)) { 45 ++s; 46 } 47 48 const char *colonPos = strchr(s, ';'); 49 50 size_t len = 51 (colonPos == NULL) ? strlen(s) : colonPos - s; 52 53 if (len >= keyLen + 1 && s[keyLen] == '=' 54 && !strncasecmp(s, key, keyLen)) { 55 value->setTo(&s[keyLen + 1], len - keyLen - 1); 56 return true; 57 } 58 59 if (colonPos == NULL) { 60 return false; 61 } 62 63 s = colonPos + 1; 64 } 65 } 66 67 static bool GetIntegerAttribute( 68 const char *s, const char *key, unsigned *x) { 69 *x = 0; 70 71 AString val; 72 if (!GetAttribute(s, key, &val)) { 73 return false; 74 } 75 76 s = val.c_str(); 77 char *end; 78 unsigned y = strtoul(s, &end, 10); 79 80 if (end == s || *end != '\0') { 81 return false; 82 } 83 84 *x = y; 85 86 return true; 87 } 88 89 static bool GetSampleRateIndex(int32_t sampleRate, size_t *tableIndex) { 90 static const int32_t kSampleRateTable[] = { 91 96000, 88200, 64000, 48000, 44100, 32000, 92 24000, 22050, 16000, 12000, 11025, 8000 93 }; 94 const size_t kNumSampleRates = 95 sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]); 96 97 *tableIndex = 0; 98 for (size_t index = 0; index < kNumSampleRates; ++index) { 99 if (sampleRate == kSampleRateTable[index]) { 100 *tableIndex = index; 101 return true; 102 } 103 } 104 105 return false; 106 } 107 108 // static 109 AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler( 110 const sp<AMessage> ¬ify, const AString &desc, const AString ¶ms) 111 : mNotifyMsg(notify), 112 mIsGeneric(false), 113 mParams(params), 114 mSizeLength(0), 115 mIndexLength(0), 116 mIndexDeltaLength(0), 117 mCTSDeltaLength(0), 118 mDTSDeltaLength(0), 119 mRandomAccessIndication(false), 120 mStreamStateIndication(0), 121 mAuxiliaryDataSizeLength(0), 122 mHasAUHeader(false), 123 mChannelConfig(0), 124 mSampleRateIndex(0), 125 mAccessUnitRTPTime(0), 126 mNextExpectedSeqNoValid(false), 127 mNextExpectedSeqNo(0), 128 mAccessUnitDamaged(false) { 129 mIsGeneric = !strncasecmp(desc.c_str(),"mpeg4-generic/", 14); 130 131 if (mIsGeneric) { 132 AString value; 133 CHECK(GetAttribute(params.c_str(), "mode", &value)); 134 135 if (!GetIntegerAttribute(params.c_str(), "sizeLength", &mSizeLength)) { 136 mSizeLength = 0; 137 } 138 139 if (!GetIntegerAttribute( 140 params.c_str(), "indexLength", &mIndexLength)) { 141 mIndexLength = 0; 142 } 143 144 if (!GetIntegerAttribute( 145 params.c_str(), "indexDeltaLength", &mIndexDeltaLength)) { 146 mIndexDeltaLength = 0; 147 } 148 149 if (!GetIntegerAttribute( 150 params.c_str(), "CTSDeltaLength", &mCTSDeltaLength)) { 151 mCTSDeltaLength = 0; 152 } 153 154 if (!GetIntegerAttribute( 155 params.c_str(), "DTSDeltaLength", &mDTSDeltaLength)) { 156 mDTSDeltaLength = 0; 157 } 158 159 unsigned x; 160 if (!GetIntegerAttribute( 161 params.c_str(), "randomAccessIndication", &x)) { 162 mRandomAccessIndication = false; 163 } else { 164 CHECK(x == 0 || x == 1); 165 mRandomAccessIndication = (x != 0); 166 } 167 168 if (!GetIntegerAttribute( 169 params.c_str(), "streamStateIndication", 170 &mStreamStateIndication)) { 171 mStreamStateIndication = 0; 172 } 173 174 if (!GetIntegerAttribute( 175 params.c_str(), "auxiliaryDataSizeLength", 176 &mAuxiliaryDataSizeLength)) { 177 mAuxiliaryDataSizeLength = 0; 178 } 179 180 mHasAUHeader = 181 mSizeLength > 0 182 || mIndexLength > 0 183 || mIndexDeltaLength > 0 184 || mCTSDeltaLength > 0 185 || mDTSDeltaLength > 0 186 || mRandomAccessIndication 187 || mStreamStateIndication > 0; 188 189 int32_t sampleRate, numChannels; 190 ASessionDescription::ParseFormatDesc( 191 desc.c_str(), &sampleRate, &numChannels); 192 193 mChannelConfig = numChannels; 194 CHECK(GetSampleRateIndex(sampleRate, &mSampleRateIndex)); 195 } 196 } 197 198 AMPEG4ElementaryAssembler::~AMPEG4ElementaryAssembler() { 199 } 200 201 struct AUHeader { 202 unsigned mSize; 203 unsigned mSerial; 204 }; 205 206 ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket( 207 const sp<ARTPSource> &source) { 208 List<sp<ABuffer> > *queue = source->queue(); 209 210 if (queue->empty()) { 211 return NOT_ENOUGH_DATA; 212 } 213 214 if (mNextExpectedSeqNoValid) { 215 List<sp<ABuffer> >::iterator it = queue->begin(); 216 while (it != queue->end()) { 217 if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) { 218 break; 219 } 220 221 it = queue->erase(it); 222 } 223 224 if (queue->empty()) { 225 return NOT_ENOUGH_DATA; 226 } 227 } 228 229 sp<ABuffer> buffer = *queue->begin(); 230 231 if (!mNextExpectedSeqNoValid) { 232 mNextExpectedSeqNoValid = true; 233 mNextExpectedSeqNo = (uint32_t)buffer->int32Data(); 234 } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) { 235 ALOGV("Not the sequence number I expected"); 236 237 return WRONG_SEQUENCE_NUMBER; 238 } 239 240 uint32_t rtpTime; 241 CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime)); 242 243 if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) { 244 submitAccessUnit(); 245 } 246 mAccessUnitRTPTime = rtpTime; 247 248 if (!mIsGeneric) { 249 mPackets.push_back(buffer); 250 } else { 251 // hexdump(buffer->data(), buffer->size()); 252 253 CHECK_GE(buffer->size(), 2u); 254 unsigned AU_headers_length = U16_AT(buffer->data()); // in bits 255 256 CHECK_GE(buffer->size(), 2 + (AU_headers_length + 7) / 8); 257 258 List<AUHeader> headers; 259 260 ABitReader bits(buffer->data() + 2, buffer->size() - 2); 261 unsigned numBitsLeft = AU_headers_length; 262 263 unsigned AU_serial = 0; 264 for (;;) { 265 if (numBitsLeft < mSizeLength) { break; } 266 267 unsigned AU_size = bits.getBits(mSizeLength); 268 numBitsLeft -= mSizeLength; 269 270 size_t n = headers.empty() ? mIndexLength : mIndexDeltaLength; 271 if (numBitsLeft < n) { break; } 272 273 unsigned AU_index = bits.getBits(n); 274 numBitsLeft -= n; 275 276 if (headers.empty()) { 277 AU_serial = AU_index; 278 } else { 279 AU_serial += 1 + AU_index; 280 } 281 282 if (mCTSDeltaLength > 0) { 283 if (numBitsLeft < 1) { 284 break; 285 } 286 --numBitsLeft; 287 if (bits.getBits(1)) { 288 if (numBitsLeft < mCTSDeltaLength) { 289 break; 290 } 291 bits.skipBits(mCTSDeltaLength); 292 numBitsLeft -= mCTSDeltaLength; 293 } 294 } 295 296 if (mDTSDeltaLength > 0) { 297 if (numBitsLeft < 1) { 298 break; 299 } 300 --numBitsLeft; 301 if (bits.getBits(1)) { 302 if (numBitsLeft < mDTSDeltaLength) { 303 break; 304 } 305 bits.skipBits(mDTSDeltaLength); 306 numBitsLeft -= mDTSDeltaLength; 307 } 308 } 309 310 if (mRandomAccessIndication) { 311 if (numBitsLeft < 1) { 312 break; 313 } 314 bits.skipBits(1); 315 --numBitsLeft; 316 } 317 318 if (mStreamStateIndication > 0) { 319 if (numBitsLeft < mStreamStateIndication) { 320 break; 321 } 322 bits.skipBits(mStreamStateIndication); 323 } 324 325 AUHeader header; 326 header.mSize = AU_size; 327 header.mSerial = AU_serial; 328 headers.push_back(header); 329 } 330 331 size_t offset = 2 + (AU_headers_length + 7) / 8; 332 333 if (mAuxiliaryDataSizeLength > 0) { 334 ABitReader bits(buffer->data() + offset, buffer->size() - offset); 335 336 unsigned auxSize = bits.getBits(mAuxiliaryDataSizeLength); 337 338 offset += (mAuxiliaryDataSizeLength + auxSize + 7) / 8; 339 } 340 341 for (List<AUHeader>::iterator it = headers.begin(); 342 it != headers.end(); ++it) { 343 const AUHeader &header = *it; 344 345 CHECK_LE(offset + header.mSize, buffer->size()); 346 347 sp<ABuffer> accessUnit = new ABuffer(header.mSize); 348 memcpy(accessUnit->data(), buffer->data() + offset, header.mSize); 349 350 offset += header.mSize; 351 352 CopyTimes(accessUnit, buffer); 353 mPackets.push_back(accessUnit); 354 } 355 356 CHECK_EQ(offset, buffer->size()); 357 } 358 359 queue->erase(queue->begin()); 360 ++mNextExpectedSeqNo; 361 362 return OK; 363 } 364 365 void AMPEG4ElementaryAssembler::submitAccessUnit() { 366 CHECK(!mPackets.empty()); 367 368 ALOGV("Access unit complete (%d nal units)", mPackets.size()); 369 370 sp<ABuffer> accessUnit; 371 372 if (mIsGeneric) { 373 accessUnit = MakeADTSCompoundFromAACFrames( 374 OMX_AUDIO_AACObjectLC - 1, 375 mSampleRateIndex, 376 mChannelConfig, 377 mPackets); 378 } else { 379 accessUnit = MakeCompoundFromPackets(mPackets); 380 } 381 382 #if 0 383 printf(mAccessUnitDamaged ? "X" : "."); 384 fflush(stdout); 385 #endif 386 387 if (mAccessUnitDamaged) { 388 accessUnit->meta()->setInt32("damaged", true); 389 } 390 391 mPackets.clear(); 392 mAccessUnitDamaged = false; 393 394 sp<AMessage> msg = mNotifyMsg->dup(); 395 msg->setBuffer("access-unit", accessUnit); 396 msg->post(); 397 } 398 399 ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::assembleMore( 400 const sp<ARTPSource> &source) { 401 AssemblyStatus status = addPacket(source); 402 if (status == MALFORMED_PACKET) { 403 mAccessUnitDamaged = true; 404 } 405 return status; 406 } 407 408 void AMPEG4ElementaryAssembler::packetLost() { 409 CHECK(mNextExpectedSeqNoValid); 410 ALOGV("packetLost (expected %d)", mNextExpectedSeqNo); 411 412 ++mNextExpectedSeqNo; 413 414 mAccessUnitDamaged = true; 415 } 416 417 void AMPEG4ElementaryAssembler::onByeReceived() { 418 sp<AMessage> msg = mNotifyMsg->dup(); 419 msg->setInt32("eos", true); 420 msg->post(); 421 } 422 423 } // namespace android 424