AudioPlayer.cpp revision 84ec55b736ae2278d6abdc1c7a0312de46ef5f3d
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::setSource(const sp<MediaSource> &source) { 51 CHECK_EQ(mSource, NULL); 52 mSource = source; 53} 54 55void AudioPlayer::start() { 56 CHECK(!mStarted); 57 CHECK(mSource != NULL); 58 59 status_t err = mSource->start(); 60 CHECK_EQ(err, OK); 61 62 sp<MetaData> format = mSource->getFormat(); 63 const char *mime; 64 bool success = format->findCString(kKeyMIMEType, &mime); 65 CHECK(success); 66 CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)); 67 68 success = format->findInt32(kKeySampleRate, &mSampleRate); 69 CHECK(success); 70 71 int32_t numChannels; 72 success = format->findInt32(kKeyChannelCount, &numChannels); 73 CHECK(success); 74 75 if (mAudioSink.get() != NULL) { 76 status_t err = mAudioSink->open( 77 mSampleRate, numChannels, AudioSystem::PCM_16_BIT, 78 DEFAULT_AUDIOSINK_BUFFERCOUNT, 79 &AudioPlayer::AudioSinkCallback, this); 80 CHECK_EQ(err, OK); 81 82 mLatencyUs = (int64_t)mAudioSink->latency() * 1000; 83 mFrameSize = mAudioSink->frameSize(); 84 85 mAudioSink->start(); 86 } else { 87 mAudioTrack = new AudioTrack( 88 AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT, 89 (numChannels == 2) 90 ? AudioSystem::CHANNEL_OUT_STEREO 91 : AudioSystem::CHANNEL_OUT_MONO, 92 8192, 0, &AudioCallback, this, 0); 93 94 CHECK_EQ(mAudioTrack->initCheck(), OK); 95 96 mLatencyUs = (int64_t)mAudioTrack->latency() * 1000; 97 mFrameSize = mAudioTrack->frameSize(); 98 99 mAudioTrack->start(); 100 } 101 102 mStarted = true; 103} 104 105void AudioPlayer::pause() { 106 CHECK(mStarted); 107 108 if (mAudioSink.get() != NULL) { 109 mAudioSink->pause(); 110 } else { 111 mAudioTrack->stop(); 112 } 113} 114 115void AudioPlayer::resume() { 116 CHECK(mStarted); 117 118 if (mAudioSink.get() != NULL) { 119 mAudioSink->start(); 120 } else { 121 mAudioTrack->start(); 122 } 123} 124 125void AudioPlayer::stop() { 126 CHECK(mStarted); 127 128 if (mAudioSink.get() != NULL) { 129 mAudioSink->stop(); 130 } else { 131 mAudioTrack->stop(); 132 133 delete mAudioTrack; 134 mAudioTrack = NULL; 135 } 136 137 // Make sure to release any buffer we hold onto so that the 138 // source is able to stop(). 139 if (mInputBuffer != NULL) { 140 LOGV("AudioPlayer releasing input buffer."); 141 142 mInputBuffer->release(); 143 mInputBuffer = NULL; 144 } 145 146 mSource->stop(); 147 148 mNumFramesPlayed = 0; 149 mPositionTimeMediaUs = -1; 150 mPositionTimeRealUs = -1; 151 mSeeking = false; 152 mStarted = false; 153} 154 155// static 156void AudioPlayer::AudioCallback(int event, void *user, void *info) { 157 static_cast<AudioPlayer *>(user)->AudioCallback(event, info); 158} 159 160// static 161void AudioPlayer::AudioSinkCallback( 162 MediaPlayerBase::AudioSink *audioSink, 163 void *buffer, size_t size, void *cookie) { 164 AudioPlayer *me = (AudioPlayer *)cookie; 165 166 me->fillBuffer(buffer, size); 167} 168 169void AudioPlayer::AudioCallback(int event, void *info) { 170 if (event != AudioTrack::EVENT_MORE_DATA) { 171 return; 172 } 173 174 AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info; 175 fillBuffer(buffer->raw, buffer->size); 176} 177 178void AudioPlayer::fillBuffer(void *data, size_t size) { 179 if (mNumFramesPlayed == 0) { 180 LOGV("AudioCallback"); 181 } 182 183 size_t size_done = 0; 184 size_t size_remaining = size; 185 while (size_remaining > 0) { 186 MediaSource::ReadOptions options; 187 188 { 189 Mutex::Autolock autoLock(mLock); 190 191 if (mSeeking) { 192 options.setSeekTo(mSeekTimeUs); 193 194 if (mInputBuffer != NULL) { 195 mInputBuffer->release(); 196 mInputBuffer = NULL; 197 } 198 mSeeking = false; 199 } 200 } 201 202 if (mInputBuffer == NULL) { 203 status_t err = mSource->read(&mInputBuffer, &options); 204 205 CHECK((err == OK && mInputBuffer != NULL) 206 || (err != OK && mInputBuffer == NULL)); 207 208 if (err != OK) { 209 memset((char *)data + size_done, 0, size_remaining); 210 break; 211 } 212 213 Mutex::Autolock autoLock(mLock); 214 CHECK(mInputBuffer->meta_data()->findInt64( 215 kKeyTime, &mPositionTimeMediaUs)); 216 217 mPositionTimeRealUs = 218 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000) 219 / mSampleRate; 220 221 LOGV("buffer->size() = %d, " 222 "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f", 223 mInputBuffer->range_length(), 224 mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6); 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