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