AMPEG4ElementaryAssembler.cpp revision 6e4c5c499999c04c2477b987f9e64f3ff2bf1a06
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 25#include <media/stagefright/foundation/ABitReader.h> 26#include <media/stagefright/foundation/ABuffer.h> 27#include <media/stagefright/foundation/ADebug.h> 28#include <media/stagefright/foundation/AMessage.h> 29#include <media/stagefright/foundation/hexdump.h> 30#include <media/stagefright/Utils.h> 31 32#include <ctype.h> 33#include <stdint.h> 34 35namespace android { 36 37static bool GetAttribute(const char *s, const char *key, AString *value) { 38 value->clear(); 39 40 size_t keyLen = strlen(key); 41 42 for (;;) { 43 while (isspace(*s)) { 44 ++s; 45 } 46 47 const char *colonPos = strchr(s, ';'); 48 49 size_t len = 50 (colonPos == NULL) ? strlen(s) : colonPos - s; 51 52 if (len >= keyLen + 1 && s[keyLen] == '=' 53 && !strncasecmp(s, key, keyLen)) { 54 value->setTo(&s[keyLen + 1], len - keyLen - 1); 55 return true; 56 } 57 58 if (colonPos == NULL) { 59 return false; 60 } 61 62 s = colonPos + 1; 63 } 64} 65 66static bool GetIntegerAttribute( 67 const char *s, const char *key, unsigned *x) { 68 *x = 0; 69 70 AString val; 71 if (!GetAttribute(s, key, &val)) { 72 return false; 73 } 74 75 s = val.c_str(); 76 char *end; 77 unsigned y = strtoul(s, &end, 10); 78 79 if (end == s || *end != '\0') { 80 return false; 81 } 82 83 *x = y; 84 85 return true; 86} 87 88// static 89AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler( 90 const sp<AMessage> ¬ify, const AString &desc, const AString ¶ms) 91 : mNotifyMsg(notify), 92 mIsGeneric(false), 93 mParams(params), 94 mSizeLength(0), 95 mIndexLength(0), 96 mIndexDeltaLength(0), 97 mCTSDeltaLength(0), 98 mDTSDeltaLength(0), 99 mRandomAccessIndication(false), 100 mStreamStateIndication(0), 101 mAuxiliaryDataSizeLength(0), 102 mHasAUHeader(false), 103 mAccessUnitRTPTime(0), 104 mNextExpectedSeqNoValid(false), 105 mNextExpectedSeqNo(0), 106 mAccessUnitDamaged(false) { 107 mIsGeneric = desc.startsWith("mpeg4-generic/"); 108 109 if (mIsGeneric) { 110 AString value; 111 CHECK(GetAttribute(params.c_str(), "mode", &value)); 112 113 if (!GetIntegerAttribute(params.c_str(), "sizeLength", &mSizeLength)) { 114 mSizeLength = 0; 115 } 116 117 if (!GetIntegerAttribute( 118 params.c_str(), "indexLength", &mIndexLength)) { 119 mIndexLength = 0; 120 } 121 122 if (!GetIntegerAttribute( 123 params.c_str(), "indexDeltaLength", &mIndexDeltaLength)) { 124 mIndexDeltaLength = 0; 125 } 126 127 if (!GetIntegerAttribute( 128 params.c_str(), "CTSDeltaLength", &mCTSDeltaLength)) { 129 mCTSDeltaLength = 0; 130 } 131 132 if (!GetIntegerAttribute( 133 params.c_str(), "DTSDeltaLength", &mDTSDeltaLength)) { 134 mDTSDeltaLength = 0; 135 } 136 137 unsigned x; 138 if (!GetIntegerAttribute( 139 params.c_str(), "randomAccessIndication", &x)) { 140 mRandomAccessIndication = false; 141 } else { 142 CHECK(x == 0 || x == 1); 143 mRandomAccessIndication = (x != 0); 144 } 145 146 if (!GetIntegerAttribute( 147 params.c_str(), "streamStateIndication", 148 &mStreamStateIndication)) { 149 mStreamStateIndication = 0; 150 } 151 152 if (!GetIntegerAttribute( 153 params.c_str(), "auxiliaryDataSizeLength", 154 &mAuxiliaryDataSizeLength)) { 155 mAuxiliaryDataSizeLength = 0; 156 } 157 158 mHasAUHeader = 159 mSizeLength > 0 160 || mIndexLength > 0 161 || mIndexDeltaLength > 0 162 || mCTSDeltaLength > 0 163 || mDTSDeltaLength > 0 164 || mRandomAccessIndication 165 || mStreamStateIndication > 0; 166 } 167} 168 169AMPEG4ElementaryAssembler::~AMPEG4ElementaryAssembler() { 170} 171 172struct AUHeader { 173 unsigned mSize; 174 unsigned mSerial; 175}; 176 177ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket( 178 const sp<ARTPSource> &source) { 179 List<sp<ABuffer> > *queue = source->queue(); 180 181 if (queue->empty()) { 182 return NOT_ENOUGH_DATA; 183 } 184 185 if (mNextExpectedSeqNoValid) { 186 List<sp<ABuffer> >::iterator it = queue->begin(); 187 while (it != queue->end()) { 188 if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) { 189 break; 190 } 191 192 it = queue->erase(it); 193 } 194 195 if (queue->empty()) { 196 return NOT_ENOUGH_DATA; 197 } 198 } 199 200 sp<ABuffer> buffer = *queue->begin(); 201 202 if (!mNextExpectedSeqNoValid) { 203 mNextExpectedSeqNoValid = true; 204 mNextExpectedSeqNo = (uint32_t)buffer->int32Data(); 205 } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) { 206 LOGV("Not the sequence number I expected"); 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 LOGV("Access unit complete (%d nal units)", mPackets.size()); 340 341 size_t totalSize = 0; 342 for (List<sp<ABuffer> >::iterator it = mPackets.begin(); 343 it != mPackets.end(); ++it) { 344 totalSize += (*it)->size(); 345 } 346 347 sp<ABuffer> accessUnit = new ABuffer(totalSize); 348 size_t offset = 0; 349 for (List<sp<ABuffer> >::iterator it = mPackets.begin(); 350 it != mPackets.end(); ++it) { 351 sp<ABuffer> nal = *it; 352 memcpy(accessUnit->data() + offset, nal->data(), nal->size()); 353 offset += nal->size(); 354 } 355 356 CopyTimes(accessUnit, *mPackets.begin()); 357 358#if 0 359 printf(mAccessUnitDamaged ? "X" : "."); 360 fflush(stdout); 361#endif 362 363 if (mAccessUnitDamaged) { 364 accessUnit->meta()->setInt32("damaged", true); 365 } 366 367 mPackets.clear(); 368 mAccessUnitDamaged = false; 369 370 sp<AMessage> msg = mNotifyMsg->dup(); 371 msg->setObject("access-unit", accessUnit); 372 msg->post(); 373} 374 375ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::assembleMore( 376 const sp<ARTPSource> &source) { 377 AssemblyStatus status = addPacket(source); 378 if (status == MALFORMED_PACKET) { 379 mAccessUnitDamaged = true; 380 } 381 return status; 382} 383 384void AMPEG4ElementaryAssembler::packetLost() { 385 CHECK(mNextExpectedSeqNoValid); 386 LOGV("packetLost (expected %d)", mNextExpectedSeqNo); 387 388 ++mNextExpectedSeqNo; 389 390 mAccessUnitDamaged = true; 391} 392 393void AMPEG4ElementaryAssembler::onByeReceived() { 394 sp<AMessage> msg = mNotifyMsg->dup(); 395 msg->setInt32("eos", true); 396 msg->post(); 397} 398 399} // namespace android 400