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