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