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