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