AMPEG4ElementaryAssembler.cpp revision 80804f4e953d6c5f6ed0c3c8e004c4cce280f5c1
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 36namespace android { 37 38static 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 67static 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 89static 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 109AMPEG4ElementaryAssembler::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 198AMPEG4ElementaryAssembler::~AMPEG4ElementaryAssembler() { 199} 200 201struct AUHeader { 202 unsigned mSize; 203 unsigned mSerial; 204}; 205 206ARTPAssembler::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 if (buffer->size() < 2) { 253 return MALFORMED_PACKET; 254 } 255 256 unsigned AU_headers_length = U16_AT(buffer->data()); // in bits 257 258 if (buffer->size() < 2 + (AU_headers_length + 7) / 8) { 259 return MALFORMED_PACKET; 260 } 261 262 List<AUHeader> headers; 263 264 ABitReader bits(buffer->data() + 2, buffer->size() - 2); 265 unsigned numBitsLeft = AU_headers_length; 266 267 unsigned AU_serial = 0; 268 for (;;) { 269 if (numBitsLeft < mSizeLength) { break; } 270 271 unsigned AU_size = bits.getBits(mSizeLength); 272 numBitsLeft -= mSizeLength; 273 274 size_t n = headers.empty() ? mIndexLength : mIndexDeltaLength; 275 if (numBitsLeft < n) { break; } 276 277 unsigned AU_index = bits.getBits(n); 278 numBitsLeft -= n; 279 280 if (headers.empty()) { 281 AU_serial = AU_index; 282 } else { 283 AU_serial += 1 + AU_index; 284 } 285 286 if (mCTSDeltaLength > 0) { 287 if (numBitsLeft < 1) { 288 break; 289 } 290 --numBitsLeft; 291 if (bits.getBits(1)) { 292 if (numBitsLeft < mCTSDeltaLength) { 293 break; 294 } 295 bits.skipBits(mCTSDeltaLength); 296 numBitsLeft -= mCTSDeltaLength; 297 } 298 } 299 300 if (mDTSDeltaLength > 0) { 301 if (numBitsLeft < 1) { 302 break; 303 } 304 --numBitsLeft; 305 if (bits.getBits(1)) { 306 if (numBitsLeft < mDTSDeltaLength) { 307 break; 308 } 309 bits.skipBits(mDTSDeltaLength); 310 numBitsLeft -= mDTSDeltaLength; 311 } 312 } 313 314 if (mRandomAccessIndication) { 315 if (numBitsLeft < 1) { 316 break; 317 } 318 bits.skipBits(1); 319 --numBitsLeft; 320 } 321 322 if (mStreamStateIndication > 0) { 323 if (numBitsLeft < mStreamStateIndication) { 324 break; 325 } 326 bits.skipBits(mStreamStateIndication); 327 } 328 329 AUHeader header; 330 header.mSize = AU_size; 331 header.mSerial = AU_serial; 332 headers.push_back(header); 333 } 334 335 size_t offset = 2 + (AU_headers_length + 7) / 8; 336 337 if (mAuxiliaryDataSizeLength > 0) { 338 ABitReader bits(buffer->data() + offset, buffer->size() - offset); 339 340 unsigned auxSize = bits.getBits(mAuxiliaryDataSizeLength); 341 342 offset += (mAuxiliaryDataSizeLength + auxSize + 7) / 8; 343 } 344 345 for (List<AUHeader>::iterator it = headers.begin(); 346 it != headers.end(); ++it) { 347 const AUHeader &header = *it; 348 349 if (buffer->size() < offset + header.mSize) { 350 return MALFORMED_PACKET; 351 } 352 353 sp<ABuffer> accessUnit = new ABuffer(header.mSize); 354 memcpy(accessUnit->data(), buffer->data() + offset, header.mSize); 355 356 offset += header.mSize; 357 358 CopyTimes(accessUnit, buffer); 359 mPackets.push_back(accessUnit); 360 } 361 362 if (offset != buffer->size()) { 363 ALOGW("potentially malformed packet (offset %d, size %d)", 364 offset, buffer->size()); 365 } 366 } 367 368 queue->erase(queue->begin()); 369 ++mNextExpectedSeqNo; 370 371 return OK; 372} 373 374void AMPEG4ElementaryAssembler::submitAccessUnit() { 375 CHECK(!mPackets.empty()); 376 377 ALOGV("Access unit complete (%zu nal units)", mPackets.size()); 378 379 sp<ABuffer> accessUnit; 380 381 if (mIsGeneric) { 382 accessUnit = MakeADTSCompoundFromAACFrames( 383 OMX_AUDIO_AACObjectLC - 1, 384 mSampleRateIndex, 385 mChannelConfig, 386 mPackets); 387 } else { 388 accessUnit = MakeCompoundFromPackets(mPackets); 389 } 390 391#if 0 392 printf(mAccessUnitDamaged ? "X" : "."); 393 fflush(stdout); 394#endif 395 396 if (mAccessUnitDamaged) { 397 accessUnit->meta()->setInt32("damaged", true); 398 } 399 400 mPackets.clear(); 401 mAccessUnitDamaged = false; 402 403 sp<AMessage> msg = mNotifyMsg->dup(); 404 msg->setBuffer("access-unit", accessUnit); 405 msg->post(); 406} 407 408ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::assembleMore( 409 const sp<ARTPSource> &source) { 410 AssemblyStatus status = addPacket(source); 411 if (status == MALFORMED_PACKET) { 412 ALOGI("access unit is damaged"); 413 mAccessUnitDamaged = true; 414 } 415 return status; 416} 417 418void AMPEG4ElementaryAssembler::packetLost() { 419 CHECK(mNextExpectedSeqNoValid); 420 ALOGV("packetLost (expected %d)", mNextExpectedSeqNo); 421 422 ++mNextExpectedSeqNo; 423 424 mAccessUnitDamaged = true; 425} 426 427void AMPEG4ElementaryAssembler::onByeReceived() { 428 sp<AMessage> msg = mNotifyMsg->dup(); 429 msg->setInt32("eos", true); 430 msg->post(); 431} 432 433} // namespace android 434