1*bebae9c0SAndroid Build Coastguard Worker /*
2*bebae9c0SAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project
3*bebae9c0SAndroid Build Coastguard Worker *
4*bebae9c0SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*bebae9c0SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*bebae9c0SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*bebae9c0SAndroid Build Coastguard Worker *
8*bebae9c0SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*bebae9c0SAndroid Build Coastguard Worker *
10*bebae9c0SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*bebae9c0SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*bebae9c0SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*bebae9c0SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*bebae9c0SAndroid Build Coastguard Worker * limitations under the License.
15*bebae9c0SAndroid Build Coastguard Worker */
16*bebae9c0SAndroid Build Coastguard Worker
17*bebae9c0SAndroid Build Coastguard Worker //#define USE_LOG SLAndroidLogLevel_Verbose
18*bebae9c0SAndroid Build Coastguard Worker
19*bebae9c0SAndroid Build Coastguard Worker #include "sles_allinclusive.h"
20*bebae9c0SAndroid Build Coastguard Worker #include "android/android_AudioSfDecoder.h"
21*bebae9c0SAndroid Build Coastguard Worker #include "android/channels.h"
22*bebae9c0SAndroid Build Coastguard Worker
23*bebae9c0SAndroid Build Coastguard Worker #include <binder/IServiceManager.h>
24*bebae9c0SAndroid Build Coastguard Worker #include <datasource/DataSourceFactory.h>
25*bebae9c0SAndroid Build Coastguard Worker #include <datasource/FileSource.h>
26*bebae9c0SAndroid Build Coastguard Worker #include <datasource/NuCachedSource2.h>
27*bebae9c0SAndroid Build Coastguard Worker #include <media/IMediaHTTPService.h>
28*bebae9c0SAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
29*bebae9c0SAndroid Build Coastguard Worker #include <media/stagefright/InterfaceUtils.h>
30*bebae9c0SAndroid Build Coastguard Worker #include <media/stagefright/MediaBuffer.h>
31*bebae9c0SAndroid Build Coastguard Worker #include <media/stagefright/MediaExtractorFactory.h>
32*bebae9c0SAndroid Build Coastguard Worker #include <media/stagefright/MetaData.h>
33*bebae9c0SAndroid Build Coastguard Worker #include <media/stagefright/SimpleDecodingSource.h>
34*bebae9c0SAndroid Build Coastguard Worker #include <media/stagefright/foundation/MediaDefs.h>
35*bebae9c0SAndroid Build Coastguard Worker
36*bebae9c0SAndroid Build Coastguard Worker
37*bebae9c0SAndroid Build Coastguard Worker #define SIZE_CACHED_HIGH_BYTES 1000000
38*bebae9c0SAndroid Build Coastguard Worker #define SIZE_CACHED_MED_BYTES 700000
39*bebae9c0SAndroid Build Coastguard Worker #define SIZE_CACHED_LOW_BYTES 400000
40*bebae9c0SAndroid Build Coastguard Worker
41*bebae9c0SAndroid Build Coastguard Worker namespace android {
42*bebae9c0SAndroid Build Coastguard Worker
43*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
AudioSfDecoder(const AudioPlayback_Parameters * params)44*bebae9c0SAndroid Build Coastguard Worker AudioSfDecoder::AudioSfDecoder(const AudioPlayback_Parameters* params) : GenericPlayer(params),
45*bebae9c0SAndroid Build Coastguard Worker mDataSource(0),
46*bebae9c0SAndroid Build Coastguard Worker mAudioSource(0),
47*bebae9c0SAndroid Build Coastguard Worker mAudioSourceStarted(false),
48*bebae9c0SAndroid Build Coastguard Worker mBitrate(-1),
49*bebae9c0SAndroid Build Coastguard Worker mDurationUsec(ANDROID_UNKNOWN_TIME),
50*bebae9c0SAndroid Build Coastguard Worker mDecodeBuffer(NULL),
51*bebae9c0SAndroid Build Coastguard Worker mSeekTimeMsec(0),
52*bebae9c0SAndroid Build Coastguard Worker // play event logic depends on the initial time being zero not ANDROID_UNKNOWN_TIME
53*bebae9c0SAndroid Build Coastguard Worker mLastDecodedPositionUs(0)
54*bebae9c0SAndroid Build Coastguard Worker {
55*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("AudioSfDecoder::AudioSfDecoder()");
56*bebae9c0SAndroid Build Coastguard Worker }
57*bebae9c0SAndroid Build Coastguard Worker
58*bebae9c0SAndroid Build Coastguard Worker
~AudioSfDecoder()59*bebae9c0SAndroid Build Coastguard Worker AudioSfDecoder::~AudioSfDecoder() {
60*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("AudioSfDecoder::~AudioSfDecoder()");
61*bebae9c0SAndroid Build Coastguard Worker }
62*bebae9c0SAndroid Build Coastguard Worker
63*bebae9c0SAndroid Build Coastguard Worker
preDestroy()64*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::preDestroy() {
65*bebae9c0SAndroid Build Coastguard Worker GenericPlayer::preDestroy();
66*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("AudioSfDecoder::preDestroy()");
67*bebae9c0SAndroid Build Coastguard Worker {
68*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mBufferSourceLock);
69*bebae9c0SAndroid Build Coastguard Worker
70*bebae9c0SAndroid Build Coastguard Worker if (NULL != mDecodeBuffer) {
71*bebae9c0SAndroid Build Coastguard Worker mDecodeBuffer->release();
72*bebae9c0SAndroid Build Coastguard Worker mDecodeBuffer = NULL;
73*bebae9c0SAndroid Build Coastguard Worker }
74*bebae9c0SAndroid Build Coastguard Worker
75*bebae9c0SAndroid Build Coastguard Worker if ((mAudioSource != 0) && mAudioSourceStarted) {
76*bebae9c0SAndroid Build Coastguard Worker mAudioSource->stop();
77*bebae9c0SAndroid Build Coastguard Worker mAudioSourceStarted = false;
78*bebae9c0SAndroid Build Coastguard Worker }
79*bebae9c0SAndroid Build Coastguard Worker }
80*bebae9c0SAndroid Build Coastguard Worker }
81*bebae9c0SAndroid Build Coastguard Worker
82*bebae9c0SAndroid Build Coastguard Worker
83*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
play()84*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::play() {
85*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("AudioSfDecoder::play");
86*bebae9c0SAndroid Build Coastguard Worker
87*bebae9c0SAndroid Build Coastguard Worker GenericPlayer::play();
88*bebae9c0SAndroid Build Coastguard Worker (new AMessage(kWhatDecode, this))->post();
89*bebae9c0SAndroid Build Coastguard Worker }
90*bebae9c0SAndroid Build Coastguard Worker
91*bebae9c0SAndroid Build Coastguard Worker
getPositionMsec(int * msec)92*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::getPositionMsec(int* msec) {
93*bebae9c0SAndroid Build Coastguard Worker int64_t timeUsec = getPositionUsec();
94*bebae9c0SAndroid Build Coastguard Worker if (timeUsec == ANDROID_UNKNOWN_TIME) {
95*bebae9c0SAndroid Build Coastguard Worker *msec = ANDROID_UNKNOWN_TIME;
96*bebae9c0SAndroid Build Coastguard Worker } else {
97*bebae9c0SAndroid Build Coastguard Worker *msec = timeUsec / 1000;
98*bebae9c0SAndroid Build Coastguard Worker }
99*bebae9c0SAndroid Build Coastguard Worker }
100*bebae9c0SAndroid Build Coastguard Worker
101*bebae9c0SAndroid Build Coastguard Worker
102*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
getPcmFormatKeyCount() const103*bebae9c0SAndroid Build Coastguard Worker uint32_t AudioSfDecoder::getPcmFormatKeyCount() const {
104*bebae9c0SAndroid Build Coastguard Worker return NB_PCMMETADATA_KEYS;
105*bebae9c0SAndroid Build Coastguard Worker }
106*bebae9c0SAndroid Build Coastguard Worker
107*bebae9c0SAndroid Build Coastguard Worker
108*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
getPcmFormatKeySize(uint32_t index,uint32_t * pKeySize)109*bebae9c0SAndroid Build Coastguard Worker bool AudioSfDecoder::getPcmFormatKeySize(uint32_t index, uint32_t* pKeySize) {
110*bebae9c0SAndroid Build Coastguard Worker if (index >= NB_PCMMETADATA_KEYS) {
111*bebae9c0SAndroid Build Coastguard Worker return false;
112*bebae9c0SAndroid Build Coastguard Worker } else {
113*bebae9c0SAndroid Build Coastguard Worker *pKeySize = strlen(kPcmDecodeMetadataKeys[index]) +1;
114*bebae9c0SAndroid Build Coastguard Worker return true;
115*bebae9c0SAndroid Build Coastguard Worker }
116*bebae9c0SAndroid Build Coastguard Worker }
117*bebae9c0SAndroid Build Coastguard Worker
118*bebae9c0SAndroid Build Coastguard Worker
119*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
getPcmFormatKeyName(uint32_t index,uint32_t keySize,char * keyName)120*bebae9c0SAndroid Build Coastguard Worker bool AudioSfDecoder::getPcmFormatKeyName(uint32_t index, uint32_t keySize, char* keyName) {
121*bebae9c0SAndroid Build Coastguard Worker uint32_t actualKeySize;
122*bebae9c0SAndroid Build Coastguard Worker if (!getPcmFormatKeySize(index, &actualKeySize)) {
123*bebae9c0SAndroid Build Coastguard Worker return false;
124*bebae9c0SAndroid Build Coastguard Worker }
125*bebae9c0SAndroid Build Coastguard Worker if (keySize < actualKeySize) {
126*bebae9c0SAndroid Build Coastguard Worker return false;
127*bebae9c0SAndroid Build Coastguard Worker }
128*bebae9c0SAndroid Build Coastguard Worker strncpy(keyName, kPcmDecodeMetadataKeys[index], actualKeySize);
129*bebae9c0SAndroid Build Coastguard Worker return true;
130*bebae9c0SAndroid Build Coastguard Worker }
131*bebae9c0SAndroid Build Coastguard Worker
132*bebae9c0SAndroid Build Coastguard Worker
133*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
getPcmFormatValueSize(uint32_t index,uint32_t * pValueSize)134*bebae9c0SAndroid Build Coastguard Worker bool AudioSfDecoder::getPcmFormatValueSize(uint32_t index, uint32_t* pValueSize) {
135*bebae9c0SAndroid Build Coastguard Worker if (index >= NB_PCMMETADATA_KEYS) {
136*bebae9c0SAndroid Build Coastguard Worker *pValueSize = 0;
137*bebae9c0SAndroid Build Coastguard Worker return false;
138*bebae9c0SAndroid Build Coastguard Worker } else {
139*bebae9c0SAndroid Build Coastguard Worker *pValueSize = sizeof(uint32_t);
140*bebae9c0SAndroid Build Coastguard Worker return true;
141*bebae9c0SAndroid Build Coastguard Worker }
142*bebae9c0SAndroid Build Coastguard Worker }
143*bebae9c0SAndroid Build Coastguard Worker
144*bebae9c0SAndroid Build Coastguard Worker
145*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
getPcmFormatKeyValue(uint32_t index,uint32_t size,uint32_t * pValue)146*bebae9c0SAndroid Build Coastguard Worker bool AudioSfDecoder::getPcmFormatKeyValue(uint32_t index, uint32_t size, uint32_t* pValue) {
147*bebae9c0SAndroid Build Coastguard Worker uint32_t valueSize = 0;
148*bebae9c0SAndroid Build Coastguard Worker if (!getPcmFormatValueSize(index, &valueSize)) {
149*bebae9c0SAndroid Build Coastguard Worker return false;
150*bebae9c0SAndroid Build Coastguard Worker } else if (size != valueSize) {
151*bebae9c0SAndroid Build Coastguard Worker // this ensures we are accessing mPcmFormatValues with a valid size for that index
152*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("Error retrieving metadata value at index %d: using size of %d, should be %d",
153*bebae9c0SAndroid Build Coastguard Worker index, size, valueSize);
154*bebae9c0SAndroid Build Coastguard Worker return false;
155*bebae9c0SAndroid Build Coastguard Worker } else {
156*bebae9c0SAndroid Build Coastguard Worker android::Mutex::Autolock autoLock(mPcmFormatLock);
157*bebae9c0SAndroid Build Coastguard Worker *pValue = mPcmFormatValues[index];
158*bebae9c0SAndroid Build Coastguard Worker return true;
159*bebae9c0SAndroid Build Coastguard Worker }
160*bebae9c0SAndroid Build Coastguard Worker }
161*bebae9c0SAndroid Build Coastguard Worker
162*bebae9c0SAndroid Build Coastguard Worker
163*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
164*bebae9c0SAndroid Build Coastguard Worker // Event handlers
165*bebae9c0SAndroid Build Coastguard Worker // it is strictly verboten to call those methods outside of the event loop
166*bebae9c0SAndroid Build Coastguard Worker
167*bebae9c0SAndroid Build Coastguard Worker // Initializes the data and audio sources, and update the PCM format info
168*bebae9c0SAndroid Build Coastguard Worker // post-condition: upon successful initialization based on the player data locator
169*bebae9c0SAndroid Build Coastguard Worker // GenericPlayer::onPrepare() was called
170*bebae9c0SAndroid Build Coastguard Worker // mDataSource != 0
171*bebae9c0SAndroid Build Coastguard Worker // mAudioSource != 0
172*bebae9c0SAndroid Build Coastguard Worker // mAudioSourceStarted == true
173*bebae9c0SAndroid Build Coastguard Worker // All error returns from this method are via notifyPrepared(status) followed by "return".
onPrepare()174*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::onPrepare() {
175*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("AudioSfDecoder::onPrepare()");
176*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mBufferSourceLock);
177*bebae9c0SAndroid Build Coastguard Worker
178*bebae9c0SAndroid Build Coastguard Worker {
179*bebae9c0SAndroid Build Coastguard Worker android::Mutex::Autolock autoLock(mPcmFormatLock);
180*bebae9c0SAndroid Build Coastguard Worker // Initialize the PCM format info with the known parameters before the start of the decode
181*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_BITSPERSAMPLE] = SL_PCMSAMPLEFORMAT_FIXED_16;
182*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CONTAINERSIZE] = 16;
183*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_ENDIANNESS] = SL_BYTEORDER_LITTLEENDIAN;
184*bebae9c0SAndroid Build Coastguard Worker // initialization with the default values: they will be replaced by the actual values
185*bebae9c0SAndroid Build Coastguard Worker // once the decoder has figured them out
186*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS] = UNKNOWN_NUMCHANNELS;
187*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_SAMPLERATE] = UNKNOWN_SAMPLERATE;
188*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CHANNELMASK] = SL_ANDROID_UNKNOWN_CHANNELMASK;
189*bebae9c0SAndroid Build Coastguard Worker }
190*bebae9c0SAndroid Build Coastguard Worker
191*bebae9c0SAndroid Build Coastguard Worker //---------------------------------
192*bebae9c0SAndroid Build Coastguard Worker // Instantiate and initialize the data source for the decoder
193*bebae9c0SAndroid Build Coastguard Worker sp<DataSource> dataSource;
194*bebae9c0SAndroid Build Coastguard Worker
195*bebae9c0SAndroid Build Coastguard Worker switch (mDataLocatorType) {
196*bebae9c0SAndroid Build Coastguard Worker
197*bebae9c0SAndroid Build Coastguard Worker case kDataLocatorNone:
198*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("AudioSfDecoder::onPrepare: no data locator set");
199*bebae9c0SAndroid Build Coastguard Worker notifyPrepared(MEDIA_ERROR_BASE);
200*bebae9c0SAndroid Build Coastguard Worker return;
201*bebae9c0SAndroid Build Coastguard Worker
202*bebae9c0SAndroid Build Coastguard Worker case kDataLocatorUri:
203*bebae9c0SAndroid Build Coastguard Worker dataSource = DataSourceFactory::getInstance()->CreateFromURI(
204*bebae9c0SAndroid Build Coastguard Worker NULL /* XXX httpService */, mDataLocator.uriRef);
205*bebae9c0SAndroid Build Coastguard Worker if (dataSource == NULL) {
206*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("AudioSfDecoder::onPrepare(): Error opening %s", mDataLocator.uriRef);
207*bebae9c0SAndroid Build Coastguard Worker notifyPrepared(MEDIA_ERROR_BASE);
208*bebae9c0SAndroid Build Coastguard Worker return;
209*bebae9c0SAndroid Build Coastguard Worker }
210*bebae9c0SAndroid Build Coastguard Worker break;
211*bebae9c0SAndroid Build Coastguard Worker
212*bebae9c0SAndroid Build Coastguard Worker case kDataLocatorFd:
213*bebae9c0SAndroid Build Coastguard Worker {
214*bebae9c0SAndroid Build Coastguard Worker // As FileSource unconditionally takes ownership of the fd and closes it, then
215*bebae9c0SAndroid Build Coastguard Worker // we have to make a dup for FileSource if the app wants to keep ownership itself
216*bebae9c0SAndroid Build Coastguard Worker int fd = mDataLocator.fdi.fd;
217*bebae9c0SAndroid Build Coastguard Worker if (mDataLocator.fdi.mCloseAfterUse) {
218*bebae9c0SAndroid Build Coastguard Worker mDataLocator.fdi.mCloseAfterUse = false;
219*bebae9c0SAndroid Build Coastguard Worker } else {
220*bebae9c0SAndroid Build Coastguard Worker fd = ::dup(fd);
221*bebae9c0SAndroid Build Coastguard Worker }
222*bebae9c0SAndroid Build Coastguard Worker dataSource = new FileSource(fd, mDataLocator.fdi.offset, mDataLocator.fdi.length);
223*bebae9c0SAndroid Build Coastguard Worker status_t err = dataSource->initCheck();
224*bebae9c0SAndroid Build Coastguard Worker if (err != OK) {
225*bebae9c0SAndroid Build Coastguard Worker notifyPrepared(err);
226*bebae9c0SAndroid Build Coastguard Worker return;
227*bebae9c0SAndroid Build Coastguard Worker }
228*bebae9c0SAndroid Build Coastguard Worker break;
229*bebae9c0SAndroid Build Coastguard Worker }
230*bebae9c0SAndroid Build Coastguard Worker
231*bebae9c0SAndroid Build Coastguard Worker // AndroidBufferQueue data source is handled by a subclass,
232*bebae9c0SAndroid Build Coastguard Worker // which does not call up to this method. Hence, the missing case.
233*bebae9c0SAndroid Build Coastguard Worker default:
234*bebae9c0SAndroid Build Coastguard Worker TRESPASS();
235*bebae9c0SAndroid Build Coastguard Worker }
236*bebae9c0SAndroid Build Coastguard Worker
237*bebae9c0SAndroid Build Coastguard Worker //---------------------------------
238*bebae9c0SAndroid Build Coastguard Worker // Instantiate and initialize the decoder attached to the data source
239*bebae9c0SAndroid Build Coastguard Worker sp<IMediaExtractor> extractor = MediaExtractorFactory::Create(dataSource);
240*bebae9c0SAndroid Build Coastguard Worker if (extractor == NULL) {
241*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("AudioSfDecoder::onPrepare: Could not instantiate extractor.");
242*bebae9c0SAndroid Build Coastguard Worker notifyPrepared(ERROR_UNSUPPORTED);
243*bebae9c0SAndroid Build Coastguard Worker return;
244*bebae9c0SAndroid Build Coastguard Worker }
245*bebae9c0SAndroid Build Coastguard Worker
246*bebae9c0SAndroid Build Coastguard Worker ssize_t audioTrackIndex = -1;
247*bebae9c0SAndroid Build Coastguard Worker bool isRawAudio = false;
248*bebae9c0SAndroid Build Coastguard Worker for (size_t i = 0; i < extractor->countTracks(); ++i) {
249*bebae9c0SAndroid Build Coastguard Worker sp<MetaData> meta = extractor->getTrackMetaData(i);
250*bebae9c0SAndroid Build Coastguard Worker
251*bebae9c0SAndroid Build Coastguard Worker const char *mime;
252*bebae9c0SAndroid Build Coastguard Worker CHECK(meta->findCString(kKeyMIMEType, &mime));
253*bebae9c0SAndroid Build Coastguard Worker
254*bebae9c0SAndroid Build Coastguard Worker if (!strncasecmp("audio/", mime, 6)) {
255*bebae9c0SAndroid Build Coastguard Worker if (isSupportedCodec(mime)) {
256*bebae9c0SAndroid Build Coastguard Worker audioTrackIndex = i;
257*bebae9c0SAndroid Build Coastguard Worker
258*bebae9c0SAndroid Build Coastguard Worker if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) {
259*bebae9c0SAndroid Build Coastguard Worker isRawAudio = true;
260*bebae9c0SAndroid Build Coastguard Worker }
261*bebae9c0SAndroid Build Coastguard Worker break;
262*bebae9c0SAndroid Build Coastguard Worker }
263*bebae9c0SAndroid Build Coastguard Worker }
264*bebae9c0SAndroid Build Coastguard Worker }
265*bebae9c0SAndroid Build Coastguard Worker
266*bebae9c0SAndroid Build Coastguard Worker if (audioTrackIndex < 0) {
267*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("AudioSfDecoder::onPrepare: Could not find a supported audio track.");
268*bebae9c0SAndroid Build Coastguard Worker notifyPrepared(ERROR_UNSUPPORTED);
269*bebae9c0SAndroid Build Coastguard Worker return;
270*bebae9c0SAndroid Build Coastguard Worker }
271*bebae9c0SAndroid Build Coastguard Worker
272*bebae9c0SAndroid Build Coastguard Worker sp<MediaSource> source = CreateMediaSourceFromIMediaSource(
273*bebae9c0SAndroid Build Coastguard Worker extractor->getTrack(audioTrackIndex));
274*bebae9c0SAndroid Build Coastguard Worker sp<MetaData> meta = source->getFormat();
275*bebae9c0SAndroid Build Coastguard Worker
276*bebae9c0SAndroid Build Coastguard Worker // we can't trust the OMXCodec (if there is one) to issue a INFO_FORMAT_CHANGED so we want
277*bebae9c0SAndroid Build Coastguard Worker // to have some meaningful values as soon as possible.
278*bebae9c0SAndroid Build Coastguard Worker int32_t channelCount;
279*bebae9c0SAndroid Build Coastguard Worker bool hasChannelCount = meta->findInt32(kKeyChannelCount, &channelCount);
280*bebae9c0SAndroid Build Coastguard Worker int32_t sr;
281*bebae9c0SAndroid Build Coastguard Worker bool hasSampleRate = meta->findInt32(kKeySampleRate, &sr);
282*bebae9c0SAndroid Build Coastguard Worker
283*bebae9c0SAndroid Build Coastguard Worker // first compute the duration
284*bebae9c0SAndroid Build Coastguard Worker off64_t size;
285*bebae9c0SAndroid Build Coastguard Worker int64_t durationUs;
286*bebae9c0SAndroid Build Coastguard Worker int32_t durationMsec;
287*bebae9c0SAndroid Build Coastguard Worker if (dataSource->getSize(&size) == OK
288*bebae9c0SAndroid Build Coastguard Worker && meta->findInt64(kKeyDuration, &durationUs)) {
289*bebae9c0SAndroid Build Coastguard Worker if (durationUs != 0) {
290*bebae9c0SAndroid Build Coastguard Worker mBitrate = size * 8000000LL / durationUs; // in bits/sec
291*bebae9c0SAndroid Build Coastguard Worker } else {
292*bebae9c0SAndroid Build Coastguard Worker mBitrate = -1;
293*bebae9c0SAndroid Build Coastguard Worker }
294*bebae9c0SAndroid Build Coastguard Worker mDurationUsec = durationUs;
295*bebae9c0SAndroid Build Coastguard Worker durationMsec = durationUs / 1000;
296*bebae9c0SAndroid Build Coastguard Worker } else {
297*bebae9c0SAndroid Build Coastguard Worker mBitrate = -1;
298*bebae9c0SAndroid Build Coastguard Worker mDurationUsec = ANDROID_UNKNOWN_TIME;
299*bebae9c0SAndroid Build Coastguard Worker durationMsec = ANDROID_UNKNOWN_TIME;
300*bebae9c0SAndroid Build Coastguard Worker }
301*bebae9c0SAndroid Build Coastguard Worker
302*bebae9c0SAndroid Build Coastguard Worker // then assign the duration under the settings lock
303*bebae9c0SAndroid Build Coastguard Worker {
304*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mSettingsLock);
305*bebae9c0SAndroid Build Coastguard Worker mDurationMsec = durationMsec;
306*bebae9c0SAndroid Build Coastguard Worker }
307*bebae9c0SAndroid Build Coastguard Worker
308*bebae9c0SAndroid Build Coastguard Worker // the audio content is not raw PCM, so we need a decoder
309*bebae9c0SAndroid Build Coastguard Worker if (!isRawAudio) {
310*bebae9c0SAndroid Build Coastguard Worker source = SimpleDecodingSource::Create(source);
311*bebae9c0SAndroid Build Coastguard Worker if (source == NULL) {
312*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("AudioSfDecoder::onPrepare: Could not instantiate decoder.");
313*bebae9c0SAndroid Build Coastguard Worker notifyPrepared(ERROR_UNSUPPORTED);
314*bebae9c0SAndroid Build Coastguard Worker return;
315*bebae9c0SAndroid Build Coastguard Worker }
316*bebae9c0SAndroid Build Coastguard Worker
317*bebae9c0SAndroid Build Coastguard Worker meta = source->getFormat();
318*bebae9c0SAndroid Build Coastguard Worker }
319*bebae9c0SAndroid Build Coastguard Worker
320*bebae9c0SAndroid Build Coastguard Worker
321*bebae9c0SAndroid Build Coastguard Worker if (source->start() != OK) {
322*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("AudioSfDecoder::onPrepare: Failed to start source/decoder.");
323*bebae9c0SAndroid Build Coastguard Worker notifyPrepared(MEDIA_ERROR_BASE);
324*bebae9c0SAndroid Build Coastguard Worker return;
325*bebae9c0SAndroid Build Coastguard Worker }
326*bebae9c0SAndroid Build Coastguard Worker
327*bebae9c0SAndroid Build Coastguard Worker //---------------------------------
328*bebae9c0SAndroid Build Coastguard Worker // The data source, and audio source (a decoder if required) are ready to be used
329*bebae9c0SAndroid Build Coastguard Worker mDataSource = dataSource;
330*bebae9c0SAndroid Build Coastguard Worker mAudioSource = source;
331*bebae9c0SAndroid Build Coastguard Worker mAudioSourceStarted = true;
332*bebae9c0SAndroid Build Coastguard Worker
333*bebae9c0SAndroid Build Coastguard Worker if (!hasChannelCount) {
334*bebae9c0SAndroid Build Coastguard Worker CHECK(meta->findInt32(kKeyChannelCount, &channelCount));
335*bebae9c0SAndroid Build Coastguard Worker }
336*bebae9c0SAndroid Build Coastguard Worker
337*bebae9c0SAndroid Build Coastguard Worker if (!hasSampleRate) {
338*bebae9c0SAndroid Build Coastguard Worker CHECK(meta->findInt32(kKeySampleRate, &sr));
339*bebae9c0SAndroid Build Coastguard Worker }
340*bebae9c0SAndroid Build Coastguard Worker // FIXME add code below once channel mask support is in, currently initialized to default
341*bebae9c0SAndroid Build Coastguard Worker // value computed from the channel count
342*bebae9c0SAndroid Build Coastguard Worker // if (!hasChannelMask) {
343*bebae9c0SAndroid Build Coastguard Worker // CHECK(meta->findInt32(kKeyChannelMask, &channelMask));
344*bebae9c0SAndroid Build Coastguard Worker // }
345*bebae9c0SAndroid Build Coastguard Worker
346*bebae9c0SAndroid Build Coastguard Worker if (!wantPrefetch()) {
347*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("AudioSfDecoder::onPrepare: no need to prefetch");
348*bebae9c0SAndroid Build Coastguard Worker // doesn't need prefetching, notify good to go
349*bebae9c0SAndroid Build Coastguard Worker mCacheStatus = kStatusHigh;
350*bebae9c0SAndroid Build Coastguard Worker mCacheFill = 1000;
351*bebae9c0SAndroid Build Coastguard Worker notifyStatus();
352*bebae9c0SAndroid Build Coastguard Worker notifyCacheFill();
353*bebae9c0SAndroid Build Coastguard Worker }
354*bebae9c0SAndroid Build Coastguard Worker
355*bebae9c0SAndroid Build Coastguard Worker {
356*bebae9c0SAndroid Build Coastguard Worker android::Mutex::Autolock autoLock(mPcmFormatLock);
357*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_SAMPLERATE] = sr;
358*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS] = channelCount;
359*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CHANNELMASK] =
360*bebae9c0SAndroid Build Coastguard Worker sles_channel_out_mask_from_count(channelCount);
361*bebae9c0SAndroid Build Coastguard Worker }
362*bebae9c0SAndroid Build Coastguard Worker
363*bebae9c0SAndroid Build Coastguard Worker // at this point we have enough information about the source to create the sink that
364*bebae9c0SAndroid Build Coastguard Worker // will consume the data
365*bebae9c0SAndroid Build Coastguard Worker createAudioSink();
366*bebae9c0SAndroid Build Coastguard Worker
367*bebae9c0SAndroid Build Coastguard Worker // signal successful completion of prepare
368*bebae9c0SAndroid Build Coastguard Worker mStateFlags |= kFlagPrepared;
369*bebae9c0SAndroid Build Coastguard Worker
370*bebae9c0SAndroid Build Coastguard Worker GenericPlayer::onPrepare();
371*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("AudioSfDecoder::onPrepare() done, mStateFlags=0x%x", mStateFlags);
372*bebae9c0SAndroid Build Coastguard Worker }
373*bebae9c0SAndroid Build Coastguard Worker
374*bebae9c0SAndroid Build Coastguard Worker
onPause()375*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::onPause() {
376*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("AudioSfDecoder::onPause()");
377*bebae9c0SAndroid Build Coastguard Worker GenericPlayer::onPause();
378*bebae9c0SAndroid Build Coastguard Worker pauseAudioSink();
379*bebae9c0SAndroid Build Coastguard Worker }
380*bebae9c0SAndroid Build Coastguard Worker
381*bebae9c0SAndroid Build Coastguard Worker
onPlay()382*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::onPlay() {
383*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("AudioSfDecoder::onPlay()");
384*bebae9c0SAndroid Build Coastguard Worker GenericPlayer::onPlay();
385*bebae9c0SAndroid Build Coastguard Worker startAudioSink();
386*bebae9c0SAndroid Build Coastguard Worker }
387*bebae9c0SAndroid Build Coastguard Worker
388*bebae9c0SAndroid Build Coastguard Worker
onSeek(const sp<AMessage> & msg)389*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::onSeek(const sp<AMessage> &msg) {
390*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("AudioSfDecoder::onSeek");
391*bebae9c0SAndroid Build Coastguard Worker int64_t timeMsec;
392*bebae9c0SAndroid Build Coastguard Worker CHECK(msg->findInt64(WHATPARAM_SEEK_SEEKTIME_MS, &timeMsec));
393*bebae9c0SAndroid Build Coastguard Worker
394*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mTimeLock);
395*bebae9c0SAndroid Build Coastguard Worker mStateFlags |= kFlagSeeking;
396*bebae9c0SAndroid Build Coastguard Worker mSeekTimeMsec = timeMsec;
397*bebae9c0SAndroid Build Coastguard Worker // don't set mLastDecodedPositionUs to ANDROID_UNKNOWN_TIME; getPositionUsec
398*bebae9c0SAndroid Build Coastguard Worker // ignores mLastDecodedPositionUs while seeking, and substitutes the seek goal instead
399*bebae9c0SAndroid Build Coastguard Worker
400*bebae9c0SAndroid Build Coastguard Worker // nop for now
401*bebae9c0SAndroid Build Coastguard Worker GenericPlayer::onSeek(msg);
402*bebae9c0SAndroid Build Coastguard Worker }
403*bebae9c0SAndroid Build Coastguard Worker
404*bebae9c0SAndroid Build Coastguard Worker
onLoop(const sp<AMessage> & msg)405*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::onLoop(const sp<AMessage> &msg) {
406*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("AudioSfDecoder::onLoop");
407*bebae9c0SAndroid Build Coastguard Worker int32_t loop;
408*bebae9c0SAndroid Build Coastguard Worker CHECK(msg->findInt32(WHATPARAM_LOOP_LOOPING, &loop));
409*bebae9c0SAndroid Build Coastguard Worker
410*bebae9c0SAndroid Build Coastguard Worker if (loop) {
411*bebae9c0SAndroid Build Coastguard Worker //SL_LOGV("AudioSfDecoder::onLoop start looping");
412*bebae9c0SAndroid Build Coastguard Worker mStateFlags |= kFlagLooping;
413*bebae9c0SAndroid Build Coastguard Worker } else {
414*bebae9c0SAndroid Build Coastguard Worker //SL_LOGV("AudioSfDecoder::onLoop stop looping");
415*bebae9c0SAndroid Build Coastguard Worker mStateFlags &= ~kFlagLooping;
416*bebae9c0SAndroid Build Coastguard Worker }
417*bebae9c0SAndroid Build Coastguard Worker
418*bebae9c0SAndroid Build Coastguard Worker // nop for now
419*bebae9c0SAndroid Build Coastguard Worker GenericPlayer::onLoop(msg);
420*bebae9c0SAndroid Build Coastguard Worker }
421*bebae9c0SAndroid Build Coastguard Worker
422*bebae9c0SAndroid Build Coastguard Worker
onCheckCache(const sp<AMessage> & msg)423*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::onCheckCache(const sp<AMessage> &msg) {
424*bebae9c0SAndroid Build Coastguard Worker //SL_LOGV("AudioSfDecoder::onCheckCache");
425*bebae9c0SAndroid Build Coastguard Worker bool eos;
426*bebae9c0SAndroid Build Coastguard Worker CacheStatus_t status = getCacheRemaining(&eos);
427*bebae9c0SAndroid Build Coastguard Worker
428*bebae9c0SAndroid Build Coastguard Worker if (eos || status == kStatusHigh
429*bebae9c0SAndroid Build Coastguard Worker || ((mStateFlags & kFlagPreparing) && (status >= kStatusEnough))) {
430*bebae9c0SAndroid Build Coastguard Worker if (mStateFlags & kFlagPlaying) {
431*bebae9c0SAndroid Build Coastguard Worker startAudioSink();
432*bebae9c0SAndroid Build Coastguard Worker }
433*bebae9c0SAndroid Build Coastguard Worker mStateFlags &= ~kFlagBuffering;
434*bebae9c0SAndroid Build Coastguard Worker
435*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("AudioSfDecoder::onCheckCache: buffering done.");
436*bebae9c0SAndroid Build Coastguard Worker
437*bebae9c0SAndroid Build Coastguard Worker if (mStateFlags & kFlagPreparing) {
438*bebae9c0SAndroid Build Coastguard Worker //SL_LOGV("AudioSfDecoder::onCheckCache: preparation done.");
439*bebae9c0SAndroid Build Coastguard Worker mStateFlags &= ~kFlagPreparing;
440*bebae9c0SAndroid Build Coastguard Worker }
441*bebae9c0SAndroid Build Coastguard Worker
442*bebae9c0SAndroid Build Coastguard Worker if (mStateFlags & kFlagPlaying) {
443*bebae9c0SAndroid Build Coastguard Worker (new AMessage(kWhatDecode, this))->post();
444*bebae9c0SAndroid Build Coastguard Worker }
445*bebae9c0SAndroid Build Coastguard Worker return;
446*bebae9c0SAndroid Build Coastguard Worker }
447*bebae9c0SAndroid Build Coastguard Worker
448*bebae9c0SAndroid Build Coastguard Worker msg->post(100000);
449*bebae9c0SAndroid Build Coastguard Worker }
450*bebae9c0SAndroid Build Coastguard Worker
451*bebae9c0SAndroid Build Coastguard Worker
onDecode()452*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::onDecode() {
453*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("AudioSfDecoder::onDecode");
454*bebae9c0SAndroid Build Coastguard Worker
455*bebae9c0SAndroid Build Coastguard Worker //-------------------------------- Need to buffer some more before decoding?
456*bebae9c0SAndroid Build Coastguard Worker bool eos;
457*bebae9c0SAndroid Build Coastguard Worker if (mDataSource == 0) {
458*bebae9c0SAndroid Build Coastguard Worker // application set play state to paused which failed, then set play state to playing
459*bebae9c0SAndroid Build Coastguard Worker return;
460*bebae9c0SAndroid Build Coastguard Worker }
461*bebae9c0SAndroid Build Coastguard Worker
462*bebae9c0SAndroid Build Coastguard Worker if (wantPrefetch()
463*bebae9c0SAndroid Build Coastguard Worker && (getCacheRemaining(&eos) == kStatusLow)
464*bebae9c0SAndroid Build Coastguard Worker && !eos) {
465*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("buffering more.");
466*bebae9c0SAndroid Build Coastguard Worker
467*bebae9c0SAndroid Build Coastguard Worker if (mStateFlags & kFlagPlaying) {
468*bebae9c0SAndroid Build Coastguard Worker pauseAudioSink();
469*bebae9c0SAndroid Build Coastguard Worker }
470*bebae9c0SAndroid Build Coastguard Worker mStateFlags |= kFlagBuffering;
471*bebae9c0SAndroid Build Coastguard Worker (new AMessage(kWhatCheckCache, this))->post(100000);
472*bebae9c0SAndroid Build Coastguard Worker return;
473*bebae9c0SAndroid Build Coastguard Worker }
474*bebae9c0SAndroid Build Coastguard Worker
475*bebae9c0SAndroid Build Coastguard Worker if (!(mStateFlags & (kFlagPlaying | kFlagBuffering | kFlagPreparing))) {
476*bebae9c0SAndroid Build Coastguard Worker // don't decode if we're not buffering, prefetching or playing
477*bebae9c0SAndroid Build Coastguard Worker //SL_LOGV("don't decode: not buffering, prefetching or playing");
478*bebae9c0SAndroid Build Coastguard Worker return;
479*bebae9c0SAndroid Build Coastguard Worker }
480*bebae9c0SAndroid Build Coastguard Worker
481*bebae9c0SAndroid Build Coastguard Worker //-------------------------------- Decode
482*bebae9c0SAndroid Build Coastguard Worker status_t err;
483*bebae9c0SAndroid Build Coastguard Worker MediaSource::ReadOptions readOptions;
484*bebae9c0SAndroid Build Coastguard Worker if (mStateFlags & kFlagSeeking) {
485*bebae9c0SAndroid Build Coastguard Worker assert(mSeekTimeMsec != ANDROID_UNKNOWN_TIME);
486*bebae9c0SAndroid Build Coastguard Worker readOptions.setSeekTo(mSeekTimeMsec * 1000);
487*bebae9c0SAndroid Build Coastguard Worker }
488*bebae9c0SAndroid Build Coastguard Worker
489*bebae9c0SAndroid Build Coastguard Worker int64_t timeUsec = ANDROID_UNKNOWN_TIME;
490*bebae9c0SAndroid Build Coastguard Worker {
491*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mBufferSourceLock);
492*bebae9c0SAndroid Build Coastguard Worker
493*bebae9c0SAndroid Build Coastguard Worker if (NULL != mDecodeBuffer) {
494*bebae9c0SAndroid Build Coastguard Worker // the current decoded buffer hasn't been rendered, drop it
495*bebae9c0SAndroid Build Coastguard Worker mDecodeBuffer->release();
496*bebae9c0SAndroid Build Coastguard Worker mDecodeBuffer = NULL;
497*bebae9c0SAndroid Build Coastguard Worker }
498*bebae9c0SAndroid Build Coastguard Worker if (!mAudioSourceStarted) {
499*bebae9c0SAndroid Build Coastguard Worker return;
500*bebae9c0SAndroid Build Coastguard Worker }
501*bebae9c0SAndroid Build Coastguard Worker err = mAudioSource->read(&mDecodeBuffer, &readOptions);
502*bebae9c0SAndroid Build Coastguard Worker if (err == OK) {
503*bebae9c0SAndroid Build Coastguard Worker // FIXME workaround apparent bug in AAC decoder: kKeyTime is 3 frames old if length is 0
504*bebae9c0SAndroid Build Coastguard Worker if (mDecodeBuffer->range_length() == 0) {
505*bebae9c0SAndroid Build Coastguard Worker timeUsec = ANDROID_UNKNOWN_TIME;
506*bebae9c0SAndroid Build Coastguard Worker } else {
507*bebae9c0SAndroid Build Coastguard Worker CHECK(mDecodeBuffer->meta_data().findInt64(kKeyTime, &timeUsec));
508*bebae9c0SAndroid Build Coastguard Worker }
509*bebae9c0SAndroid Build Coastguard Worker } else {
510*bebae9c0SAndroid Build Coastguard Worker // errors are handled below
511*bebae9c0SAndroid Build Coastguard Worker }
512*bebae9c0SAndroid Build Coastguard Worker }
513*bebae9c0SAndroid Build Coastguard Worker
514*bebae9c0SAndroid Build Coastguard Worker {
515*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mTimeLock);
516*bebae9c0SAndroid Build Coastguard Worker if (mStateFlags & kFlagSeeking) {
517*bebae9c0SAndroid Build Coastguard Worker mStateFlags &= ~kFlagSeeking;
518*bebae9c0SAndroid Build Coastguard Worker mSeekTimeMsec = ANDROID_UNKNOWN_TIME;
519*bebae9c0SAndroid Build Coastguard Worker }
520*bebae9c0SAndroid Build Coastguard Worker if (timeUsec != ANDROID_UNKNOWN_TIME) {
521*bebae9c0SAndroid Build Coastguard Worker // Note that though we've decoded this position, we haven't rendered it yet.
522*bebae9c0SAndroid Build Coastguard Worker // So a GetPosition called after this point will observe the advanced position,
523*bebae9c0SAndroid Build Coastguard Worker // even though the PCM may not have been supplied to the sink. That's OK as
524*bebae9c0SAndroid Build Coastguard Worker // we don't claim to provide AAC frame-accurate (let alone sample-accurate) GetPosition.
525*bebae9c0SAndroid Build Coastguard Worker mLastDecodedPositionUs = timeUsec;
526*bebae9c0SAndroid Build Coastguard Worker }
527*bebae9c0SAndroid Build Coastguard Worker }
528*bebae9c0SAndroid Build Coastguard Worker
529*bebae9c0SAndroid Build Coastguard Worker //-------------------------------- Handle return of decode
530*bebae9c0SAndroid Build Coastguard Worker if (err != OK) {
531*bebae9c0SAndroid Build Coastguard Worker bool continueDecoding = false;
532*bebae9c0SAndroid Build Coastguard Worker switch (err) {
533*bebae9c0SAndroid Build Coastguard Worker case ERROR_END_OF_STREAM:
534*bebae9c0SAndroid Build Coastguard Worker if (0 < mDurationUsec) {
535*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mTimeLock);
536*bebae9c0SAndroid Build Coastguard Worker mLastDecodedPositionUs = mDurationUsec;
537*bebae9c0SAndroid Build Coastguard Worker }
538*bebae9c0SAndroid Build Coastguard Worker // handle notification and looping at end of stream
539*bebae9c0SAndroid Build Coastguard Worker if (mStateFlags & kFlagPlaying) {
540*bebae9c0SAndroid Build Coastguard Worker notify(PLAYEREVENT_ENDOFSTREAM, 1, true /*async*/);
541*bebae9c0SAndroid Build Coastguard Worker }
542*bebae9c0SAndroid Build Coastguard Worker if (mStateFlags & kFlagLooping) {
543*bebae9c0SAndroid Build Coastguard Worker seek(0);
544*bebae9c0SAndroid Build Coastguard Worker // kick-off decoding again
545*bebae9c0SAndroid Build Coastguard Worker continueDecoding = true;
546*bebae9c0SAndroid Build Coastguard Worker }
547*bebae9c0SAndroid Build Coastguard Worker break;
548*bebae9c0SAndroid Build Coastguard Worker case INFO_FORMAT_CHANGED:
549*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("MediaSource::read encountered INFO_FORMAT_CHANGED");
550*bebae9c0SAndroid Build Coastguard Worker // reconfigure output
551*bebae9c0SAndroid Build Coastguard Worker {
552*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mBufferSourceLock);
553*bebae9c0SAndroid Build Coastguard Worker hasNewDecodeParams();
554*bebae9c0SAndroid Build Coastguard Worker }
555*bebae9c0SAndroid Build Coastguard Worker continueDecoding = true;
556*bebae9c0SAndroid Build Coastguard Worker break;
557*bebae9c0SAndroid Build Coastguard Worker case INFO_DISCONTINUITY:
558*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("MediaSource::read encountered INFO_DISCONTINUITY");
559*bebae9c0SAndroid Build Coastguard Worker continueDecoding = true;
560*bebae9c0SAndroid Build Coastguard Worker break;
561*bebae9c0SAndroid Build Coastguard Worker default:
562*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("MediaSource::read returned error %d", err);
563*bebae9c0SAndroid Build Coastguard Worker break;
564*bebae9c0SAndroid Build Coastguard Worker }
565*bebae9c0SAndroid Build Coastguard Worker if (continueDecoding) {
566*bebae9c0SAndroid Build Coastguard Worker if (NULL == mDecodeBuffer) {
567*bebae9c0SAndroid Build Coastguard Worker (new AMessage(kWhatDecode, this))->post();
568*bebae9c0SAndroid Build Coastguard Worker return;
569*bebae9c0SAndroid Build Coastguard Worker }
570*bebae9c0SAndroid Build Coastguard Worker } else {
571*bebae9c0SAndroid Build Coastguard Worker return;
572*bebae9c0SAndroid Build Coastguard Worker }
573*bebae9c0SAndroid Build Coastguard Worker }
574*bebae9c0SAndroid Build Coastguard Worker
575*bebae9c0SAndroid Build Coastguard Worker //-------------------------------- Render
576*bebae9c0SAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage(kWhatRender, this);
577*bebae9c0SAndroid Build Coastguard Worker msg->post();
578*bebae9c0SAndroid Build Coastguard Worker
579*bebae9c0SAndroid Build Coastguard Worker }
580*bebae9c0SAndroid Build Coastguard Worker
581*bebae9c0SAndroid Build Coastguard Worker
onMessageReceived(const sp<AMessage> & msg)582*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::onMessageReceived(const sp<AMessage> &msg) {
583*bebae9c0SAndroid Build Coastguard Worker switch (msg->what()) {
584*bebae9c0SAndroid Build Coastguard Worker case kWhatDecode:
585*bebae9c0SAndroid Build Coastguard Worker onDecode();
586*bebae9c0SAndroid Build Coastguard Worker break;
587*bebae9c0SAndroid Build Coastguard Worker
588*bebae9c0SAndroid Build Coastguard Worker case kWhatRender:
589*bebae9c0SAndroid Build Coastguard Worker onRender();
590*bebae9c0SAndroid Build Coastguard Worker break;
591*bebae9c0SAndroid Build Coastguard Worker
592*bebae9c0SAndroid Build Coastguard Worker case kWhatCheckCache:
593*bebae9c0SAndroid Build Coastguard Worker onCheckCache(msg);
594*bebae9c0SAndroid Build Coastguard Worker break;
595*bebae9c0SAndroid Build Coastguard Worker
596*bebae9c0SAndroid Build Coastguard Worker default:
597*bebae9c0SAndroid Build Coastguard Worker GenericPlayer::onMessageReceived(msg);
598*bebae9c0SAndroid Build Coastguard Worker break;
599*bebae9c0SAndroid Build Coastguard Worker }
600*bebae9c0SAndroid Build Coastguard Worker }
601*bebae9c0SAndroid Build Coastguard Worker
602*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
603*bebae9c0SAndroid Build Coastguard Worker // Prepared state, prefetch status notifications
notifyPrepared(status_t prepareRes)604*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::notifyPrepared(status_t prepareRes) {
605*bebae9c0SAndroid Build Coastguard Worker assert(!(mStateFlags & (kFlagPrepared | kFlagPreparedUnsuccessfully)));
606*bebae9c0SAndroid Build Coastguard Worker if (NO_ERROR == prepareRes) {
607*bebae9c0SAndroid Build Coastguard Worker // The "then" fork is not currently used, but is kept here to make it easier
608*bebae9c0SAndroid Build Coastguard Worker // to replace by a new signalPrepareCompletion(status) if we re-visit this later.
609*bebae9c0SAndroid Build Coastguard Worker mStateFlags |= kFlagPrepared;
610*bebae9c0SAndroid Build Coastguard Worker } else {
611*bebae9c0SAndroid Build Coastguard Worker mStateFlags |= kFlagPreparedUnsuccessfully;
612*bebae9c0SAndroid Build Coastguard Worker }
613*bebae9c0SAndroid Build Coastguard Worker // Do not call the superclass onPrepare to notify, because it uses a default error
614*bebae9c0SAndroid Build Coastguard Worker // status code but we can provide a more specific one.
615*bebae9c0SAndroid Build Coastguard Worker // GenericPlayer::onPrepare();
616*bebae9c0SAndroid Build Coastguard Worker notify(PLAYEREVENT_PREPARED, (int32_t)prepareRes, true /*async*/);
617*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("AudioSfDecoder::onPrepare() done, mStateFlags=0x%x", mStateFlags);
618*bebae9c0SAndroid Build Coastguard Worker }
619*bebae9c0SAndroid Build Coastguard Worker
620*bebae9c0SAndroid Build Coastguard Worker
onNotify(const sp<AMessage> & msg)621*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::onNotify(const sp<AMessage> &msg) {
622*bebae9c0SAndroid Build Coastguard Worker notif_cbf_t notifyClient;
623*bebae9c0SAndroid Build Coastguard Worker void* notifyUser;
624*bebae9c0SAndroid Build Coastguard Worker {
625*bebae9c0SAndroid Build Coastguard Worker android::Mutex::Autolock autoLock(mNotifyClientLock);
626*bebae9c0SAndroid Build Coastguard Worker if (NULL == mNotifyClient) {
627*bebae9c0SAndroid Build Coastguard Worker return;
628*bebae9c0SAndroid Build Coastguard Worker } else {
629*bebae9c0SAndroid Build Coastguard Worker notifyClient = mNotifyClient;
630*bebae9c0SAndroid Build Coastguard Worker notifyUser = mNotifyUser;
631*bebae9c0SAndroid Build Coastguard Worker }
632*bebae9c0SAndroid Build Coastguard Worker }
633*bebae9c0SAndroid Build Coastguard Worker int32_t val;
634*bebae9c0SAndroid Build Coastguard Worker if (msg->findInt32(PLAYEREVENT_PREFETCHSTATUSCHANGE, &val)) {
635*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("\tASfPlayer notifying %s = %d", PLAYEREVENT_PREFETCHSTATUSCHANGE, val);
636*bebae9c0SAndroid Build Coastguard Worker notifyClient(kEventPrefetchStatusChange, val, 0, notifyUser);
637*bebae9c0SAndroid Build Coastguard Worker }
638*bebae9c0SAndroid Build Coastguard Worker else if (msg->findInt32(PLAYEREVENT_PREFETCHFILLLEVELUPDATE, &val)) {
639*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("\tASfPlayer notifying %s = %d", PLAYEREVENT_PREFETCHFILLLEVELUPDATE, val);
640*bebae9c0SAndroid Build Coastguard Worker notifyClient(kEventPrefetchFillLevelUpdate, val, 0, notifyUser);
641*bebae9c0SAndroid Build Coastguard Worker }
642*bebae9c0SAndroid Build Coastguard Worker else if (msg->findInt32(PLAYEREVENT_ENDOFSTREAM, &val)) {
643*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("\tASfPlayer notifying %s = %d", PLAYEREVENT_ENDOFSTREAM, val);
644*bebae9c0SAndroid Build Coastguard Worker notifyClient(kEventEndOfStream, val, 0, notifyUser);
645*bebae9c0SAndroid Build Coastguard Worker }
646*bebae9c0SAndroid Build Coastguard Worker else {
647*bebae9c0SAndroid Build Coastguard Worker GenericPlayer::onNotify(msg);
648*bebae9c0SAndroid Build Coastguard Worker }
649*bebae9c0SAndroid Build Coastguard Worker }
650*bebae9c0SAndroid Build Coastguard Worker
651*bebae9c0SAndroid Build Coastguard Worker
652*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
653*bebae9c0SAndroid Build Coastguard Worker // Private utility functions
654*bebae9c0SAndroid Build Coastguard Worker
wantPrefetch()655*bebae9c0SAndroid Build Coastguard Worker bool AudioSfDecoder::wantPrefetch() {
656*bebae9c0SAndroid Build Coastguard Worker if (mDataSource != 0) {
657*bebae9c0SAndroid Build Coastguard Worker return (mDataSource->flags() & DataSource::kWantsPrefetching);
658*bebae9c0SAndroid Build Coastguard Worker } else {
659*bebae9c0SAndroid Build Coastguard Worker // happens if an improper data locator was passed, if the media extractor couldn't be
660*bebae9c0SAndroid Build Coastguard Worker // initialized, if there is no audio track in the media, if the OMX decoder couldn't be
661*bebae9c0SAndroid Build Coastguard Worker // instantiated, if the source couldn't be opened, or if the MediaSource
662*bebae9c0SAndroid Build Coastguard Worker // couldn't be started
663*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("AudioSfDecoder::wantPrefetch() tries to access NULL mDataSource");
664*bebae9c0SAndroid Build Coastguard Worker return false;
665*bebae9c0SAndroid Build Coastguard Worker }
666*bebae9c0SAndroid Build Coastguard Worker }
667*bebae9c0SAndroid Build Coastguard Worker
668*bebae9c0SAndroid Build Coastguard Worker
getPositionUsec()669*bebae9c0SAndroid Build Coastguard Worker int64_t AudioSfDecoder::getPositionUsec() {
670*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mTimeLock);
671*bebae9c0SAndroid Build Coastguard Worker if (mStateFlags & kFlagSeeking) {
672*bebae9c0SAndroid Build Coastguard Worker return mSeekTimeMsec * 1000;
673*bebae9c0SAndroid Build Coastguard Worker } else {
674*bebae9c0SAndroid Build Coastguard Worker return mLastDecodedPositionUs;
675*bebae9c0SAndroid Build Coastguard Worker }
676*bebae9c0SAndroid Build Coastguard Worker }
677*bebae9c0SAndroid Build Coastguard Worker
678*bebae9c0SAndroid Build Coastguard Worker
getCacheRemaining(bool * eos)679*bebae9c0SAndroid Build Coastguard Worker CacheStatus_t AudioSfDecoder::getCacheRemaining(bool *eos) {
680*bebae9c0SAndroid Build Coastguard Worker sp<NuCachedSource2> cachedSource =
681*bebae9c0SAndroid Build Coastguard Worker static_cast<NuCachedSource2 *>(mDataSource.get());
682*bebae9c0SAndroid Build Coastguard Worker
683*bebae9c0SAndroid Build Coastguard Worker CacheStatus_t oldStatus = mCacheStatus;
684*bebae9c0SAndroid Build Coastguard Worker
685*bebae9c0SAndroid Build Coastguard Worker status_t finalStatus;
686*bebae9c0SAndroid Build Coastguard Worker size_t dataRemaining = cachedSource->approxDataRemaining(&finalStatus);
687*bebae9c0SAndroid Build Coastguard Worker *eos = (finalStatus != OK);
688*bebae9c0SAndroid Build Coastguard Worker
689*bebae9c0SAndroid Build Coastguard Worker CHECK_GE(mBitrate, 0);
690*bebae9c0SAndroid Build Coastguard Worker
691*bebae9c0SAndroid Build Coastguard Worker int64_t dataRemainingUs = dataRemaining * 8000000LL / mBitrate;
692*bebae9c0SAndroid Build Coastguard Worker //SL_LOGV("AudioSfDecoder::getCacheRemaining: approx %.2f secs remaining (eos=%d)",
693*bebae9c0SAndroid Build Coastguard Worker // dataRemainingUs / 1E6, *eos);
694*bebae9c0SAndroid Build Coastguard Worker
695*bebae9c0SAndroid Build Coastguard Worker if (*eos) {
696*bebae9c0SAndroid Build Coastguard Worker // data is buffered up to the end of the stream, it can't get any better than this
697*bebae9c0SAndroid Build Coastguard Worker mCacheStatus = kStatusHigh;
698*bebae9c0SAndroid Build Coastguard Worker mCacheFill = 1000;
699*bebae9c0SAndroid Build Coastguard Worker
700*bebae9c0SAndroid Build Coastguard Worker } else {
701*bebae9c0SAndroid Build Coastguard Worker if (mDurationUsec > 0) {
702*bebae9c0SAndroid Build Coastguard Worker // known duration:
703*bebae9c0SAndroid Build Coastguard Worker
704*bebae9c0SAndroid Build Coastguard Worker // fill level is ratio of how much has been played + how much is
705*bebae9c0SAndroid Build Coastguard Worker // cached, divided by total duration
706*bebae9c0SAndroid Build Coastguard Worker int64_t currentPositionUsec = getPositionUsec();
707*bebae9c0SAndroid Build Coastguard Worker if (currentPositionUsec == ANDROID_UNKNOWN_TIME) {
708*bebae9c0SAndroid Build Coastguard Worker // if we don't know where we are, assume the worst for the fill ratio
709*bebae9c0SAndroid Build Coastguard Worker currentPositionUsec = 0;
710*bebae9c0SAndroid Build Coastguard Worker }
711*bebae9c0SAndroid Build Coastguard Worker if (mDurationUsec > 0) {
712*bebae9c0SAndroid Build Coastguard Worker mCacheFill = (int16_t) ((1000.0
713*bebae9c0SAndroid Build Coastguard Worker * (double)(currentPositionUsec + dataRemainingUs) / mDurationUsec));
714*bebae9c0SAndroid Build Coastguard Worker } else {
715*bebae9c0SAndroid Build Coastguard Worker mCacheFill = 0;
716*bebae9c0SAndroid Build Coastguard Worker }
717*bebae9c0SAndroid Build Coastguard Worker //SL_LOGV("cacheFill = %d", mCacheFill);
718*bebae9c0SAndroid Build Coastguard Worker
719*bebae9c0SAndroid Build Coastguard Worker // cache status is evaluated against duration thresholds
720*bebae9c0SAndroid Build Coastguard Worker if (dataRemainingUs > DURATION_CACHED_HIGH_MS*1000) {
721*bebae9c0SAndroid Build Coastguard Worker mCacheStatus = kStatusHigh;
722*bebae9c0SAndroid Build Coastguard Worker //ALOGV("high");
723*bebae9c0SAndroid Build Coastguard Worker } else if (dataRemainingUs > DURATION_CACHED_MED_MS*1000) {
724*bebae9c0SAndroid Build Coastguard Worker //ALOGV("enough");
725*bebae9c0SAndroid Build Coastguard Worker mCacheStatus = kStatusEnough;
726*bebae9c0SAndroid Build Coastguard Worker } else if (dataRemainingUs < DURATION_CACHED_LOW_MS*1000) {
727*bebae9c0SAndroid Build Coastguard Worker //ALOGV("low");
728*bebae9c0SAndroid Build Coastguard Worker mCacheStatus = kStatusLow;
729*bebae9c0SAndroid Build Coastguard Worker } else {
730*bebae9c0SAndroid Build Coastguard Worker mCacheStatus = kStatusIntermediate;
731*bebae9c0SAndroid Build Coastguard Worker }
732*bebae9c0SAndroid Build Coastguard Worker
733*bebae9c0SAndroid Build Coastguard Worker } else {
734*bebae9c0SAndroid Build Coastguard Worker // unknown duration:
735*bebae9c0SAndroid Build Coastguard Worker
736*bebae9c0SAndroid Build Coastguard Worker // cache status is evaluated against cache amount thresholds
737*bebae9c0SAndroid Build Coastguard Worker // (no duration so we don't have the bitrate either, could be derived from format?)
738*bebae9c0SAndroid Build Coastguard Worker if (dataRemaining > SIZE_CACHED_HIGH_BYTES) {
739*bebae9c0SAndroid Build Coastguard Worker mCacheStatus = kStatusHigh;
740*bebae9c0SAndroid Build Coastguard Worker } else if (dataRemaining > SIZE_CACHED_MED_BYTES) {
741*bebae9c0SAndroid Build Coastguard Worker mCacheStatus = kStatusEnough;
742*bebae9c0SAndroid Build Coastguard Worker } else if (dataRemaining < SIZE_CACHED_LOW_BYTES) {
743*bebae9c0SAndroid Build Coastguard Worker mCacheStatus = kStatusLow;
744*bebae9c0SAndroid Build Coastguard Worker } else {
745*bebae9c0SAndroid Build Coastguard Worker mCacheStatus = kStatusIntermediate;
746*bebae9c0SAndroid Build Coastguard Worker }
747*bebae9c0SAndroid Build Coastguard Worker }
748*bebae9c0SAndroid Build Coastguard Worker
749*bebae9c0SAndroid Build Coastguard Worker }
750*bebae9c0SAndroid Build Coastguard Worker
751*bebae9c0SAndroid Build Coastguard Worker if (oldStatus != mCacheStatus) {
752*bebae9c0SAndroid Build Coastguard Worker notifyStatus();
753*bebae9c0SAndroid Build Coastguard Worker }
754*bebae9c0SAndroid Build Coastguard Worker
755*bebae9c0SAndroid Build Coastguard Worker if (abs(mCacheFill - mLastNotifiedCacheFill) > mCacheFillNotifThreshold) {
756*bebae9c0SAndroid Build Coastguard Worker notifyCacheFill();
757*bebae9c0SAndroid Build Coastguard Worker }
758*bebae9c0SAndroid Build Coastguard Worker
759*bebae9c0SAndroid Build Coastguard Worker return mCacheStatus;
760*bebae9c0SAndroid Build Coastguard Worker }
761*bebae9c0SAndroid Build Coastguard Worker
762*bebae9c0SAndroid Build Coastguard Worker
hasNewDecodeParams()763*bebae9c0SAndroid Build Coastguard Worker void AudioSfDecoder::hasNewDecodeParams() {
764*bebae9c0SAndroid Build Coastguard Worker
765*bebae9c0SAndroid Build Coastguard Worker if ((mAudioSource != 0) && mAudioSourceStarted) {
766*bebae9c0SAndroid Build Coastguard Worker sp<MetaData> meta = mAudioSource->getFormat();
767*bebae9c0SAndroid Build Coastguard Worker
768*bebae9c0SAndroid Build Coastguard Worker int32_t channelCount;
769*bebae9c0SAndroid Build Coastguard Worker CHECK(meta->findInt32(kKeyChannelCount, &channelCount));
770*bebae9c0SAndroid Build Coastguard Worker int32_t sr;
771*bebae9c0SAndroid Build Coastguard Worker CHECK(meta->findInt32(kKeySampleRate, &sr));
772*bebae9c0SAndroid Build Coastguard Worker
773*bebae9c0SAndroid Build Coastguard Worker // FIXME similar to onPrepare()
774*bebae9c0SAndroid Build Coastguard Worker {
775*bebae9c0SAndroid Build Coastguard Worker android::Mutex::Autolock autoLock(mPcmFormatLock);
776*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("format changed: old sr=%d, channels=%d; new sr=%d, channels=%d",
777*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_SAMPLERATE],
778*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS],
779*bebae9c0SAndroid Build Coastguard Worker sr, channelCount);
780*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_NUMCHANNELS] = channelCount;
781*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_SAMPLERATE] = sr;
782*bebae9c0SAndroid Build Coastguard Worker mPcmFormatValues[ANDROID_KEY_INDEX_PCMFORMAT_CHANNELMASK] =
783*bebae9c0SAndroid Build Coastguard Worker sles_channel_out_mask_from_count(channelCount);
784*bebae9c0SAndroid Build Coastguard Worker }
785*bebae9c0SAndroid Build Coastguard Worker // there's no need to do a notify of PLAYEREVENT_CHANNEL_COUNT,
786*bebae9c0SAndroid Build Coastguard Worker // because the only listener is for volume updates, and decoders don't support that
787*bebae9c0SAndroid Build Coastguard Worker }
788*bebae9c0SAndroid Build Coastguard Worker
789*bebae9c0SAndroid Build Coastguard Worker // alert users of those params
790*bebae9c0SAndroid Build Coastguard Worker updateAudioSink();
791*bebae9c0SAndroid Build Coastguard Worker }
792*bebae9c0SAndroid Build Coastguard Worker
793*bebae9c0SAndroid Build Coastguard Worker static const char* const kPlaybackOnlyCodecs[] = { MEDIA_MIMETYPE_AUDIO_AMR_NB,
794*bebae9c0SAndroid Build Coastguard Worker MEDIA_MIMETYPE_AUDIO_AMR_WB };
795*bebae9c0SAndroid Build Coastguard Worker #define NB_PLAYBACK_ONLY_CODECS (sizeof(kPlaybackOnlyCodecs)/sizeof(kPlaybackOnlyCodecs[0]))
796*bebae9c0SAndroid Build Coastguard Worker
isSupportedCodec(const char * mime)797*bebae9c0SAndroid Build Coastguard Worker bool AudioSfDecoder::isSupportedCodec(const char* mime) {
798*bebae9c0SAndroid Build Coastguard Worker bool codecRequiresPermission = false;
799*bebae9c0SAndroid Build Coastguard Worker for (unsigned int i = 0 ; i < NB_PLAYBACK_ONLY_CODECS ; i++) {
800*bebae9c0SAndroid Build Coastguard Worker if (!strcasecmp(mime, kPlaybackOnlyCodecs[i])) {
801*bebae9c0SAndroid Build Coastguard Worker codecRequiresPermission = true;
802*bebae9c0SAndroid Build Coastguard Worker break;
803*bebae9c0SAndroid Build Coastguard Worker }
804*bebae9c0SAndroid Build Coastguard Worker }
805*bebae9c0SAndroid Build Coastguard Worker if (codecRequiresPermission) {
806*bebae9c0SAndroid Build Coastguard Worker // verify only the system can decode, for playback only
807*bebae9c0SAndroid Build Coastguard Worker return checkCallingPermission(
808*bebae9c0SAndroid Build Coastguard Worker String16("android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"));
809*bebae9c0SAndroid Build Coastguard Worker } else {
810*bebae9c0SAndroid Build Coastguard Worker return true;
811*bebae9c0SAndroid Build Coastguard Worker }
812*bebae9c0SAndroid Build Coastguard Worker }
813*bebae9c0SAndroid Build Coastguard Worker
814*bebae9c0SAndroid Build Coastguard Worker } // namespace android
815