NuPlayerDriver.cpp revision 21a1d72bb42710d149532653490154f89330b9dd
157b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien/* 257b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * Copyright (C) 2010 The Android Open Source Project 357b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * 457b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * Licensed under the Apache License, Version 2.0 (the "License"); 557b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * you may not use this file except in compliance with the License. 657b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * You may obtain a copy of the License at 757b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * 857b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * http://www.apache.org/licenses/LICENSE-2.0 957b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * 1057b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * Unless required by applicable law or agreed to in writing, software 1157b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * distributed under the License is distributed on an "AS IS" BASIS, 1257b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1357b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * See the License for the specific language governing permissions and 1457b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien * limitations under the License. 1557b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien */ 1657b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 1757b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien//#define LOG_NDEBUG 0 1857b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien#define LOG_TAG "NuPlayerDriver" 1957b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien#include <inttypes.h> 2057b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien#include <utils/Log.h> 2157b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 2257b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien#include "NuPlayerDriver.h" 2357b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 2457b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien#include "NuPlayer.h" 2557b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien#include "NuPlayerSource.h" 2657b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 2757b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien#include <media/stagefright/foundation/ADebug.h> 2857b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien#include <media/stagefright/foundation/ALooper.h> 2957b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien#include <media/stagefright/MetaData.h> 3057b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 3157b6dae9894b9362ef04517ff477fd491f9d433bRaph Leviennamespace android { 3257b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 3357b6dae9894b9362ef04517ff477fd491f9d433bRaph LevienNuPlayerDriver::NuPlayerDriver() 3457b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien : mState(STATE_IDLE), 3557b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mIsAsyncPrepare(false), 3657b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mAsyncResult(UNKNOWN_ERROR), 3757b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mSetSurfaceInProgress(false), 3857b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mDurationUs(-1), 3957b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mPositionUs(-1), 4057b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mNotifyTimeRealUs(-1), 4157b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mPauseStartedTimeUs(-1), 4257b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mNumFramesTotal(0), 4357b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mNumFramesDropped(0), 4457b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mLooper(new ALooper), 45c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien mPlayerFlags(0), 4657b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mAtEOS(false), 4757b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mLooping(false), 4857b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mAutoLoop(false), 4957b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mStartupSeekTimeUs(-1) { 50c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien mLooper->setName("NuPlayerDriver Looper"); 5157b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 5257b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mLooper->start( 5357b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien false, /* runOnCallingThread */ 5457b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien true, /* canCallJava */ 5557b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien PRIORITY_AUDIO); 5657b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 5757b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mPlayer = new NuPlayer; 5857b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mLooper->registerHandler(mPlayer); 5957b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 6057b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mPlayer->setDriver(this); 6157b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien} 6257b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 63c88ef135fcc2661ec7addc171ebc60787df38affRaph LevienNuPlayerDriver::~NuPlayerDriver() { 6457b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mLooper->stop(); 6557b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien} 6657b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 67c88ef135fcc2661ec7addc171ebc60787df38affRaph Levienstatus_t NuPlayerDriver::initCheck() { 6857b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien return OK; 6957b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien} 7057b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 7157b6dae9894b9362ef04517ff477fd491f9d433bRaph Levienstatus_t NuPlayerDriver::setUID(uid_t uid) { 7257b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien mPlayer->setUID(uid); 7357b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 7457b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien return OK; 7557b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien} 7657b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 7757b6dae9894b9362ef04517ff477fd491f9d433bRaph Levienstatus_t NuPlayerDriver::setDataSource( 7857b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien const sp<IMediaHTTPService> &httpService, 7957b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien const char *url, 80c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien const KeyedVector<String8, String8> *headers) { 8157b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien Mutex::Autolock autoLock(mLock); 8257b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien 8357b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien ALOGV("setDataSource: url=%s", url); 84c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien if (mState != STATE_IDLE) { 8557b6dae9894b9362ef04517ff477fd491f9d433bRaph Levien return INVALID_OPERATION; 869c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien } 879c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 889c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mState = STATE_SET_DATASOURCE_PENDING; 899c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 909c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mPlayer->setDataSourceAsync(httpService, url, headers); 919c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 929c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien while (mState == STATE_SET_DATASOURCE_PENDING) { 939c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mCondition.wait(mLock); 946d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 956d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 96c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien return mAsyncResult; 976d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien} 989c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 99c88ef135fcc2661ec7addc171ebc60787df38affRaph Levienstatus_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) { 1009c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien Mutex::Autolock autoLock(mLock); 1019c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 1029c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien ALOGV("setDataSource: fd=%d", fd); 103c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien if (mState != STATE_IDLE) { 1049c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien return INVALID_OPERATION; 1059c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien } 1069c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 1079c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mState = STATE_SET_DATASOURCE_PENDING; 1089c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 1099c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mPlayer->setDataSourceAsync(fd, offset, length); 1109c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 1119c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien while (mState == STATE_SET_DATASOURCE_PENDING) { 1129c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mCondition.wait(mLock); 1136d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 1146d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 115c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien return mAsyncResult; 1166d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien} 1176d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 118c88ef135fcc2661ec7addc171ebc60787df38affRaph Levienstatus_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) { 1196d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien Mutex::Autolock autoLock(mLock); 1209c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 121c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien ALOGV("setDataSource: stream source"); 1229c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien if (mState != STATE_IDLE) { 1239c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien return INVALID_OPERATION; 1249c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien } 125c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien 1269c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mState = STATE_SET_DATASOURCE_PENDING; 1279c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 1286d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mPlayer->setDataSourceAsync(source); 1296d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 1309c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien while (mState == STATE_SET_DATASOURCE_PENDING) { 1319c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mCondition.wait(mLock); 1329c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien } 1339c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 1349c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien return mAsyncResult; 1359c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien} 1369c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 1376d15657e4a3826d4d47d5358f1dde211484527e9Raph Levienstatus_t NuPlayerDriver::setVideoSurfaceTexture( 1386d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien const sp<IGraphicBufferProducer> &bufferProducer) { 139c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien Mutex::Autolock autoLock(mLock); 1406d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 1419c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien if (mSetSurfaceInProgress) { 142c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien return INVALID_OPERATION; 1439c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien } 1449c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 1459c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien switch (mState) { 146c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien case STATE_SET_DATASOURCE_PENDING: 1479c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien case STATE_RESET_IN_PROGRESS: 1489c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien return INVALID_OPERATION; 1499c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 1509c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien default: 1519c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien break; 1529c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien } 1539c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 1549c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mSetSurfaceInProgress = true; 1559c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 1566d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mPlayer->setVideoSurfaceTextureAsync(bufferProducer); 1576d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 158c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien while (mSetSurfaceInProgress) { 1596d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mCondition.wait(mLock); 1609c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien } 161c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien 1629c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien return OK; 1639c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien} 1649c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien 165c88ef135fcc2661ec7addc171ebc60787df38affRaph Levienstatus_t NuPlayerDriver::prepare() { 1669c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien Mutex::Autolock autoLock(mLock); 1679c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien return prepare_l(); 1686d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien} 1696d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 1706d15657e4a3826d4d47d5358f1dde211484527e9Raph Levienstatus_t NuPlayerDriver::prepare_l() { 1716d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien switch (mState) { 1726d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien case STATE_UNPREPARED: 1736d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mState = STATE_PREPARING; 1746d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 1756d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien // Make sure we're not posting any notifications, success or 1766d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien // failure information is only communicated through our result 177c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien // code. 1786d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mIsAsyncPrepare = false; 1796d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mPlayer->prepareAsync(); 180c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien while (mState == STATE_PREPARING) { 1816d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mCondition.wait(mLock); 1826d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 1836d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien return (mState == STATE_PREPARED) ? OK : UNKNOWN_ERROR; 184c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien case STATE_STOPPED: 1856d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien // this is really just paused. handle as seek to start 1866d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mAtEOS = false; 1879c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mState = STATE_STOPPED_AND_PREPARING; 1889c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mIsAsyncPrepare = false; 1899c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mPlayer->seekToAsync(0); 1909c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien while (mState == STATE_STOPPED_AND_PREPARING) { 1919c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mCondition.wait(mLock); 1929c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien } 1939c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien return (mState == STATE_STOPPED_AND_PREPARED) ? OK : UNKNOWN_ERROR; 1946d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien default: 1956d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien return INVALID_OPERATION; 196c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien }; 1976d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien} 1986d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 199c88ef135fcc2661ec7addc171ebc60787df38affRaph Levienstatus_t NuPlayerDriver::prepareAsync() { 2006d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien Mutex::Autolock autoLock(mLock); 2016d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 202c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien switch (mState) { 2036d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien case STATE_UNPREPARED: 2049c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mState = STATE_PREPARING; 205c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien mIsAsyncPrepare = true; 2069c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mPlayer->prepareAsync(); 2079c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien return OK; 2089c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien case STATE_STOPPED: 209c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien // this is really just paused. handle as seek to start 2109c4cc648abcae144f3b99d612e58ef01d5e52cceRaph Levien mAtEOS = false; 2116d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mState = STATE_STOPPED_AND_PREPARING; 2126d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mIsAsyncPrepare = true; 2136d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mPlayer->seekToAsync(0); 2146d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien return OK; 2156d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien default: 2166d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien return INVALID_OPERATION; 2176d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien }; 2186d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien} 2196d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 2206d15657e4a3826d4d47d5358f1dde211484527e9Raph Levienstatus_t NuPlayerDriver::start() { 2216d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien Mutex::Autolock autoLock(mLock); 222c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien 2236d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien switch (mState) { 2246d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien case STATE_UNPREPARED: 225c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien { 2266d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien status_t err = prepare_l(); 2276d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 228c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien if (err != OK) { 2296d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien return err; 2306d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 231c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien 2326d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien CHECK_EQ(mState, STATE_PREPARED); 2336d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 234c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien // fall through 2356d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 2366d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 237c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien case STATE_PREPARED: 2386d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien { 2396d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mAtEOS = false; 240c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien mPlayer->start(); 2416d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 2426d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien if (mStartupSeekTimeUs >= 0) { 243c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien if (mStartupSeekTimeUs == 0) { 2446d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien notifySeekComplete_l(); 2456d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } else { 246c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien mPlayer->seekToAsync(mStartupSeekTimeUs); 2476d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 2486d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 249c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien mStartupSeekTimeUs = -1; 2506d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 2516d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien break; 252c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien } 2536d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 2546d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien case STATE_RUNNING: 255c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien { 2566d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien if (mAtEOS) { 2576d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mPlayer->seekToAsync(0); 258c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien mAtEOS = false; 2596d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mPositionUs = -1; 2606d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 261c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien break; 2626d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 2636d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 264c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien case STATE_PAUSED: 2656d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien case STATE_STOPPED_AND_PREPARED: 2666d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien { 267c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien if (mAtEOS) { 2686d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mPlayer->seekToAsync(0); 2696d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mAtEOS = false; 270c88ef135fcc2661ec7addc171ebc60787df38affRaph Levien mPlayer->resume(); 2716d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mPositionUs = -1; 2726d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } else { 2736d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mPlayer->resume(); 2746d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien if (mNotifyTimeRealUs != -1) { 2756d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien // Pause time must be set if here by setPauseStartedTimeIfNeeded(). 2766d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien //CHECK(mPauseStartedTimeUs != -1); 2776d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 2786d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien // if no seek occurs, adjust our notify time so that getCurrentPosition() 2796d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien // is continuous if read immediately after calling start(). 2806d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mNotifyTimeRealUs += ALooper::GetNowUs() - mPauseStartedTimeUs; 2816d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 2826d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 2836d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien break; 2846d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 2856d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 2866d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien default: 2876d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien return INVALID_OPERATION; 2886d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien } 2896d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 2906d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mState = STATE_RUNNING; 2916d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mPauseStartedTimeUs = -1; 2926d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 2936d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien return OK; 2946d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien} 2956d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 2966d15657e4a3826d4d47d5358f1dde211484527e9Raph Levienstatus_t NuPlayerDriver::stop() { 2976d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien Mutex::Autolock autoLock(mLock); 2986d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 2996d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien switch (mState) { 3006d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien case STATE_RUNNING: 3016d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mPlayer->pause(); 3026d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien // fall through 3036d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 3046d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien case STATE_PAUSED: 3056d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mState = STATE_STOPPED; 3066d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien notifyListener_l(MEDIA_STOPPED); 3076d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien break; 3086d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien 3096d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien case STATE_PREPARED: 3106d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien case STATE_STOPPED: 3116d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien case STATE_STOPPED_AND_PREPARING: 3126d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien case STATE_STOPPED_AND_PREPARED: 3136d15657e4a3826d4d47d5358f1dde211484527e9Raph Levien mState = STATE_STOPPED; 314 break; 315 316 default: 317 return INVALID_OPERATION; 318 } 319 setPauseStartedTimeIfNeeded(); 320 321 return OK; 322} 323 324status_t NuPlayerDriver::pause() { 325 Mutex::Autolock autoLock(mLock); 326 327 switch (mState) { 328 case STATE_PAUSED: 329 case STATE_PREPARED: 330 return OK; 331 332 case STATE_RUNNING: 333 setPauseStartedTimeIfNeeded(); 334 mState = STATE_PAUSED; 335 notifyListener_l(MEDIA_PAUSED); 336 mPlayer->pause(); 337 break; 338 339 default: 340 return INVALID_OPERATION; 341 } 342 343 return OK; 344} 345 346bool NuPlayerDriver::isPlaying() { 347 return mState == STATE_RUNNING && !mAtEOS; 348} 349 350status_t NuPlayerDriver::seekTo(int msec) { 351 Mutex::Autolock autoLock(mLock); 352 353 int64_t seekTimeUs = msec * 1000ll; 354 355 switch (mState) { 356 case STATE_PREPARED: 357 { 358 mStartupSeekTimeUs = seekTimeUs; 359 // pretend that the seek completed. It will actually happen when starting playback. 360 // TODO: actually perform the seek here, so the player is ready to go at the new 361 // location 362 notifySeekComplete_l(); 363 break; 364 } 365 366 case STATE_RUNNING: 367 case STATE_PAUSED: 368 { 369 mAtEOS = false; 370 // seeks can take a while, so we essentially paused 371 notifyListener_l(MEDIA_PAUSED); 372 mPlayer->seekToAsync(seekTimeUs); 373 break; 374 } 375 376 default: 377 return INVALID_OPERATION; 378 } 379 380 mPositionUs = seekTimeUs; 381 mNotifyTimeRealUs = -1; 382 return OK; 383} 384 385status_t NuPlayerDriver::getCurrentPosition(int *msec) { 386 Mutex::Autolock autoLock(mLock); 387 388 if (mPositionUs < 0) { 389 // mPositionUs is the media time. 390 // It is negative under these cases 391 // (1) == -1 after reset, or very first playback, no stream notification yet. 392 // (2) == -1 start after end of stream, no stream notification yet. 393 // (3) == large negative # after ~292,471 years of continuous playback. 394 395 //CHECK_EQ(mPositionUs, -1); 396 *msec = 0; 397 } else if (mNotifyTimeRealUs == -1) { 398 // A seek has occurred just occurred, no stream notification yet. 399 // mPositionUs (>= 0) is the new media position. 400 *msec = mPositionUs / 1000; 401 } else { 402 // mPosition must be valid (i.e. >= 0) by the first check above. 403 // We're either playing or have pause time set: mPauseStartedTimeUs is >= 0 404 //LOG_ALWAYS_FATAL_IF( 405 // !isPlaying() && mPauseStartedTimeUs < 0, 406 // "Player in non-playing mState(%d) and mPauseStartedTimeUs(%lld) < 0", 407 // mState, (long long)mPauseStartedTimeUs); 408 ALOG_ASSERT(mNotifyTimeRealUs >= 0); 409 int64_t nowUs = 410 (isPlaying() ? ALooper::GetNowUs() : mPauseStartedTimeUs); 411 *msec = (mPositionUs + nowUs - mNotifyTimeRealUs + 500ll) / 1000; 412 // It is possible for *msec to be negative if the media position is > 596 hours. 413 // but we turn on this checking in NDEBUG == 0 mode. 414 ALOG_ASSERT(*msec >= 0); 415 ALOGV("getCurrentPosition nowUs(%lld)", (long long)nowUs); 416 } 417 ALOGV("getCurrentPosition returning(%d) mPositionUs(%lld) mNotifyRealTimeUs(%lld)", 418 *msec, (long long)mPositionUs, (long long)mNotifyTimeRealUs); 419 return OK; 420} 421 422status_t NuPlayerDriver::getDuration(int *msec) { 423 Mutex::Autolock autoLock(mLock); 424 425 if (mDurationUs < 0) { 426 return UNKNOWN_ERROR; 427 } 428 429 *msec = (mDurationUs + 500ll) / 1000; 430 431 return OK; 432} 433 434status_t NuPlayerDriver::reset() { 435 Mutex::Autolock autoLock(mLock); 436 437 switch (mState) { 438 case STATE_IDLE: 439 return OK; 440 441 case STATE_SET_DATASOURCE_PENDING: 442 case STATE_RESET_IN_PROGRESS: 443 return INVALID_OPERATION; 444 445 case STATE_PREPARING: 446 { 447 CHECK(mIsAsyncPrepare); 448 449 notifyListener_l(MEDIA_PREPARED); 450 break; 451 } 452 453 default: 454 break; 455 } 456 457 if (mState != STATE_STOPPED) { 458 notifyListener_l(MEDIA_STOPPED); 459 } 460 461 mState = STATE_RESET_IN_PROGRESS; 462 mPlayer->resetAsync(); 463 464 while (mState == STATE_RESET_IN_PROGRESS) { 465 mCondition.wait(mLock); 466 } 467 468 mDurationUs = -1; 469 mPositionUs = -1; 470 mStartupSeekTimeUs = -1; 471 mLooping = false; 472 473 return OK; 474} 475 476status_t NuPlayerDriver::setLooping(int loop) { 477 mLooping = loop != 0; 478 return OK; 479} 480 481player_type NuPlayerDriver::playerType() { 482 return NU_PLAYER; 483} 484 485status_t NuPlayerDriver::invoke(const Parcel &request, Parcel *reply) { 486 if (reply == NULL) { 487 ALOGE("reply is a NULL pointer"); 488 return BAD_VALUE; 489 } 490 491 int32_t methodId; 492 status_t ret = request.readInt32(&methodId); 493 if (ret != OK) { 494 ALOGE("Failed to retrieve the requested method to invoke"); 495 return ret; 496 } 497 498 switch (methodId) { 499 case INVOKE_ID_SET_VIDEO_SCALING_MODE: 500 { 501 int mode = request.readInt32(); 502 return mPlayer->setVideoScalingMode(mode); 503 } 504 505 case INVOKE_ID_GET_TRACK_INFO: 506 { 507 return mPlayer->getTrackInfo(reply); 508 } 509 510 case INVOKE_ID_SELECT_TRACK: 511 { 512 int trackIndex = request.readInt32(); 513 return mPlayer->selectTrack(trackIndex, true /* select */); 514 } 515 516 case INVOKE_ID_UNSELECT_TRACK: 517 { 518 int trackIndex = request.readInt32(); 519 return mPlayer->selectTrack(trackIndex, false /* select */); 520 } 521 522 case INVOKE_ID_GET_SELECTED_TRACK: 523 { 524 int32_t type = request.readInt32(); 525 return mPlayer->getSelectedTrack(type, reply); 526 } 527 528 default: 529 { 530 return INVALID_OPERATION; 531 } 532 } 533} 534 535void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) { 536 mPlayer->setAudioSink(audioSink); 537 mAudioSink = audioSink; 538} 539 540status_t NuPlayerDriver::setParameter( 541 int /* key */, const Parcel & /* request */) { 542 return INVALID_OPERATION; 543} 544 545status_t NuPlayerDriver::getParameter(int /* key */, Parcel * /* reply */) { 546 return INVALID_OPERATION; 547} 548 549status_t NuPlayerDriver::getMetadata( 550 const media::Metadata::Filter& /* ids */, Parcel *records) { 551 Mutex::Autolock autoLock(mLock); 552 553 using media::Metadata; 554 555 Metadata meta(records); 556 557 meta.appendBool( 558 Metadata::kPauseAvailable, 559 mPlayerFlags & NuPlayer::Source::FLAG_CAN_PAUSE); 560 561 meta.appendBool( 562 Metadata::kSeekBackwardAvailable, 563 mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_BACKWARD); 564 565 meta.appendBool( 566 Metadata::kSeekForwardAvailable, 567 mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK_FORWARD); 568 569 meta.appendBool( 570 Metadata::kSeekAvailable, 571 mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK); 572 573 return OK; 574} 575 576void NuPlayerDriver::notifyResetComplete() { 577 Mutex::Autolock autoLock(mLock); 578 579 CHECK_EQ(mState, STATE_RESET_IN_PROGRESS); 580 mState = STATE_IDLE; 581 mCondition.broadcast(); 582} 583 584void NuPlayerDriver::notifySetSurfaceComplete() { 585 Mutex::Autolock autoLock(mLock); 586 587 CHECK(mSetSurfaceInProgress); 588 mSetSurfaceInProgress = false; 589 590 mCondition.broadcast(); 591} 592 593void NuPlayerDriver::notifyDuration(int64_t durationUs) { 594 Mutex::Autolock autoLock(mLock); 595 mDurationUs = durationUs; 596} 597 598void NuPlayerDriver::notifyPosition(int64_t positionUs) { 599 Mutex::Autolock autoLock(mLock); 600 if (isPlaying()) { 601 mPositionUs = positionUs; 602 mNotifyTimeRealUs = ALooper::GetNowUs(); 603 } 604} 605 606void NuPlayerDriver::notifySeekComplete() { 607 Mutex::Autolock autoLock(mLock); 608 notifySeekComplete_l(); 609} 610 611void NuPlayerDriver::notifySeekComplete_l() { 612 bool wasSeeking = true; 613 if (mState == STATE_STOPPED_AND_PREPARING) { 614 wasSeeking = false; 615 mState = STATE_STOPPED_AND_PREPARED; 616 mCondition.broadcast(); 617 if (!mIsAsyncPrepare) { 618 // if we are preparing synchronously, no need to notify listener 619 return; 620 } 621 } else if (mState == STATE_STOPPED) { 622 // no need to notify listener 623 return; 624 } 625 notifyListener_l(wasSeeking ? MEDIA_SEEK_COMPLETE : MEDIA_PREPARED); 626} 627 628void NuPlayerDriver::notifyFrameStats( 629 int64_t numFramesTotal, int64_t numFramesDropped) { 630 Mutex::Autolock autoLock(mLock); 631 mNumFramesTotal = numFramesTotal; 632 mNumFramesDropped = numFramesDropped; 633} 634 635status_t NuPlayerDriver::dump( 636 int fd, const Vector<String16> & /* args */) const { 637 Mutex::Autolock autoLock(mLock); 638 639 FILE *out = fdopen(dup(fd), "w"); 640 641 fprintf(out, " NuPlayer\n"); 642 fprintf(out, " numFramesTotal(%" PRId64 "), numFramesDropped(%" PRId64 "), " 643 "percentageDropped(%.2f)\n", 644 mNumFramesTotal, 645 mNumFramesDropped, 646 mNumFramesTotal == 0 647 ? 0.0 : (double)mNumFramesDropped / mNumFramesTotal); 648 649 fclose(out); 650 out = NULL; 651 652 return OK; 653} 654 655void NuPlayerDriver::notifyListener( 656 int msg, int ext1, int ext2, const Parcel *in) { 657 Mutex::Autolock autoLock(mLock); 658 notifyListener_l(msg, ext1, ext2, in); 659} 660 661void NuPlayerDriver::notifyListener_l( 662 int msg, int ext1, int ext2, const Parcel *in) { 663 switch (msg) { 664 case MEDIA_PLAYBACK_COMPLETE: 665 { 666 if (mState != STATE_RESET_IN_PROGRESS) { 667 if (mLooping || (mAutoLoop 668 && (mAudioSink == NULL || mAudioSink->realtime()))) { 669 mPlayer->seekToAsync(0); 670 break; 671 } 672 673 mPlayer->pause(); 674 mState = STATE_PAUSED; 675 } 676 // fall through 677 } 678 679 case MEDIA_ERROR: 680 { 681 mAtEOS = true; 682 setPauseStartedTimeIfNeeded(); 683 break; 684 } 685 686 default: 687 break; 688 } 689 690 mLock.unlock(); 691 sendEvent(msg, ext1, ext2, in); 692 mLock.lock(); 693} 694 695void NuPlayerDriver::notifySetDataSourceCompleted(status_t err) { 696 Mutex::Autolock autoLock(mLock); 697 698 CHECK_EQ(mState, STATE_SET_DATASOURCE_PENDING); 699 700 mAsyncResult = err; 701 mState = (err == OK) ? STATE_UNPREPARED : STATE_IDLE; 702 mCondition.broadcast(); 703} 704 705void NuPlayerDriver::notifyPrepareCompleted(status_t err) { 706 Mutex::Autolock autoLock(mLock); 707 708 if (mState != STATE_PREPARING) { 709 // We were preparing asynchronously when the client called 710 // reset(), we sent a premature "prepared" notification and 711 // then initiated the reset. This notification is stale. 712 CHECK(mState == STATE_RESET_IN_PROGRESS || mState == STATE_IDLE); 713 return; 714 } 715 716 CHECK_EQ(mState, STATE_PREPARING); 717 718 mAsyncResult = err; 719 720 if (err == OK) { 721 // update state before notifying client, so that if client calls back into NuPlayerDriver 722 // in response, NuPlayerDriver has the right state 723 mState = STATE_PREPARED; 724 if (mIsAsyncPrepare) { 725 notifyListener_l(MEDIA_PREPARED); 726 } 727 } else { 728 mState = STATE_UNPREPARED; 729 if (mIsAsyncPrepare) { 730 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 731 } 732 } 733 734 sp<MetaData> meta = mPlayer->getFileMeta(); 735 int32_t loop; 736 if (meta != NULL 737 && meta->findInt32(kKeyAutoLoop, &loop) && loop != 0) { 738 mAutoLoop = true; 739 } 740 741 mCondition.broadcast(); 742} 743 744void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) { 745 Mutex::Autolock autoLock(mLock); 746 747 mPlayerFlags = flags; 748} 749 750void NuPlayerDriver::setPauseStartedTimeIfNeeded() { 751 if (mPauseStartedTimeUs == -1) { 752 mPauseStartedTimeUs = ALooper::GetNowUs(); 753 } 754} 755 756} // namespace android 757