AudioPlayer.cpp revision ad6516d9247bd0a76a393810b041c3e4094f0e36
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 "AudioPlayer" 19#include <utils/Log.h> 20 21#include <media/AudioTrack.h> 22#include <media/stagefright/AudioPlayer.h> 23#include <media/stagefright/MediaDebug.h> 24#include <media/stagefright/MediaDefs.h> 25#include <media/stagefright/MediaSource.h> 26#include <media/stagefright/MetaData.h> 27 28namespace android { 29 30AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink) 31 : mAudioTrack(NULL), 32 mInputBuffer(NULL), 33 mSampleRate(0), 34 mLatencyUs(0), 35 mFrameSize(0), 36 mNumFramesPlayed(0), 37 mPositionTimeMediaUs(-1), 38 mPositionTimeRealUs(-1), 39 mSeeking(false), 40 mStarted(false), 41 mAudioSink(audioSink) { 42} 43 44AudioPlayer::~AudioPlayer() { 45 if (mStarted) { 46 stop(); 47 } 48} 49 50void AudioPlayer::setListenerCallback( 51 void (*notify)(void *cookie, int what), void *cookie) { 52 mListenerCallback = notify; 53 mListenerCookie = cookie; 54} 55 56void AudioPlayer::setSource(const sp<MediaSource> &source) { 57 CHECK_EQ(mSource, NULL); 58 mSource = source; 59} 60 61status_t AudioPlayer::start() { 62 CHECK(!mStarted); 63 CHECK(mSource != NULL); 64 65 status_t err = mSource->start(); 66 67 if (err != OK) { 68 return err; 69 } 70 71 sp<MetaData> format = mSource->getFormat(); 72 const char *mime; 73 bool success = format->findCString(kKeyMIMEType, &mime); 74 CHECK(success); 75 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)); 76 77 success = format->findInt32(kKeySampleRate, &mSampleRate); 78 CHECK(success); 79 80 int32_t numChannels; 81 success = format->findInt32(kKeyChannelCount, &numChannels); 82 CHECK(success); 83 84 if (mAudioSink.get() != NULL) { 85 status_t err = mAudioSink->open( 86 mSampleRate, numChannels, AudioSystem::PCM_16_BIT, 87 DEFAULT_AUDIOSINK_BUFFERCOUNT, 88 &AudioPlayer::AudioSinkCallback, this); 89 if (err != OK) { 90 mSource->stop(); 91 92 return err; 93 } 94 95 mLatencyUs = (int64_t)mAudioSink->latency() * 1000; 96 mFrameSize = mAudioSink->frameSize(); 97 98 mAudioSink->start(); 99 } else { 100 mAudioTrack = new AudioTrack( 101 AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT, 102 (numChannels == 2) 103 ? AudioSystem::CHANNEL_OUT_STEREO 104 : AudioSystem::CHANNEL_OUT_MONO, 105 8192, 0, &AudioCallback, this, 0); 106 107 if (mAudioTrack->initCheck() != OK) { 108 delete mAudioTrack; 109 mAudioTrack = NULL; 110 111 mSource->stop(); 112 113 return mAudioTrack->initCheck(); 114 } 115 116 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000; 117 mFrameSize = mAudioTrack->frameSize(); 118 119 mAudioTrack->start(); 120 } 121 122 mStarted = true; 123 124 return OK; 125} 126 127void AudioPlayer::pause() { 128 CHECK(mStarted); 129 130 if (mAudioSink.get() != NULL) { 131 mAudioSink->pause(); 132 } else { 133 mAudioTrack->stop(); 134 } 135} 136 137void AudioPlayer::resume() { 138 CHECK(mStarted); 139 140 if (mAudioSink.get() != NULL) { 141 mAudioSink->start(); 142 } else { 143 mAudioTrack->start(); 144 } 145} 146 147void AudioPlayer::stop() { 148 CHECK(mStarted); 149 150 if (mAudioSink.get() != NULL) { 151 mAudioSink->stop(); 152 mAudioSink->close(); 153 } else { 154 mAudioTrack->stop(); 155 156 delete mAudioTrack; 157 mAudioTrack = NULL; 158 } 159 160 // Make sure to release any buffer we hold onto so that the 161 // source is able to stop(). 162 if (mInputBuffer != NULL) { 163 LOGV("AudioPlayer releasing input buffer."); 164 165 mInputBuffer->release(); 166 mInputBuffer = NULL; 167 } 168 169 mSource->stop(); 170 171 mNumFramesPlayed = 0; 172 mPositionTimeMediaUs = -1; 173 mPositionTimeRealUs = -1; 174 mSeeking = false; 175 mStarted = false; 176} 177 178// static 179void AudioPlayer::AudioCallback(int event, void *user, void *info) { 180 static_cast<AudioPlayer *>(user)->AudioCallback(event, info); 181} 182 183// static 184void AudioPlayer::AudioSinkCallback( 185 MediaPlayerBase::AudioSink *audioSink, 186 void *buffer, size_t size, void *cookie) { 187 AudioPlayer *me = (AudioPlayer *)cookie; 188 189 me->fillBuffer(buffer, size); 190} 191 192void AudioPlayer::AudioCallback(int event, void *info) { 193 if (event != AudioTrack::EVENT_MORE_DATA) { 194 return; 195 } 196 197 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info; 198 fillBuffer(buffer->raw, buffer->size); 199} 200 201void AudioPlayer::fillBuffer(void *data, size_t size) { 202 if (mNumFramesPlayed == 0) { 203 LOGV("AudioCallback"); 204 } 205 206 size_t size_done = 0; 207 size_t size_remaining = size; 208 while (size_remaining > 0) { 209 MediaSource::ReadOptions options; 210 211 { 212 Mutex::Autolock autoLock(mLock); 213 214 if (mSeeking) { 215 options.setSeekTo(mSeekTimeUs); 216 217 if (mInputBuffer != NULL) { 218 mInputBuffer->release(); 219 mInputBuffer = NULL; 220 } 221 } 222 } 223 224 if (mInputBuffer == NULL) { 225 status_t err = mSource->read(&mInputBuffer, &options); 226 227 CHECK((err == OK && mInputBuffer != NULL) 228 || (err != OK && mInputBuffer == NULL)); 229 230 if (mSeeking) { 231 mSeeking = false; 232 233 if (mListenerCallback) { 234 (*mListenerCallback)(mListenerCookie, SEEK_COMPLETE); 235 } 236 } 237 238 if (err != OK) { 239 if (mListenerCallback) { 240 (*mListenerCallback)(mListenerCookie, REACHED_EOS); 241 } 242 243 memset((char *)data + size_done, 0, size_remaining); 244 break; 245 } 246 247 Mutex::Autolock autoLock(mLock); 248 CHECK(mInputBuffer->meta_data()->findInt64( 249 kKeyTime, &mPositionTimeMediaUs)); 250 251 mPositionTimeRealUs = 252 -mLatencyUs 253 + ((mNumFramesPlayed + size_done / mFrameSize) * 1000000) 254 / mSampleRate; 255 256 LOGV("buffer->size() = %d, " 257 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f", 258 mInputBuffer->range_length(), 259 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6); 260 } 261 262 if (mInputBuffer->range_length() == 0) { 263 mInputBuffer->release(); 264 mInputBuffer = NULL; 265 266 continue; 267 } 268 269 size_t copy = size_remaining; 270 if (copy > mInputBuffer->range_length()) { 271 copy = mInputBuffer->range_length(); 272 } 273 274 memcpy((char *)data + size_done, 275 (const char *)mInputBuffer->data() + mInputBuffer->range_offset(), 276 copy); 277 278 mInputBuffer->set_range(mInputBuffer->range_offset() + copy, 279 mInputBuffer->range_length() - copy); 280 281 size_done += copy; 282 size_remaining -= copy; 283 } 284 285 Mutex::Autolock autoLock(mLock); 286 mNumFramesPlayed += size / mFrameSize; 287} 288 289int64_t AudioPlayer::getRealTimeUs() { 290 Mutex::Autolock autoLock(mLock); 291 return getRealTimeUsLocked(); 292} 293 294int64_t AudioPlayer::getRealTimeUsLocked() const { 295 return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate; 296} 297 298int64_t AudioPlayer::getMediaTimeUs() { 299 Mutex::Autolock autoLock(mLock); 300 301 if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) { 302 return 0; 303 } 304 305 return mPositionTimeMediaUs + (getRealTimeUsLocked() - mPositionTimeRealUs); 306} 307 308bool AudioPlayer::getMediaTimeMapping( 309 int64_t *realtime_us, int64_t *mediatime_us) { 310 Mutex::Autolock autoLock(mLock); 311 312 *realtime_us = mPositionTimeRealUs; 313 *mediatime_us = mPositionTimeMediaUs; 314 315 return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1; 316} 317 318status_t AudioPlayer::seekTo(int64_t time_us) { 319 Mutex::Autolock autoLock(mLock); 320 321 mSeeking = true; 322 mSeekTimeUs = time_us; 323 324 return OK; 325} 326 327} 328