AwesomePlayer.cpp revision b9280d5c2313c41eb490f58198c4e59118e0e3e6
1/* 2 * Copyright (C) 2009 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 "AwesomePlayer" 19#include <utils/Log.h> 20 21#include "include/AwesomePlayer.h" 22#include "include/SoftwareRenderer.h" 23 24#include <binder/IPCThreadState.h> 25#include <media/stagefright/AudioPlayer.h> 26#include <media/stagefright/DataSource.h> 27#include <media/stagefright/FileSource.h> 28#include <media/stagefright/MediaBuffer.h> 29#include <media/stagefright/MediaDefs.h> 30#include <media/stagefright/MediaExtractor.h> 31#include <media/stagefright/MediaDebug.h> 32#include <media/stagefright/MediaSource.h> 33#include <media/stagefright/MetaData.h> 34#include <media/stagefright/OMXCodec.h> 35 36namespace android { 37 38struct AwesomeEvent : public TimedEventQueue::Event { 39 AwesomeEvent(AwesomePlayer *player, int32_t code) 40 : mPlayer(player), 41 mCode(code) { 42 } 43 44protected: 45 virtual ~AwesomeEvent() {} 46 47 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) { 48 mPlayer->onEvent(mCode); 49 } 50 51private: 52 AwesomePlayer *mPlayer; 53 int32_t mCode; 54 55 AwesomeEvent(const AwesomeEvent &); 56 AwesomeEvent &operator=(const AwesomeEvent &); 57}; 58 59struct AwesomeRemoteRenderer : public AwesomeRenderer { 60 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target) 61 : mTarget(target) { 62 } 63 64 virtual void render(MediaBuffer *buffer) { 65 void *id; 66 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) { 67 mTarget->render((IOMX::buffer_id)id); 68 } 69 } 70 71private: 72 sp<IOMXRenderer> mTarget; 73 74 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &); 75 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &); 76}; 77 78struct AwesomeLocalRenderer : public AwesomeRenderer { 79 AwesomeLocalRenderer( 80 OMX_COLOR_FORMATTYPE colorFormat, 81 const sp<ISurface> &surface, 82 size_t displayWidth, size_t displayHeight, 83 size_t decodedWidth, size_t decodedHeight) 84 : mTarget(new SoftwareRenderer( 85 colorFormat, surface, displayWidth, displayHeight, 86 decodedWidth, decodedHeight)) { 87 } 88 89 virtual void render(MediaBuffer *buffer) { 90 mTarget->render( 91 (const uint8_t *)buffer->data() + buffer->range_offset(), 92 buffer->range_length(), NULL); 93 } 94 95protected: 96 virtual ~AwesomeLocalRenderer() { 97 delete mTarget; 98 mTarget = NULL; 99 } 100 101private: 102 SoftwareRenderer *mTarget; 103 104 AwesomeLocalRenderer(const AwesomeLocalRenderer &); 105 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);; 106}; 107 108AwesomePlayer::AwesomePlayer() 109 : mTimeSource(NULL), 110 mAudioPlayer(NULL), 111 mLastVideoBuffer(NULL), 112 mVideoBuffer(NULL) { 113 CHECK_EQ(mClient.connect(), OK); 114 115 DataSource::RegisterDefaultSniffers(); 116 117 mVideoEvent = new AwesomeEvent(this, 0); 118 mVideoEventPending = false; 119 mStreamDoneEvent = new AwesomeEvent(this, 1); 120 mStreamDoneEventPending = false; 121 122 mQueue.start(); 123 124 reset(); 125} 126 127AwesomePlayer::~AwesomePlayer() { 128 mQueue.stop(); 129 130 reset(); 131 132 mClient.disconnect(); 133} 134 135void AwesomePlayer::cancelPlayerEvents() { 136 mQueue.cancelEvent(mVideoEvent->eventID()); 137 mVideoEventPending = false; 138 mQueue.cancelEvent(mStreamDoneEvent->eventID()); 139 mStreamDoneEventPending = false; 140} 141 142void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) { 143 Mutex::Autolock autoLock(mLock); 144 mListener = listener; 145} 146 147status_t AwesomePlayer::setDataSource(const char *uri) { 148 Mutex::Autolock autoLock(mLock); 149 150 reset_l(); 151 152 sp<MediaExtractor> extractor = MediaExtractor::CreateFromURI(uri); 153 154 if (extractor == NULL) { 155 return UNKNOWN_ERROR; 156 } 157 158 return setDataSource_l(extractor); 159} 160 161status_t AwesomePlayer::setDataSource( 162 int fd, int64_t offset, int64_t length) { 163 Mutex::Autolock autoLock(mLock); 164 165 reset_l(); 166 167 sp<DataSource> source = new FileSource(fd, offset, length); 168 169 status_t err = source->initCheck(); 170 171 if (err != OK) { 172 return err; 173 } 174 175 sp<MediaExtractor> extractor = MediaExtractor::Create(source); 176 177 if (extractor == NULL) { 178 return UNKNOWN_ERROR; 179 } 180 181 return setDataSource_l(extractor); 182} 183 184status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { 185 reset_l(); 186 187 bool haveAudio = false; 188 bool haveVideo = false; 189 for (size_t i = 0; i < extractor->countTracks(); ++i) { 190 sp<MetaData> meta = extractor->getTrackMetaData(i); 191 192 const char *mime; 193 CHECK(meta->findCString(kKeyMIMEType, &mime)); 194 195 if (!haveVideo && !strncasecmp(mime, "video/", 6)) { 196 if (setVideoSource(extractor->getTrack(i)) == OK) { 197 haveVideo = true; 198 } 199 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) { 200 if (setAudioSource(extractor->getTrack(i)) == OK) { 201 haveAudio = true; 202 } 203 } 204 205 if (haveAudio && haveVideo) { 206 break; 207 } 208 } 209 210 return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK; 211} 212 213void AwesomePlayer::reset() { 214 Mutex::Autolock autoLock(mLock); 215 reset_l(); 216} 217 218void AwesomePlayer::reset_l() { 219 cancelPlayerEvents(); 220 221 mVideoRenderer.clear(); 222 223 if (mLastVideoBuffer) { 224 mLastVideoBuffer->release(); 225 mLastVideoBuffer = NULL; 226 } 227 228 if (mVideoBuffer) { 229 mVideoBuffer->release(); 230 mVideoBuffer = NULL; 231 } 232 233 if (mVideoSource != NULL) { 234 mVideoSource->stop(); 235 mVideoSource.clear(); 236 } 237 238 mAudioSource.clear(); 239 240 if (mTimeSource != mAudioPlayer) { 241 delete mTimeSource; 242 } 243 mTimeSource = NULL; 244 245 delete mAudioPlayer; 246 mAudioPlayer = NULL; 247 248 mDurationUs = -1; 249 mFlags = 0; 250 mVideoWidth = mVideoHeight = -1; 251 mTimeSourceDeltaUs = 0; 252 mVideoTimeUs = 0; 253 254 mSeeking = false; 255 mSeekTimeUs = 0; 256} 257 258// static 259void AwesomePlayer::AudioNotify(void *_me, int what) { 260 AwesomePlayer *me = (AwesomePlayer *)_me; 261 262 Mutex::Autolock autoLock(me->mLock); 263 264 switch (what) { 265 case AudioPlayer::REACHED_EOS: 266 me->postStreamDoneEvent_l(); 267 break; 268 269 case AudioPlayer::SEEK_COMPLETE: 270 { 271 me->notifyListener_l(MEDIA_SEEK_COMPLETE); 272 break; 273 } 274 275 default: 276 CHECK(!"should not be here."); 277 break; 278 } 279} 280 281void AwesomePlayer::notifyListener_l(int msg) { 282 if (mListener != NULL) { 283 sp<MediaPlayerBase> listener = mListener.promote(); 284 285 if (listener != NULL) { 286 listener->sendEvent(msg); 287 } 288 } 289} 290 291void AwesomePlayer::onStreamDone() { 292 // Posted whenever any stream finishes playing. 293 294 Mutex::Autolock autoLock(mLock); 295 mStreamDoneEventPending = false; 296 297 if (mFlags & LOOPING) { 298 seekTo_l(0); 299 300 if (mVideoRenderer != NULL) { 301 postVideoEvent_l(); 302 } 303 } else { 304 notifyListener_l(MEDIA_PLAYBACK_COMPLETE); 305 306 pause_l(); 307 } 308} 309 310status_t AwesomePlayer::play() { 311 Mutex::Autolock autoLock(mLock); 312 313 if (mFlags & PLAYING) { 314 return OK; 315 } 316 317 mFlags |= PLAYING; 318 mFlags |= FIRST_FRAME; 319 320 bool deferredAudioSeek = false; 321 322 if (mAudioSource != NULL) { 323 if (mAudioPlayer == NULL) { 324 if (mAudioSink != NULL) { 325 mAudioPlayer = new AudioPlayer(mAudioSink); 326 327 mAudioPlayer->setListenerCallback( 328 &AwesomePlayer::AudioNotify, this); 329 330 mAudioPlayer->setSource(mAudioSource); 331 mAudioPlayer->start(); 332 333 delete mTimeSource; 334 mTimeSource = mAudioPlayer; 335 336 deferredAudioSeek = true; 337 } 338 } else { 339 mAudioPlayer->resume(); 340 } 341 } 342 343 if (mTimeSource == NULL && mAudioPlayer == NULL) { 344 mTimeSource = new SystemTimeSource; 345 } 346 347 if (mVideoSource != NULL) { 348 if (mVideoRenderer == NULL) { 349 initRenderer_l(); 350 } 351 352 if (mVideoRenderer != NULL) { 353 // Kick off video playback 354 postVideoEvent_l(); 355 } 356 } 357 358 if (deferredAudioSeek) { 359 // If there was a seek request while we were paused 360 // and we're just starting up again, honor the request now. 361 seekAudioIfNecessary_l(); 362 } 363 364 return OK; 365} 366 367void AwesomePlayer::initRenderer_l() { 368 if (mISurface != NULL) { 369 sp<MetaData> meta = mVideoSource->getFormat(); 370 371 int32_t format; 372 const char *component; 373 int32_t decodedWidth, decodedHeight; 374 CHECK(meta->findInt32(kKeyColorFormat, &format)); 375 CHECK(meta->findCString(kKeyDecoderComponent, &component)); 376 CHECK(meta->findInt32(kKeyWidth, &decodedWidth)); 377 CHECK(meta->findInt32(kKeyHeight, &decodedHeight)); 378 379 mVideoRenderer.clear(); 380 381 // Must ensure that mVideoRenderer's destructor is actually executed 382 // before creating a new one. 383 IPCThreadState::self()->flushCommands(); 384 385 if (!strncmp("OMX.", component, 4)) { 386 // Our OMX codecs allocate buffers on the media_server side 387 // therefore they require a remote IOMXRenderer that knows how 388 // to display them. 389 mVideoRenderer = new AwesomeRemoteRenderer( 390 mClient.interface()->createRenderer( 391 mISurface, component, 392 (OMX_COLOR_FORMATTYPE)format, 393 decodedWidth, decodedHeight, 394 mVideoWidth, mVideoHeight)); 395 } else { 396 // Other decoders are instantiated locally and as a consequence 397 // allocate their buffers in local address space. 398 mVideoRenderer = new AwesomeLocalRenderer( 399 (OMX_COLOR_FORMATTYPE)format, 400 mISurface, 401 mVideoWidth, mVideoHeight, 402 decodedWidth, decodedHeight); 403 } 404 } 405} 406 407status_t AwesomePlayer::pause() { 408 Mutex::Autolock autoLock(mLock); 409 return pause_l(); 410} 411 412status_t AwesomePlayer::pause_l() { 413 if (!(mFlags & PLAYING)) { 414 return OK; 415 } 416 417 cancelPlayerEvents(); 418 419 if (mAudioPlayer != NULL) { 420 mAudioPlayer->pause(); 421 } 422 423 mFlags &= ~PLAYING; 424 425 return OK; 426} 427 428bool AwesomePlayer::isPlaying() const { 429 Mutex::Autolock autoLock(mLock); 430 431 return mFlags & PLAYING; 432} 433 434void AwesomePlayer::setISurface(const sp<ISurface> &isurface) { 435 Mutex::Autolock autoLock(mLock); 436 437 mISurface = isurface; 438} 439 440void AwesomePlayer::setAudioSink( 441 const sp<MediaPlayerBase::AudioSink> &audioSink) { 442 Mutex::Autolock autoLock(mLock); 443 444 mAudioSink = audioSink; 445} 446 447status_t AwesomePlayer::setLooping(bool shouldLoop) { 448 Mutex::Autolock autoLock(mLock); 449 450 mFlags = mFlags & ~LOOPING; 451 452 if (shouldLoop) { 453 mFlags |= LOOPING; 454 } 455 456 return OK; 457} 458 459status_t AwesomePlayer::getDuration(int64_t *durationUs) { 460 Mutex::Autolock autoLock(mLock); 461 462 if (mDurationUs < 0) { 463 return UNKNOWN_ERROR; 464 } 465 466 *durationUs = mDurationUs; 467 468 return OK; 469} 470 471status_t AwesomePlayer::getPosition(int64_t *positionUs) { 472 Mutex::Autolock autoLock(mLock); 473 474 if (mVideoRenderer != NULL) { 475 *positionUs = mVideoTimeUs; 476 } else if (mAudioPlayer != NULL) { 477 *positionUs = mAudioPlayer->getMediaTimeUs(); 478 } else { 479 *positionUs = 0; 480 } 481 482 return OK; 483} 484 485status_t AwesomePlayer::seekTo(int64_t timeUs) { 486 Mutex::Autolock autoLock(mLock); 487 return seekTo_l(timeUs); 488} 489 490status_t AwesomePlayer::seekTo_l(int64_t timeUs) { 491 mSeeking = true; 492 mSeekTimeUs = timeUs; 493 494 seekAudioIfNecessary_l(); 495 496 return OK; 497} 498 499void AwesomePlayer::seekAudioIfNecessary_l() { 500 if (mSeeking && mVideoRenderer == NULL && mAudioPlayer != NULL) { 501 mAudioPlayer->seekTo(mSeekTimeUs); 502 503 mSeeking = false; 504 } 505} 506 507status_t AwesomePlayer::getVideoDimensions( 508 int32_t *width, int32_t *height) const { 509 Mutex::Autolock autoLock(mLock); 510 511 if (mVideoWidth < 0 || mVideoHeight < 0) { 512 return UNKNOWN_ERROR; 513 } 514 515 *width = mVideoWidth; 516 *height = mVideoHeight; 517 518 return OK; 519} 520 521status_t AwesomePlayer::setAudioSource(const sp<MediaSource> &source) { 522 if (source == NULL) { 523 return UNKNOWN_ERROR; 524 } 525 526 sp<MetaData> meta = source->getFormat(); 527 528 const char *mime; 529 CHECK(meta->findCString(kKeyMIMEType, &mime)); 530 531 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) { 532 mAudioSource = source; 533 } else { 534 mAudioSource = OMXCodec::Create( 535 mClient.interface(), source->getFormat(), 536 false, // createEncoder 537 source); 538 } 539 540 if (mAudioSource != NULL) { 541 int64_t durationUs; 542 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) { 543 if (mDurationUs < 0 || durationUs > mDurationUs) { 544 mDurationUs = durationUs; 545 } 546 } 547 } 548 549 return mAudioSource != NULL ? OK : UNKNOWN_ERROR; 550} 551 552status_t AwesomePlayer::setVideoSource(const sp<MediaSource> &source) { 553 if (source == NULL) { 554 return UNKNOWN_ERROR; 555 } 556 557 mVideoSource = OMXCodec::Create( 558 mClient.interface(), source->getFormat(), 559 false, // createEncoder 560 source); 561 562 if (mVideoSource != NULL) { 563 int64_t durationUs; 564 if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) { 565 if (mDurationUs < 0 || durationUs > mDurationUs) { 566 mDurationUs = durationUs; 567 } 568 } 569 570 CHECK(source->getFormat()->findInt32(kKeyWidth, &mVideoWidth)); 571 CHECK(source->getFormat()->findInt32(kKeyHeight, &mVideoHeight)); 572 573 mVideoSource->start(); 574 } 575 576 return mVideoSource != NULL ? OK : UNKNOWN_ERROR; 577} 578 579void AwesomePlayer::onEvent(int32_t code) { 580 if (code == 1) { 581 onStreamDone(); 582 return; 583 } 584 585 Mutex::Autolock autoLock(mLock); 586 mVideoEventPending = false; 587 588 if (mSeeking) { 589 if (mLastVideoBuffer) { 590 mLastVideoBuffer->release(); 591 mLastVideoBuffer = NULL; 592 } 593 594 if (mVideoBuffer) { 595 mVideoBuffer->release(); 596 mVideoBuffer = NULL; 597 } 598 } 599 600 if (!mVideoBuffer) { 601 MediaSource::ReadOptions options; 602 if (mSeeking) { 603 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6); 604 605 options.setSeekTo(mSeekTimeUs); 606 } 607 for (;;) { 608 status_t err = mVideoSource->read(&mVideoBuffer, &options); 609 options.clearSeekTo(); 610 611 if (err != OK) { 612 CHECK_EQ(mVideoBuffer, NULL); 613 614 if (err == INFO_FORMAT_CHANGED) { 615 LOGV("VideoSource signalled format change."); 616 617 initRenderer_l(); 618 continue; 619 } 620 621 postStreamDoneEvent_l(); 622 return; 623 } 624 625 if (mVideoBuffer->range_length() == 0) { 626 // Some decoders, notably the PV AVC software decoder 627 // return spurious empty buffers that we just want to ignore. 628 629 mVideoBuffer->release(); 630 mVideoBuffer = NULL; 631 continue; 632 } 633 634 break; 635 } 636 } 637 638 int64_t timeUs; 639 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)); 640 641 mVideoTimeUs = timeUs; 642 643 if (mSeeking) { 644 if (mAudioPlayer != NULL) { 645 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6); 646 647 mAudioPlayer->seekTo(timeUs); 648 } else { 649 // If we're playing video only, report seek complete now, 650 // otherwise audio player will notify us later. 651 notifyListener_l(MEDIA_SEEK_COMPLETE); 652 } 653 654 mFlags |= FIRST_FRAME; 655 mSeeking = false; 656 } 657 658 if (mFlags & FIRST_FRAME) { 659 mFlags &= ~FIRST_FRAME; 660 661 mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs; 662 } 663 664 int64_t realTimeUs, mediaTimeUs; 665 if (mAudioPlayer != NULL 666 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) { 667 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs; 668 } 669 670 int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs; 671 672 int64_t latenessUs = nowUs - timeUs; 673 674 if (latenessUs > 40000) { 675 // We're more than 40ms late. 676 LOGI("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6); 677 678 mVideoBuffer->release(); 679 mVideoBuffer = NULL; 680 681 postVideoEvent_l(); 682 return; 683 } 684 685 if (latenessUs < -10000) { 686 // We're more than 10ms early. 687 688 postVideoEvent_l(10000); 689 return; 690 } 691 692 mVideoRenderer->render(mVideoBuffer); 693 694 if (mLastVideoBuffer) { 695 mLastVideoBuffer->release(); 696 mLastVideoBuffer = NULL; 697 } 698 mLastVideoBuffer = mVideoBuffer; 699 mVideoBuffer = NULL; 700 701 postVideoEvent_l(); 702} 703 704void AwesomePlayer::postVideoEvent_l(int64_t delayUs) { 705 if (mVideoEventPending) { 706 return; 707 } 708 709 mVideoEventPending = true; 710 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs); 711} 712 713void AwesomePlayer::postStreamDoneEvent_l() { 714 if (mStreamDoneEventPending) { 715 return; 716 } 717 mStreamDoneEventPending = true; 718 mQueue.postEvent(mStreamDoneEvent); 719} 720 721} // namespace android 722 723