android_GenericPlayer.cpp revision 37dc2fccf3f122b79ebd554de209d0a3c94ae161
1/* 2 * Copyright (C) 2011 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 USE_LOG SLAndroidLogLevel_Verbose 18 19#include "sles_allinclusive.h" 20 21namespace android { 22 23//-------------------------------------------------------------------------------------------------- 24GenericPlayer::GenericPlayer(const AudioPlayback_Parameters* params) : 25 mDataLocatorType(kDataLocatorNone), 26 mNotifyClient(NULL), 27 mNotifyUser(NULL), 28 mStateFlags(0), 29 mLooperPriority(PRIORITY_DEFAULT), 30 mPlaybackParams(*params), 31 mChannelCount(1) 32{ 33 SL_LOGI("GenericPlayer::GenericPlayer()"); 34 35 mLooper = new android::ALooper(); 36 37 mAndroidAudioLevels.mMute = false; 38 mAndroidAudioLevels.mFinalVolume[0] = 1.0f; 39 mAndroidAudioLevels.mFinalVolume[1] = 1.0f; 40} 41 42 43GenericPlayer::~GenericPlayer() { 44 SL_LOGI("GenericPlayer::~GenericPlayer()"); 45 46 mLooper->stop(); 47 mLooper->unregisterHandler(id()); 48 mLooper.clear(); 49 50} 51 52 53void GenericPlayer::init(const notif_cbf_t cbf, void* notifUser) { 54 SL_LOGI("GenericPlayer::init()"); 55 56 mNotifyClient = cbf; 57 mNotifyUser = notifUser; 58 59 mLooper->registerHandler(this); 60 mLooper->start(false /*runOnCallingThread*/, false /*canCallJava*/, mLooperPriority); 61} 62 63 64void GenericPlayer::setDataSource(const char *uri) { 65 resetDataLocator(); 66 67 mDataLocator.uriRef = uri; 68 69 mDataLocatorType = kDataLocatorUri; 70} 71 72 73void GenericPlayer::setDataSource(int fd, int64_t offset, int64_t length) { 74 resetDataLocator(); 75 76 mDataLocator.fdi.fd = fd; 77 78 struct stat sb; 79 int ret = fstat(fd, &sb); 80 if (ret != 0) { 81 SL_LOGE("GenericPlayer::setDataSource: fstat(%d) failed: %d, %s", fd, ret, strerror(errno)); 82 return; 83 } 84 85 if (offset >= sb.st_size) { 86 SL_LOGE("SfPlayer::setDataSource: invalid offset"); 87 return; 88 } 89 mDataLocator.fdi.offset = offset; 90 91 if (PLAYER_FD_FIND_FILE_SIZE == length) { 92 mDataLocator.fdi.length = sb.st_size; 93 } else if (offset + length > sb.st_size) { 94 mDataLocator.fdi.length = sb.st_size - offset; 95 } else { 96 mDataLocator.fdi.length = length; 97 } 98 99 mDataLocatorType = kDataLocatorFd; 100} 101 102 103void GenericPlayer::prepare() { 104 SL_LOGI("GenericPlayer::prepare()"); 105 sp<AMessage> msg = new AMessage(kWhatPrepare, id()); 106 msg->post(); 107} 108 109 110void GenericPlayer::play() { 111 SL_LOGI("GenericPlayer::play()"); 112 sp<AMessage> msg = new AMessage(kWhatPlay, id()); 113 msg->post(); 114} 115 116 117void GenericPlayer::pause() { 118 SL_LOGI("GenericPlayer::pause()"); 119 sp<AMessage> msg = new AMessage(kWhatPause, id()); 120 msg->post(); 121} 122 123 124void GenericPlayer::stop() { 125 SL_LOGI("GenericPlayer::stop()"); 126 (new AMessage(kWhatPause, id()))->post(); 127 128 // after a stop, playback should resume from the start. 129 seek(0); 130} 131 132 133void GenericPlayer::seek(int64_t timeMsec) { 134 SL_LOGV("GenericPlayer::seek %lld", timeMsec); 135 sp<AMessage> msg = new AMessage(kWhatSeek, id()); 136 msg->setInt64(WHATPARAM_SEEK_SEEKTIME_MS, timeMsec); 137 msg->post(); 138} 139 140 141void GenericPlayer::loop(bool loop) { 142 sp<AMessage> msg = new AMessage(kWhatLoop, id()); 143 msg->setInt32(WHATPARAM_LOOP_LOOPING, (int32_t)loop); 144 msg->post(); 145} 146 147 148//-------------------------------------------------- 149void GenericPlayer::getDurationMsec(int* msec) { 150 // unknown duration 151 *msec = -1; 152} 153 154//-------------------------------------------------- 155void GenericPlayer::updateVolume(bool mute, bool useStereoPos, 156 XApermille stereoPos, XAmillibel volume) { 157 158 // compute amplification as the combination of volume level and stereo position 159 float leftVol = 1.0f, rightVol = 1.0f; 160 // amplification from volume level 161 leftVol *= sles_to_android_amplification(volume); 162 rightVol = leftVol; 163 164 // amplification from direct level (changed in SLEffectSendtItf and SLAndroidEffectSendItf) 165 // FIXME use calculation below when supporting effects 166 //leftVol *= mAndroidAudioLevels.mAmplFromDirectLevel; 167 //rightVol *= mAndroidAudioLevels.mAmplFromDirectLevel; 168 169 // amplification from stereo position 170 if (useStereoPos) { 171 // panning law depends on number of channels of content: stereo panning vs 2ch. balance 172 if (1 == mChannelCount) { 173 // stereo panning 174 double theta = (1000 + stereoPos) * M_PI_4 / 1000.0f; // 0 <= theta <= Pi/2 175 leftVol *= cos(theta); 176 rightVol *= sin(theta); 177 } else { 178 // stereo balance 179 if (stereoPos > 0) { 180 leftVol *= (1000 - stereoPos) / 1000.0f; 181 rightVol *= 1.0f; 182 } else { 183 leftVol *= 1.0f; 184 rightVol *= (1000 + stereoPos) / 1000.0f; 185 } 186 } 187 } 188 189 { 190 Mutex::Autolock _l(mSettingsLock); 191 mAndroidAudioLevels.mMute = mute; 192 mAndroidAudioLevels.mFinalVolume[0] = leftVol; 193 mAndroidAudioLevels.mFinalVolume[1] = rightVol; 194 } 195 196 // send a message for the volume to be updated by the object which implements the volume 197 (new AMessage(kWhatVolumeUpdate, id()))->post(); 198} 199 200 201//-------------------------------------------------- 202/* 203 * post-condition: mDataLocatorType == kDataLocatorNone 204 * 205 */ 206void GenericPlayer::resetDataLocator() { 207 mDataLocatorType = kDataLocatorNone; 208} 209 210 211void GenericPlayer::notify(const char* event, int data, bool async) { 212 sp<AMessage> msg = new AMessage(kWhatNotif, id()); 213 msg->setInt32(event, (int32_t)data); 214 if (async) { 215 msg->post(); 216 } else { 217 this->onNotify(msg); 218 } 219} 220 221 222void GenericPlayer::notify(const char* event, int data1, int data2, bool async) { 223 sp<AMessage> msg = new AMessage(kWhatNotif, id()); 224 msg->setRect(event, 0, 0, (int32_t)data1, (int32_t)data2); 225 if (async) { 226 msg->post(); 227 } else { 228 this->onNotify(msg); 229 } 230} 231 232 233//-------------------------------------------------- 234// AHandler implementation 235void GenericPlayer::onMessageReceived(const sp<AMessage> &msg) { 236 switch (msg->what()) { 237 case kWhatPrepare: 238 onPrepare(); 239 break; 240 241 case kWhatNotif: 242 onNotify(msg); 243 break; 244 245 case kWhatPlay: 246 onPlay(); 247 break; 248 249 case kWhatPause: 250 onPause(); 251 break; 252 253 case kWhatSeek: 254 onSeek(msg); 255 break; 256 257 case kWhatLoop: 258 onLoop(msg); 259 break; 260 261 case kWhatVolumeUpdate: 262 onVolumeUpdate(); 263 break; 264 265 default: 266 TRESPASS(); 267 } 268} 269 270 271//-------------------------------------------------- 272// Event handlers 273void GenericPlayer::onPrepare() { 274 SL_LOGI("GenericPlayer::onPrepare()"); 275 if (!(mStateFlags & kFlagPrepared)) { 276 mStateFlags |= kFlagPrepared; 277 notify(PLAYEREVENT_PREPARED, PLAYER_SUCCESS, false /*async*/); 278 } 279 SL_LOGI("GenericPlayer::onPrepare() done, mStateFlags=0x%x", mStateFlags); 280} 281 282 283void GenericPlayer::onNotify(const sp<AMessage> &msg) { 284 if (NULL == mNotifyClient) { 285 return; 286 } 287 288 int32_t val1, val2; 289 if (msg->findInt32(PLAYEREVENT_PREPARED, &val1)) { 290 SL_LOGV("GenericPlayer notifying %s = %d", PLAYEREVENT_PREPARED, val1); 291 mNotifyClient(kEventPrepared, val1, 0, mNotifyUser); 292 } else if (msg->findRect(PLAYEREVENT_VIDEO_SIZE_UPDATE, &val1, &val2, &val1, &val2)) { 293 SL_LOGD("GenericPlayer notifying %s = %d, %d", PLAYEREVENT_VIDEO_SIZE_UPDATE, val1, val2); 294 mNotifyClient(kEventHasVideoSize, val1, val2, mNotifyUser); 295 } 296} 297 298 299void GenericPlayer::onPlay() { 300 SL_LOGI("GenericPlayer::onPlay()"); 301 if ((mStateFlags & kFlagPrepared)) { 302 SL_LOGI("starting player"); 303 mStateFlags |= kFlagPlaying; 304 } else { 305 SL_LOGV("NOT starting player mStateFlags=0x%x", mStateFlags); 306 } 307} 308 309 310void GenericPlayer::onPause() { 311 SL_LOGI("GenericPlayer::onPause()"); 312 if ((mStateFlags & kFlagPrepared)) { 313 mStateFlags &= ~kFlagPlaying; 314 } 315 316} 317 318 319void GenericPlayer::onSeek(const sp<AMessage> &msg) { 320 SL_LOGV("GenericPlayer::onSeek"); 321} 322 323 324void GenericPlayer::onLoop(const sp<AMessage> &msg) { 325 SL_LOGV("GenericPlayer::onLoop"); 326} 327 328 329void GenericPlayer::onVolumeUpdate() { 330 331} 332 333} // namespace android 334