SimplePlayer.cpp revision e98f8c04faf27df3b1829d336299ad51dad569cf
1/* 2 * Copyright (C) 2012 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 "SimplePlayer" 19#include <utils/Log.h> 20 21#include "SimplePlayer.h" 22 23#include <gui/SurfaceTextureClient.h> 24#include <media/AudioTrack.h> 25#include <media/stagefright/foundation/ABuffer.h> 26#include <media/stagefright/foundation/ADebug.h> 27#include <media/stagefright/foundation/AMessage.h> 28#include <media/stagefright/MediaCodec.h> 29#include <media/stagefright/MediaErrors.h> 30#include <media/stagefright/NativeWindowWrapper.h> 31#include <media/stagefright/NuMediaExtractor.h> 32 33namespace android { 34 35SimplePlayer::SimplePlayer() 36 : mState(UNINITIALIZED), 37 mDoMoreStuffGeneration(0), 38 mStartTimeRealUs(-1ll) { 39} 40 41SimplePlayer::~SimplePlayer() { 42} 43 44// static 45status_t PostAndAwaitResponse( 46 const sp<AMessage> &msg, sp<AMessage> *response) { 47 status_t err = msg->postAndAwaitResponse(response); 48 49 if (err != OK) { 50 return err; 51 } 52 53 if (!(*response)->findInt32("err", &err)) { 54 err = OK; 55 } 56 57 return err; 58} 59status_t SimplePlayer::setDataSource(const char *path) { 60 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); 61 msg->setString("path", path); 62 sp<AMessage> response; 63 return PostAndAwaitResponse(msg, &response); 64} 65 66status_t SimplePlayer::setSurface(const sp<ISurfaceTexture> &surfaceTexture) { 67 sp<AMessage> msg = new AMessage(kWhatSetSurface, id()); 68 69 sp<SurfaceTextureClient> surfaceTextureClient; 70 if (surfaceTexture != NULL) { 71 surfaceTextureClient = new SurfaceTextureClient(surfaceTexture); 72 } 73 74 msg->setObject( 75 "native-window", new NativeWindowWrapper(surfaceTextureClient)); 76 77 sp<AMessage> response; 78 return PostAndAwaitResponse(msg, &response); 79} 80 81status_t SimplePlayer::prepare() { 82 sp<AMessage> msg = new AMessage(kWhatPrepare, id()); 83 sp<AMessage> response; 84 return PostAndAwaitResponse(msg, &response); 85} 86 87status_t SimplePlayer::start() { 88 sp<AMessage> msg = new AMessage(kWhatStart, id()); 89 sp<AMessage> response; 90 return PostAndAwaitResponse(msg, &response); 91} 92 93status_t SimplePlayer::stop() { 94 sp<AMessage> msg = new AMessage(kWhatStop, id()); 95 sp<AMessage> response; 96 return PostAndAwaitResponse(msg, &response); 97} 98 99status_t SimplePlayer::reset() { 100 sp<AMessage> msg = new AMessage(kWhatReset, id()); 101 sp<AMessage> response; 102 return PostAndAwaitResponse(msg, &response); 103} 104 105void SimplePlayer::onMessageReceived(const sp<AMessage> &msg) { 106 switch (msg->what()) { 107 case kWhatSetDataSource: 108 { 109 status_t err; 110 if (mState != UNINITIALIZED) { 111 err = INVALID_OPERATION; 112 } else { 113 CHECK(msg->findString("path", &mPath)); 114 mState = UNPREPARED; 115 } 116 117 uint32_t replyID; 118 CHECK(msg->senderAwaitsResponse(&replyID)); 119 120 sp<AMessage> response = new AMessage; 121 response->setInt32("err", err); 122 response->postReply(replyID); 123 break; 124 } 125 126 case kWhatSetSurface: 127 { 128 status_t err; 129 if (mState != UNPREPARED) { 130 err = INVALID_OPERATION; 131 } else { 132 sp<RefBase> obj; 133 CHECK(msg->findObject("native-window", &obj)); 134 135 mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get()); 136 137 err = OK; 138 } 139 140 uint32_t replyID; 141 CHECK(msg->senderAwaitsResponse(&replyID)); 142 143 sp<AMessage> response = new AMessage; 144 response->setInt32("err", err); 145 response->postReply(replyID); 146 break; 147 } 148 149 case kWhatPrepare: 150 { 151 status_t err; 152 if (mState != UNPREPARED) { 153 err = INVALID_OPERATION; 154 } else { 155 err = onPrepare(); 156 157 if (err == OK) { 158 mState = STOPPED; 159 } 160 } 161 162 uint32_t replyID; 163 CHECK(msg->senderAwaitsResponse(&replyID)); 164 165 sp<AMessage> response = new AMessage; 166 response->setInt32("err", err); 167 response->postReply(replyID); 168 break; 169 } 170 171 case kWhatStart: 172 { 173 status_t err = OK; 174 175 if (mState == UNPREPARED) { 176 err = onPrepare(); 177 178 if (err == OK) { 179 mState = STOPPED; 180 } 181 } 182 183 if (err == OK) { 184 if (mState != STOPPED) { 185 err = INVALID_OPERATION; 186 } else { 187 err = onStart(); 188 189 if (err == OK) { 190 mState = STARTED; 191 } 192 } 193 } 194 195 uint32_t replyID; 196 CHECK(msg->senderAwaitsResponse(&replyID)); 197 198 sp<AMessage> response = new AMessage; 199 response->setInt32("err", err); 200 response->postReply(replyID); 201 break; 202 } 203 204 case kWhatStop: 205 { 206 status_t err; 207 208 if (mState != STARTED) { 209 err = INVALID_OPERATION; 210 } else { 211 err = onStop(); 212 213 if (err == OK) { 214 mState = STOPPED; 215 } 216 } 217 218 uint32_t replyID; 219 CHECK(msg->senderAwaitsResponse(&replyID)); 220 221 sp<AMessage> response = new AMessage; 222 response->setInt32("err", err); 223 response->postReply(replyID); 224 break; 225 } 226 227 case kWhatReset: 228 { 229 status_t err = OK; 230 231 if (mState == STARTED) { 232 CHECK_EQ(onStop(), (status_t)OK); 233 mState = STOPPED; 234 } 235 236 if (mState == STOPPED) { 237 err = onReset(); 238 mState = UNINITIALIZED; 239 } 240 241 uint32_t replyID; 242 CHECK(msg->senderAwaitsResponse(&replyID)); 243 244 sp<AMessage> response = new AMessage; 245 response->setInt32("err", err); 246 response->postReply(replyID); 247 break; 248 } 249 250 case kWhatDoMoreStuff: 251 { 252 int32_t generation; 253 CHECK(msg->findInt32("generation", &generation)); 254 255 if (generation != mDoMoreStuffGeneration) { 256 break; 257 } 258 259 status_t err = onDoMoreStuff(); 260 261 if (err == OK) { 262 msg->post(10000ll); 263 } 264 break; 265 } 266 267 default: 268 TRESPASS(); 269 } 270} 271 272status_t SimplePlayer::onPrepare() { 273 CHECK_EQ(mState, UNPREPARED); 274 275 mExtractor = new NuMediaExtractor; 276 277 status_t err = mExtractor->setDataSource(mPath.c_str()); 278 279 if (err != OK) { 280 mExtractor.clear(); 281 return err; 282 } 283 284 if (mCodecLooper == NULL) { 285 mCodecLooper = new ALooper; 286 mCodecLooper->start(); 287 } 288 289 bool haveAudio = false; 290 bool haveVideo = false; 291 for (size_t i = 0; i < mExtractor->countTracks(); ++i) { 292 sp<AMessage> format; 293 status_t err = mExtractor->getTrackFormat(i, &format); 294 CHECK_EQ(err, (status_t)OK); 295 296 AString mime; 297 CHECK(format->findString("mime", &mime)); 298 299 if (!haveAudio && !strncasecmp(mime.c_str(), "audio/", 6)) { 300 haveAudio = true; 301 } else if (!haveVideo && !strncasecmp(mime.c_str(), "video/", 6)) { 302 haveVideo = true; 303 } else { 304 continue; 305 } 306 307 err = mExtractor->selectTrack(i); 308 CHECK_EQ(err, (status_t)OK); 309 310 CodecState *state = 311 &mStateByTrackIndex.editValueAt( 312 mStateByTrackIndex.add(i, CodecState())); 313 314 state->mNumFramesWritten = 0; 315 state->mCodec = MediaCodec::CreateByType( 316 mCodecLooper, mime.c_str(), false /* encoder */); 317 318 CHECK(state->mCodec != NULL); 319 320 err = state->mCodec->configure( 321 format, mNativeWindow->getSurfaceTextureClient(), 322 0 /* flags */); 323 324 CHECK_EQ(err, (status_t)OK); 325 326 size_t j = 0; 327 sp<ABuffer> buffer; 328 while (format->findBuffer(StringPrintf("csd-%d", j).c_str(), &buffer)) { 329 state->mCSD.push_back(buffer); 330 331 ++j; 332 } 333 } 334 335 for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { 336 CodecState *state = &mStateByTrackIndex.editValueAt(i); 337 338 status_t err = state->mCodec->start(); 339 CHECK_EQ(err, (status_t)OK); 340 341 err = state->mCodec->getInputBuffers(&state->mBuffers[0]); 342 CHECK_EQ(err, (status_t)OK); 343 344 err = state->mCodec->getOutputBuffers(&state->mBuffers[1]); 345 CHECK_EQ(err, (status_t)OK); 346 347 for (size_t j = 0; j < state->mCSD.size(); ++j) { 348 const sp<ABuffer> &srcBuffer = state->mCSD.itemAt(j); 349 350 size_t index; 351 err = state->mCodec->dequeueInputBuffer(&index, -1ll); 352 CHECK_EQ(err, (status_t)OK); 353 354 const sp<ABuffer> &dstBuffer = state->mBuffers[0].itemAt(index); 355 356 CHECK_LE(srcBuffer->size(), dstBuffer->capacity()); 357 dstBuffer->setRange(0, srcBuffer->size()); 358 memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size()); 359 360 err = state->mCodec->queueInputBuffer( 361 index, 362 0, 363 dstBuffer->size(), 364 0ll, 365 MediaCodec::BUFFER_FLAG_CODECCONFIG); 366 CHECK_EQ(err, (status_t)OK); 367 } 368 } 369 370 return OK; 371} 372 373status_t SimplePlayer::onStart() { 374 CHECK_EQ(mState, STOPPED); 375 376 mStartTimeRealUs = -1ll; 377 378 sp<AMessage> msg = new AMessage(kWhatDoMoreStuff, id()); 379 msg->setInt32("generation", ++mDoMoreStuffGeneration); 380 msg->post(); 381 382 return OK; 383} 384 385status_t SimplePlayer::onStop() { 386 CHECK_EQ(mState, STARTED); 387 388 ++mDoMoreStuffGeneration; 389 390 return OK; 391} 392 393status_t SimplePlayer::onReset() { 394 CHECK_EQ(mState, STOPPED); 395 396 for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { 397 CodecState *state = &mStateByTrackIndex.editValueAt(i); 398 399 CHECK_EQ(state->mCodec->stop(), (status_t)OK); 400 } 401 402 mStartTimeRealUs = -1ll; 403 404 mStateByTrackIndex.clear(); 405 mCodecLooper.clear(); 406 mExtractor.clear(); 407 mNativeWindow.clear(); 408 mPath.clear(); 409 410 return OK; 411} 412 413status_t SimplePlayer::onDoMoreStuff() { 414 ALOGV("onDoMoreStuff"); 415 for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { 416 CodecState *state = &mStateByTrackIndex.editValueAt(i); 417 418 status_t err; 419 do { 420 size_t index; 421 err = state->mCodec->dequeueInputBuffer(&index); 422 423 if (err == OK) { 424 ALOGV("dequeued input buffer on track %d", 425 mStateByTrackIndex.keyAt(i)); 426 427 state->mAvailInputBufferIndices.push_back(index); 428 } else { 429 ALOGV("dequeueInputBuffer on track %d returned %d", 430 mStateByTrackIndex.keyAt(i), err); 431 } 432 } while (err == OK); 433 434 do { 435 BufferInfo info; 436 err = state->mCodec->dequeueOutputBuffer( 437 &info.mIndex, 438 &info.mOffset, 439 &info.mSize, 440 &info.mPresentationTimeUs, 441 &info.mFlags); 442 443 if (err == OK) { 444 ALOGV("dequeued output buffer on track %d", 445 mStateByTrackIndex.keyAt(i)); 446 447 state->mAvailOutputBufferInfos.push_back(info); 448 } else if (err == INFO_FORMAT_CHANGED) { 449 err = onOutputFormatChanged(mStateByTrackIndex.keyAt(i), state); 450 CHECK_EQ(err, (status_t)OK); 451 } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { 452 err = state->mCodec->getOutputBuffers(&state->mBuffers[1]); 453 CHECK_EQ(err, (status_t)OK); 454 } else { 455 ALOGV("dequeueOutputBuffer on track %d returned %d", 456 mStateByTrackIndex.keyAt(i), err); 457 } 458 } while (err == OK 459 || err == INFO_FORMAT_CHANGED 460 || err == INFO_OUTPUT_BUFFERS_CHANGED); 461 } 462 463 for (;;) { 464 size_t trackIndex; 465 status_t err = mExtractor->getSampleTrackIndex(&trackIndex); 466 467 if (err != OK) { 468 ALOGI("encountered input EOS."); 469 break; 470 } else { 471 CodecState *state = &mStateByTrackIndex.editValueFor(trackIndex); 472 473 if (state->mAvailInputBufferIndices.empty()) { 474 break; 475 } 476 477 size_t index = *state->mAvailInputBufferIndices.begin(); 478 state->mAvailInputBufferIndices.erase( 479 state->mAvailInputBufferIndices.begin()); 480 481 const sp<ABuffer> &dstBuffer = 482 state->mBuffers[0].itemAt(index); 483 484 err = mExtractor->readSampleData(dstBuffer); 485 CHECK_EQ(err, (status_t)OK); 486 487 int64_t timeUs; 488 CHECK_EQ(mExtractor->getSampleTime(&timeUs), (status_t)OK); 489 490 err = state->mCodec->queueInputBuffer( 491 index, 492 dstBuffer->offset(), 493 dstBuffer->size(), 494 timeUs, 495 0); 496 CHECK_EQ(err, (status_t)OK); 497 498 ALOGV("enqueued input data on track %d", trackIndex); 499 500 err = mExtractor->advance(); 501 CHECK_EQ(err, (status_t)OK); 502 } 503 } 504 505 int64_t nowUs = ALooper::GetNowUs(); 506 507 if (mStartTimeRealUs < 0ll) { 508 mStartTimeRealUs = nowUs + 1000000ll; 509 } 510 511 for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) { 512 CodecState *state = &mStateByTrackIndex.editValueAt(i); 513 514 while (!state->mAvailOutputBufferInfos.empty()) { 515 BufferInfo *info = &*state->mAvailOutputBufferInfos.begin(); 516 517 int64_t whenRealUs = info->mPresentationTimeUs + mStartTimeRealUs; 518 int64_t lateByUs = nowUs - whenRealUs; 519 520 if (lateByUs > -10000ll) { 521 bool release = true; 522 523 if (lateByUs > 30000ll) { 524 ALOGI("track %d buffer late by %lld us, dropping.", 525 mStateByTrackIndex.keyAt(i), lateByUs); 526 state->mCodec->releaseOutputBuffer(info->mIndex); 527 } else { 528 if (state->mAudioTrack != NULL) { 529 const sp<ABuffer> &srcBuffer = 530 state->mBuffers[1].itemAt(info->mIndex); 531 532 renderAudio(state, info, srcBuffer); 533 534 if (info->mSize > 0) { 535 release = false; 536 } 537 } 538 539 if (release) { 540 state->mCodec->renderOutputBufferAndRelease( 541 info->mIndex); 542 } 543 } 544 545 if (release) { 546 state->mAvailOutputBufferInfos.erase( 547 state->mAvailOutputBufferInfos.begin()); 548 549 info = NULL; 550 } else { 551 break; 552 } 553 } else { 554 ALOGV("track %d buffer early by %lld us.", 555 mStateByTrackIndex.keyAt(i), -lateByUs); 556 break; 557 } 558 } 559 } 560 561 return OK; 562} 563 564status_t SimplePlayer::onOutputFormatChanged( 565 size_t trackIndex, CodecState *state) { 566 sp<AMessage> format; 567 status_t err = state->mCodec->getOutputFormat(&format); 568 569 if (err != OK) { 570 return err; 571 } 572 573 AString mime; 574 CHECK(format->findString("mime", &mime)); 575 576 if (!strncasecmp(mime.c_str(), "audio/", 6)) { 577 int32_t channelCount; 578 int32_t sampleRate; 579 CHECK(format->findInt32("channel-count", &channelCount)); 580 CHECK(format->findInt32("sample-rate", &sampleRate)); 581 582 state->mAudioTrack = new AudioTrack( 583 AUDIO_STREAM_MUSIC, 584 sampleRate, 585 AUDIO_FORMAT_PCM_16_BIT, 586 (channelCount == 1) 587 ? AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO, 588 0); 589 590 state->mNumFramesWritten = 0; 591 } 592 593 return OK; 594} 595 596void SimplePlayer::renderAudio( 597 CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer) { 598 CHECK(state->mAudioTrack != NULL); 599 600 if (state->mAudioTrack->stopped()) { 601 state->mAudioTrack->start(); 602 } 603 604 uint32_t numFramesPlayed; 605 CHECK_EQ(state->mAudioTrack->getPosition(&numFramesPlayed), (status_t)OK); 606 607 uint32_t numFramesAvailableToWrite = 608 state->mAudioTrack->frameCount() 609 - (state->mNumFramesWritten - numFramesPlayed); 610 611 size_t numBytesAvailableToWrite = 612 numFramesAvailableToWrite * state->mAudioTrack->frameSize(); 613 614 size_t copy = info->mSize; 615 if (copy > numBytesAvailableToWrite) { 616 copy = numBytesAvailableToWrite; 617 } 618 619 if (copy == 0) { 620 return; 621 } 622 623 int64_t startTimeUs = ALooper::GetNowUs(); 624 625 ssize_t nbytes = state->mAudioTrack->write( 626 buffer->base() + info->mOffset, copy); 627 628 CHECK_EQ(nbytes, (ssize_t)copy); 629 630 int64_t delayUs = ALooper::GetNowUs() - startTimeUs; 631 632 uint32_t numFramesWritten = nbytes / state->mAudioTrack->frameSize(); 633 634 if (delayUs > 2000ll) { 635 ALOGW("AudioTrack::write took %lld us, numFramesAvailableToWrite=%u, " 636 "numFramesWritten=%u", 637 delayUs, numFramesAvailableToWrite, numFramesWritten); 638 } 639 640 info->mOffset += nbytes; 641 info->mSize -= nbytes; 642 643 state->mNumFramesWritten += numFramesWritten; 644} 645 646} // namespace android 647