APacketSource.cpp revision c9e894872c298b25fe9d74e68aa1e7287a541ac3
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 "APacketSource.h" 18 19#include "ASessionDescription.h" 20 21#include "avc_utils.h" 22 23#include <ctype.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/AString.h> 30#include <media/stagefright/foundation/base64.h> 31#include <media/stagefright/foundation/hexdump.h> 32#include <media/stagefright/MediaBuffer.h> 33#include <media/stagefright/MediaDefs.h> 34#include <media/stagefright/MetaData.h> 35#include <utils/Vector.h> 36 37namespace android { 38 39static bool GetAttribute(const char *s, const char *key, AString *value) { 40 value->clear(); 41 42 size_t keyLen = strlen(key); 43 44 for (;;) { 45 while (isspace(*s)) { 46 ++s; 47 } 48 49 const char *colonPos = strchr(s, ';'); 50 51 size_t len = 52 (colonPos == NULL) ? strlen(s) : colonPos - s; 53 54 if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(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 sp<ABuffer> decodeHex(const AString &s) { 68 if ((s.size() % 2) != 0) { 69 return NULL; 70 } 71 72 size_t outLen = s.size() / 2; 73 sp<ABuffer> buffer = new ABuffer(outLen); 74 uint8_t *out = buffer->data(); 75 76 uint8_t accum = 0; 77 for (size_t i = 0; i < s.size(); ++i) { 78 char c = s.c_str()[i]; 79 unsigned value; 80 if (c >= '0' && c <= '9') { 81 value = c - '0'; 82 } else if (c >= 'a' && c <= 'f') { 83 value = c - 'a' + 10; 84 } else if (c >= 'A' && c <= 'F') { 85 value = c - 'A' + 10; 86 } else { 87 return NULL; 88 } 89 90 accum = (accum << 4) | value; 91 92 if (i & 1) { 93 *out++ = accum; 94 95 accum = 0; 96 } 97 } 98 99 return buffer; 100} 101 102static sp<ABuffer> MakeAVCCodecSpecificData( 103 const char *params, int32_t *width, int32_t *height) { 104 *width = 0; 105 *height = 0; 106 107 AString val; 108 if (!GetAttribute(params, "profile-level-id", &val)) { 109 return NULL; 110 } 111 112 sp<ABuffer> profileLevelID = decodeHex(val); 113 CHECK(profileLevelID != NULL); 114 CHECK_EQ(profileLevelID->size(), 3u); 115 116 Vector<sp<ABuffer> > paramSets; 117 118 size_t numSeqParameterSets = 0; 119 size_t totalSeqParameterSetSize = 0; 120 size_t numPicParameterSets = 0; 121 size_t totalPicParameterSetSize = 0; 122 123 if (!GetAttribute(params, "sprop-parameter-sets", &val)) { 124 return NULL; 125 } 126 127 size_t start = 0; 128 for (;;) { 129 ssize_t commaPos = val.find(",", start); 130 size_t end = (commaPos < 0) ? val.size() : commaPos; 131 132 AString nalString(val, start, end - start); 133 sp<ABuffer> nal = decodeBase64(nalString); 134 CHECK(nal != NULL); 135 CHECK_GT(nal->size(), 0u); 136 CHECK_LE(nal->size(), 65535u); 137 138 uint8_t nalType = nal->data()[0] & 0x1f; 139 if (numSeqParameterSets == 0) { 140 CHECK_EQ((unsigned)nalType, 7u); 141 } else if (numPicParameterSets > 0) { 142 CHECK_EQ((unsigned)nalType, 8u); 143 } 144 if (nalType == 7) { 145 ++numSeqParameterSets; 146 totalSeqParameterSetSize += nal->size(); 147 } else { 148 CHECK_EQ((unsigned)nalType, 8u); 149 ++numPicParameterSets; 150 totalPicParameterSetSize += nal->size(); 151 } 152 153 paramSets.push(nal); 154 155 if (commaPos < 0) { 156 break; 157 } 158 159 start = commaPos + 1; 160 } 161 162 CHECK_LT(numSeqParameterSets, 32u); 163 CHECK_LE(numPicParameterSets, 255u); 164 165 size_t csdSize = 166 1 + 3 + 1 + 1 167 + 2 * numSeqParameterSets + totalSeqParameterSetSize 168 + 1 + 2 * numPicParameterSets + totalPicParameterSetSize; 169 170 sp<ABuffer> csd = new ABuffer(csdSize); 171 uint8_t *out = csd->data(); 172 173 *out++ = 0x01; // configurationVersion 174 memcpy(out, profileLevelID->data(), 3); 175 out += 3; 176 *out++ = (0x3f << 2) | 1; // lengthSize == 2 bytes 177 *out++ = 0xe0 | numSeqParameterSets; 178 179 for (size_t i = 0; i < numSeqParameterSets; ++i) { 180 sp<ABuffer> nal = paramSets.editItemAt(i); 181 182 *out++ = nal->size() >> 8; 183 *out++ = nal->size() & 0xff; 184 185 memcpy(out, nal->data(), nal->size()); 186 187 out += nal->size(); 188 189 if (i == 0) { 190 FindAVCDimensions(nal, width, height); 191 LOG(INFO) << "dimensions " << *width << "x" << *height; 192 } 193 } 194 195 *out++ = numPicParameterSets; 196 197 for (size_t i = 0; i < numPicParameterSets; ++i) { 198 sp<ABuffer> nal = paramSets.editItemAt(i + numSeqParameterSets); 199 200 *out++ = nal->size() >> 8; 201 *out++ = nal->size() & 0xff; 202 203 memcpy(out, nal->data(), nal->size()); 204 205 out += nal->size(); 206 } 207 208 // hexdump(csd->data(), csd->size()); 209 210 return csd; 211} 212 213sp<ABuffer> MakeAACCodecSpecificData(const char *params) { 214 AString val; 215 CHECK(GetAttribute(params, "config", &val)); 216 217 sp<ABuffer> config = decodeHex(val); 218 CHECK(config != NULL); 219 CHECK_GE(config->size(), 4u); 220 221 const uint8_t *data = config->data(); 222 uint32_t x = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; 223 x = (x >> 1) & 0xffff; 224 225 static const uint8_t kStaticESDS[] = { 226 0x03, 22, 227 0x00, 0x00, // ES_ID 228 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag 229 230 0x04, 17, 231 0x40, // Audio ISO/IEC 14496-3 232 0x00, 0x00, 0x00, 0x00, 233 0x00, 0x00, 0x00, 0x00, 234 0x00, 0x00, 0x00, 0x00, 235 236 0x05, 2, 237 // AudioSpecificInfo follows 238 }; 239 240 sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + 2); 241 memcpy(csd->data(), kStaticESDS, sizeof(kStaticESDS)); 242 csd->data()[sizeof(kStaticESDS)] = (x >> 8) & 0xff; 243 csd->data()[sizeof(kStaticESDS) + 1] = x & 0xff; 244 245 // hexdump(csd->data(), csd->size()); 246 247 return csd; 248} 249 250// From mpeg4-generic configuration data. 251sp<ABuffer> MakeAACCodecSpecificData2(const char *params) { 252 AString val; 253 unsigned long objectType; 254 if (GetAttribute(params, "objectType", &val)) { 255 const char *s = val.c_str(); 256 char *end; 257 objectType = strtoul(s, &end, 10); 258 CHECK(end > s && *end == '\0'); 259 } else { 260 objectType = 0x40; // Audio ISO/IEC 14496-3 261 } 262 263 CHECK(GetAttribute(params, "config", &val)); 264 265 sp<ABuffer> config = decodeHex(val); 266 CHECK(config != NULL); 267 268 // Make sure size fits into a single byte and doesn't have to 269 // be encoded. 270 CHECK_LT(20 + config->size(), 128u); 271 272 const uint8_t *data = config->data(); 273 274 static const uint8_t kStaticESDS[] = { 275 0x03, 22, 276 0x00, 0x00, // ES_ID 277 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag 278 279 0x04, 17, 280 0x40, // Audio ISO/IEC 14496-3 281 0x00, 0x00, 0x00, 0x00, 282 0x00, 0x00, 0x00, 0x00, 283 0x00, 0x00, 0x00, 0x00, 284 285 0x05, 2, 286 // AudioSpecificInfo follows 287 }; 288 289 sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + config->size()); 290 uint8_t *dst = csd->data(); 291 *dst++ = 0x03; 292 *dst++ = 20 + config->size(); 293 *dst++ = 0x00; // ES_ID 294 *dst++ = 0x00; 295 *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 296 *dst++ = 0x04; 297 *dst++ = 15 + config->size(); 298 *dst++ = objectType; 299 for (int i = 0; i < 12; ++i) { *dst++ = 0x00; } 300 *dst++ = 0x05; 301 *dst++ = config->size(); 302 memcpy(dst, config->data(), config->size()); 303 304 // hexdump(csd->data(), csd->size()); 305 306 return csd; 307} 308 309static size_t GetSizeWidth(size_t x) { 310 size_t n = 1; 311 while (x > 127) { 312 ++n; 313 x >>= 7; 314 } 315 return n; 316} 317 318static uint8_t *EncodeSize(uint8_t *dst, size_t x) { 319 while (x > 127) { 320 *dst++ = (x & 0x7f) | 0x80; 321 x >>= 7; 322 } 323 *dst++ = x; 324 return dst; 325} 326 327static bool ExtractDimensionsFromVOLHeader( 328 const sp<ABuffer> &config, int32_t *width, int32_t *height) { 329 *width = 0; 330 *height = 0; 331 332 const uint8_t *ptr = config->data(); 333 size_t offset = 0; 334 bool foundVOL = false; 335 while (offset + 3 < config->size()) { 336 if (memcmp("\x00\x00\x01", &ptr[offset], 3) 337 || (ptr[offset + 3] & 0xf0) != 0x20) { 338 ++offset; 339 continue; 340 } 341 342 foundVOL = true; 343 break; 344 } 345 346 if (!foundVOL) { 347 return false; 348 } 349 350 ABitReader br(&ptr[offset + 4], config->size() - offset - 4); 351 br.skipBits(1); // random_accessible_vol 352 unsigned video_object_type_indication = br.getBits(8); 353 354 CHECK_NE(video_object_type_indication, 355 0x21u /* Fine Granularity Scalable */); 356 357 unsigned video_object_layer_verid; 358 unsigned video_object_layer_priority; 359 if (br.getBits(1)) { 360 video_object_layer_verid = br.getBits(4); 361 video_object_layer_priority = br.getBits(3); 362 } 363 unsigned aspect_ratio_info = br.getBits(4); 364 if (aspect_ratio_info == 0x0f /* extended PAR */) { 365 br.skipBits(8); // par_width 366 br.skipBits(8); // par_height 367 } 368 if (br.getBits(1)) { // vol_control_parameters 369 br.skipBits(2); // chroma_format 370 br.skipBits(1); // low_delay 371 if (br.getBits(1)) { // vbv_parameters 372 TRESPASS(); 373 } 374 } 375 unsigned video_object_layer_shape = br.getBits(2); 376 CHECK_EQ(video_object_layer_shape, 0x00u /* rectangular */); 377 378 CHECK(br.getBits(1)); // marker_bit 379 unsigned vop_time_increment_resolution = br.getBits(16); 380 CHECK(br.getBits(1)); // marker_bit 381 382 if (br.getBits(1)) { // fixed_vop_rate 383 // range [0..vop_time_increment_resolution) 384 385 // vop_time_increment_resolution 386 // 2 => 0..1, 1 bit 387 // 3 => 0..2, 2 bits 388 // 4 => 0..3, 2 bits 389 // 5 => 0..4, 3 bits 390 // ... 391 392 CHECK_GT(vop_time_increment_resolution, 0u); 393 --vop_time_increment_resolution; 394 395 unsigned numBits = 0; 396 while (vop_time_increment_resolution > 0) { 397 ++numBits; 398 vop_time_increment_resolution >>= 1; 399 } 400 401 br.skipBits(numBits); // fixed_vop_time_increment 402 } 403 404 CHECK(br.getBits(1)); // marker_bit 405 unsigned video_object_layer_width = br.getBits(13); 406 CHECK(br.getBits(1)); // marker_bit 407 unsigned video_object_layer_height = br.getBits(13); 408 CHECK(br.getBits(1)); // marker_bit 409 410 unsigned interlaced = br.getBits(1); 411 412 *width = video_object_layer_width; 413 *height = video_object_layer_height; 414 415 LOG(INFO) << "VOL dimensions = " << *width << "x" << *height; 416 417 return true; 418} 419 420sp<ABuffer> MakeMPEG4VideoCodecSpecificData( 421 const char *params, int32_t *width, int32_t *height) { 422 *width = 0; 423 *height = 0; 424 425 AString val; 426 CHECK(GetAttribute(params, "config", &val)); 427 428 sp<ABuffer> config = decodeHex(val); 429 CHECK(config != NULL); 430 431 if (!ExtractDimensionsFromVOLHeader(config, width, height)) { 432 return NULL; 433 } 434 435 size_t len1 = config->size() + GetSizeWidth(config->size()) + 1; 436 size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13; 437 size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3; 438 439 sp<ABuffer> csd = new ABuffer(len3); 440 uint8_t *dst = csd->data(); 441 *dst++ = 0x03; 442 dst = EncodeSize(dst, len2 + 3); 443 *dst++ = 0x00; // ES_ID 444 *dst++ = 0x00; 445 *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 446 447 *dst++ = 0x04; 448 dst = EncodeSize(dst, len1 + 13); 449 *dst++ = 0x01; // Video ISO/IEC 14496-2 Simple Profile 450 for (size_t i = 0; i < 12; ++i) { 451 *dst++ = 0x00; 452 } 453 454 *dst++ = 0x05; 455 dst = EncodeSize(dst, config->size()); 456 memcpy(dst, config->data(), config->size()); 457 dst += config->size(); 458 459 // hexdump(csd->data(), csd->size()); 460 461 return csd; 462} 463 464static bool GetClockRate(const AString &desc, uint32_t *clockRate) { 465 ssize_t slashPos = desc.find("/"); 466 if (slashPos < 0) { 467 return false; 468 } 469 470 const char *s = desc.c_str() + slashPos + 1; 471 472 char *end; 473 unsigned long x = strtoul(s, &end, 10); 474 475 if (end == s || (*end != '\0' && *end != '/')) { 476 return false; 477 } 478 479 *clockRate = x; 480 481 return true; 482} 483 484APacketSource::APacketSource( 485 const sp<ASessionDescription> &sessionDesc, size_t index) 486 : mInitCheck(NO_INIT), 487 mFormat(new MetaData), 488 mEOSResult(OK), 489 mRTPTimeBase(0), 490 mNormalPlayTimeBaseUs(0), 491 mLastNormalPlayTimeUs(0) { 492 unsigned long PT; 493 AString desc; 494 AString params; 495 sessionDesc->getFormatType(index, &PT, &desc, ¶ms); 496 497 CHECK(GetClockRate(desc, &mClockRate)); 498 499 int64_t durationUs; 500 if (sessionDesc->getDurationUs(&durationUs)) { 501 mFormat->setInt64(kKeyDuration, durationUs); 502 } else { 503 mFormat->setInt64(kKeyDuration, 60 * 60 * 1000000ll); 504 } 505 506 mInitCheck = OK; 507 if (!strncmp(desc.c_str(), "H264/", 5)) { 508 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); 509 510 int32_t width, height; 511 if (!sessionDesc->getDimensions(index, PT, &width, &height)) { 512 width = -1; 513 height = -1; 514 } 515 516 int32_t encWidth, encHeight; 517 sp<ABuffer> codecSpecificData = 518 MakeAVCCodecSpecificData(params.c_str(), &encWidth, &encHeight); 519 520 if (codecSpecificData != NULL) { 521 if (width < 0) { 522 // If no explicit width/height given in the sdp, use the dimensions 523 // extracted from the first sequence parameter set. 524 width = encWidth; 525 height = encHeight; 526 } 527 528 mFormat->setData( 529 kKeyAVCC, 0, 530 codecSpecificData->data(), codecSpecificData->size()); 531 } else if (width < 0) { 532 mInitCheck = ERROR_UNSUPPORTED; 533 return; 534 } 535 536 mFormat->setInt32(kKeyWidth, width); 537 mFormat->setInt32(kKeyHeight, height); 538 } else if (!strncmp(desc.c_str(), "H263-2000/", 10) 539 || !strncmp(desc.c_str(), "H263-1998/", 10)) { 540 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); 541 542 int32_t width, height; 543 if (!sessionDesc->getDimensions(index, PT, &width, &height)) { 544 mInitCheck = ERROR_UNSUPPORTED; 545 return; 546 } 547 548 mFormat->setInt32(kKeyWidth, width); 549 mFormat->setInt32(kKeyHeight, height); 550 } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) { 551 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 552 553 int32_t sampleRate, numChannels; 554 ASessionDescription::ParseFormatDesc( 555 desc.c_str(), &sampleRate, &numChannels); 556 557 mFormat->setInt32(kKeySampleRate, sampleRate); 558 mFormat->setInt32(kKeyChannelCount, numChannels); 559 560 sp<ABuffer> codecSpecificData = 561 MakeAACCodecSpecificData(params.c_str()); 562 563 mFormat->setData( 564 kKeyESDS, 0, 565 codecSpecificData->data(), codecSpecificData->size()); 566 } else if (!strncmp(desc.c_str(), "AMR/", 4)) { 567 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB); 568 569 int32_t sampleRate, numChannels; 570 ASessionDescription::ParseFormatDesc( 571 desc.c_str(), &sampleRate, &numChannels); 572 573 mFormat->setInt32(kKeySampleRate, sampleRate); 574 mFormat->setInt32(kKeyChannelCount, numChannels); 575 576 if (sampleRate != 8000 || numChannels != 1) { 577 mInitCheck = ERROR_UNSUPPORTED; 578 } 579 } else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) { 580 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB); 581 582 int32_t sampleRate, numChannels; 583 ASessionDescription::ParseFormatDesc( 584 desc.c_str(), &sampleRate, &numChannels); 585 586 mFormat->setInt32(kKeySampleRate, sampleRate); 587 mFormat->setInt32(kKeyChannelCount, numChannels); 588 589 if (sampleRate != 16000 || numChannels != 1) { 590 mInitCheck = ERROR_UNSUPPORTED; 591 } 592 } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)) { 593 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); 594 595 int32_t width, height; 596 if (!sessionDesc->getDimensions(index, PT, &width, &height)) { 597 width = -1; 598 height = -1; 599 } 600 601 int32_t encWidth, encHeight; 602 sp<ABuffer> codecSpecificData = 603 MakeMPEG4VideoCodecSpecificData( 604 params.c_str(), &encWidth, &encHeight); 605 606 if (codecSpecificData != NULL) { 607 mFormat->setData( 608 kKeyESDS, 0, 609 codecSpecificData->data(), codecSpecificData->size()); 610 611 if (width < 0) { 612 width = encWidth; 613 height = encHeight; 614 } 615 } else if (width < 0) { 616 mInitCheck = ERROR_UNSUPPORTED; 617 return; 618 } 619 620 mFormat->setInt32(kKeyWidth, width); 621 mFormat->setInt32(kKeyHeight, height); 622 } else if (!strncmp(desc.c_str(), "mpeg4-generic/", 14)) { 623 AString val; 624 if (!GetAttribute(params.c_str(), "mode", &val) 625 || (strcasecmp(val.c_str(), "AAC-lbr") 626 && strcasecmp(val.c_str(), "AAC-hbr"))) { 627 mInitCheck = ERROR_UNSUPPORTED; 628 return; 629 } 630 631 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); 632 633 int32_t sampleRate, numChannels; 634 ASessionDescription::ParseFormatDesc( 635 desc.c_str(), &sampleRate, &numChannels); 636 637 mFormat->setInt32(kKeySampleRate, sampleRate); 638 mFormat->setInt32(kKeyChannelCount, numChannels); 639 640 sp<ABuffer> codecSpecificData = 641 MakeAACCodecSpecificData2(params.c_str()); 642 643 mFormat->setData( 644 kKeyESDS, 0, 645 codecSpecificData->data(), codecSpecificData->size()); 646 } else { 647 mInitCheck = ERROR_UNSUPPORTED; 648 } 649} 650 651APacketSource::~APacketSource() { 652} 653 654status_t APacketSource::initCheck() const { 655 return mInitCheck; 656} 657 658status_t APacketSource::start(MetaData *params) { 659 return OK; 660} 661 662status_t APacketSource::stop() { 663 return OK; 664} 665 666sp<MetaData> APacketSource::getFormat() { 667 return mFormat; 668} 669 670status_t APacketSource::read( 671 MediaBuffer **out, const ReadOptions *) { 672 *out = NULL; 673 674 Mutex::Autolock autoLock(mLock); 675 while (mEOSResult == OK && mBuffers.empty()) { 676 mCondition.wait(mLock); 677 } 678 679 if (!mBuffers.empty()) { 680 const sp<ABuffer> buffer = *mBuffers.begin(); 681 682 updateNormalPlayTime_l(buffer); 683 684 MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size()); 685 686 int64_t timeUs; 687 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 688 689 mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs); 690 691 memcpy(mediaBuffer->data(), buffer->data(), buffer->size()); 692 *out = mediaBuffer; 693 694 mBuffers.erase(mBuffers.begin()); 695 return OK; 696 } 697 698 return mEOSResult; 699} 700 701void APacketSource::updateNormalPlayTime_l(const sp<ABuffer> &buffer) { 702 uint32_t rtpTime; 703 CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime)); 704 705 mLastNormalPlayTimeUs = 706 (((double)rtpTime - (double)mRTPTimeBase) / mClockRate) 707 * 1000000ll 708 + mNormalPlayTimeBaseUs; 709} 710 711void APacketSource::queueAccessUnit(const sp<ABuffer> &buffer) { 712 int32_t damaged; 713 if (buffer->meta()->findInt32("damaged", &damaged) && damaged) { 714 LOG(VERBOSE) << "discarding damaged AU"; 715 return; 716 } 717 718 Mutex::Autolock autoLock(mLock); 719 mBuffers.push_back(buffer); 720 mCondition.signal(); 721} 722 723void APacketSource::signalEOS(status_t result) { 724 CHECK(result != OK); 725 726 Mutex::Autolock autoLock(mLock); 727 mEOSResult = result; 728 mCondition.signal(); 729} 730 731void APacketSource::flushQueue() { 732 Mutex::Autolock autoLock(mLock); 733 mBuffers.clear(); 734} 735 736int64_t APacketSource::getNormalPlayTimeUs() { 737 Mutex::Autolock autoLock(mLock); 738 return mLastNormalPlayTimeUs; 739} 740 741void APacketSource::setNormalPlayTimeMapping( 742 uint32_t rtpTime, int64_t normalPlayTimeUs) { 743 Mutex::Autolock autoLock(mLock); 744 745 mRTPTimeBase = rtpTime; 746 mNormalPlayTimeBaseUs = normalPlayTimeUs; 747} 748 749int64_t APacketSource::getQueueDurationUs(bool *eos) { 750 Mutex::Autolock autoLock(mLock); 751 752 *eos = (mEOSResult != OK); 753 754 if (mBuffers.size() < 2) { 755 return 0; 756 } 757 758 const sp<ABuffer> first = *mBuffers.begin(); 759 const sp<ABuffer> last = *--mBuffers.end(); 760 761 int64_t firstTimeUs; 762 CHECK(first->meta()->findInt64("timeUs", &firstTimeUs)); 763 764 int64_t lastTimeUs; 765 CHECK(last->meta()->findInt64("timeUs", &lastTimeUs)); 766 767 CHECK_GE(lastTimeUs, firstTimeUs); 768 769 return lastTimeUs - firstTimeUs; 770} 771 772} // namespace android 773