OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / media / libstagefright / AudioPlayer.cpp
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 <binder/IPCThreadState.h>
22 #include <media/AudioTrack.h>
23 #include <media/stagefright/AudioPlayer.h>
24 #include <media/stagefright/MediaDebug.h>
25 #include <media/stagefright/MediaDefs.h>
26 #include <media/stagefright/MediaErrors.h>
27 #include <media/stagefright/MediaSource.h>
28 #include <media/stagefright/MetaData.h>
29
30 #include "include/AwesomePlayer.h"
31
32 namespace android {
33
34 AudioPlayer::AudioPlayer(
35         const sp<MediaPlayerBase::AudioSink> &audioSink,
36         AwesomePlayer *observer)
37     : mAudioTrack(NULL),
38       mInputBuffer(NULL),
39       mSampleRate(0),
40       mLatencyUs(0),
41       mFrameSize(0),
42       mNumFramesPlayed(0),
43       mPositionTimeMediaUs(-1),
44       mPositionTimeRealUs(-1),
45       mSeeking(false),
46       mReachedEOS(false),
47       mFinalStatus(OK),
48       mStarted(false),
49       mIsFirstBuffer(false),
50       mFirstBufferResult(OK),
51       mFirstBuffer(NULL),
52       mAudioSink(audioSink),
53       mObserver(observer) {
54 }
55
56 AudioPlayer::~AudioPlayer() {
57     if (mStarted) {
58         reset();
59     }
60 }
61
62 void AudioPlayer::setSource(const sp<MediaSource> &source) {
63     CHECK_EQ(mSource, NULL);
64     mSource = source;
65 }
66
67 status_t AudioPlayer::start(bool sourceAlreadyStarted) {
68     CHECK(!mStarted);
69     CHECK(mSource != NULL);
70
71     status_t err;
72     if (!sourceAlreadyStarted) {
73         err = mSource->start();
74
75         if (err != OK) {
76             return err;
77         }
78     }
79
80     // We allow an optional INFO_FORMAT_CHANGED at the very beginning
81     // of playback, if there is one, getFormat below will retrieve the
82     // updated format, if there isn't, we'll stash away the valid buffer
83     // of data to be used on the first audio callback.
84
85     CHECK(mFirstBuffer == NULL);
86
87     mFirstBufferResult = mSource->read(&mFirstBuffer);
88     if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
89         LOGV("INFO_FORMAT_CHANGED!!!");
90
91         CHECK(mFirstBuffer == NULL);
92         mFirstBufferResult = OK;
93         mIsFirstBuffer = false;
94     } else {
95         mIsFirstBuffer = true;
96     }
97
98     sp<MetaData> format = mSource->getFormat();
99     const char *mime;
100     bool success = format->findCString(kKeyMIMEType, &mime);
101     CHECK(success);
102     CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW));
103
104     success = format->findInt32(kKeySampleRate, &mSampleRate);
105     CHECK(success);
106
107     int32_t numChannels;
108     success = format->findInt32(kKeyChannelCount, &numChannels);
109     CHECK(success);
110
111     if (mAudioSink.get() != NULL) {
112         status_t err = mAudioSink->open(
113                 mSampleRate, numChannels, AudioSystem::PCM_16_BIT,
114                 DEFAULT_AUDIOSINK_BUFFERCOUNT,
115                 &AudioPlayer::AudioSinkCallback, this);
116         if (err != OK) {
117             if (mFirstBuffer != NULL) {
118                 mFirstBuffer->release();
119                 mFirstBuffer = NULL;
120             }
121
122             if (!sourceAlreadyStarted) {
123                 mSource->stop();
124             }
125
126             return err;
127         }
128
129         mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
130         mFrameSize = mAudioSink->frameSize();
131
132         mAudioSink->start();
133     } else {
134         mAudioTrack = new AudioTrack(
135                 AudioSystem::MUSIC, mSampleRate, AudioSystem::PCM_16_BIT,
136                 (numChannels == 2)
137                     ? AudioSystem::CHANNEL_OUT_STEREO
138                     : AudioSystem::CHANNEL_OUT_MONO,
139                 0, 0, &AudioCallback, this, 0);
140
141         if ((err = mAudioTrack->initCheck()) != OK) {
142             delete mAudioTrack;
143             mAudioTrack = NULL;
144
145             if (mFirstBuffer != NULL) {
146                 mFirstBuffer->release();
147                 mFirstBuffer = NULL;
148             }
149
150             if (!sourceAlreadyStarted) {
151                 mSource->stop();
152             }
153
154             return err;
155         }
156
157         mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
158         mFrameSize = mAudioTrack->frameSize();
159
160         mAudioTrack->start();
161     }
162
163     mStarted = true;
164
165     return OK;
166 }
167
168 void AudioPlayer::pause(bool playPendingSamples) {
169     CHECK(mStarted);
170
171     if (playPendingSamples) {
172         if (mAudioSink.get() != NULL) {
173             mAudioSink->stop();
174         } else {
175             mAudioTrack->stop();
176         }
177     } else {
178         if (mAudioSink.get() != NULL) {
179             mAudioSink->pause();
180         } else {
181             mAudioTrack->pause();
182         }
183     }
184 }
185
186 void AudioPlayer::resume() {
187     CHECK(mStarted);
188
189     if (mAudioSink.get() != NULL) {
190         mAudioSink->start();
191     } else {
192         mAudioTrack->start();
193     }
194 }
195
196 void AudioPlayer::reset() {
197     CHECK(mStarted);
198
199     if (mAudioSink.get() != NULL) {
200         mAudioSink->stop();
201         mAudioSink->close();
202     } else {
203         mAudioTrack->stop();
204
205         delete mAudioTrack;
206         mAudioTrack = NULL;
207     }
208
209     // Make sure to release any buffer we hold onto so that the
210     // source is able to stop().
211
212     if (mFirstBuffer != NULL) {
213         mFirstBuffer->release();
214         mFirstBuffer = NULL;
215     }
216
217     if (mInputBuffer != NULL) {
218         LOGV("AudioPlayer releasing input buffer.");
219
220         mInputBuffer->release();
221         mInputBuffer = NULL;
222     }
223
224     mSource->stop();
225
226     // The following hack is necessary to ensure that the OMX
227     // component is completely released by the time we may try
228     // to instantiate it again.
229     wp<MediaSource> tmp = mSource;
230     mSource.clear();
231     while (tmp.promote() != NULL) {
232         usleep(1000);
233     }
234     IPCThreadState::self()->flushCommands();
235
236     mNumFramesPlayed = 0;
237     mPositionTimeMediaUs = -1;
238     mPositionTimeRealUs = -1;
239     mSeeking = false;
240     mReachedEOS = false;
241     mFinalStatus = OK;
242     mStarted = false;
243 }
244
245 // static
246 void AudioPlayer::AudioCallback(int event, void *user, void *info) {
247     static_cast<AudioPlayer *>(user)->AudioCallback(event, info);
248 }
249
250 bool AudioPlayer::isSeeking() {
251     Mutex::Autolock autoLock(mLock);
252     return mSeeking;
253 }
254
255 bool AudioPlayer::reachedEOS(status_t *finalStatus) {
256     *finalStatus = OK;
257
258     Mutex::Autolock autoLock(mLock);
259     *finalStatus = mFinalStatus;
260     return mReachedEOS;
261 }
262
263 // static
264 size_t AudioPlayer::AudioSinkCallback(
265         MediaPlayerBase::AudioSink *audioSink,
266         void *buffer, size_t size, void *cookie) {
267     AudioPlayer *me = (AudioPlayer *)cookie;
268
269     return me->fillBuffer(buffer, size);
270 }
271
272 void AudioPlayer::AudioCallback(int event, void *info) {
273     if (event != AudioTrack::EVENT_MORE_DATA) {
274         return;
275     }
276
277     AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
278     size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
279
280     buffer->size = numBytesWritten;
281 }
282
283 size_t AudioPlayer::fillBuffer(void *data, size_t size) {
284     if (mNumFramesPlayed == 0) {
285         LOGV("AudioCallback");
286     }
287
288     if (mReachedEOS) {
289         return 0;
290     }
291
292     size_t size_done = 0;
293     size_t size_remaining = size;
294     while (size_remaining > 0) {
295         MediaSource::ReadOptions options;
296
297         {
298             Mutex::Autolock autoLock(mLock);
299
300             if (mSeeking) {
301                 if (mIsFirstBuffer) {
302                     if (mFirstBuffer != NULL) {
303                         mFirstBuffer->release();
304                         mFirstBuffer = NULL;
305                     }
306                     mIsFirstBuffer = false;
307                 }
308
309                 options.setSeekTo(mSeekTimeUs);
310
311                 if (mInputBuffer != NULL) {
312                     mInputBuffer->release();
313                     mInputBuffer = NULL;
314                 }
315
316                 mSeeking = false;
317                 if (mObserver) {
318                     mObserver->postAudioSeekComplete();
319                 }
320             }
321         }
322
323         if (mInputBuffer == NULL) {
324             status_t err;
325
326             if (mIsFirstBuffer) {
327                 mInputBuffer = mFirstBuffer;
328                 mFirstBuffer = NULL;
329                 err = mFirstBufferResult;
330
331                 mIsFirstBuffer = false;
332             } else {
333                 err = mSource->read(&mInputBuffer, &options);
334             }
335
336             CHECK((err == OK && mInputBuffer != NULL)
337                    || (err != OK && mInputBuffer == NULL));
338
339             Mutex::Autolock autoLock(mLock);
340
341             if (err != OK) {
342                 if (mObserver && !mReachedEOS) {
343                     mObserver->postAudioEOS();
344                 }
345
346                 mReachedEOS = true;
347                 mFinalStatus = err;
348                 break;
349             }
350
351             CHECK(mInputBuffer->meta_data()->findInt64(
352                         kKeyTime, &mPositionTimeMediaUs));
353
354             mPositionTimeRealUs =
355                 ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
356                     / mSampleRate;
357
358             LOGV("buffer->size() = %d, "
359                  "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
360                  mInputBuffer->range_length(),
361                  mPositionTimeMediaUs / 1E6, mPositionTimeRealUs / 1E6);
362         }
363
364         if (mInputBuffer->range_length() == 0) {
365             mInputBuffer->release();
366             mInputBuffer = NULL;
367
368             continue;
369         }
370
371         size_t copy = size_remaining;
372         if (copy > mInputBuffer->range_length()) {
373             copy = mInputBuffer->range_length();
374         }
375
376         memcpy((char *)data + size_done,
377                (const char *)mInputBuffer->data() + mInputBuffer->range_offset(),
378                copy);
379
380         mInputBuffer->set_range(mInputBuffer->range_offset() + copy,
381                                 mInputBuffer->range_length() - copy);
382
383         size_done += copy;
384         size_remaining -= copy;
385     }
386
387     Mutex::Autolock autoLock(mLock);
388     mNumFramesPlayed += size_done / mFrameSize;
389
390     return size_done;
391 }
392
393 int64_t AudioPlayer::getRealTimeUs() {
394     Mutex::Autolock autoLock(mLock);
395     return getRealTimeUsLocked();
396 }
397
398 int64_t AudioPlayer::getRealTimeUsLocked() const {
399     return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
400 }
401
402 int64_t AudioPlayer::getMediaTimeUs() {
403     Mutex::Autolock autoLock(mLock);
404
405     if (mPositionTimeMediaUs < 0 || mPositionTimeRealUs < 0) {
406         return 0;
407     }
408
409     int64_t realTimeOffset = getRealTimeUsLocked() - mPositionTimeRealUs;
410     if (realTimeOffset < 0) {
411         realTimeOffset = 0;
412     }
413
414     return mPositionTimeMediaUs + realTimeOffset;
415 }
416
417 bool AudioPlayer::getMediaTimeMapping(
418         int64_t *realtime_us, int64_t *mediatime_us) {
419     Mutex::Autolock autoLock(mLock);
420
421     *realtime_us = mPositionTimeRealUs;
422     *mediatime_us = mPositionTimeMediaUs;
423
424     return mPositionTimeRealUs != -1 && mPositionTimeMediaUs != -1;
425 }
426
427 status_t AudioPlayer::seekTo(int64_t time_us) {
428     Mutex::Autolock autoLock(mLock);
429
430     mSeeking = true;
431     mReachedEOS = false;
432     mSeekTimeUs = time_us;
433
434     if (mAudioSink != NULL) {
435         mAudioSink->flush();
436     } else {
437         mAudioTrack->flush();
438     }
439
440     return OK;
441 }
442
443 }