blob: 42f18d32e6d519a5e7cf49c100b9dee7962a6eea [file] [log] [blame]
Andreas Huber27366fc2009-11-20 09:32:46 -08001/*
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
Glenn Kastenb0d6f102011-04-13 11:16:49 -070017#undef DEBUG_HDCP
Glenn Kasten1b11b642011-03-23 14:34:31 -070018
Andreas Huber27366fc2009-11-20 09:32:46 -080019//#define LOG_NDEBUG 0
20#define LOG_TAG "AwesomePlayer"
21#include <utils/Log.h>
22
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080023#include <dlfcn.h>
24
Andreas Huber27366fc2009-11-20 09:32:46 -080025#include "include/AwesomePlayer.h"
Andreas Huber77d8dc22011-04-21 10:06:43 -070026#include "include/DRMExtractor.h"
Andreas Huber1314e732009-12-14 14:18:22 -080027#include "include/SoftwareRenderer.h"
Andreas Huber4d61f602010-06-10 11:17:50 -070028#include "include/NuCachedSource2.h"
29#include "include/ThrottledSource.h"
Andreas Huber54d09722010-10-12 11:34:37 -070030#include "include/MPEG2TSExtractor.h"
Andreas Huber77d8dc22011-04-21 10:06:43 -070031#include "include/WVMExtractor.h"
Andreas Huber27366fc2009-11-20 09:32:46 -080032
Gloria Wang13bc8cd2011-05-11 11:24:09 -070033#include "timedtext/TimedTextPlayer.h"
34
Andreas Hubera67d5382009-12-10 15:32:12 -080035#include <binder/IPCThreadState.h>
Gloria Wangd211f412011-02-19 18:37:57 -080036#include <binder/IServiceManager.h>
37#include <media/IMediaPlayerService.h>
Andreas Huber52b52cd2010-11-23 11:41:34 -080038#include <media/stagefright/foundation/hexdump.h>
39#include <media/stagefright/foundation/ADebug.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080040#include <media/stagefright/AudioPlayer.h>
41#include <media/stagefright/DataSource.h>
42#include <media/stagefright/FileSource.h>
43#include <media/stagefright/MediaBuffer.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080044#include <media/stagefright/MediaDefs.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080045#include <media/stagefright/MediaExtractor.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080046#include <media/stagefright/MediaSource.h>
47#include <media/stagefright/MetaData.h>
48#include <media/stagefright/OMXCodec.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080049
Andreas Hubere3c01832010-08-16 08:49:37 -070050#include <surfaceflinger/Surface.h>
Glenn Kastencc562a32011-02-08 17:26:17 -080051#include <gui/ISurfaceTexture.h>
52#include <gui/SurfaceTextureClient.h>
Glenn Kastenb8763f62011-01-28 12:37:51 -080053#include <surfaceflinger/ISurfaceComposer.h>
Mathias Agopian000479f2010-02-09 17:46:37 -080054
Andreas Huberae9d5072010-12-06 10:36:06 -080055#include <media/stagefright/foundation/AMessage.h>
Andreas Huber202348e2010-06-07 14:35:29 -070056
Glenn Kasten1b11b642011-03-23 14:34:31 -070057#include <cutils/properties.h>
58
Andreas Huber6a1f5f92010-11-15 09:03:03 -080059#define USE_SURFACE_ALLOC 1
James Dong5bc53032011-08-11 17:38:35 -070060#define FRAME_DROP_FREQ 0
Andreas Huber6a1f5f92010-11-15 09:03:03 -080061
Andreas Huber27366fc2009-11-20 09:32:46 -080062namespace android {
63
Andreas Huber87ab9cd2010-09-03 13:20:33 -070064static int64_t kLowWaterMarkUs = 2000000ll; // 2secs
Gloria Wang7096f552011-08-10 14:19:05 -070065static int64_t kHighWaterMarkUs = 5000000ll; // 5secs
Andreas Huber96346652011-01-19 15:07:19 -080066static const size_t kLowWaterMarkBytes = 40000;
67static const size_t kHighWaterMarkBytes = 200000;
Andreas Huber87ab9cd2010-09-03 13:20:33 -070068
Andreas Huber27366fc2009-11-20 09:32:46 -080069struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huber6be780e2010-02-08 14:40:30 -080070 AwesomeEvent(
71 AwesomePlayer *player,
72 void (AwesomePlayer::*method)())
Andreas Huber27366fc2009-11-20 09:32:46 -080073 : mPlayer(player),
Andreas Huber6be780e2010-02-08 14:40:30 -080074 mMethod(method) {
Andreas Huber27366fc2009-11-20 09:32:46 -080075 }
76
77protected:
78 virtual ~AwesomeEvent() {}
79
80 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huber6be780e2010-02-08 14:40:30 -080081 (mPlayer->*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080082 }
83
84private:
85 AwesomePlayer *mPlayer;
Andreas Huber6be780e2010-02-08 14:40:30 -080086 void (AwesomePlayer::*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080087
88 AwesomeEvent(const AwesomeEvent &);
89 AwesomeEvent &operator=(const AwesomeEvent &);
90};
91
Andreas Huber1314e732009-12-14 14:18:22 -080092struct AwesomeLocalRenderer : public AwesomeRenderer {
93 AwesomeLocalRenderer(
Glenn Kastencc562a32011-02-08 17:26:17 -080094 const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta)
95 : mTarget(new SoftwareRenderer(nativeWindow, meta)) {
Andreas Huber1314e732009-12-14 14:18:22 -080096 }
97
98 virtual void render(MediaBuffer *buffer) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -080099 render((const uint8_t *)buffer->data() + buffer->range_offset(),
100 buffer->range_length());
101 }
102
103 void render(const void *data, size_t size) {
104 mTarget->render(data, size, NULL);
Andreas Huber1314e732009-12-14 14:18:22 -0800105 }
106
107protected:
108 virtual ~AwesomeLocalRenderer() {
109 delete mTarget;
110 mTarget = NULL;
111 }
112
113private:
Andreas Huberc23dabf2010-11-16 13:05:53 -0800114 SoftwareRenderer *mTarget;
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800115
Andreas Huber1314e732009-12-14 14:18:22 -0800116 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
117 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
118};
119
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700120struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
Andreas Huber940c8662010-11-16 15:26:30 -0800121 AwesomeNativeWindowRenderer(
122 const sp<ANativeWindow> &nativeWindow,
123 int32_t rotationDegrees)
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700124 : mNativeWindow(nativeWindow) {
Andreas Huber940c8662010-11-16 15:26:30 -0800125 applyRotation(rotationDegrees);
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700126 }
127
128 virtual void render(MediaBuffer *buffer) {
Glenn Kasten5c2faf32011-06-27 10:10:19 -0700129 int64_t timeUs;
130 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
131 native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000);
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700132 status_t err = mNativeWindow->queueBuffer(
133 mNativeWindow.get(), buffer->graphicBuffer().get());
134 if (err != 0) {
135 LOGE("queueBuffer failed with error %s (%d)", strerror(-err),
136 -err);
137 return;
138 }
139
140 sp<MetaData> metaData = buffer->meta_data();
141 metaData->setInt32(kKeyRendered, 1);
142 }
143
144protected:
145 virtual ~AwesomeNativeWindowRenderer() {}
146
147private:
148 sp<ANativeWindow> mNativeWindow;
149
Andreas Huber940c8662010-11-16 15:26:30 -0800150 void applyRotation(int32_t rotationDegrees) {
151 uint32_t transform;
152 switch (rotationDegrees) {
153 case 0: transform = 0; break;
154 case 90: transform = HAL_TRANSFORM_ROT_90; break;
155 case 180: transform = HAL_TRANSFORM_ROT_180; break;
156 case 270: transform = HAL_TRANSFORM_ROT_270; break;
157 default: transform = 0; break;
158 }
159
160 if (transform) {
161 CHECK_EQ(0, native_window_set_buffers_transform(
162 mNativeWindow.get(), transform));
163 }
164 }
165
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700166 AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
167 AwesomeNativeWindowRenderer &operator=(
168 const AwesomeNativeWindowRenderer &);
169};
170
Gloria Wangd211f412011-02-19 18:37:57 -0800171// To collect the decoder usage
172void addBatteryData(uint32_t params) {
173 sp<IBinder> binder =
174 defaultServiceManager()->getService(String16("media.player"));
175 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
176 CHECK(service.get() != NULL);
Andreas Huber52b52cd2010-11-23 11:41:34 -0800177
Gloria Wangd211f412011-02-19 18:37:57 -0800178 service->addBatteryData(params);
179}
180
181////////////////////////////////////////////////////////////////////////////////
Andreas Huber27366fc2009-11-20 09:32:46 -0800182AwesomePlayer::AwesomePlayer()
Andreas Huber406a18b2010-02-18 16:45:13 -0800183 : mQueueStarted(false),
Andreas Huber603d7392011-06-30 15:47:02 -0700184 mUIDValid(false),
Andreas Huber406a18b2010-02-18 16:45:13 -0800185 mTimeSource(NULL),
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800186 mVideoRendererIsPreview(false),
Andreas Huber27366fc2009-11-20 09:32:46 -0800187 mAudioPlayer(NULL),
James Dong08adfd22011-01-16 11:30:13 -0800188 mDisplayWidth(0),
189 mDisplayHeight(0),
Andreas Huberffdf4782010-02-09 14:05:43 -0800190 mFlags(0),
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700191 mExtractorFlags(0),
Andreas Huberba7ec912010-02-12 10:42:02 -0800192 mVideoBuffer(NULL),
Andreas Huber3a785fe2011-03-14 10:55:40 -0700193 mDecryptHandle(NULL),
Gloria Wangc6091dd2011-05-03 15:59:03 -0700194 mLastVideoTimeUs(-1),
195 mTextPlayer(NULL) {
Andreas Huber52b52cd2010-11-23 11:41:34 -0800196 CHECK_EQ(mClient.connect(), (status_t)OK);
Andreas Huber27366fc2009-11-20 09:32:46 -0800197
198 DataSource::RegisterDefaultSniffers();
199
Andreas Huber6be780e2010-02-08 14:40:30 -0800200 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800201 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800202 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800203 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800204 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800205 mBufferingEventPending = false;
Andreas Huber52c78322011-01-11 15:05:28 -0800206 mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
207 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800208
209 mCheckAudioStatusEvent = new AwesomeEvent(
210 this, &AwesomePlayer::onCheckAudioStatus);
211
Andreas Huber70d10c02010-02-03 11:37:29 -0800212 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800213
Andreas Huber27366fc2009-11-20 09:32:46 -0800214 reset();
215}
216
217AwesomePlayer::~AwesomePlayer() {
Andreas Huber406a18b2010-02-18 16:45:13 -0800218 if (mQueueStarted) {
219 mQueue.stop();
220 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800221
222 reset();
223
224 mClient.disconnect();
225}
226
Andreas Huber22cf4b02011-11-16 10:46:05 -0800227void AwesomePlayer::cancelPlayerEvents(bool keepNotifications) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800228 mQueue.cancelEvent(mVideoEvent->eventID());
229 mVideoEventPending = false;
Andreas Huber52c78322011-01-11 15:05:28 -0800230 mQueue.cancelEvent(mVideoLagEvent->eventID());
231 mVideoLagEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800232
Andreas Huber22cf4b02011-11-16 10:46:05 -0800233 if (!keepNotifications) {
234 mQueue.cancelEvent(mStreamDoneEvent->eventID());
235 mStreamDoneEventPending = false;
236 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
237 mAudioStatusEventPending = false;
238
Andreas Huberb9e63832010-01-26 16:20:10 -0800239 mQueue.cancelEvent(mBufferingEvent->eventID());
240 mBufferingEventPending = false;
241 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800242}
243
Andreas Hubera3f43842010-01-21 10:28:45 -0800244void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800245 Mutex::Autolock autoLock(mLock);
246 mListener = listener;
247}
248
Andreas Huber603d7392011-06-30 15:47:02 -0700249void AwesomePlayer::setUID(uid_t uid) {
Steve Block71f2cf12011-10-20 11:56:00 +0100250 ALOGV("AwesomePlayer running on behalf of uid %d", uid);
Andreas Huber603d7392011-06-30 15:47:02 -0700251
252 mUID = uid;
253 mUIDValid = true;
254}
255
Andreas Huber433c9ac2010-01-27 16:49:05 -0800256status_t AwesomePlayer::setDataSource(
257 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800258 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800259 return setDataSource_l(uri, headers);
260}
Andreas Huber27366fc2009-11-20 09:32:46 -0800261
Andreas Huberba7ec912010-02-12 10:42:02 -0800262status_t AwesomePlayer::setDataSource_l(
263 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800264 reset_l();
265
Andreas Huberffdf4782010-02-09 14:05:43 -0800266 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800267
Andreas Huberffdf4782010-02-09 14:05:43 -0800268 if (headers) {
269 mUriHeaders = *headers;
Andreas Huber53182c42011-02-24 14:42:48 -0800270
271 ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));
272 if (index >= 0) {
273 // Browser is in "incognito" mode, suppress logging URLs.
274
275 // This isn't something that should be passed to the server.
276 mUriHeaders.removeItemsAt(index);
277
Andreas Huberfddf5d92011-06-07 15:52:25 -0700278 modifyFlags(INCOGNITO, SET);
Andreas Huber53182c42011-02-24 14:42:48 -0800279 }
280 }
281
282 if (!(mFlags & INCOGNITO)) {
283 LOGI("setDataSource_l('%s')", mUri.string());
284 } else {
285 LOGI("setDataSource_l(URL suppressed)");
Andreas Huberb9e63832010-01-26 16:20:10 -0800286 }
287
Andreas Huberffdf4782010-02-09 14:05:43 -0800288 // The actual work will be done during preparation in the call to
289 // ::finishSetDataSource_l to avoid blocking the calling thread in
290 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800291
Andreas Huberfddf5d92011-06-07 15:52:25 -0700292 {
293 Mutex::Autolock autoLock(mStatsLock);
294 mStats.mFd = -1;
295 mStats.mURI = mUri;
296 }
297
Andreas Huberffdf4782010-02-09 14:05:43 -0800298 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800299}
300
301status_t AwesomePlayer::setDataSource(
302 int fd, int64_t offset, int64_t length) {
303 Mutex::Autolock autoLock(mLock);
304
305 reset_l();
306
Andreas Huberba7ec912010-02-12 10:42:02 -0800307 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huber27366fc2009-11-20 09:32:46 -0800308
Andreas Huberba7ec912010-02-12 10:42:02 -0800309 status_t err = dataSource->initCheck();
Andreas Huber27366fc2009-11-20 09:32:46 -0800310
311 if (err != OK) {
312 return err;
313 }
314
Andreas Huberba7ec912010-02-12 10:42:02 -0800315 mFileSource = dataSource;
316
Andreas Huberfddf5d92011-06-07 15:52:25 -0700317 {
318 Mutex::Autolock autoLock(mStatsLock);
319 mStats.mFd = fd;
320 mStats.mURI = String8();
321 }
322
Andreas Huberba7ec912010-02-12 10:42:02 -0800323 return setDataSource_l(dataSource);
324}
325
Andreas Huber52b52cd2010-11-23 11:41:34 -0800326status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
Andreas Huberd9367262010-12-16 10:16:36 -0800327 return INVALID_OPERATION;
Andreas Huber52b52cd2010-11-23 11:41:34 -0800328}
329
Andreas Huberba7ec912010-02-12 10:42:02 -0800330status_t AwesomePlayer::setDataSource_l(
331 const sp<DataSource> &dataSource) {
332 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800333
334 if (extractor == NULL) {
335 return UNKNOWN_ERROR;
336 }
337
James Dongaadbd802011-12-08 19:31:59 -0800338 if (extractor->getDrmFlag()) {
339 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
340 if (mDecryptHandle != NULL) {
341 CHECK(mDrmManagerClient);
342 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
343 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
344 }
Gloria Wangadc4d9c2011-02-08 13:24:08 -0800345 }
Gloria Wangd5770912010-06-22 13:55:38 -0700346 }
347
Andreas Huber27366fc2009-11-20 09:32:46 -0800348 return setDataSource_l(extractor);
349}
350
351status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700352 // Attempt to approximate overall stream bitrate by summing all
353 // tracks' individual bitrates, if not all of them advertise bitrate,
354 // we have to fail.
355
356 int64_t totalBitRate = 0;
357
358 for (size_t i = 0; i < extractor->countTracks(); ++i) {
359 sp<MetaData> meta = extractor->getTrackMetaData(i);
360
361 int32_t bitrate;
362 if (!meta->findInt32(kKeyBitRate, &bitrate)) {
Andreas Huberfddf5d92011-06-07 15:52:25 -0700363 const char *mime;
364 CHECK(meta->findCString(kKeyMIMEType, &mime));
Steve Block71f2cf12011-10-20 11:56:00 +0100365 ALOGV("track of type '%s' does not publish bitrate", mime);
Andreas Huberfddf5d92011-06-07 15:52:25 -0700366
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700367 totalBitRate = -1;
368 break;
369 }
370
371 totalBitRate += bitrate;
372 }
373
374 mBitrate = totalBitRate;
375
Steve Block71f2cf12011-10-20 11:56:00 +0100376 ALOGV("mBitrate = %lld bits/sec", mBitrate);
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700377
Andreas Huberfddf5d92011-06-07 15:52:25 -0700378 {
379 Mutex::Autolock autoLock(mStatsLock);
380 mStats.mBitrate = mBitrate;
381 mStats.mTracks.clear();
382 mStats.mAudioTrackIndex = -1;
383 mStats.mVideoTrackIndex = -1;
384 }
385
Andreas Huber27366fc2009-11-20 09:32:46 -0800386 bool haveAudio = false;
387 bool haveVideo = false;
388 for (size_t i = 0; i < extractor->countTracks(); ++i) {
389 sp<MetaData> meta = extractor->getTrackMetaData(i);
390
Andreas Huberd2b76d72011-10-26 11:22:40 -0700391 const char *_mime;
392 CHECK(meta->findCString(kKeyMIMEType, &_mime));
Andreas Huber27366fc2009-11-20 09:32:46 -0800393
Andreas Huberd2b76d72011-10-26 11:22:40 -0700394 String8 mime = String8(_mime);
395
396 if (!haveVideo && !strncasecmp(mime.string(), "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800397 setVideoSource(extractor->getTrack(i));
398 haveVideo = true;
James Dong08adfd22011-01-16 11:30:13 -0800399
400 // Set the presentation/display size
401 int32_t displayWidth, displayHeight;
402 bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
403 if (success) {
404 success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
405 }
406 if (success) {
407 mDisplayWidth = displayWidth;
408 mDisplayHeight = displayHeight;
409 }
410
Andreas Huberfddf5d92011-06-07 15:52:25 -0700411 {
412 Mutex::Autolock autoLock(mStatsLock);
413 mStats.mVideoTrackIndex = mStats.mTracks.size();
414 mStats.mTracks.push();
415 TrackStat *stat =
416 &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
Andreas Huberd2b76d72011-10-26 11:22:40 -0700417 stat->mMIME = mime.string();
Andreas Huberfddf5d92011-06-07 15:52:25 -0700418 }
Andreas Huberd2b76d72011-10-26 11:22:40 -0700419 } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800420 setAudioSource(extractor->getTrack(i));
421 haveAudio = true;
Andreas Huber9fee0b22010-09-03 14:09:21 -0700422
Andreas Huberfddf5d92011-06-07 15:52:25 -0700423 {
424 Mutex::Autolock autoLock(mStatsLock);
425 mStats.mAudioTrackIndex = mStats.mTracks.size();
426 mStats.mTracks.push();
427 TrackStat *stat =
428 &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
Andreas Huberd2b76d72011-10-26 11:22:40 -0700429 stat->mMIME = mime.string();
Andreas Huberfddf5d92011-06-07 15:52:25 -0700430 }
431
Andreas Huberd2b76d72011-10-26 11:22:40 -0700432 if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_AUDIO_VORBIS)) {
Andreas Huber1913c1a2010-10-04 11:09:31 -0700433 // Only do this for vorbis audio, none of the other audio
434 // formats even support this ringtone specific hack and
435 // retrieving the metadata on some extractors may turn out
436 // to be very expensive.
437 sp<MetaData> fileMeta = extractor->getMetaData();
438 int32_t loop;
439 if (fileMeta != NULL
440 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
Andreas Huberfddf5d92011-06-07 15:52:25 -0700441 modifyFlags(AUTO_LOOPING, SET);
Andreas Huber1913c1a2010-10-04 11:09:31 -0700442 }
Andreas Huber9fee0b22010-09-03 14:09:21 -0700443 }
Andreas Huberd2b76d72011-10-26 11:22:40 -0700444 } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
Gloria Wangc6091dd2011-05-03 15:59:03 -0700445 addTextSource(extractor->getTrack(i));
Andreas Huber27366fc2009-11-20 09:32:46 -0800446 }
447 }
448
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700449 if (!haveAudio && !haveVideo) {
450 return UNKNOWN_ERROR;
451 }
452
453 mExtractorFlags = extractor->flags();
454
455 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800456}
457
458void AwesomePlayer::reset() {
459 Mutex::Autolock autoLock(mLock);
460 reset_l();
461}
462
463void AwesomePlayer::reset_l() {
James Dong08adfd22011-01-16 11:30:13 -0800464 mDisplayWidth = 0;
465 mDisplayHeight = 0;
Andreas Huber90c65652011-01-04 10:19:13 -0800466
Gloria Wangd5770912010-06-22 13:55:38 -0700467 if (mDecryptHandle != NULL) {
468 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
469 Playback::STOP, 0);
Gloria Wangd5770912010-06-22 13:55:38 -0700470 mDecryptHandle = NULL;
471 mDrmManagerClient = NULL;
472 }
473
Gloria Wangd211f412011-02-19 18:37:57 -0800474 if (mFlags & PLAYING) {
475 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
476 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
477 params |= IMediaPlayerService::kBatteryDataTrackAudio;
478 }
479 if (mVideoSource != NULL) {
480 params |= IMediaPlayerService::kBatteryDataTrackVideo;
481 }
482 addBatteryData(params);
483 }
484
Andreas Huberedbb4d82010-03-12 08:59:22 -0800485 if (mFlags & PREPARING) {
Andreas Huberfddf5d92011-06-07 15:52:25 -0700486 modifyFlags(PREPARE_CANCELLED, SET);
Andreas Huberedbb4d82010-03-12 08:59:22 -0800487 if (mConnectingDataSource != NULL) {
488 LOGI("interrupting the connection process");
489 mConnectingDataSource->disconnect();
490 }
Andreas Hubereaf2c5a2010-10-19 12:18:51 -0700491
492 if (mFlags & PREPARING_CONNECTED) {
493 // We are basically done preparing, we're just buffering
494 // enough data to start playback, we can safely interrupt that.
495 finishAsyncPrepare_l();
496 }
Andreas Huberedbb4d82010-03-12 08:59:22 -0800497 }
498
Andreas Huberffdf4782010-02-09 14:05:43 -0800499 while (mFlags & PREPARING) {
500 mPreparedCondition.wait(mLock);
501 }
502
Andreas Huber27366fc2009-11-20 09:32:46 -0800503 cancelPlayerEvents();
504
Andreas Huber77d8dc22011-04-21 10:06:43 -0700505 mWVMExtractor.clear();
Andreas Huber4d61f602010-06-10 11:17:50 -0700506 mCachedSource.clear();
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800507 mAudioTrack.clear();
508 mVideoTrack.clear();
509
Andreas Huberba7ec912010-02-12 10:42:02 -0800510 // Shutdown audio first, so that the respone to the reset request
511 // appears to happen instantaneously as far as the user is concerned
512 // If we did this later, audio would continue playing while we
513 // shutdown the video-related resources and the player appear to
514 // not be as responsive to a reset request.
Gloria Wange28857c2011-08-31 10:24:18 -0700515 if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
516 && mAudioSource != NULL) {
Andreas Huberedbb4d82010-03-12 08:59:22 -0800517 // If we had an audio player, it would have effectively
518 // taken possession of the audio source and stopped it when
519 // _it_ is stopped. Otherwise this is still our responsibility.
520 mAudioSource->stop();
521 }
Andreas Huberba7ec912010-02-12 10:42:02 -0800522 mAudioSource.clear();
523
Andreas Huberba7ec912010-02-12 10:42:02 -0800524 mTimeSource = NULL;
525
526 delete mAudioPlayer;
527 mAudioPlayer = NULL;
528
Gloria Wangc6091dd2011-05-03 15:59:03 -0700529 if (mTextPlayer != NULL) {
530 delete mTextPlayer;
531 mTextPlayer = NULL;
532 }
533
Andreas Huber3522b5a52010-01-22 14:36:53 -0800534 mVideoRenderer.clear();
535
Andreas Huber27366fc2009-11-20 09:32:46 -0800536 if (mVideoSource != NULL) {
Andreas Huber3a785fe2011-03-14 10:55:40 -0700537 shutdownVideoDecoder_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800538 }
539
Andreas Huber27366fc2009-11-20 09:32:46 -0800540 mDurationUs = -1;
Andreas Huberfddf5d92011-06-07 15:52:25 -0700541 modifyFlags(0, ASSIGN);
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700542 mExtractorFlags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800543 mTimeSourceDeltaUs = 0;
544 mVideoTimeUs = 0;
545
Andreas Hubera2c29972011-02-24 12:05:40 -0800546 mSeeking = NO_SEEK;
Gloria Wang3c578f22011-08-18 14:52:36 -0700547 mSeekNotificationSent = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800548 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800549
Andreas Huberffdf4782010-02-09 14:05:43 -0800550 mUri.setTo("");
551 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800552
553 mFileSource.clear();
554
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700555 mBitrate = -1;
Andreas Huber3a785fe2011-03-14 10:55:40 -0700556 mLastVideoTimeUs = -1;
Andreas Huberfddf5d92011-06-07 15:52:25 -0700557
558 {
559 Mutex::Autolock autoLock(mStatsLock);
560 mStats.mFd = -1;
561 mStats.mURI = String8();
562 mStats.mBitrate = -1;
563 mStats.mAudioTrackIndex = -1;
564 mStats.mVideoTrackIndex = -1;
565 mStats.mNumVideoFramesDecoded = 0;
566 mStats.mNumVideoFramesDropped = 0;
567 mStats.mVideoWidth = -1;
568 mStats.mVideoHeight = -1;
569 mStats.mFlags = 0;
570 mStats.mTracks.clear();
571 }
572
Andreas Huberbf0a0642011-08-16 12:41:41 -0700573 mWatchForAudioSeekComplete = false;
574 mWatchForAudioEOS = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800575}
576
Andreas Huber6be780e2010-02-08 14:40:30 -0800577void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800578 if (mListener != NULL) {
579 sp<MediaPlayerBase> listener = mListener.promote();
580
581 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800582 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800583 }
584 }
585}
586
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700587bool AwesomePlayer::getBitrate(int64_t *bitrate) {
James Dongb1262a82010-11-16 14:04:54 -0800588 off64_t size;
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700589 if (mDurationUs >= 0 && mCachedSource != NULL
590 && mCachedSource->getSize(&size) == OK) {
591 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec
592 return true;
593 }
594
595 if (mBitrate >= 0) {
596 *bitrate = mBitrate;
597 return true;
598 }
599
600 *bitrate = 0;
601
602 return false;
603}
604
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700605// Returns true iff cached duration is available/applicable.
606bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700607 int64_t bitrate;
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700608
Andreas Hubera6be6dc2011-10-11 15:24:07 -0700609 if (mCachedSource != NULL && getBitrate(&bitrate)) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000610 status_t finalStatus;
611 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700612 *durationUs = cachedDataRemaining * 8000000ll / bitrate;
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000613 *eos = (finalStatus != OK);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700614 return true;
Andreas Huber77d8dc22011-04-21 10:06:43 -0700615 } else if (mWVMExtractor != NULL) {
616 status_t finalStatus;
617 *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus);
618 *eos = (finalStatus != OK);
619 return true;
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700620 }
621
622 return false;
623}
624
Andreas Huber10b920c2010-11-11 15:37:17 -0800625void AwesomePlayer::ensureCacheIsFetching_l() {
626 if (mCachedSource != NULL) {
627 mCachedSource->resumeFetchingIfNecessary();
628 }
629}
630
Andreas Huber52c78322011-01-11 15:05:28 -0800631void AwesomePlayer::onVideoLagUpdate() {
632 Mutex::Autolock autoLock(mLock);
633 if (!mVideoLagEventPending) {
634 return;
635 }
636 mVideoLagEventPending = false;
637
638 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
639 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
640
Andreas Huber16ede3c2011-03-25 13:03:14 -0700641 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
Steve Block71f2cf12011-10-20 11:56:00 +0100642 ALOGV("video late by %lld ms.", videoLateByUs / 1000ll);
Andreas Huber52c78322011-01-11 15:05:28 -0800643
644 notifyListener_l(
645 MEDIA_INFO,
646 MEDIA_INFO_VIDEO_TRACK_LAGGING,
647 videoLateByUs / 1000ll);
648 }
649
650 postVideoLagEvent_l();
651}
652
Andreas Huberb9e63832010-01-26 16:20:10 -0800653void AwesomePlayer::onBufferingUpdate() {
654 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800655 if (!mBufferingEventPending) {
656 return;
657 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800658 mBufferingEventPending = false;
659
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700660 if (mCachedSource != NULL) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000661 status_t finalStatus;
662 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
663 bool eos = (finalStatus != OK);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700664
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700665 if (eos) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000666 if (finalStatus == ERROR_END_OF_STREAM) {
667 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
668 }
Andreas Huber05f67872010-10-04 11:36:39 -0700669 if (mFlags & PREPARING) {
Steve Block71f2cf12011-10-20 11:56:00 +0100670 ALOGV("cache has reached EOS, prepare is done.");
Andreas Huber05f67872010-10-04 11:36:39 -0700671 finishAsyncPrepare_l();
672 }
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700673 } else {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700674 int64_t bitrate;
675 if (getBitrate(&bitrate)) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700676 size_t cachedSize = mCachedSource->cachedSize();
677 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
678
679 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
680 if (percentage > 100) {
681 percentage = 100;
682 }
683
684 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
685 } else {
686 // We don't know the bitrate of the stream, use absolute size
687 // limits to maintain the cache.
688
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700689 if ((mFlags & PLAYING) && !eos
690 && (cachedDataRemaining < kLowWaterMarkBytes)) {
691 LOGI("cache is running low (< %d) , pausing.",
692 kLowWaterMarkBytes);
Andreas Huberfddf5d92011-06-07 15:52:25 -0700693 modifyFlags(CACHE_UNDERRUN, SET);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700694 pause_l();
Andreas Huber10b920c2010-11-11 15:37:17 -0800695 ensureCacheIsFetching_l();
James Donga9d0feb2011-05-25 19:37:03 -0700696 sendCacheStats();
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700697 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
698 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
699 if (mFlags & CACHE_UNDERRUN) {
700 LOGI("cache has filled up (> %d), resuming.",
701 kHighWaterMarkBytes);
Andreas Huberfddf5d92011-06-07 15:52:25 -0700702 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700703 play_l();
704 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
705 } else if (mFlags & PREPARING) {
Steve Block71f2cf12011-10-20 11:56:00 +0100706 ALOGV("cache has filled up (> %d), prepare is done",
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700707 kHighWaterMarkBytes);
708 finishAsyncPrepare_l();
709 }
710 }
711 }
712 }
Andreas Huber77d8dc22011-04-21 10:06:43 -0700713 } else if (mWVMExtractor != NULL) {
714 status_t finalStatus;
715
716 int64_t cachedDurationUs
717 = mWVMExtractor->getCachedDurationUs(&finalStatus);
718
719 bool eos = (finalStatus != OK);
720
721 if (eos) {
722 if (finalStatus == ERROR_END_OF_STREAM) {
723 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
724 }
725 if (mFlags & PREPARING) {
Steve Block71f2cf12011-10-20 11:56:00 +0100726 ALOGV("cache has reached EOS, prepare is done.");
Andreas Huber77d8dc22011-04-21 10:06:43 -0700727 finishAsyncPrepare_l();
728 }
729 } else {
730 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
731 if (percentage > 100) {
732 percentage = 100;
733 }
734
735 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
736 }
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700737 }
738
739 int64_t cachedDurationUs;
740 bool eos;
741 if (getCachedDuration_l(&cachedDurationUs, &eos)) {
Steve Block71f2cf12011-10-20 11:56:00 +0100742 ALOGV("cachedDurationUs = %.2f secs, eos=%d",
Andreas Huber10b920c2010-11-11 15:37:17 -0800743 cachedDurationUs / 1E6, eos);
744
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700745 if ((mFlags & PLAYING) && !eos
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700746 && (cachedDurationUs < kLowWaterMarkUs)) {
747 LOGI("cache is running low (%.2f secs) , pausing.",
748 cachedDurationUs / 1E6);
Andreas Huberfddf5d92011-06-07 15:52:25 -0700749 modifyFlags(CACHE_UNDERRUN, SET);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700750 pause_l();
Andreas Huber10b920c2010-11-11 15:37:17 -0800751 ensureCacheIsFetching_l();
James Donga9d0feb2011-05-25 19:37:03 -0700752 sendCacheStats();
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700753 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
Andreas Hubera6be6dc2011-10-11 15:24:07 -0700754 } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700755 if (mFlags & CACHE_UNDERRUN) {
756 LOGI("cache has filled up (%.2f secs), resuming.",
757 cachedDurationUs / 1E6);
Andreas Huberfddf5d92011-06-07 15:52:25 -0700758 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700759 play_l();
760 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
761 } else if (mFlags & PREPARING) {
Steve Block71f2cf12011-10-20 11:56:00 +0100762 ALOGV("cache has filled up (%.2f secs), prepare is done",
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700763 cachedDurationUs / 1E6);
764 finishAsyncPrepare_l();
Andreas Huberc23296e2010-08-25 12:31:48 -0700765 }
Andreas Huberc23296e2010-08-25 12:31:48 -0700766 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800767 }
Andreas Huber4d61f602010-06-10 11:17:50 -0700768
Andreas Huber4d61f602010-06-10 11:17:50 -0700769 postBufferingEvent_l();
Andreas Huberb9e63832010-01-26 16:20:10 -0800770}
771
James Donga9d0feb2011-05-25 19:37:03 -0700772void AwesomePlayer::sendCacheStats() {
773 sp<MediaPlayerBase> listener = mListener.promote();
James Dong44328702011-06-01 15:27:20 -0700774 if (listener != NULL && mCachedSource != NULL) {
James Donga9d0feb2011-05-25 19:37:03 -0700775 int32_t kbps = 0;
776 status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
777 if (err == OK) {
778 listener->sendEvent(
779 MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
780 }
781 }
782}
783
Andreas Huber27366fc2009-11-20 09:32:46 -0800784void AwesomePlayer::onStreamDone() {
785 // Posted whenever any stream finishes playing.
786
787 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800788 if (!mStreamDoneEventPending) {
789 return;
790 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800791 mStreamDoneEventPending = false;
792
Andreas Huberd6c421f2011-02-16 09:05:38 -0800793 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Steve Block71f2cf12011-10-20 11:56:00 +0100794 ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
Andreas Huber971305d2010-07-07 13:35:27 -0700795
796 notifyListener_l(
797 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
798
Andreas Huberc743f452010-10-05 10:25:34 -0700799 pause_l(true /* at eos */);
Andreas Huber971305d2010-07-07 13:35:27 -0700800
Andreas Huberfddf5d92011-06-07 15:52:25 -0700801 modifyFlags(AT_EOS, SET);
Andreas Huber971305d2010-07-07 13:35:27 -0700802 return;
803 }
804
805 const bool allDone =
806 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
807 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
808
809 if (!allDone) {
810 return;
811 }
812
Andreas Huber4960f3a2011-08-18 10:53:23 -0700813 if ((mFlags & LOOPING)
814 || ((mFlags & AUTO_LOOPING)
815 && (mAudioSink == NULL || mAudioSink->realtime()))) {
816 // Don't AUTO_LOOP if we're being recorded, since that cannot be
817 // turned off and recording would go on indefinitely.
818
Andreas Huber27366fc2009-11-20 09:32:46 -0800819 seekTo_l(0);
820
Andreas Huber7085b6842010-02-03 16:02:02 -0800821 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800822 postVideoEvent_l();
823 }
824 } else {
Steve Block71f2cf12011-10-20 11:56:00 +0100825 ALOGV("MEDIA_PLAYBACK_COMPLETE");
Andreas Huber971305d2010-07-07 13:35:27 -0700826 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800827
Andreas Huberc743f452010-10-05 10:25:34 -0700828 pause_l(true /* at eos */);
Andreas Huber406a18b2010-02-18 16:45:13 -0800829
Andreas Huberfddf5d92011-06-07 15:52:25 -0700830 modifyFlags(AT_EOS, SET);
Andreas Huber27366fc2009-11-20 09:32:46 -0800831 }
832}
833
834status_t AwesomePlayer::play() {
835 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -0700836
Andreas Huberfddf5d92011-06-07 15:52:25 -0700837 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber4d61f602010-06-10 11:17:50 -0700838
Andreas Huberba7ec912010-02-12 10:42:02 -0800839 return play_l();
840}
Andreas Huber27366fc2009-11-20 09:32:46 -0800841
Andreas Huberba7ec912010-02-12 10:42:02 -0800842status_t AwesomePlayer::play_l() {
Andreas Huberfddf5d92011-06-07 15:52:25 -0700843 modifyFlags(SEEK_PREVIEW, CLEAR);
Andreas Huber0a84f4f2011-02-07 11:43:12 -0800844
Andreas Huber27366fc2009-11-20 09:32:46 -0800845 if (mFlags & PLAYING) {
846 return OK;
847 }
848
Andreas Huberffdf4782010-02-09 14:05:43 -0800849 if (!(mFlags & PREPARED)) {
850 status_t err = prepare_l();
851
852 if (err != OK) {
853 return err;
854 }
855 }
856
Andreas Huberfddf5d92011-06-07 15:52:25 -0700857 modifyFlags(PLAYING, SET);
858 modifyFlags(FIRST_FRAME, SET);
Andreas Huber27366fc2009-11-20 09:32:46 -0800859
Gloria Wang95dbffb2010-11-04 17:38:39 -0700860 if (mDecryptHandle != NULL) {
861 int64_t position;
862 getPosition(&position);
863 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
864 Playback::START, position / 1000);
865 }
866
Andreas Huber27366fc2009-11-20 09:32:46 -0800867 if (mAudioSource != NULL) {
868 if (mAudioPlayer == NULL) {
869 if (mAudioSink != NULL) {
Andreas Huber2b359ed2010-09-28 11:56:39 -0700870 mAudioPlayer = new AudioPlayer(mAudioSink, this);
Andreas Huber27366fc2009-11-20 09:32:46 -0800871 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800872
Andreas Huber27366fc2009-11-20 09:32:46 -0800873 mTimeSource = mAudioPlayer;
874
Andreas Huber498422f2011-03-16 10:41:25 -0700875 // If there was a seek request before we ever started,
876 // honor the request now.
877 // Make sure to do this before starting the audio player
878 // to avoid a race condition.
879 seekAudioIfNecessary_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800880 }
Andreas Huberce8a1012011-02-11 13:09:36 -0800881 }
882
883 CHECK(!(mFlags & AUDIO_RUNNING));
884
885 if (mVideoSource == NULL) {
Andreas Huber232d5f22011-07-14 13:02:47 -0700886 // We don't want to post an error notification at this point,
887 // the error returned from MediaPlayer::start() will suffice.
888
889 status_t err = startAudioPlayer_l(
890 false /* sendErrorNotification */);
Andreas Huberce8a1012011-02-11 13:09:36 -0800891
892 if (err != OK) {
893 delete mAudioPlayer;
894 mAudioPlayer = NULL;
895
Andreas Huberfddf5d92011-06-07 15:52:25 -0700896 modifyFlags((PLAYING | FIRST_FRAME), CLEAR);
Andreas Huberce8a1012011-02-11 13:09:36 -0800897
898 if (mDecryptHandle != NULL) {
899 mDrmManagerClient->setPlaybackStatus(
900 mDecryptHandle, Playback::STOP, 0);
901 }
902
903 return err;
904 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800905 }
906 }
907
908 if (mTimeSource == NULL && mAudioPlayer == NULL) {
Andreas Huber971305d2010-07-07 13:35:27 -0700909 mTimeSource = &mSystemTimeSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800910 }
911
912 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800913 // Kick off video playback
914 postVideoEvent_l();
Andreas Huber52c78322011-01-11 15:05:28 -0800915
916 if (mAudioSource != NULL && mVideoSource != NULL) {
917 postVideoLagEvent_l();
918 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800919 }
920
Andreas Huber406a18b2010-02-18 16:45:13 -0800921 if (mFlags & AT_EOS) {
922 // Legacy behaviour, if a stream finishes playing and then
923 // is started again, we play from the start...
924 seekTo_l(0);
925 }
926
Gloria Wangd211f412011-02-19 18:37:57 -0800927 uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
928 | IMediaPlayerService::kBatteryDataTrackDecoder;
929 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
930 params |= IMediaPlayerService::kBatteryDataTrackAudio;
931 }
932 if (mVideoSource != NULL) {
933 params |= IMediaPlayerService::kBatteryDataTrackVideo;
934 }
935 addBatteryData(params);
936
Andreas Huber27366fc2009-11-20 09:32:46 -0800937 return OK;
938}
939
Andreas Huber232d5f22011-07-14 13:02:47 -0700940status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
Andreas Huberce8a1012011-02-11 13:09:36 -0800941 CHECK(!(mFlags & AUDIO_RUNNING));
942
943 if (mAudioSource == NULL || mAudioPlayer == NULL) {
944 return OK;
945 }
946
947 if (!(mFlags & AUDIOPLAYER_STARTED)) {
Andreas Huberfddf5d92011-06-07 15:52:25 -0700948 modifyFlags(AUDIOPLAYER_STARTED, SET);
Andreas Huberce8a1012011-02-11 13:09:36 -0800949
Andreas Huber5fd43e32011-05-10 13:56:39 -0700950 bool wasSeeking = mAudioPlayer->isSeeking();
951
Andreas Huberce8a1012011-02-11 13:09:36 -0800952 // We've already started the MediaSource in order to enable
953 // the prefetcher to read its data.
954 status_t err = mAudioPlayer->start(
955 true /* sourceAlreadyStarted */);
956
957 if (err != OK) {
Andreas Huber232d5f22011-07-14 13:02:47 -0700958 if (sendErrorNotification) {
959 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
960 }
961
Andreas Huberce8a1012011-02-11 13:09:36 -0800962 return err;
963 }
Andreas Huber5fd43e32011-05-10 13:56:39 -0700964
965 if (wasSeeking) {
966 CHECK(!mAudioPlayer->isSeeking());
967
968 // We will have finished the seek while starting the audio player.
Andreas Huber67a041f2011-09-01 11:39:11 -0700969 postAudioSeekComplete();
Andreas Huber5fd43e32011-05-10 13:56:39 -0700970 }
Andreas Huberce8a1012011-02-11 13:09:36 -0800971 } else {
972 mAudioPlayer->resume();
973 }
974
Andreas Huberfddf5d92011-06-07 15:52:25 -0700975 modifyFlags(AUDIO_RUNNING, SET);
Andreas Huberce8a1012011-02-11 13:09:36 -0800976
977 mWatchForAudioEOS = true;
978
979 return OK;
980}
981
Andreas Hubere3c01832010-08-16 08:49:37 -0700982void AwesomePlayer::notifyVideoSize_l() {
983 sp<MetaData> meta = mVideoSource->getFormat();
984
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800985 int32_t cropLeft, cropTop, cropRight, cropBottom;
986 if (!meta->findRect(
987 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
988 int32_t width, height;
989 CHECK(meta->findInt32(kKeyWidth, &width));
990 CHECK(meta->findInt32(kKeyHeight, &height));
991
992 cropLeft = cropTop = 0;
993 cropRight = width - 1;
994 cropBottom = height - 1;
995
Steve Block71f2cf12011-10-20 11:56:00 +0100996 ALOGV("got dimensions only %d x %d", width, height);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800997 } else {
Steve Block71f2cf12011-10-20 11:56:00 +0100998 ALOGV("got crop rect %d, %d, %d, %d",
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800999 cropLeft, cropTop, cropRight, cropBottom);
1000 }
1001
James Dong7e91d912011-03-18 12:19:43 -07001002 int32_t displayWidth;
1003 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
Steve Block71f2cf12011-10-20 11:56:00 +01001004 ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
James Dong7e91d912011-03-18 12:19:43 -07001005 mDisplayWidth = displayWidth;
1006 }
1007 int32_t displayHeight;
1008 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
Steve Block71f2cf12011-10-20 11:56:00 +01001009 ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
James Dong7e91d912011-03-18 12:19:43 -07001010 mDisplayHeight = displayHeight;
1011 }
1012
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001013 int32_t usableWidth = cropRight - cropLeft + 1;
1014 int32_t usableHeight = cropBottom - cropTop + 1;
James Dong08adfd22011-01-16 11:30:13 -08001015 if (mDisplayWidth != 0) {
1016 usableWidth = mDisplayWidth;
1017 }
1018 if (mDisplayHeight != 0) {
1019 usableHeight = mDisplayHeight;
1020 }
Andreas Hubere3c01832010-08-16 08:49:37 -07001021
Andreas Huberfddf5d92011-06-07 15:52:25 -07001022 {
1023 Mutex::Autolock autoLock(mStatsLock);
1024 mStats.mVideoWidth = usableWidth;
1025 mStats.mVideoHeight = usableHeight;
1026 }
1027
Andreas Huber940c8662010-11-16 15:26:30 -08001028 int32_t rotationDegrees;
1029 if (!mVideoTrack->getFormat()->findInt32(
1030 kKeyRotation, &rotationDegrees)) {
1031 rotationDegrees = 0;
1032 }
1033
1034 if (rotationDegrees == 90 || rotationDegrees == 270) {
1035 notifyListener_l(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001036 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
Andreas Huber940c8662010-11-16 15:26:30 -08001037 } else {
1038 notifyListener_l(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001039 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
Andreas Huber940c8662010-11-16 15:26:30 -08001040 }
Andreas Hubere3c01832010-08-16 08:49:37 -07001041}
1042
Andreas Huber27366fc2009-11-20 09:32:46 -08001043void AwesomePlayer::initRenderer_l() {
Glenn Kastencc562a32011-02-08 17:26:17 -08001044 if (mNativeWindow == NULL) {
Andreas Huberc23dabf2010-11-16 13:05:53 -08001045 return;
1046 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001047
Andreas Huberc23dabf2010-11-16 13:05:53 -08001048 sp<MetaData> meta = mVideoSource->getFormat();
Andreas Huber27366fc2009-11-20 09:32:46 -08001049
Andreas Huberc23dabf2010-11-16 13:05:53 -08001050 int32_t format;
1051 const char *component;
1052 int32_t decodedWidth, decodedHeight;
1053 CHECK(meta->findInt32(kKeyColorFormat, &format));
1054 CHECK(meta->findCString(kKeyDecoderComponent, &component));
1055 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
1056 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
Andreas Hubera67d5382009-12-10 15:32:12 -08001057
Andreas Huber940c8662010-11-16 15:26:30 -08001058 int32_t rotationDegrees;
1059 if (!mVideoTrack->getFormat()->findInt32(
1060 kKeyRotation, &rotationDegrees)) {
1061 rotationDegrees = 0;
1062 }
1063
Andreas Huberc23dabf2010-11-16 13:05:53 -08001064 mVideoRenderer.clear();
Andreas Hubera67d5382009-12-10 15:32:12 -08001065
Andreas Huberc23dabf2010-11-16 13:05:53 -08001066 // Must ensure that mVideoRenderer's destructor is actually executed
1067 // before creating a new one.
1068 IPCThreadState::self()->flushCommands();
1069
Andreas Huber4b3913a2011-05-11 14:13:42 -07001070 if (USE_SURFACE_ALLOC
1071 && !strncmp(component, "OMX.", 4)
Andreas Huberbc554952011-09-08 14:12:44 -07001072 && strncmp(component, "OMX.google.", 11)
1073 && strcmp(component, "OMX.Nvidia.mpeg2v.decode")) {
Andreas Huberc23dabf2010-11-16 13:05:53 -08001074 // Hardware decoders avoid the CPU color conversion by decoding
1075 // directly to ANativeBuffers, so we must use a renderer that
1076 // just pushes those buffers to the ANativeWindow.
Andreas Huber940c8662010-11-16 15:26:30 -08001077 mVideoRenderer =
Glenn Kastencc562a32011-02-08 17:26:17 -08001078 new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
Andreas Huberc23dabf2010-11-16 13:05:53 -08001079 } else {
1080 // Other decoders are instantiated locally and as a consequence
1081 // allocate their buffers in local address space. This renderer
1082 // then performs a color conversion and copy to get the data
1083 // into the ANativeBuffer.
Glenn Kastencc562a32011-02-08 17:26:17 -08001084 mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
Andreas Huber27366fc2009-11-20 09:32:46 -08001085 }
1086}
1087
1088status_t AwesomePlayer::pause() {
1089 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -07001090
Andreas Huberfddf5d92011-06-07 15:52:25 -07001091 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber4d61f602010-06-10 11:17:50 -07001092
Andreas Huber27366fc2009-11-20 09:32:46 -08001093 return pause_l();
1094}
1095
Andreas Huberc743f452010-10-05 10:25:34 -07001096status_t AwesomePlayer::pause_l(bool at_eos) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001097 if (!(mFlags & PLAYING)) {
1098 return OK;
1099 }
1100
Andreas Huber22cf4b02011-11-16 10:46:05 -08001101 cancelPlayerEvents(true /* keepNotifications */);
Andreas Huber27366fc2009-11-20 09:32:46 -08001102
Andreas Huberce8a1012011-02-11 13:09:36 -08001103 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huberc743f452010-10-05 10:25:34 -07001104 if (at_eos) {
1105 // If we played the audio stream to completion we
1106 // want to make sure that all samples remaining in the audio
1107 // track's queue are played out.
1108 mAudioPlayer->pause(true /* playPendingSamples */);
1109 } else {
1110 mAudioPlayer->pause();
1111 }
Andreas Huberce8a1012011-02-11 13:09:36 -08001112
Andreas Huberfddf5d92011-06-07 15:52:25 -07001113 modifyFlags(AUDIO_RUNNING, CLEAR);
Andreas Huber27366fc2009-11-20 09:32:46 -08001114 }
1115
Gloria Wangc6091dd2011-05-03 15:59:03 -07001116 if (mFlags & TEXTPLAYER_STARTED) {
1117 mTextPlayer->pause();
Andreas Huberfddf5d92011-06-07 15:52:25 -07001118 modifyFlags(TEXT_RUNNING, CLEAR);
Gloria Wangc6091dd2011-05-03 15:59:03 -07001119 }
1120
Andreas Huberfddf5d92011-06-07 15:52:25 -07001121 modifyFlags(PLAYING, CLEAR);
Andreas Huber27366fc2009-11-20 09:32:46 -08001122
Gloria Wangd5770912010-06-22 13:55:38 -07001123 if (mDecryptHandle != NULL) {
1124 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1125 Playback::PAUSE, 0);
1126 }
1127
Gloria Wangd211f412011-02-19 18:37:57 -08001128 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
1129 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
1130 params |= IMediaPlayerService::kBatteryDataTrackAudio;
1131 }
1132 if (mVideoSource != NULL) {
1133 params |= IMediaPlayerService::kBatteryDataTrackVideo;
1134 }
1135
1136 addBatteryData(params);
1137
Andreas Huber27366fc2009-11-20 09:32:46 -08001138 return OK;
1139}
1140
1141bool AwesomePlayer::isPlaying() const {
Andreas Huber4d61f602010-06-10 11:17:50 -07001142 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
Andreas Huber27366fc2009-11-20 09:32:46 -08001143}
1144
Andreas Huber07754c52011-08-29 13:01:23 -07001145status_t AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
Glenn Kastencc562a32011-02-08 17:26:17 -08001146 Mutex::Autolock autoLock(mLock);
1147
Andreas Huber07754c52011-08-29 13:01:23 -07001148 status_t err;
Glenn Kastencc562a32011-02-08 17:26:17 -08001149 if (surfaceTexture != NULL) {
Andreas Huber07754c52011-08-29 13:01:23 -07001150 err = setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
Gloria Wang91784c992011-08-09 15:29:34 -07001151 } else {
Andreas Huber07754c52011-08-29 13:01:23 -07001152 err = setNativeWindow_l(NULL);
Andreas Huber3a785fe2011-03-14 10:55:40 -07001153 }
Andreas Huber07754c52011-08-29 13:01:23 -07001154
1155 return err;
Andreas Huber3a785fe2011-03-14 10:55:40 -07001156}
1157
1158void AwesomePlayer::shutdownVideoDecoder_l() {
1159 if (mVideoBuffer) {
1160 mVideoBuffer->release();
1161 mVideoBuffer = NULL;
Glenn Kastencc562a32011-02-08 17:26:17 -08001162 }
1163
Andreas Huber3a785fe2011-03-14 10:55:40 -07001164 mVideoSource->stop();
1165
1166 // The following hack is necessary to ensure that the OMX
1167 // component is completely released by the time we may try
1168 // to instantiate it again.
1169 wp<MediaSource> tmp = mVideoSource;
1170 mVideoSource.clear();
1171 while (tmp.promote() != NULL) {
1172 usleep(1000);
1173 }
1174 IPCThreadState::self()->flushCommands();
Steve Block71f2cf12011-10-20 11:56:00 +01001175 ALOGV("video decoder shutdown completed");
Andreas Huber3a785fe2011-03-14 10:55:40 -07001176}
1177
Andreas Huber07754c52011-08-29 13:01:23 -07001178status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
Andreas Huber3a785fe2011-03-14 10:55:40 -07001179 mNativeWindow = native;
1180
1181 if (mVideoSource == NULL) {
Andreas Huber07754c52011-08-29 13:01:23 -07001182 return OK;
Andreas Huber3a785fe2011-03-14 10:55:40 -07001183 }
1184
Steve Block71f2cf12011-10-20 11:56:00 +01001185 ALOGV("attempting to reconfigure to use new surface");
Andreas Huber3a785fe2011-03-14 10:55:40 -07001186
1187 bool wasPlaying = (mFlags & PLAYING) != 0;
1188
1189 pause_l();
1190 mVideoRenderer.clear();
1191
1192 shutdownVideoDecoder_l();
1193
Andreas Huber07754c52011-08-29 13:01:23 -07001194 status_t err = initVideoDecoder();
1195
1196 if (err != OK) {
1197 LOGE("failed to reinstantiate video decoder after surface change.");
1198 return err;
1199 }
Andreas Huber3a785fe2011-03-14 10:55:40 -07001200
1201 if (mLastVideoTimeUs >= 0) {
1202 mSeeking = SEEK;
Andreas Huber3a785fe2011-03-14 10:55:40 -07001203 mSeekTimeUs = mLastVideoTimeUs;
Andreas Huberfddf5d92011-06-07 15:52:25 -07001204 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
Andreas Huber3a785fe2011-03-14 10:55:40 -07001205 }
1206
1207 if (wasPlaying) {
1208 play_l();
1209 }
Andreas Huber07754c52011-08-29 13:01:23 -07001210
1211 return OK;
Andreas Hubere3c01832010-08-16 08:49:37 -07001212}
1213
Andreas Huber27366fc2009-11-20 09:32:46 -08001214void AwesomePlayer::setAudioSink(
1215 const sp<MediaPlayerBase::AudioSink> &audioSink) {
1216 Mutex::Autolock autoLock(mLock);
1217
1218 mAudioSink = audioSink;
1219}
1220
1221status_t AwesomePlayer::setLooping(bool shouldLoop) {
1222 Mutex::Autolock autoLock(mLock);
1223
Andreas Huberfddf5d92011-06-07 15:52:25 -07001224 modifyFlags(LOOPING, CLEAR);
Andreas Huber27366fc2009-11-20 09:32:46 -08001225
1226 if (shouldLoop) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001227 modifyFlags(LOOPING, SET);
Andreas Huber27366fc2009-11-20 09:32:46 -08001228 }
1229
1230 return OK;
1231}
1232
1233status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -07001234 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001235
1236 if (mDurationUs < 0) {
1237 return UNKNOWN_ERROR;
1238 }
1239
1240 *durationUs = mDurationUs;
1241
1242 return OK;
1243}
1244
1245status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Hubera6be6dc2011-10-11 15:24:07 -07001246 if (mSeeking != NO_SEEK) {
Andreas Huberddb709c2010-04-07 10:24:35 -07001247 *positionUs = mSeekTimeUs;
Andreas Huber16ede3c2011-03-25 13:03:14 -07001248 } else if (mVideoSource != NULL
1249 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
Andreas Huber252573c2010-03-26 10:17:17 -07001250 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001251 *positionUs = mVideoTimeUs;
1252 } else if (mAudioPlayer != NULL) {
1253 *positionUs = mAudioPlayer->getMediaTimeUs();
1254 } else {
1255 *positionUs = 0;
1256 }
1257
1258 return OK;
1259}
1260
1261status_t AwesomePlayer::seekTo(int64_t timeUs) {
Andreas Huber10b9b3f2010-10-08 10:16:24 -07001262 if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001263 Mutex::Autolock autoLock(mLock);
1264 return seekTo_l(timeUs);
1265 }
1266
1267 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -08001268}
1269
Gloria Wangc6091dd2011-05-03 15:59:03 -07001270status_t AwesomePlayer::setTimedTextTrackIndex(int32_t index) {
1271 if (mTextPlayer != NULL) {
1272 if (index >= 0) { // to turn on a text track
1273 status_t err = mTextPlayer->setTimedTextTrackIndex(index);
1274 if (err != OK) {
1275 return err;
1276 }
1277
Andreas Huberfddf5d92011-06-07 15:52:25 -07001278 modifyFlags(TEXT_RUNNING, SET);
1279 modifyFlags(TEXTPLAYER_STARTED, SET);
Gloria Wangc6091dd2011-05-03 15:59:03 -07001280 return OK;
1281 } else { // to turn off the text track display
1282 if (mFlags & TEXT_RUNNING) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001283 modifyFlags(TEXT_RUNNING, CLEAR);
Gloria Wangc6091dd2011-05-03 15:59:03 -07001284 }
1285 if (mFlags & TEXTPLAYER_STARTED) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001286 modifyFlags(TEXTPLAYER_STARTED, CLEAR);
Gloria Wangc6091dd2011-05-03 15:59:03 -07001287 }
1288
1289 return mTextPlayer->setTimedTextTrackIndex(index);
1290 }
1291 } else {
1292 return INVALID_OPERATION;
1293 }
1294}
1295
Andreas Huber27366fc2009-11-20 09:32:46 -08001296status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001297 if (mFlags & CACHE_UNDERRUN) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001298 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber4d61f602010-06-10 11:17:50 -07001299 play_l();
1300 }
1301
Andreas Huber16ede3c2011-03-25 13:03:14 -07001302 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1303 // Video playback completed before, there's no pending
1304 // video event right now. In order for this new seek
1305 // to be honored, we need to post one.
1306
1307 postVideoEvent_l();
1308 }
1309
Andreas Hubera2c29972011-02-24 12:05:40 -08001310 mSeeking = SEEK;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001311 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -08001312 mSeekTimeUs = timeUs;
Andreas Huberfddf5d92011-06-07 15:52:25 -07001313 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
Andreas Huber27366fc2009-11-20 09:32:46 -08001314
1315 seekAudioIfNecessary_l();
1316
Gloria Wangc6091dd2011-05-03 15:59:03 -07001317 if (mFlags & TEXTPLAYER_STARTED) {
1318 mTextPlayer->seekTo(mSeekTimeUs);
1319 }
1320
Andreas Huber8e2b9412010-03-31 09:40:15 -07001321 if (!(mFlags & PLAYING)) {
Steve Block71f2cf12011-10-20 11:56:00 +01001322 ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
Andreas Huber8e2b9412010-03-31 09:40:15 -07001323 " immediately.");
1324
1325 notifyListener_l(MEDIA_SEEK_COMPLETE);
1326 mSeekNotificationSent = true;
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001327
1328 if ((mFlags & PREPARED) && mVideoSource != NULL) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001329 modifyFlags(SEEK_PREVIEW, SET);
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001330 postVideoEvent_l();
1331 }
Andreas Huber8e2b9412010-03-31 09:40:15 -07001332 }
1333
Andreas Huber27366fc2009-11-20 09:32:46 -08001334 return OK;
1335}
1336
1337void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Hubera2c29972011-02-24 12:05:40 -08001338 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001339 mAudioPlayer->seekTo(mSeekTimeUs);
1340
Andreas Huber70d10c02010-02-03 11:37:29 -08001341 mWatchForAudioSeekComplete = true;
1342 mWatchForAudioEOS = true;
Gloria Wangd5770912010-06-22 13:55:38 -07001343
1344 if (mDecryptHandle != NULL) {
1345 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1346 Playback::PAUSE, 0);
1347 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1348 Playback::START, mSeekTimeUs / 1000);
1349 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001350 }
1351}
1352
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001353void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1354 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001355
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001356 mAudioTrack = source;
1357}
1358
Gloria Wangc6091dd2011-05-03 15:59:03 -07001359void AwesomePlayer::addTextSource(sp<MediaSource> source) {
Gloria Wang13bc8cd2011-05-11 11:24:09 -07001360 Mutex::Autolock autoLock(mTimedTextLock);
Gloria Wangc6091dd2011-05-03 15:59:03 -07001361 CHECK(source != NULL);
1362
1363 if (mTextPlayer == NULL) {
1364 mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
1365 }
1366
1367 mTextPlayer->addTextSource(source);
1368}
1369
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001370status_t AwesomePlayer::initAudioDecoder() {
1371 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -08001372
1373 const char *mime;
1374 CHECK(meta->findCString(kKeyMIMEType, &mime));
1375
1376 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001377 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -08001378 } else {
1379 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001380 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -08001381 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001382 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -08001383 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001384
1385 if (mAudioSource != NULL) {
1386 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001387 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -07001388 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001389 if (mDurationUs < 0 || durationUs > mDurationUs) {
1390 mDurationUs = durationUs;
1391 }
1392 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001393
Andreas Huber3c78a1b2010-05-13 09:15:21 -07001394 status_t err = mAudioSource->start();
1395
1396 if (err != OK) {
1397 mAudioSource.clear();
1398 return err;
1399 }
Andreas Huberd0332ad2010-04-12 16:05:57 -07001400 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1401 // For legacy reasons we're simply going to ignore the absence
1402 // of an audio decoder for QCELP instead of aborting playback
1403 // altogether.
1404 return OK;
1405 }
Andreas Huberdc9927d2010-03-08 15:46:13 -08001406
Andreas Huberfddf5d92011-06-07 15:52:25 -07001407 if (mAudioSource != NULL) {
1408 Mutex::Autolock autoLock(mStatsLock);
1409 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
1410
1411 const char *component;
1412 if (!mAudioSource->getFormat()
1413 ->findCString(kKeyDecoderComponent, &component)) {
1414 component = "none";
1415 }
1416
1417 stat->mDecoderName = component;
1418 }
1419
Andreas Huber27366fc2009-11-20 09:32:46 -08001420 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1421}
1422
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001423void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1424 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001425
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001426 mVideoTrack = source;
1427}
1428
Andreas Huber4c19bf92010-09-08 14:32:20 -07001429status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
Glenn Kastenb8763f62011-01-28 12:37:51 -08001430
1431 // Either the application or the DRM system can independently say
1432 // that there must be a hardware-protected path to an external video sink.
1433 // For now we always require a hardware-protected path to external video sink
1434 // if content is DRMed, but eventually this could be optional per DRM agent.
1435 // When the application wants protection, then
1436 // (USE_SURFACE_ALLOC && (mSurface != 0) &&
1437 // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
1438 // will be true, but that part is already handled by SurfaceFlinger.
Glenn Kasten1b11b642011-03-23 14:34:31 -07001439
1440#ifdef DEBUG_HDCP
1441 // For debugging, we allow a system property to control the protected usage.
1442 // In case of uninitialized or unexpected property, we default to "DRM only".
1443 bool setProtectionBit = false;
1444 char value[PROPERTY_VALUE_MAX];
1445 if (property_get("persist.sys.hdcp_checking", value, NULL)) {
1446 if (!strcmp(value, "never")) {
1447 // nop
1448 } else if (!strcmp(value, "always")) {
1449 setProtectionBit = true;
1450 } else if (!strcmp(value, "drm-only")) {
1451 if (mDecryptHandle != NULL) {
1452 setProtectionBit = true;
1453 }
1454 // property value is empty, or unexpected value
1455 } else {
1456 if (mDecryptHandle != NULL) {
1457 setProtectionBit = true;
1458 }
1459 }
1460 // can' read property value
1461 } else {
1462 if (mDecryptHandle != NULL) {
1463 setProtectionBit = true;
1464 }
1465 }
1466 // note that usage bit is already cleared, so no need to clear it in the "else" case
1467 if (setProtectionBit) {
1468 flags |= OMXCodec::kEnableGrallocUsageProtected;
1469 }
1470#else
Glenn Kastenb8763f62011-01-28 12:37:51 -08001471 if (mDecryptHandle != NULL) {
1472 flags |= OMXCodec::kEnableGrallocUsageProtected;
1473 }
Glenn Kasten1b11b642011-03-23 14:34:31 -07001474#endif
Steve Block71f2cf12011-10-20 11:56:00 +01001475 ALOGV("initVideoDecoder flags=0x%x", flags);
Andreas Huber27366fc2009-11-20 09:32:46 -08001476 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001477 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -08001478 false, // createEncoder
Andreas Huber57648e42010-08-04 10:14:30 -07001479 mVideoTrack,
Glenn Kastencc562a32011-02-08 17:26:17 -08001480 NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001481
1482 if (mVideoSource != NULL) {
1483 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001484 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -07001485 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001486 if (mDurationUs < 0 || durationUs > mDurationUs) {
1487 mDurationUs = durationUs;
1488 }
1489 }
1490
Andreas Huber1919e5a2010-05-20 10:37:06 -07001491 status_t err = mVideoSource->start();
1492
1493 if (err != OK) {
1494 mVideoSource.clear();
1495 return err;
1496 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001497 }
1498
Andreas Huberfddf5d92011-06-07 15:52:25 -07001499 if (mVideoSource != NULL) {
James Dong5bc53032011-08-11 17:38:35 -07001500 const char *componentName;
Andreas Huberfddf5d92011-06-07 15:52:25 -07001501 CHECK(mVideoSource->getFormat()
James Dong5bc53032011-08-11 17:38:35 -07001502 ->findCString(kKeyDecoderComponent, &componentName));
Andreas Huberfddf5d92011-06-07 15:52:25 -07001503
James Dong5bc53032011-08-11 17:38:35 -07001504 {
1505 Mutex::Autolock autoLock(mStatsLock);
1506 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
1507
1508 stat->mDecoderName = componentName;
1509 }
1510
1511 static const char *kPrefix = "OMX.Nvidia.";
1512 static const char *kSuffix = ".decode";
1513 static const size_t kSuffixLength = strlen(kSuffix);
1514
1515 size_t componentNameLength = strlen(componentName);
1516
1517 if (!strncmp(componentName, kPrefix, strlen(kPrefix))
1518 && componentNameLength >= kSuffixLength
1519 && !strcmp(&componentName[
1520 componentNameLength - kSuffixLength], kSuffix)) {
1521 modifyFlags(SLOW_DECODER_HACK, SET);
1522 }
Andreas Huberfddf5d92011-06-07 15:52:25 -07001523 }
1524
Andreas Huber27366fc2009-11-20 09:32:46 -08001525 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1526}
1527
Andreas Huber4d450a82010-10-19 09:34:44 -07001528void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
Andreas Hubera2c29972011-02-24 12:05:40 -08001529 if (mSeeking == SEEK_VIDEO_ONLY) {
1530 mSeeking = NO_SEEK;
1531 return;
1532 }
1533
1534 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
Andreas Huber4d450a82010-10-19 09:34:44 -07001535 return;
1536 }
1537
1538 if (mAudioPlayer != NULL) {
Steve Block71f2cf12011-10-20 11:56:00 +01001539 ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
Andreas Huber4d450a82010-10-19 09:34:44 -07001540
1541 // If we don't have a video time, seek audio to the originally
1542 // requested seek time instead.
1543
1544 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
Andreas Huber4d450a82010-10-19 09:34:44 -07001545 mWatchForAudioSeekComplete = true;
Andreas Huber16ede3c2011-03-25 13:03:14 -07001546 mWatchForAudioEOS = true;
Andreas Huber4d450a82010-10-19 09:34:44 -07001547 } else if (!mSeekNotificationSent) {
1548 // If we're playing video only, report seek complete now,
1549 // otherwise audio player will notify us later.
1550 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huberf8a5b552011-03-16 15:42:45 -07001551 mSeekNotificationSent = true;
Andreas Huber4d450a82010-10-19 09:34:44 -07001552 }
1553
Andreas Huberfddf5d92011-06-07 15:52:25 -07001554 modifyFlags(FIRST_FRAME, SET);
Andreas Hubera2c29972011-02-24 12:05:40 -08001555 mSeeking = NO_SEEK;
Gloria Wang3f9a8192010-10-29 14:50:17 -07001556
1557 if (mDecryptHandle != NULL) {
1558 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1559 Playback::PAUSE, 0);
1560 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1561 Playback::START, videoTimeUs / 1000);
1562 }
Andreas Huber4d450a82010-10-19 09:34:44 -07001563}
1564
Andreas Huber6be780e2010-02-08 14:40:30 -08001565void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -08001566 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -08001567 if (!mVideoEventPending) {
1568 // The event has been cancelled in reset_l() but had already
1569 // been scheduled for execution at that time.
1570 return;
1571 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001572 mVideoEventPending = false;
1573
Andreas Hubera2c29972011-02-24 12:05:40 -08001574 if (mSeeking != NO_SEEK) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001575 if (mVideoBuffer) {
1576 mVideoBuffer->release();
1577 mVideoBuffer = NULL;
1578 }
Andreas Huber4d61f602010-06-10 11:17:50 -07001579
Andreas Huber77d8dc22011-04-21 10:06:43 -07001580 if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001581 && !(mFlags & SEEK_PREVIEW)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001582 // We're going to seek the video source first, followed by
1583 // the audio source.
1584 // In order to avoid jumps in the DataSource offset caused by
1585 // the audio codec prefetching data from the old locations
1586 // while the video codec is already reading data from the new
1587 // locations, we'll "pause" the audio source, causing it to
1588 // stop reading input data until a subsequent seek.
1589
Andreas Huberce8a1012011-02-11 13:09:36 -08001590 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001591 mAudioPlayer->pause();
Andreas Huberce8a1012011-02-11 13:09:36 -08001592
Andreas Huberfddf5d92011-06-07 15:52:25 -07001593 modifyFlags(AUDIO_RUNNING, CLEAR);
Andreas Huber4d61f602010-06-10 11:17:50 -07001594 }
1595 mAudioSource->pause();
1596 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001597 }
1598
1599 if (!mVideoBuffer) {
1600 MediaSource::ReadOptions options;
Andreas Hubera2c29972011-02-24 12:05:40 -08001601 if (mSeeking != NO_SEEK) {
Steve Block71f2cf12011-10-20 11:56:00 +01001602 ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -08001603
Andreas Huber6624c9f2010-07-20 15:04:28 -07001604 options.setSeekTo(
Andreas Hubera2c29972011-02-24 12:05:40 -08001605 mSeekTimeUs,
1606 mSeeking == SEEK_VIDEO_ONLY
1607 ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
1608 : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
Andreas Huber27366fc2009-11-20 09:32:46 -08001609 }
1610 for (;;) {
1611 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -08001612 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -08001613
1614 if (err != OK) {
Andreas Huber52b52cd2010-11-23 11:41:34 -08001615 CHECK(mVideoBuffer == NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001616
1617 if (err == INFO_FORMAT_CHANGED) {
Steve Block71f2cf12011-10-20 11:56:00 +01001618 ALOGV("VideoSource signalled format change.");
Andreas Huber27366fc2009-11-20 09:32:46 -08001619
Andreas Hubere3c01832010-08-16 08:49:37 -07001620 notifyVideoSize_l();
1621
Andreas Huber7085b6842010-02-03 16:02:02 -08001622 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001623 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -08001624 initRenderer_l();
1625 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001626 continue;
1627 }
1628
Andreas Huber4d450a82010-10-19 09:34:44 -07001629 // So video playback is complete, but we may still have
1630 // a seek request pending that needs to be applied
1631 // to the audio track.
Andreas Hubera2c29972011-02-24 12:05:40 -08001632 if (mSeeking != NO_SEEK) {
Steve Block71f2cf12011-10-20 11:56:00 +01001633 ALOGV("video stream ended while seeking!");
Andreas Huber4d450a82010-10-19 09:34:44 -07001634 }
1635 finishSeekIfNecessary(-1);
1636
Andreas Huber16ede3c2011-03-25 13:03:14 -07001637 if (mAudioPlayer != NULL
1638 && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1639 startAudioPlayer_l();
1640 }
1641
Andreas Huberfddf5d92011-06-07 15:52:25 -07001642 modifyFlags(VIDEO_AT_EOS, SET);
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001643 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -08001644 return;
1645 }
1646
Andreas Hubera67d5382009-12-10 15:32:12 -08001647 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -08001648 // Some decoders, notably the PV AVC software decoder
1649 // return spurious empty buffers that we just want to ignore.
1650
Andreas Hubera67d5382009-12-10 15:32:12 -08001651 mVideoBuffer->release();
1652 mVideoBuffer = NULL;
1653 continue;
1654 }
1655
Andreas Huber27366fc2009-11-20 09:32:46 -08001656 break;
1657 }
Andreas Huberfddf5d92011-06-07 15:52:25 -07001658
1659 {
1660 Mutex::Autolock autoLock(mStatsLock);
1661 ++mStats.mNumVideoFramesDecoded;
1662 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001663 }
1664
1665 int64_t timeUs;
1666 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1667
Andreas Huber3a785fe2011-03-14 10:55:40 -07001668 mLastVideoTimeUs = timeUs;
1669
Andreas Hubera2c29972011-02-24 12:05:40 -08001670 if (mSeeking == SEEK_VIDEO_ONLY) {
1671 if (mSeekTimeUs > timeUs) {
1672 LOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
1673 mSeekTimeUs, timeUs);
1674 }
1675 }
1676
Andreas Huber252573c2010-03-26 10:17:17 -07001677 {
1678 Mutex::Autolock autoLock(mMiscStateLock);
1679 mVideoTimeUs = timeUs;
1680 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001681
Andreas Hubera2c29972011-02-24 12:05:40 -08001682 SeekType wasSeeking = mSeeking;
Andreas Huber4d450a82010-10-19 09:34:44 -07001683 finishSeekIfNecessary(timeUs);
Andreas Huber27366fc2009-11-20 09:32:46 -08001684
Andreas Huberce8a1012011-02-11 13:09:36 -08001685 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1686 status_t err = startAudioPlayer_l();
1687 if (err != OK) {
Andreas Huber232d5f22011-07-14 13:02:47 -07001688 LOGE("Starting the audio player failed w/ err %d", err);
Andreas Huberce8a1012011-02-11 13:09:36 -08001689 return;
1690 }
1691 }
1692
Gloria Wangc6091dd2011-05-03 15:59:03 -07001693 if ((mFlags & TEXTPLAYER_STARTED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
1694 mTextPlayer->resume();
Andreas Huberfddf5d92011-06-07 15:52:25 -07001695 modifyFlags(TEXT_RUNNING, SET);
Gloria Wangc6091dd2011-05-03 15:59:03 -07001696 }
1697
Andreas Huber84584472011-09-08 11:33:47 -07001698 TimeSource *ts =
1699 ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
1700 ? &mSystemTimeSource : mTimeSource;
Andreas Huber971305d2010-07-07 13:35:27 -07001701
Andreas Huber27366fc2009-11-20 09:32:46 -08001702 if (mFlags & FIRST_FRAME) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001703 modifyFlags(FIRST_FRAME, CLEAR);
James Dong5bc53032011-08-11 17:38:35 -07001704 mSinceLastDropped = 0;
Andreas Huber971305d2010-07-07 13:35:27 -07001705 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001706 }
1707
1708 int64_t realTimeUs, mediaTimeUs;
Andreas Huber971305d2010-07-07 13:35:27 -07001709 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
Andreas Huber27366fc2009-11-20 09:32:46 -08001710 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1711 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1712 }
1713
Andreas Hubera2c29972011-02-24 12:05:40 -08001714 if (wasSeeking == SEEK_VIDEO_ONLY) {
1715 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1716
1717 int64_t latenessUs = nowUs - timeUs;
1718
1719 if (latenessUs > 0) {
1720 LOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
1721 }
1722 }
1723
1724 if (wasSeeking == NO_SEEK) {
Andreas Huber614d22c2010-10-29 15:47:52 -07001725 // Let's display the first frame after seeking right away.
Andreas Huberf88f8442010-08-10 11:18:36 -07001726
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001727 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001728
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001729 int64_t latenessUs = nowUs - timeUs;
1730
Andreas Hubera2c29972011-02-24 12:05:40 -08001731 if (latenessUs > 500000ll
Andreas Hubera2c29972011-02-24 12:05:40 -08001732 && mAudioPlayer != NULL
1733 && mAudioPlayer->getMediaTimeMapping(
1734 &realTimeUs, &mediaTimeUs)) {
1735 LOGI("we're much too late (%.2f secs), video skipping ahead",
1736 latenessUs / 1E6);
1737
1738 mVideoBuffer->release();
1739 mVideoBuffer = NULL;
1740
1741 mSeeking = SEEK_VIDEO_ONLY;
1742 mSeekTimeUs = mediaTimeUs;
1743
1744 postVideoEvent_l();
1745 return;
1746 }
1747
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001748 if (latenessUs > 40000) {
1749 // We're more than 40ms late.
Steve Block71f2cf12011-10-20 11:56:00 +01001750 ALOGV("we're late by %lld us (%.2f secs)",
Andreas Huber2334d822011-04-01 13:27:42 -07001751 latenessUs, latenessUs / 1E6);
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001752
James Dong5bc53032011-08-11 17:38:35 -07001753 if (!(mFlags & SLOW_DECODER_HACK)
1754 || mSinceLastDropped > FRAME_DROP_FREQ)
Andreas Huberfddf5d92011-06-07 15:52:25 -07001755 {
Steve Block71f2cf12011-10-20 11:56:00 +01001756 ALOGV("we're late by %lld us (%.2f secs) dropping "
James Dong5bc53032011-08-11 17:38:35 -07001757 "one after %d frames",
1758 latenessUs, latenessUs / 1E6, mSinceLastDropped);
Andreas Huberfddf5d92011-06-07 15:52:25 -07001759
James Dong5bc53032011-08-11 17:38:35 -07001760 mSinceLastDropped = 0;
1761 mVideoBuffer->release();
1762 mVideoBuffer = NULL;
1763
1764 {
1765 Mutex::Autolock autoLock(mStatsLock);
1766 ++mStats.mNumVideoFramesDropped;
1767 }
1768
1769 postVideoEvent_l();
1770 return;
1771 }
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001772 }
1773
1774 if (latenessUs < -10000) {
1775 // We're more than 10ms early.
1776
1777 postVideoEvent_l(10000);
pmehendale28f939d2011-01-06 14:43:49 -08001778 return;
1779 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001780 }
1781
Gloria Wang91784c992011-08-09 15:29:34 -07001782 if ((mNativeWindow != NULL)
1783 && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001784 mVideoRendererIsPreview = false;
1785
Andreas Huber7085b6842010-02-03 16:02:02 -08001786 initRenderer_l();
1787 }
1788
1789 if (mVideoRenderer != NULL) {
James Dong5bc53032011-08-11 17:38:35 -07001790 mSinceLastDropped++;
Andreas Huber7085b6842010-02-03 16:02:02 -08001791 mVideoRenderer->render(mVideoBuffer);
1792 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001793
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001794 mVideoBuffer->release();
Andreas Huber27366fc2009-11-20 09:32:46 -08001795 mVideoBuffer = NULL;
1796
Andreas Hubera2c29972011-02-24 12:05:40 -08001797 if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001798 modifyFlags(SEEK_PREVIEW, CLEAR);
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001799 return;
1800 }
1801
Andreas Huber27366fc2009-11-20 09:32:46 -08001802 postVideoEvent_l();
1803}
1804
1805void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1806 if (mVideoEventPending) {
1807 return;
1808 }
1809
1810 mVideoEventPending = true;
1811 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1812}
1813
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001814void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001815 if (mStreamDoneEventPending) {
1816 return;
1817 }
1818 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001819
1820 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -08001821 mQueue.postEvent(mStreamDoneEvent);
1822}
1823
Andreas Huberb9e63832010-01-26 16:20:10 -08001824void AwesomePlayer::postBufferingEvent_l() {
Andreas Huberb9e63832010-01-26 16:20:10 -08001825 if (mBufferingEventPending) {
1826 return;
1827 }
1828 mBufferingEventPending = true;
1829 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1830}
1831
Andreas Huber52c78322011-01-11 15:05:28 -08001832void AwesomePlayer::postVideoLagEvent_l() {
1833 if (mVideoLagEventPending) {
1834 return;
1835 }
1836 mVideoLagEventPending = true;
1837 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1838}
1839
Andreas Huber67a041f2011-09-01 11:39:11 -07001840void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) {
1841 Mutex::Autolock autoLock(mAudioLock);
Andreas Huber70d10c02010-02-03 11:37:29 -08001842 if (mAudioStatusEventPending) {
1843 return;
1844 }
1845 mAudioStatusEventPending = true;
Andreas Huber4dc482d2011-03-22 10:31:21 -07001846 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
Andreas Huber70d10c02010-02-03 11:37:29 -08001847}
1848
1849void AwesomePlayer::onCheckAudioStatus() {
Andreas Huber67a041f2011-09-01 11:39:11 -07001850 {
1851 Mutex::Autolock autoLock(mAudioLock);
1852 if (!mAudioStatusEventPending) {
1853 // Event was dispatched and while we were blocking on the mutex,
1854 // has already been cancelled.
1855 return;
1856 }
1857
1858 mAudioStatusEventPending = false;
Andreas Huberc0178f12010-02-17 15:58:57 -08001859 }
1860
Andreas Huber67a041f2011-09-01 11:39:11 -07001861 Mutex::Autolock autoLock(mLock);
Andreas Huber70d10c02010-02-03 11:37:29 -08001862
1863 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1864 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001865
1866 if (!mSeekNotificationSent) {
1867 notifyListener_l(MEDIA_SEEK_COMPLETE);
1868 mSeekNotificationSent = true;
1869 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001870
Andreas Hubera2c29972011-02-24 12:05:40 -08001871 mSeeking = NO_SEEK;
Andreas Huber70d10c02010-02-03 11:37:29 -08001872 }
1873
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001874 status_t finalStatus;
1875 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001876 mWatchForAudioEOS = false;
Andreas Huberfddf5d92011-06-07 15:52:25 -07001877 modifyFlags(AUDIO_AT_EOS, SET);
1878 modifyFlags(FIRST_FRAME, SET);
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001879 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001880 }
Andreas Huber70d10c02010-02-03 11:37:29 -08001881}
1882
Andreas Huber6be780e2010-02-08 14:40:30 -08001883status_t AwesomePlayer::prepare() {
1884 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001885 return prepare_l();
1886}
Andreas Huber6be780e2010-02-08 14:40:30 -08001887
Andreas Huberffdf4782010-02-09 14:05:43 -08001888status_t AwesomePlayer::prepare_l() {
1889 if (mFlags & PREPARED) {
1890 return OK;
1891 }
1892
1893 if (mFlags & PREPARING) {
1894 return UNKNOWN_ERROR;
1895 }
1896
1897 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001898 status_t err = prepareAsync_l();
1899
1900 if (err != OK) {
1901 return err;
1902 }
1903
Andreas Huberffdf4782010-02-09 14:05:43 -08001904 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001905 mPreparedCondition.wait(mLock);
1906 }
1907
Andreas Huberffdf4782010-02-09 14:05:43 -08001908 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001909}
1910
1911status_t AwesomePlayer::prepareAsync() {
1912 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001913
1914 if (mFlags & PREPARING) {
1915 return UNKNOWN_ERROR; // async prepare already pending
1916 }
1917
1918 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001919 return prepareAsync_l();
1920}
1921
1922status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001923 if (mFlags & PREPARING) {
1924 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001925 }
1926
Andreas Huber406a18b2010-02-18 16:45:13 -08001927 if (!mQueueStarted) {
1928 mQueue.start();
1929 mQueueStarted = true;
1930 }
1931
Andreas Huberfddf5d92011-06-07 15:52:25 -07001932 modifyFlags(PREPARING, SET);
Andreas Huber6be780e2010-02-08 14:40:30 -08001933 mAsyncPrepareEvent = new AwesomeEvent(
1934 this, &AwesomePlayer::onPrepareAsyncEvent);
1935
1936 mQueue.postEvent(mAsyncPrepareEvent);
1937
1938 return OK;
1939}
1940
Andreas Huberffdf4782010-02-09 14:05:43 -08001941status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001942 sp<DataSource> dataSource;
1943
Andreas Huber77d8dc22011-04-21 10:06:43 -07001944 bool isWidevineStreaming = false;
1945 if (!strncasecmp("widevine://", mUri.string(), 11)) {
1946 isWidevineStreaming = true;
1947
1948 String8 newURI = String8("http://");
1949 newURI.append(mUri.string() + 11);
1950
1951 mUri = newURI;
1952 }
1953
Andreas Huberb8e651a2011-12-05 11:34:43 -08001954 AString sniffedMIME;
1955
Andreas Huber118a1502011-02-17 13:35:08 -08001956 if (!strncasecmp("http://", mUri.string(), 7)
Andreas Huber77d8dc22011-04-21 10:06:43 -07001957 || !strncasecmp("https://", mUri.string(), 8)
1958 || isWidevineStreaming) {
Andreas Huber5f5719e2011-03-08 15:59:28 -08001959 mConnectingDataSource = HTTPBase::Create(
1960 (mFlags & INCOGNITO)
1961 ? HTTPBase::kFlagIncognito
1962 : 0);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001963
Andreas Huber603d7392011-06-30 15:47:02 -07001964 if (mUIDValid) {
1965 mConnectingDataSource->setUID(mUID);
1966 }
1967
Andreas Huber7f325942011-10-07 13:40:45 -07001968 String8 cacheConfig;
1969 bool disconnectAtHighwatermark;
1970 NuCachedSource2::RemoveCacheSpecificHeaders(
1971 &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
1972
Andreas Huberedbb4d82010-03-12 08:59:22 -08001973 mLock.unlock();
Andreas Huber3a53dc52010-06-11 09:57:46 -07001974 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001975 mLock.lock();
1976
1977 if (err != OK) {
1978 mConnectingDataSource.clear();
1979
1980 LOGI("mConnectingDataSource->connect() returned %d", err);
1981 return err;
1982 }
1983
Andreas Huber77d8dc22011-04-21 10:06:43 -07001984 if (!isWidevineStreaming) {
1985 // The widevine extractor does its own caching.
1986
Andreas Huber4d61f602010-06-10 11:17:50 -07001987#if 0
Andreas Huber77d8dc22011-04-21 10:06:43 -07001988 mCachedSource = new NuCachedSource2(
1989 new ThrottledSource(
1990 mConnectingDataSource, 50 * 1024 /* bytes/sec */));
Andreas Huber4d61f602010-06-10 11:17:50 -07001991#else
Andreas Huber7f325942011-10-07 13:40:45 -07001992 mCachedSource = new NuCachedSource2(
1993 mConnectingDataSource,
1994 cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
1995 disconnectAtHighwatermark);
Andreas Huber4d61f602010-06-10 11:17:50 -07001996#endif
Andreas Huber4d61f602010-06-10 11:17:50 -07001997
Andreas Huber77d8dc22011-04-21 10:06:43 -07001998 dataSource = mCachedSource;
1999 } else {
2000 dataSource = mConnectingDataSource;
Andreas Huber96346652011-01-19 15:07:19 -08002001 }
2002
Andreas Huberedbb4d82010-03-12 08:59:22 -08002003 mConnectingDataSource.clear();
Andreas Huber4d61f602010-06-10 11:17:50 -07002004
Andreas Hubera2e57ca2011-03-30 11:15:27 -07002005 String8 contentType = dataSource->getMIMEType();
Andreas Huber96346652011-01-19 15:07:19 -08002006
Andreas Hubera2e57ca2011-03-30 11:15:27 -07002007 if (strncasecmp(contentType.string(), "audio/", 6)) {
2008 // We're not doing this for streams that appear to be audio-only
2009 // streams to ensure that even low bandwidth streams start
2010 // playing back fairly instantly.
Andreas Huber96346652011-01-19 15:07:19 -08002011
Andreas Hubera2e57ca2011-03-30 11:15:27 -07002012 // We're going to prefill the cache before trying to instantiate
2013 // the extractor below, as the latter is an operation that otherwise
2014 // could block on the datasource for a significant amount of time.
2015 // During that time we'd be unable to abort the preparation phase
2016 // without this prefill.
James Dongba43d422011-05-19 08:49:09 -07002017 if (mCachedSource != NULL) {
2018 // We're going to prefill the cache before trying to instantiate
2019 // the extractor below, as the latter is an operation that otherwise
2020 // could block on the datasource for a significant amount of time.
2021 // During that time we'd be unable to abort the preparation phase
2022 // without this prefill.
Andreas Huber96346652011-01-19 15:07:19 -08002023
James Dongba43d422011-05-19 08:49:09 -07002024 mLock.unlock();
Andreas Hubera2e57ca2011-03-30 11:15:27 -07002025
Andreas Huber7dea9aa2011-12-07 12:50:47 -08002026 // Initially make sure we have at least 192 KB for the sniff
Andreas Huberb8e651a2011-12-05 11:34:43 -08002027 // to complete without blocking.
Andreas Huber7dea9aa2011-12-07 12:50:47 -08002028 static const size_t kMinBytesForSniffing = 192 * 1024;
Andreas Huberb8e651a2011-12-05 11:34:43 -08002029
2030 off64_t metaDataSize = -1ll;
James Dongba43d422011-05-19 08:49:09 -07002031 for (;;) {
2032 status_t finalStatus;
2033 size_t cachedDataRemaining =
2034 mCachedSource->approxDataRemaining(&finalStatus);
Andreas Hubera2e57ca2011-03-30 11:15:27 -07002035
Andreas Huberb8e651a2011-12-05 11:34:43 -08002036 if (finalStatus != OK
2037 || (metaDataSize >= 0
2038 && cachedDataRemaining >= metaDataSize)
James Dongba43d422011-05-19 08:49:09 -07002039 || (mFlags & PREPARE_CANCELLED)) {
2040 break;
2041 }
2042
Andreas Huber68d2f952011-12-05 13:30:52 -08002043 ALOGV("now cached %d bytes of data", cachedDataRemaining);
Andreas Huberb8e651a2011-12-05 11:34:43 -08002044
2045 if (metaDataSize < 0
2046 && cachedDataRemaining >= kMinBytesForSniffing) {
2047 String8 tmp;
2048 float confidence;
2049 sp<AMessage> meta;
2050 if (!dataSource->sniff(&tmp, &confidence, &meta)) {
2051 mLock.lock();
2052 return UNKNOWN_ERROR;
2053 }
2054
2055 // We successfully identified the file's extractor to
2056 // be, remember this mime type so we don't have to
2057 // sniff it again when we call MediaExtractor::Create()
2058 // below.
2059 sniffedMIME = tmp.string();
2060
2061 if (meta == NULL
2062 || !meta->findInt64(
2063 "meta-data-size", &metaDataSize)) {
2064 metaDataSize = kHighWaterMarkBytes;
2065 }
2066
2067 CHECK_GE(metaDataSize, 0ll);
Andreas Huber68d2f952011-12-05 13:30:52 -08002068 ALOGV("metaDataSize = %lld bytes", metaDataSize);
Andreas Huberb8e651a2011-12-05 11:34:43 -08002069 }
2070
James Dongba43d422011-05-19 08:49:09 -07002071 usleep(200000);
Andreas Hubera2e57ca2011-03-30 11:15:27 -07002072 }
2073
James Dongba43d422011-05-19 08:49:09 -07002074 mLock.lock();
Andreas Huber96346652011-01-19 15:07:19 -08002075 }
2076
James Dongba43d422011-05-19 08:49:09 -07002077 if (mFlags & PREPARE_CANCELLED) {
2078 LOGI("Prepare cancelled while waiting for initial cache fill.");
2079 return UNKNOWN_ERROR;
2080 }
Andreas Huber96346652011-01-19 15:07:19 -08002081 }
Andreas Huberedbb4d82010-03-12 08:59:22 -08002082 } else {
2083 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
2084 }
Andreas Huberffdf4782010-02-09 14:05:43 -08002085
2086 if (dataSource == NULL) {
2087 return UNKNOWN_ERROR;
2088 }
2089
Andreas Huber77d8dc22011-04-21 10:06:43 -07002090 sp<MediaExtractor> extractor;
Andreas Huberffdf4782010-02-09 14:05:43 -08002091
Andreas Huber77d8dc22011-04-21 10:06:43 -07002092 if (isWidevineStreaming) {
2093 String8 mimeType;
2094 float confidence;
2095 sp<AMessage> dummy;
Jeff Tinkerd0d19db2011-12-07 20:23:20 -08002096 bool success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
Andreas Huber77d8dc22011-04-21 10:06:43 -07002097
2098 if (!success
2099 || strcasecmp(
2100 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
2101 return ERROR_UNSUPPORTED;
2102 }
2103
Jeff Tinkerd0d19db2011-12-07 20:23:20 -08002104 dataSource->DrmInitialization();
2105
Andreas Huber77d8dc22011-04-21 10:06:43 -07002106 mWVMExtractor = new WVMExtractor(dataSource);
2107 mWVMExtractor->setAdaptiveStreamingMode(true);
Jeff Tinker9f704f62011-12-09 08:57:23 -08002108 mWVMExtractor->setDrmFlag(true);
Andreas Huber77d8dc22011-04-21 10:06:43 -07002109 extractor = mWVMExtractor;
2110 } else {
Andreas Huberb8e651a2011-12-05 11:34:43 -08002111 extractor = MediaExtractor::Create(
2112 dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
Andreas Huber77d8dc22011-04-21 10:06:43 -07002113
2114 if (extractor == NULL) {
2115 return UNKNOWN_ERROR;
2116 }
Andreas Huberffdf4782010-02-09 14:05:43 -08002117 }
2118
James Dongaadbd802011-12-08 19:31:59 -08002119 if (extractor->getDrmFlag()) {
2120 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
Gloria Wangae775272011-02-24 16:40:57 -08002121
James Dongaadbd802011-12-08 19:31:59 -08002122 if (mDecryptHandle != NULL) {
2123 CHECK(mDrmManagerClient);
2124 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
2125 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
2126 }
Gloria Wangc2c22e72010-11-01 15:53:16 -07002127 }
Gloria Wangd5770912010-06-22 13:55:38 -07002128 }
2129
Andreas Huber77d8dc22011-04-21 10:06:43 -07002130 status_t err = setDataSource_l(extractor);
2131
2132 if (err != OK) {
2133 mWVMExtractor.clear();
2134
2135 return err;
2136 }
2137
2138 return OK;
Andreas Huberffdf4782010-02-09 14:05:43 -08002139}
2140
Andreas Huber3ac94ef2010-03-05 10:42:10 -08002141void AwesomePlayer::abortPrepare(status_t err) {
2142 CHECK(err != OK);
2143
2144 if (mIsAsyncPrepare) {
2145 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2146 }
2147
2148 mPrepareResult = err;
Andreas Huberfddf5d92011-06-07 15:52:25 -07002149 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08002150 mAsyncPrepareEvent = NULL;
2151 mPreparedCondition.broadcast();
2152}
2153
Andreas Huberf71daba2010-03-24 09:24:40 -07002154// static
2155bool AwesomePlayer::ContinuePreparation(void *cookie) {
2156 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
2157
2158 return (me->mFlags & PREPARE_CANCELLED) == 0;
2159}
2160
Andreas Huber6be780e2010-02-08 14:40:30 -08002161void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber87ab9cd2010-09-03 13:20:33 -07002162 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08002163
Andreas Huber87ab9cd2010-09-03 13:20:33 -07002164 if (mFlags & PREPARE_CANCELLED) {
2165 LOGI("prepare was cancelled before doing anything");
2166 abortPrepare(UNKNOWN_ERROR);
2167 return;
2168 }
2169
2170 if (mUri.size() > 0) {
2171 status_t err = finishSetDataSource_l();
2172
2173 if (err != OK) {
2174 abortPrepare(err);
Andreas Huberedbb4d82010-03-12 08:59:22 -08002175 return;
2176 }
Andreas Huber6be780e2010-02-08 14:40:30 -08002177 }
2178
Andreas Huber87ab9cd2010-09-03 13:20:33 -07002179 if (mVideoTrack != NULL && mVideoSource == NULL) {
2180 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08002181
Andreas Huber87ab9cd2010-09-03 13:20:33 -07002182 if (err != OK) {
2183 abortPrepare(err);
2184 return;
2185 }
2186 }
2187
2188 if (mAudioTrack != NULL && mAudioSource == NULL) {
2189 status_t err = initAudioDecoder();
2190
2191 if (err != OK) {
2192 abortPrepare(err);
2193 return;
2194 }
2195 }
2196
Andreas Huberfddf5d92011-06-07 15:52:25 -07002197 modifyFlags(PREPARING_CONNECTED, SET);
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07002198
Andreas Hubera6be6dc2011-10-11 15:24:07 -07002199 if (isStreamingHTTP()) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -07002200 postBufferingEvent_l();
2201 } else {
2202 finishAsyncPrepare_l();
2203 }
2204}
2205
2206void AwesomePlayer::finishAsyncPrepare_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08002207 if (mIsAsyncPrepare) {
Andreas Hubere3c01832010-08-16 08:49:37 -07002208 if (mVideoSource == NULL) {
Andreas Huberffdf4782010-02-09 14:05:43 -08002209 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
2210 } else {
Andreas Hubere3c01832010-08-16 08:49:37 -07002211 notifyVideoSize_l();
Andreas Huberffdf4782010-02-09 14:05:43 -08002212 }
2213
2214 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08002215 }
2216
Andreas Huberffdf4782010-02-09 14:05:43 -08002217 mPrepareResult = OK;
Andreas Huberfddf5d92011-06-07 15:52:25 -07002218 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2219 modifyFlags(PREPARED, SET);
Andreas Huber6be780e2010-02-08 14:40:30 -08002220 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08002221 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -08002222}
2223
Andreas Huber62f7ffe2010-05-06 10:18:05 -07002224uint32_t AwesomePlayer::flags() const {
2225 return mExtractorFlags;
2226}
2227
Andreas Huber4dc482d2011-03-22 10:31:21 -07002228void AwesomePlayer::postAudioEOS(int64_t delayUs) {
Andreas Huber67a041f2011-09-01 11:39:11 -07002229 postCheckAudioStatusEvent(delayUs);
Andreas Huber2b359ed2010-09-28 11:56:39 -07002230}
2231
2232void AwesomePlayer::postAudioSeekComplete() {
Andreas Huber67a041f2011-09-01 11:39:11 -07002233 postCheckAudioStatusEvent(0);
Andreas Huber2b359ed2010-09-28 11:56:39 -07002234}
2235
Gloria Wangd01ec6e2011-04-25 17:28:22 -07002236status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
Gloria Wang13bc8cd2011-05-11 11:24:09 -07002237 switch (key) {
2238 case KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX:
2239 {
2240 Mutex::Autolock autoLock(mTimedTextLock);
2241 return setTimedTextTrackIndex(request.readInt32());
2242 }
2243 case KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE:
2244 {
2245 Mutex::Autolock autoLock(mTimedTextLock);
2246 if (mTextPlayer == NULL) {
2247 mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
2248 }
2249
2250 return mTextPlayer->setParameter(key, request);
2251 }
James Donga9d0feb2011-05-25 19:37:03 -07002252 case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
2253 {
2254 return setCacheStatCollectFreq(request);
2255 }
Gloria Wang13bc8cd2011-05-11 11:24:09 -07002256 default:
2257 {
2258 return ERROR_UNSUPPORTED;
2259 }
Gloria Wangc6091dd2011-05-03 15:59:03 -07002260 }
Gloria Wangd01ec6e2011-04-25 17:28:22 -07002261}
2262
James Donga9d0feb2011-05-25 19:37:03 -07002263status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
2264 if (mCachedSource != NULL) {
2265 int32_t freqMs = request.readInt32();
2266 LOGD("Request to keep cache stats in the past %d ms",
2267 freqMs);
2268 return mCachedSource->setCacheStatCollectFreq(freqMs);
2269 }
2270 return ERROR_UNSUPPORTED;
2271}
2272
Gloria Wangd01ec6e2011-04-25 17:28:22 -07002273status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
Glenn Kasten6ff9b812011-07-25 09:26:22 -07002274 switch (key) {
2275 case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
2276 {
2277 int32_t channelCount;
2278 if (mAudioTrack == 0 ||
2279 !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
2280 channelCount = 0;
2281 }
2282 reply->writeInt32(channelCount);
2283 }
2284 return OK;
2285 default:
2286 {
2287 return ERROR_UNSUPPORTED;
2288 }
2289 }
Gloria Wangd01ec6e2011-04-25 17:28:22 -07002290}
Andreas Huber27366fc2009-11-20 09:32:46 -08002291
Andreas Huber77d8dc22011-04-21 10:06:43 -07002292bool AwesomePlayer::isStreamingHTTP() const {
2293 return mCachedSource != NULL || mWVMExtractor != NULL;
2294}
2295
Andreas Huberfddf5d92011-06-07 15:52:25 -07002296status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
2297 Mutex::Autolock autoLock(mStatsLock);
2298
2299 FILE *out = fdopen(dup(fd), "w");
2300
2301 fprintf(out, " AwesomePlayer\n");
2302 if (mStats.mFd < 0) {
2303 fprintf(out, " URI(%s)", mStats.mURI.string());
2304 } else {
2305 fprintf(out, " fd(%d)", mStats.mFd);
2306 }
2307
2308 fprintf(out, ", flags(0x%08x)", mStats.mFlags);
2309
2310 if (mStats.mBitrate >= 0) {
2311 fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
2312 }
2313
2314 fprintf(out, "\n");
2315
2316 for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
2317 const TrackStat &stat = mStats.mTracks.itemAt(i);
2318
2319 fprintf(out, " Track %d\n", i + 1);
2320 fprintf(out, " MIME(%s)", stat.mMIME.string());
2321
2322 if (!stat.mDecoderName.isEmpty()) {
2323 fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
2324 }
2325
2326 fprintf(out, "\n");
2327
2328 if ((ssize_t)i == mStats.mVideoTrackIndex) {
2329 fprintf(out,
2330 " videoDimensions(%d x %d), "
2331 "numVideoFramesDecoded(%lld), "
2332 "numVideoFramesDropped(%lld)\n",
2333 mStats.mVideoWidth,
2334 mStats.mVideoHeight,
2335 mStats.mNumVideoFramesDecoded,
2336 mStats.mNumVideoFramesDropped);
2337 }
2338 }
2339
2340 fclose(out);
2341 out = NULL;
2342
2343 return OK;
2344}
2345
2346void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
2347 switch (mode) {
2348 case SET:
2349 mFlags |= value;
2350 break;
2351 case CLEAR:
2352 mFlags &= ~value;
2353 break;
2354 case ASSIGN:
2355 mFlags = value;
2356 break;
2357 default:
2358 TRESPASS();
2359 }
2360
2361 {
2362 Mutex::Autolock autoLock(mStatsLock);
2363 mStats.mFlags = mFlags;
2364 }
2365}
2366
Andreas Huber27366fc2009-11-20 09:32:46 -08002367} // namespace android