NuPlayerDecoder.cpp revision 4923cee4fb3b29538d8f46bceeea7d5128242a71
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 "NuPlayerDecoder" 19#include <utils/Log.h> 20#include <inttypes.h> 21 22#include "NuPlayerDecoder.h" 23 24#include <media/ICrypto.h> 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/MediaBuffer.h> 30#include <media/stagefright/MediaCodec.h> 31#include <media/stagefright/MediaDefs.h> 32#include <media/stagefright/MediaErrors.h> 33 34namespace android { 35 36NuPlayer::Decoder::Decoder( 37 const sp<AMessage> ¬ify, 38 const sp<NativeWindowWrapper> &nativeWindow) 39 : mNotify(notify), 40 mNativeWindow(nativeWindow), 41 mBufferGeneration(0), 42 mPaused(true), 43 mComponentName("decoder") { 44 // Every decoder has its own looper because MediaCodec operations 45 // are blocking, but NuPlayer needs asynchronous operations. 46 mDecoderLooper = new ALooper; 47 mDecoderLooper->setName("NPDecoder"); 48 mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 49 50 mCodecLooper = new ALooper; 51 mCodecLooper->setName("NPDecoder-CL"); 52 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 53} 54 55NuPlayer::Decoder::~Decoder() { 56 mDecoderLooper->unregisterHandler(id()); 57 mDecoderLooper->stop(); 58 59 releaseAndResetMediaBuffers(); 60} 61 62static 63status_t PostAndAwaitResponse( 64 const sp<AMessage> &msg, sp<AMessage> *response) { 65 status_t err = msg->postAndAwaitResponse(response); 66 67 if (err != OK) { 68 return err; 69 } 70 71 if (!(*response)->findInt32("err", &err)) { 72 err = OK; 73 } 74 75 return err; 76} 77 78void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) { 79 mCSDsForCurrentFormat.clear(); 80 for (int32_t i = 0; ; ++i) { 81 AString tag = "csd-"; 82 tag.append(i); 83 sp<ABuffer> buffer; 84 if (!format->findBuffer(tag.c_str(), &buffer)) { 85 break; 86 } 87 mCSDsForCurrentFormat.push(buffer); 88 } 89} 90 91void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) { 92 CHECK(mCodec == NULL); 93 94 ++mBufferGeneration; 95 96 AString mime; 97 CHECK(format->findString("mime", &mime)); 98 99 sp<Surface> surface = NULL; 100 if (mNativeWindow != NULL) { 101 surface = mNativeWindow->getSurfaceTextureClient(); 102 } 103 104 mComponentName = mime; 105 mComponentName.append(" decoder"); 106 ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), surface.get()); 107 108 mCodec = MediaCodec::CreateByType(mCodecLooper, mime.c_str(), false /* encoder */); 109 int32_t secure = 0; 110 if (format->findInt32("secure", &secure) && secure != 0) { 111 if (mCodec != NULL) { 112 mCodec->getName(&mComponentName); 113 mComponentName.append(".secure"); 114 mCodec->release(); 115 ALOGI("[%s] creating", mComponentName.c_str()); 116 mCodec = MediaCodec::CreateByComponentName( 117 mCodecLooper, mComponentName.c_str()); 118 } 119 } 120 if (mCodec == NULL) { 121 ALOGE("Failed to create %s%s decoder", 122 (secure ? "secure " : ""), mime.c_str()); 123 handleError(UNKNOWN_ERROR); 124 return; 125 } 126 127 mCodec->getName(&mComponentName); 128 129 status_t err; 130 if (mNativeWindow != NULL) { 131 // disconnect from surface as MediaCodec will reconnect 132 err = native_window_api_disconnect( 133 surface.get(), NATIVE_WINDOW_API_MEDIA); 134 // We treat this as a warning, as this is a preparatory step. 135 // Codec will try to connect to the surface, which is where 136 // any error signaling will occur. 137 ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err); 138 } 139 err = mCodec->configure( 140 format, surface, NULL /* crypto */, 0 /* flags */); 141 if (err != OK) { 142 ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err); 143 handleError(err); 144 return; 145 } 146 rememberCodecSpecificData(format); 147 148 // the following should work in configured state 149 CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat)); 150 CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat)); 151 152 err = mCodec->start(); 153 if (err != OK) { 154 ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err); 155 handleError(err); 156 return; 157 } 158 159 // the following should work after start 160 CHECK_EQ((status_t)OK, mCodec->getInputBuffers(&mInputBuffers)); 161 releaseAndResetMediaBuffers(); 162 CHECK_EQ((status_t)OK, mCodec->getOutputBuffers(&mOutputBuffers)); 163 ALOGV("[%s] got %zu input and %zu output buffers", 164 mComponentName.c_str(), 165 mInputBuffers.size(), 166 mOutputBuffers.size()); 167 168 requestCodecNotification(); 169 mPaused = false; 170} 171 172void NuPlayer::Decoder::releaseAndResetMediaBuffers() { 173 for (size_t i = 0; i < mMediaBuffers.size(); i++) { 174 if (mMediaBuffers[i] != NULL) { 175 mMediaBuffers[i]->release(); 176 mMediaBuffers.editItemAt(i) = NULL; 177 } 178 } 179 mMediaBuffers.resize(mInputBuffers.size()); 180 for (size_t i = 0; i < mMediaBuffers.size(); i++) { 181 mMediaBuffers.editItemAt(i) = NULL; 182 } 183 mInputBufferIsDequeued.clear(); 184 mInputBufferIsDequeued.resize(mInputBuffers.size()); 185 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) { 186 mInputBufferIsDequeued.editItemAt(i) = false; 187 } 188} 189 190void NuPlayer::Decoder::requestCodecNotification() { 191 if (mCodec != NULL) { 192 sp<AMessage> reply = new AMessage(kWhatCodecNotify, id()); 193 reply->setInt32("generation", mBufferGeneration); 194 mCodec->requestActivityNotification(reply); 195 } 196} 197 198bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) { 199 int32_t generation; 200 CHECK(msg->findInt32("generation", &generation)); 201 return generation != mBufferGeneration; 202} 203 204void NuPlayer::Decoder::init() { 205 mDecoderLooper->registerHandler(this); 206} 207 208void NuPlayer::Decoder::configure(const sp<AMessage> &format) { 209 sp<AMessage> msg = new AMessage(kWhatConfigure, id()); 210 msg->setMessage("format", format); 211 msg->post(); 212} 213 214void NuPlayer::Decoder::signalUpdateFormat(const sp<AMessage> &format) { 215 sp<AMessage> msg = new AMessage(kWhatUpdateFormat, id()); 216 msg->setMessage("format", format); 217 msg->post(); 218} 219 220status_t NuPlayer::Decoder::getInputBuffers(Vector<sp<ABuffer> > *buffers) const { 221 sp<AMessage> msg = new AMessage(kWhatGetInputBuffers, id()); 222 msg->setPointer("buffers", buffers); 223 224 sp<AMessage> response; 225 return PostAndAwaitResponse(msg, &response); 226} 227 228void NuPlayer::Decoder::handleError(int32_t err) 229{ 230 mCodec->release(); 231 232 sp<AMessage> notify = mNotify->dup(); 233 notify->setInt32("what", kWhatError); 234 notify->setInt32("err", err); 235 notify->post(); 236} 237 238bool NuPlayer::Decoder::handleAnInputBuffer() { 239 size_t bufferIx = -1; 240 status_t res = mCodec->dequeueInputBuffer(&bufferIx); 241 ALOGV("[%s] dequeued input: %d", 242 mComponentName.c_str(), res == OK ? (int)bufferIx : res); 243 if (res != OK) { 244 if (res != -EAGAIN) { 245 handleError(res); 246 } 247 return false; 248 } 249 250 CHECK_LT(bufferIx, mInputBuffers.size()); 251 252 if (mMediaBuffers[bufferIx] != NULL) { 253 mMediaBuffers[bufferIx]->release(); 254 mMediaBuffers.editItemAt(bufferIx) = NULL; 255 } 256 mInputBufferIsDequeued.editItemAt(bufferIx) = true; 257 258 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id()); 259 reply->setSize("buffer-ix", bufferIx); 260 reply->setInt32("generation", mBufferGeneration); 261 262 if (!mCSDsToSubmit.isEmpty()) { 263 sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0); 264 ALOGI("[%s] resubmitting CSD", mComponentName.c_str()); 265 reply->setBuffer("buffer", buffer); 266 mCSDsToSubmit.removeAt(0); 267 reply->post(); 268 return true; 269 } 270 271 sp<AMessage> notify = mNotify->dup(); 272 notify->setInt32("what", kWhatFillThisBuffer); 273 notify->setBuffer("buffer", mInputBuffers[bufferIx]); 274 notify->setMessage("reply", reply); 275 notify->post(); 276 return true; 277} 278 279void android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) { 280 size_t bufferIx; 281 CHECK(msg->findSize("buffer-ix", &bufferIx)); 282 CHECK_LT(bufferIx, mInputBuffers.size()); 283 sp<ABuffer> codecBuffer = mInputBuffers[bufferIx]; 284 285 sp<ABuffer> buffer; 286 bool hasBuffer = msg->findBuffer("buffer", &buffer); 287 288 // handle widevine classic source - that fills an arbitrary input buffer 289 MediaBuffer *mediaBuffer = NULL; 290 if (hasBuffer) { 291 mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase()); 292 if (mediaBuffer != NULL) { 293 // likely filled another buffer than we requested: adjust buffer index 294 size_t ix; 295 for (ix = 0; ix < mInputBuffers.size(); ix++) { 296 const sp<ABuffer> &buf = mInputBuffers[ix]; 297 if (buf->data() == mediaBuffer->data()) { 298 // all input buffers are dequeued on start, hence the check 299 CHECK(mInputBufferIsDequeued[ix]); 300 ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu", 301 mComponentName.c_str(), ix, bufferIx); 302 303 // TRICKY: need buffer for the metadata, so instead, set 304 // codecBuffer to the same (though incorrect) buffer to 305 // avoid a memcpy into the codecBuffer 306 codecBuffer = buffer; 307 codecBuffer->setRange( 308 mediaBuffer->range_offset(), 309 mediaBuffer->range_length()); 310 bufferIx = ix; 311 break; 312 } 313 } 314 CHECK(ix < mInputBuffers.size()); 315 } 316 } 317 318 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 319 320 if (buffer == NULL /* includes !hasBuffer */) { 321 int32_t streamErr = ERROR_END_OF_STREAM; 322 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer); 323 324 if (streamErr == OK) { 325 /* buffers are returned to hold on to */ 326 return; 327 } 328 329 // attempt to queue EOS 330 status_t err = mCodec->queueInputBuffer( 331 bufferIx, 332 0, 333 0, 334 0, 335 MediaCodec::BUFFER_FLAG_EOS); 336 if (streamErr == ERROR_END_OF_STREAM && err != OK) { 337 streamErr = err; 338 // err will not be ERROR_END_OF_STREAM 339 } 340 341 if (streamErr != ERROR_END_OF_STREAM) { 342 handleError(streamErr); 343 } 344 } else { 345 int64_t timeUs = 0; 346 uint32_t flags = 0; 347 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 348 349 int32_t eos, csd; 350 // we do not expect SYNCFRAME for decoder 351 if (buffer->meta()->findInt32("eos", &eos) && eos) { 352 flags |= MediaCodec::BUFFER_FLAG_EOS; 353 } else if (buffer->meta()->findInt32("csd", &csd) && csd) { 354 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG; 355 } 356 357 // copy into codec buffer 358 if (buffer != codecBuffer) { 359 CHECK_LE(buffer->size(), codecBuffer->capacity()); 360 codecBuffer->setRange(0, buffer->size()); 361 memcpy(codecBuffer->data(), buffer->data(), buffer->size()); 362 } 363 364 status_t err = mCodec->queueInputBuffer( 365 bufferIx, 366 codecBuffer->offset(), 367 codecBuffer->size(), 368 timeUs, 369 flags); 370 if (err != OK) { 371 ALOGE("Failed to queue input buffer for %s (err=%d)", 372 mComponentName.c_str(), err); 373 handleError(err); 374 } 375 376 if (mediaBuffer != NULL) { 377 CHECK(mMediaBuffers[bufferIx] == NULL); 378 mMediaBuffers.editItemAt(bufferIx) = mediaBuffer; 379 } 380 } 381} 382 383bool NuPlayer::Decoder::handleAnOutputBuffer() { 384 size_t bufferIx = -1; 385 size_t offset; 386 size_t size; 387 int64_t timeUs; 388 uint32_t flags; 389 status_t res = mCodec->dequeueOutputBuffer( 390 &bufferIx, &offset, &size, &timeUs, &flags); 391 392 if (res != OK) { 393 ALOGV("[%s] dequeued output: %d", mComponentName.c_str(), res); 394 } else { 395 ALOGV("[%s] dequeued output: %d (time=%lld flags=%" PRIu32 ")", 396 mComponentName.c_str(), (int)bufferIx, timeUs, flags); 397 } 398 399 if (res == INFO_OUTPUT_BUFFERS_CHANGED) { 400 res = mCodec->getOutputBuffers(&mOutputBuffers); 401 if (res != OK) { 402 ALOGE("Failed to get output buffers for %s after INFO event (err=%d)", 403 mComponentName.c_str(), res); 404 handleError(res); 405 return false; 406 } 407 // NuPlayer ignores this 408 return true; 409 } else if (res == INFO_FORMAT_CHANGED) { 410 sp<AMessage> format = new AMessage(); 411 res = mCodec->getOutputFormat(&format); 412 if (res != OK) { 413 ALOGE("Failed to get output format for %s after INFO event (err=%d)", 414 mComponentName.c_str(), res); 415 handleError(res); 416 return false; 417 } 418 419 sp<AMessage> notify = mNotify->dup(); 420 notify->setInt32("what", kWhatOutputFormatChanged); 421 notify->setMessage("format", format); 422 notify->post(); 423 return true; 424 } else if (res == INFO_DISCONTINUITY) { 425 // nothing to do 426 return true; 427 } else if (res != OK) { 428 if (res != -EAGAIN) { 429 handleError(res); 430 } 431 return false; 432 } 433 434 CHECK_LT(bufferIx, mOutputBuffers.size()); 435 sp<ABuffer> buffer = mOutputBuffers[bufferIx]; 436 buffer->setRange(offset, size); 437 buffer->meta()->clear(); 438 buffer->meta()->setInt64("timeUs", timeUs); 439 if (flags & MediaCodec::BUFFER_FLAG_EOS) { 440 buffer->meta()->setInt32("eos", true); 441 } 442 // we do not expect CODECCONFIG or SYNCFRAME for decoder 443 444 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, id()); 445 reply->setSize("buffer-ix", bufferIx); 446 reply->setInt32("generation", mBufferGeneration); 447 448 sp<AMessage> notify = mNotify->dup(); 449 notify->setInt32("what", kWhatDrainThisBuffer); 450 notify->setBuffer("buffer", buffer); 451 notify->setMessage("reply", reply); 452 notify->post(); 453 454 // FIXME: This should be handled after rendering is complete, 455 // but Renderer needs it now 456 if (flags & MediaCodec::BUFFER_FLAG_EOS) { 457 ALOGV("queueing eos [%s]", mComponentName.c_str()); 458 sp<AMessage> notify = mNotify->dup(); 459 notify->setInt32("what", kWhatEOS); 460 notify->setInt32("err", ERROR_END_OF_STREAM); 461 notify->post(); 462 } 463 return true; 464} 465 466void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) { 467 status_t err; 468 int32_t render; 469 size_t bufferIx; 470 CHECK(msg->findSize("buffer-ix", &bufferIx)); 471 if (msg->findInt32("render", &render) && render) { 472 int64_t timestampNs; 473 CHECK(msg->findInt64("timestampNs", ×tampNs)); 474 err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs); 475 } else { 476 err = mCodec->releaseOutputBuffer(bufferIx); 477 } 478 if (err != OK) { 479 ALOGE("failed to release output buffer for %s (err=%d)", 480 mComponentName.c_str(), err); 481 handleError(err); 482 } 483} 484 485void NuPlayer::Decoder::onFlush() { 486 status_t err = OK; 487 if (mCodec != NULL) { 488 err = mCodec->flush(); 489 mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator 490 ++mBufferGeneration; 491 } 492 493 if (err != OK) { 494 ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err); 495 handleError(err); 496 return; 497 } 498 499 releaseAndResetMediaBuffers(); 500 501 sp<AMessage> notify = mNotify->dup(); 502 notify->setInt32("what", kWhatFlushCompleted); 503 notify->post(); 504 mPaused = true; 505} 506 507void NuPlayer::Decoder::onResume() { 508 mPaused = false; 509} 510 511void NuPlayer::Decoder::onShutdown() { 512 status_t err = OK; 513 if (mCodec != NULL) { 514 err = mCodec->release(); 515 mCodec = NULL; 516 ++mBufferGeneration; 517 518 if (mNativeWindow != NULL) { 519 // reconnect to surface as MediaCodec disconnected from it 520 status_t error = 521 native_window_api_connect( 522 mNativeWindow->getNativeWindow().get(), 523 NATIVE_WINDOW_API_MEDIA); 524 ALOGW_IF(error != NO_ERROR, 525 "[%s] failed to connect to native window, error=%d", 526 mComponentName.c_str(), error); 527 } 528 mComponentName = "decoder"; 529 } 530 531 releaseAndResetMediaBuffers(); 532 533 if (err != OK) { 534 ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err); 535 handleError(err); 536 return; 537 } 538 539 sp<AMessage> notify = mNotify->dup(); 540 notify->setInt32("what", kWhatShutdownCompleted); 541 notify->post(); 542 mPaused = true; 543} 544 545void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) { 546 ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str()); 547 548 switch (msg->what()) { 549 case kWhatConfigure: 550 { 551 sp<AMessage> format; 552 CHECK(msg->findMessage("format", &format)); 553 onConfigure(format); 554 break; 555 } 556 557 case kWhatUpdateFormat: 558 { 559 sp<AMessage> format; 560 CHECK(msg->findMessage("format", &format)); 561 rememberCodecSpecificData(format); 562 break; 563 } 564 565 case kWhatGetInputBuffers: 566 { 567 uint32_t replyID; 568 CHECK(msg->senderAwaitsResponse(&replyID)); 569 570 Vector<sp<ABuffer> > *dstBuffers; 571 CHECK(msg->findPointer("buffers", (void **)&dstBuffers)); 572 573 dstBuffers->clear(); 574 for (size_t i = 0; i < mInputBuffers.size(); i++) { 575 dstBuffers->push(mInputBuffers[i]); 576 } 577 578 (new AMessage)->postReply(replyID); 579 break; 580 } 581 582 case kWhatCodecNotify: 583 { 584 if (!isStaleReply(msg)) { 585 if (!mPaused) { 586 while (handleAnInputBuffer()) { 587 } 588 } 589 590 while (handleAnOutputBuffer()) { 591 } 592 } 593 594 requestCodecNotification(); 595 break; 596 } 597 598 case kWhatInputBufferFilled: 599 { 600 if (!isStaleReply(msg)) { 601 onInputBufferFilled(msg); 602 } 603 604 break; 605 } 606 607 case kWhatRenderBuffer: 608 { 609 if (!isStaleReply(msg)) { 610 onRenderBuffer(msg); 611 } 612 break; 613 } 614 615 case kWhatFlush: 616 { 617 sp<AMessage> format; 618 if (msg->findMessage("new-format", &format)) { 619 rememberCodecSpecificData(format); 620 } 621 onFlush(); 622 break; 623 } 624 625 case kWhatResume: 626 { 627 onResume(); 628 break; 629 } 630 631 case kWhatShutdown: 632 { 633 onShutdown(); 634 break; 635 } 636 637 default: 638 TRESPASS(); 639 break; 640 } 641} 642 643void NuPlayer::Decoder::signalFlush(const sp<AMessage> &format) { 644 sp<AMessage> msg = new AMessage(kWhatFlush, id()); 645 if (format != NULL) { 646 msg->setMessage("new-format", format); 647 } 648 msg->post(); 649} 650 651void NuPlayer::Decoder::signalResume() { 652 (new AMessage(kWhatResume, id()))->post(); 653} 654 655void NuPlayer::Decoder::initiateShutdown() { 656 (new AMessage(kWhatShutdown, id()))->post(); 657} 658 659bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const { 660 if (targetFormat == NULL) { 661 return true; 662 } 663 664 AString mime; 665 if (!targetFormat->findString("mime", &mime)) { 666 return false; 667 } 668 669 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { 670 // field-by-field comparison 671 const char * keys[] = { "channel-count", "sample-rate", "is-adts" }; 672 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) { 673 int32_t oldVal, newVal; 674 if (!mOutputFormat->findInt32(keys[i], &oldVal) || 675 !targetFormat->findInt32(keys[i], &newVal) || 676 oldVal != newVal) { 677 return false; 678 } 679 } 680 681 sp<ABuffer> oldBuf, newBuf; 682 if (mOutputFormat->findBuffer("csd-0", &oldBuf) && 683 targetFormat->findBuffer("csd-0", &newBuf)) { 684 if (oldBuf->size() != newBuf->size()) { 685 return false; 686 } 687 return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size()); 688 } 689 } 690 return false; 691} 692 693bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const { 694 if (mOutputFormat == NULL) { 695 return false; 696 } 697 698 if (targetFormat == NULL) { 699 return true; 700 } 701 702 AString oldMime, newMime; 703 if (!mOutputFormat->findString("mime", &oldMime) 704 || !targetFormat->findString("mime", &newMime) 705 || !(oldMime == newMime)) { 706 return false; 707 } 708 709 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/")); 710 bool seamless; 711 if (audio) { 712 seamless = supportsSeamlessAudioFormatChange(targetFormat); 713 } else { 714 int32_t isAdaptive; 715 seamless = (mCodec != NULL && 716 mInputFormat->findInt32("adaptive-playback", &isAdaptive) && 717 isAdaptive); 718 } 719 720 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str()); 721 return seamless; 722} 723 724struct CCData { 725 CCData(uint8_t type, uint8_t data1, uint8_t data2) 726 : mType(type), mData1(data1), mData2(data2) { 727 } 728 bool getChannel(size_t *channel) const { 729 if (mData1 >= 0x10 && mData1 <= 0x1f) { 730 *channel = (mData1 >= 0x18 ? 1 : 0) + (mType ? 2 : 0); 731 return true; 732 } 733 return false; 734 } 735 736 uint8_t mType; 737 uint8_t mData1; 738 uint8_t mData2; 739}; 740 741static bool isNullPad(CCData *cc) { 742 return cc->mData1 < 0x10 && cc->mData2 < 0x10; 743} 744 745static void dumpBytePair(const sp<ABuffer> &ccBuf) { 746 size_t offset = 0; 747 AString out; 748 749 while (offset < ccBuf->size()) { 750 char tmp[128]; 751 752 CCData *cc = (CCData *) (ccBuf->data() + offset); 753 754 if (isNullPad(cc)) { 755 // 1 null pad or XDS metadata, ignore 756 offset += sizeof(CCData); 757 continue; 758 } 759 760 if (cc->mData1 >= 0x20 && cc->mData1 <= 0x7f) { 761 // 2 basic chars 762 sprintf(tmp, "[%d]Basic: %c %c", cc->mType, cc->mData1, cc->mData2); 763 } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19) 764 && cc->mData2 >= 0x30 && cc->mData2 <= 0x3f) { 765 // 1 special char 766 sprintf(tmp, "[%d]Special: %02x %02x", cc->mType, cc->mData1, cc->mData2); 767 } else if ((cc->mData1 == 0x12 || cc->mData1 == 0x1A) 768 && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){ 769 // 1 Spanish/French char 770 sprintf(tmp, "[%d]Spanish: %02x %02x", cc->mType, cc->mData1, cc->mData2); 771 } else if ((cc->mData1 == 0x13 || cc->mData1 == 0x1B) 772 && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){ 773 // 1 Portuguese/German/Danish char 774 sprintf(tmp, "[%d]German: %02x %02x", cc->mType, cc->mData1, cc->mData2); 775 } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19) 776 && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f){ 777 // Mid-Row Codes (Table 69) 778 sprintf(tmp, "[%d]Mid-row: %02x %02x", cc->mType, cc->mData1, cc->mData2); 779 } else if (((cc->mData1 == 0x14 || cc->mData1 == 0x1c) 780 && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f) 781 || 782 ((cc->mData1 == 0x17 || cc->mData1 == 0x1f) 783 && cc->mData2 >= 0x21 && cc->mData2 <= 0x23)){ 784 // Misc Control Codes (Table 70) 785 sprintf(tmp, "[%d]Ctrl: %02x %02x", cc->mType, cc->mData1, cc->mData2); 786 } else if ((cc->mData1 & 0x70) == 0x10 787 && (cc->mData2 & 0x40) == 0x40 788 && ((cc->mData1 & 0x07) || !(cc->mData2 & 0x20)) ) { 789 // Preamble Address Codes (Table 71) 790 sprintf(tmp, "[%d]PAC: %02x %02x", cc->mType, cc->mData1, cc->mData2); 791 } else { 792 sprintf(tmp, "[%d]Invalid: %02x %02x", cc->mType, cc->mData1, cc->mData2); 793 } 794 795 if (out.size() > 0) { 796 out.append(", "); 797 } 798 799 out.append(tmp); 800 801 offset += sizeof(CCData); 802 } 803 804 ALOGI("%s", out.c_str()); 805} 806 807NuPlayer::CCDecoder::CCDecoder(const sp<AMessage> ¬ify) 808 : mNotify(notify), 809 mCurrentChannel(0), 810 mSelectedTrack(-1) { 811 for (size_t i = 0; i < sizeof(mTrackIndices)/sizeof(mTrackIndices[0]); ++i) { 812 mTrackIndices[i] = -1; 813 } 814} 815 816size_t NuPlayer::CCDecoder::getTrackCount() const { 817 return mFoundChannels.size(); 818} 819 820sp<AMessage> NuPlayer::CCDecoder::getTrackInfo(size_t index) const { 821 if (!isTrackValid(index)) { 822 return NULL; 823 } 824 825 sp<AMessage> format = new AMessage(); 826 827 format->setInt32("type", MEDIA_TRACK_TYPE_SUBTITLE); 828 format->setString("language", "und"); 829 format->setString("mime", MEDIA_MIMETYPE_TEXT_CEA_608); 830 //CC1, field 0 channel 0 831 bool isDefaultAuto = (mFoundChannels[index] == 0); 832 format->setInt32("auto", isDefaultAuto); 833 format->setInt32("default", isDefaultAuto); 834 format->setInt32("forced", 0); 835 836 return format; 837} 838 839status_t NuPlayer::CCDecoder::selectTrack(size_t index, bool select) { 840 if (!isTrackValid(index)) { 841 return BAD_VALUE; 842 } 843 844 if (select) { 845 if (mSelectedTrack == (ssize_t)index) { 846 ALOGE("track %zu already selected", index); 847 return BAD_VALUE; 848 } 849 ALOGV("selected track %zu", index); 850 mSelectedTrack = index; 851 } else { 852 if (mSelectedTrack != (ssize_t)index) { 853 ALOGE("track %zu is not selected", index); 854 return BAD_VALUE; 855 } 856 ALOGV("unselected track %zu", index); 857 mSelectedTrack = -1; 858 } 859 860 return OK; 861} 862 863bool NuPlayer::CCDecoder::isSelected() const { 864 return mSelectedTrack >= 0 && mSelectedTrack < (int32_t) getTrackCount(); 865} 866 867bool NuPlayer::CCDecoder::isTrackValid(size_t index) const { 868 return index < getTrackCount(); 869} 870 871int32_t NuPlayer::CCDecoder::getTrackIndex(size_t channel) const { 872 if (channel < sizeof(mTrackIndices)/sizeof(mTrackIndices[0])) { 873 return mTrackIndices[channel]; 874 } 875 return -1; 876} 877 878// returns true if a new CC track is found 879bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) { 880 int64_t timeUs; 881 CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); 882 883 sp<ABuffer> sei; 884 if (!accessUnit->meta()->findBuffer("sei", &sei) || sei == NULL) { 885 return false; 886 } 887 888 bool trackAdded = false; 889 890 NALBitReader br(sei->data() + 1, sei->size() - 1); 891 // sei_message() 892 while (br.atLeastNumBitsLeft(16)) { // at least 16-bit for sei_message() 893 uint32_t payload_type = 0; 894 size_t payload_size = 0; 895 uint8_t last_byte; 896 897 do { 898 last_byte = br.getBits(8); 899 payload_type += last_byte; 900 } while (last_byte == 0xFF); 901 902 do { 903 last_byte = br.getBits(8); 904 payload_size += last_byte; 905 } while (last_byte == 0xFF); 906 907 // sei_payload() 908 if (payload_type == 4) { 909 // user_data_registered_itu_t_t35() 910 911 // ATSC A/72: 6.4.2 912 uint8_t itu_t_t35_country_code = br.getBits(8); 913 uint16_t itu_t_t35_provider_code = br.getBits(16); 914 uint32_t user_identifier = br.getBits(32); 915 uint8_t user_data_type_code = br.getBits(8); 916 917 payload_size -= 1 + 2 + 4 + 1; 918 919 if (itu_t_t35_country_code == 0xB5 920 && itu_t_t35_provider_code == 0x0031 921 && user_identifier == 'GA94' 922 && user_data_type_code == 0x3) { 923 // MPEG_cc_data() 924 // ATSC A/53 Part 4: 6.2.3.1 925 br.skipBits(1); //process_em_data_flag 926 bool process_cc_data_flag = br.getBits(1); 927 br.skipBits(1); //additional_data_flag 928 size_t cc_count = br.getBits(5); 929 br.skipBits(8); // em_data; 930 payload_size -= 2; 931 932 if (process_cc_data_flag) { 933 AString out; 934 935 sp<ABuffer> ccBuf = new ABuffer(cc_count * sizeof(CCData)); 936 ccBuf->setRange(0, 0); 937 938 for (size_t i = 0; i < cc_count; i++) { 939 uint8_t marker = br.getBits(5); 940 CHECK_EQ(marker, 0x1f); 941 942 bool cc_valid = br.getBits(1); 943 uint8_t cc_type = br.getBits(2); 944 // remove odd parity bit 945 uint8_t cc_data_1 = br.getBits(8) & 0x7f; 946 uint8_t cc_data_2 = br.getBits(8) & 0x7f; 947 948 if (cc_valid 949 && (cc_type == 0 || cc_type == 1)) { 950 CCData cc(cc_type, cc_data_1, cc_data_2); 951 if (!isNullPad(&cc)) { 952 size_t channel; 953 if (cc.getChannel(&channel) && getTrackIndex(channel) < 0) { 954 mTrackIndices[channel] = mFoundChannels.size(); 955 mFoundChannels.push_back(channel); 956 trackAdded = true; 957 } 958 memcpy(ccBuf->data() + ccBuf->size(), 959 (void *)&cc, sizeof(cc)); 960 ccBuf->setRange(0, ccBuf->size() + sizeof(CCData)); 961 } 962 } 963 } 964 payload_size -= cc_count * 3; 965 966 mCCMap.add(timeUs, ccBuf); 967 break; 968 } 969 } else { 970 ALOGV("Malformed SEI payload type 4"); 971 } 972 } else { 973 ALOGV("Unsupported SEI payload type %d", payload_type); 974 } 975 976 // skipping remaining bits of this payload 977 br.skipBits(payload_size * 8); 978 } 979 980 return trackAdded; 981} 982 983sp<ABuffer> NuPlayer::CCDecoder::filterCCBuf( 984 const sp<ABuffer> &ccBuf, size_t index) { 985 sp<ABuffer> filteredCCBuf = new ABuffer(ccBuf->size()); 986 filteredCCBuf->setRange(0, 0); 987 988 size_t cc_count = ccBuf->size() / sizeof(CCData); 989 const CCData* cc_data = (const CCData*)ccBuf->data(); 990 for (size_t i = 0; i < cc_count; ++i) { 991 size_t channel; 992 if (cc_data[i].getChannel(&channel)) { 993 mCurrentChannel = channel; 994 } 995 if (mCurrentChannel == mFoundChannels[index]) { 996 memcpy(filteredCCBuf->data() + filteredCCBuf->size(), 997 (void *)&cc_data[i], sizeof(CCData)); 998 filteredCCBuf->setRange(0, filteredCCBuf->size() + sizeof(CCData)); 999 } 1000 } 1001 1002 return filteredCCBuf; 1003} 1004 1005void NuPlayer::CCDecoder::decode(const sp<ABuffer> &accessUnit) { 1006 if (extractFromSEI(accessUnit)) { 1007 ALOGI("Found CEA-608 track"); 1008 sp<AMessage> msg = mNotify->dup(); 1009 msg->setInt32("what", kWhatTrackAdded); 1010 msg->post(); 1011 } 1012 // TODO: extract CC from other sources 1013} 1014 1015void NuPlayer::CCDecoder::display(int64_t timeUs) { 1016 if (!isTrackValid(mSelectedTrack)) { 1017 ALOGE("Could not find current track(index=%d)", mSelectedTrack); 1018 return; 1019 } 1020 1021 ssize_t index = mCCMap.indexOfKey(timeUs); 1022 if (index < 0) { 1023 ALOGV("cc for timestamp %" PRId64 " not found", timeUs); 1024 return; 1025 } 1026 1027 sp<ABuffer> ccBuf = filterCCBuf(mCCMap.valueAt(index), mSelectedTrack); 1028 1029 if (ccBuf->size() > 0) { 1030#if 0 1031 dumpBytePair(ccBuf); 1032#endif 1033 1034 ccBuf->meta()->setInt32("trackIndex", mSelectedTrack); 1035 ccBuf->meta()->setInt64("timeUs", timeUs); 1036 ccBuf->meta()->setInt64("durationUs", 0ll); 1037 1038 sp<AMessage> msg = mNotify->dup(); 1039 msg->setInt32("what", kWhatClosedCaptionData); 1040 msg->setBuffer("buffer", ccBuf); 1041 msg->post(); 1042 } 1043 1044 // remove all entries before timeUs 1045 mCCMap.removeItemsAt(0, index + 1); 1046} 1047 1048void NuPlayer::CCDecoder::flush() { 1049 mCCMap.clear(); 1050} 1051 1052} // namespace android 1053 1054