blob: 6fce890b5cc46960964439bb7d2e15f169e0afd7 [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)) {
Steve Block6215d3f2012-01-04 20:05:49 +0000283 ALOGI("setDataSource_l('%s')", mUri.string());
Andreas Huber53182c42011-02-24 14:42:48 -0800284 } else {
Steve Block6215d3f2012-01-04 20:05:49 +0000285 ALOGI("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 Dongd70c64d2011-12-14 10:57:05 -0800338 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
339 if (mDecryptHandle != NULL) {
340 CHECK(mDrmManagerClient);
341 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
342 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
Gloria Wangadc4d9c2011-02-08 13:24:08 -0800343 }
Gloria Wangd5770912010-06-22 13:55:38 -0700344 }
345
Andreas Huber27366fc2009-11-20 09:32:46 -0800346 return setDataSource_l(extractor);
347}
348
349status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700350 // Attempt to approximate overall stream bitrate by summing all
351 // tracks' individual bitrates, if not all of them advertise bitrate,
352 // we have to fail.
353
354 int64_t totalBitRate = 0;
355
356 for (size_t i = 0; i < extractor->countTracks(); ++i) {
357 sp<MetaData> meta = extractor->getTrackMetaData(i);
358
359 int32_t bitrate;
360 if (!meta->findInt32(kKeyBitRate, &bitrate)) {
Andreas Huberfddf5d92011-06-07 15:52:25 -0700361 const char *mime;
362 CHECK(meta->findCString(kKeyMIMEType, &mime));
Steve Block71f2cf12011-10-20 11:56:00 +0100363 ALOGV("track of type '%s' does not publish bitrate", mime);
Andreas Huberfddf5d92011-06-07 15:52:25 -0700364
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700365 totalBitRate = -1;
366 break;
367 }
368
369 totalBitRate += bitrate;
370 }
371
372 mBitrate = totalBitRate;
373
Steve Block71f2cf12011-10-20 11:56:00 +0100374 ALOGV("mBitrate = %lld bits/sec", mBitrate);
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700375
Andreas Huberfddf5d92011-06-07 15:52:25 -0700376 {
377 Mutex::Autolock autoLock(mStatsLock);
378 mStats.mBitrate = mBitrate;
379 mStats.mTracks.clear();
380 mStats.mAudioTrackIndex = -1;
381 mStats.mVideoTrackIndex = -1;
382 }
383
Andreas Huber27366fc2009-11-20 09:32:46 -0800384 bool haveAudio = false;
385 bool haveVideo = false;
386 for (size_t i = 0; i < extractor->countTracks(); ++i) {
387 sp<MetaData> meta = extractor->getTrackMetaData(i);
388
Andreas Huberd2b76d72011-10-26 11:22:40 -0700389 const char *_mime;
390 CHECK(meta->findCString(kKeyMIMEType, &_mime));
Andreas Huber27366fc2009-11-20 09:32:46 -0800391
Andreas Huberd2b76d72011-10-26 11:22:40 -0700392 String8 mime = String8(_mime);
393
394 if (!haveVideo && !strncasecmp(mime.string(), "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800395 setVideoSource(extractor->getTrack(i));
396 haveVideo = true;
James Dong08adfd22011-01-16 11:30:13 -0800397
398 // Set the presentation/display size
399 int32_t displayWidth, displayHeight;
400 bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
401 if (success) {
402 success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
403 }
404 if (success) {
405 mDisplayWidth = displayWidth;
406 mDisplayHeight = displayHeight;
407 }
408
Andreas Huberfddf5d92011-06-07 15:52:25 -0700409 {
410 Mutex::Autolock autoLock(mStatsLock);
411 mStats.mVideoTrackIndex = mStats.mTracks.size();
412 mStats.mTracks.push();
413 TrackStat *stat =
414 &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
Andreas Huberd2b76d72011-10-26 11:22:40 -0700415 stat->mMIME = mime.string();
Andreas Huberfddf5d92011-06-07 15:52:25 -0700416 }
Andreas Huberd2b76d72011-10-26 11:22:40 -0700417 } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800418 setAudioSource(extractor->getTrack(i));
419 haveAudio = true;
Andreas Huber9fee0b22010-09-03 14:09:21 -0700420
Andreas Huberfddf5d92011-06-07 15:52:25 -0700421 {
422 Mutex::Autolock autoLock(mStatsLock);
423 mStats.mAudioTrackIndex = mStats.mTracks.size();
424 mStats.mTracks.push();
425 TrackStat *stat =
426 &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
Andreas Huberd2b76d72011-10-26 11:22:40 -0700427 stat->mMIME = mime.string();
Andreas Huberfddf5d92011-06-07 15:52:25 -0700428 }
429
Andreas Huberd2b76d72011-10-26 11:22:40 -0700430 if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_AUDIO_VORBIS)) {
Andreas Huber1913c1a2010-10-04 11:09:31 -0700431 // Only do this for vorbis audio, none of the other audio
432 // formats even support this ringtone specific hack and
433 // retrieving the metadata on some extractors may turn out
434 // to be very expensive.
435 sp<MetaData> fileMeta = extractor->getMetaData();
436 int32_t loop;
437 if (fileMeta != NULL
438 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
Andreas Huberfddf5d92011-06-07 15:52:25 -0700439 modifyFlags(AUTO_LOOPING, SET);
Andreas Huber1913c1a2010-10-04 11:09:31 -0700440 }
Andreas Huber9fee0b22010-09-03 14:09:21 -0700441 }
Andreas Huberd2b76d72011-10-26 11:22:40 -0700442 } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
Gloria Wangc6091dd2011-05-03 15:59:03 -0700443 addTextSource(extractor->getTrack(i));
Andreas Huber27366fc2009-11-20 09:32:46 -0800444 }
445 }
446
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700447 if (!haveAudio && !haveVideo) {
448 return UNKNOWN_ERROR;
449 }
450
451 mExtractorFlags = extractor->flags();
452
453 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800454}
455
456void AwesomePlayer::reset() {
457 Mutex::Autolock autoLock(mLock);
458 reset_l();
459}
460
461void AwesomePlayer::reset_l() {
James Dong08adfd22011-01-16 11:30:13 -0800462 mDisplayWidth = 0;
463 mDisplayHeight = 0;
Andreas Huber90c65652011-01-04 10:19:13 -0800464
Gloria Wangd5770912010-06-22 13:55:38 -0700465 if (mDecryptHandle != NULL) {
466 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
467 Playback::STOP, 0);
Gloria Wangd5770912010-06-22 13:55:38 -0700468 mDecryptHandle = NULL;
469 mDrmManagerClient = NULL;
470 }
471
Gloria Wangd211f412011-02-19 18:37:57 -0800472 if (mFlags & PLAYING) {
473 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
474 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
475 params |= IMediaPlayerService::kBatteryDataTrackAudio;
476 }
477 if (mVideoSource != NULL) {
478 params |= IMediaPlayerService::kBatteryDataTrackVideo;
479 }
480 addBatteryData(params);
481 }
482
Andreas Huberedbb4d82010-03-12 08:59:22 -0800483 if (mFlags & PREPARING) {
Andreas Huberfddf5d92011-06-07 15:52:25 -0700484 modifyFlags(PREPARE_CANCELLED, SET);
Andreas Huberedbb4d82010-03-12 08:59:22 -0800485 if (mConnectingDataSource != NULL) {
Steve Block6215d3f2012-01-04 20:05:49 +0000486 ALOGI("interrupting the connection process");
Andreas Huberedbb4d82010-03-12 08:59:22 -0800487 mConnectingDataSource->disconnect();
488 }
Andreas Hubereaf2c5a2010-10-19 12:18:51 -0700489
490 if (mFlags & PREPARING_CONNECTED) {
491 // We are basically done preparing, we're just buffering
492 // enough data to start playback, we can safely interrupt that.
493 finishAsyncPrepare_l();
494 }
Andreas Huberedbb4d82010-03-12 08:59:22 -0800495 }
496
Andreas Huberffdf4782010-02-09 14:05:43 -0800497 while (mFlags & PREPARING) {
498 mPreparedCondition.wait(mLock);
499 }
500
Andreas Huber27366fc2009-11-20 09:32:46 -0800501 cancelPlayerEvents();
502
Andreas Huber77d8dc22011-04-21 10:06:43 -0700503 mWVMExtractor.clear();
Andreas Huber4d61f602010-06-10 11:17:50 -0700504 mCachedSource.clear();
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800505 mAudioTrack.clear();
506 mVideoTrack.clear();
507
Andreas Huberba7ec912010-02-12 10:42:02 -0800508 // Shutdown audio first, so that the respone to the reset request
509 // appears to happen instantaneously as far as the user is concerned
510 // If we did this later, audio would continue playing while we
511 // shutdown the video-related resources and the player appear to
512 // not be as responsive to a reset request.
Gloria Wange28857c2011-08-31 10:24:18 -0700513 if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
514 && mAudioSource != NULL) {
Andreas Huberedbb4d82010-03-12 08:59:22 -0800515 // If we had an audio player, it would have effectively
516 // taken possession of the audio source and stopped it when
517 // _it_ is stopped. Otherwise this is still our responsibility.
518 mAudioSource->stop();
519 }
Andreas Huberba7ec912010-02-12 10:42:02 -0800520 mAudioSource.clear();
521
Andreas Huberba7ec912010-02-12 10:42:02 -0800522 mTimeSource = NULL;
523
524 delete mAudioPlayer;
525 mAudioPlayer = NULL;
526
Gloria Wangc6091dd2011-05-03 15:59:03 -0700527 if (mTextPlayer != NULL) {
528 delete mTextPlayer;
529 mTextPlayer = NULL;
530 }
531
Andreas Huber3522b5a52010-01-22 14:36:53 -0800532 mVideoRenderer.clear();
533
Andreas Huber27366fc2009-11-20 09:32:46 -0800534 if (mVideoSource != NULL) {
Andreas Huber3a785fe2011-03-14 10:55:40 -0700535 shutdownVideoDecoder_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800536 }
537
Andreas Huber27366fc2009-11-20 09:32:46 -0800538 mDurationUs = -1;
Andreas Huberfddf5d92011-06-07 15:52:25 -0700539 modifyFlags(0, ASSIGN);
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700540 mExtractorFlags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800541 mTimeSourceDeltaUs = 0;
542 mVideoTimeUs = 0;
543
Andreas Hubera2c29972011-02-24 12:05:40 -0800544 mSeeking = NO_SEEK;
Gloria Wang3c578f22011-08-18 14:52:36 -0700545 mSeekNotificationSent = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800546 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800547
Andreas Huberffdf4782010-02-09 14:05:43 -0800548 mUri.setTo("");
549 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800550
551 mFileSource.clear();
552
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700553 mBitrate = -1;
Andreas Huber3a785fe2011-03-14 10:55:40 -0700554 mLastVideoTimeUs = -1;
Andreas Huberfddf5d92011-06-07 15:52:25 -0700555
556 {
557 Mutex::Autolock autoLock(mStatsLock);
558 mStats.mFd = -1;
559 mStats.mURI = String8();
560 mStats.mBitrate = -1;
561 mStats.mAudioTrackIndex = -1;
562 mStats.mVideoTrackIndex = -1;
563 mStats.mNumVideoFramesDecoded = 0;
564 mStats.mNumVideoFramesDropped = 0;
565 mStats.mVideoWidth = -1;
566 mStats.mVideoHeight = -1;
567 mStats.mFlags = 0;
568 mStats.mTracks.clear();
569 }
570
Andreas Huberbf0a0642011-08-16 12:41:41 -0700571 mWatchForAudioSeekComplete = false;
572 mWatchForAudioEOS = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800573}
574
Andreas Huber6be780e2010-02-08 14:40:30 -0800575void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800576 if (mListener != NULL) {
577 sp<MediaPlayerBase> listener = mListener.promote();
578
579 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800580 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800581 }
582 }
583}
584
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700585bool AwesomePlayer::getBitrate(int64_t *bitrate) {
James Dongb1262a82010-11-16 14:04:54 -0800586 off64_t size;
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700587 if (mDurationUs >= 0 && mCachedSource != NULL
588 && mCachedSource->getSize(&size) == OK) {
589 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec
590 return true;
591 }
592
593 if (mBitrate >= 0) {
594 *bitrate = mBitrate;
595 return true;
596 }
597
598 *bitrate = 0;
599
600 return false;
601}
602
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700603// Returns true iff cached duration is available/applicable.
604bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700605 int64_t bitrate;
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700606
Andreas Hubera6be6dc2011-10-11 15:24:07 -0700607 if (mCachedSource != NULL && getBitrate(&bitrate)) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000608 status_t finalStatus;
609 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700610 *durationUs = cachedDataRemaining * 8000000ll / bitrate;
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000611 *eos = (finalStatus != OK);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700612 return true;
Andreas Huber77d8dc22011-04-21 10:06:43 -0700613 } else if (mWVMExtractor != NULL) {
614 status_t finalStatus;
615 *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus);
616 *eos = (finalStatus != OK);
617 return true;
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700618 }
619
620 return false;
621}
622
Andreas Huber10b920c2010-11-11 15:37:17 -0800623void AwesomePlayer::ensureCacheIsFetching_l() {
624 if (mCachedSource != NULL) {
625 mCachedSource->resumeFetchingIfNecessary();
626 }
627}
628
Andreas Huber52c78322011-01-11 15:05:28 -0800629void AwesomePlayer::onVideoLagUpdate() {
630 Mutex::Autolock autoLock(mLock);
631 if (!mVideoLagEventPending) {
632 return;
633 }
634 mVideoLagEventPending = false;
635
636 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
637 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
638
Andreas Huber16ede3c2011-03-25 13:03:14 -0700639 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
Steve Block71f2cf12011-10-20 11:56:00 +0100640 ALOGV("video late by %lld ms.", videoLateByUs / 1000ll);
Andreas Huber52c78322011-01-11 15:05:28 -0800641
642 notifyListener_l(
643 MEDIA_INFO,
644 MEDIA_INFO_VIDEO_TRACK_LAGGING,
645 videoLateByUs / 1000ll);
646 }
647
648 postVideoLagEvent_l();
649}
650
Andreas Huberb9e63832010-01-26 16:20:10 -0800651void AwesomePlayer::onBufferingUpdate() {
652 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800653 if (!mBufferingEventPending) {
654 return;
655 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800656 mBufferingEventPending = false;
657
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700658 if (mCachedSource != NULL) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000659 status_t finalStatus;
660 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
661 bool eos = (finalStatus != OK);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700662
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700663 if (eos) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000664 if (finalStatus == ERROR_END_OF_STREAM) {
665 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
666 }
Andreas Huber05f67872010-10-04 11:36:39 -0700667 if (mFlags & PREPARING) {
Steve Block71f2cf12011-10-20 11:56:00 +0100668 ALOGV("cache has reached EOS, prepare is done.");
Andreas Huber05f67872010-10-04 11:36:39 -0700669 finishAsyncPrepare_l();
670 }
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700671 } else {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700672 int64_t bitrate;
673 if (getBitrate(&bitrate)) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700674 size_t cachedSize = mCachedSource->cachedSize();
675 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
676
677 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
678 if (percentage > 100) {
679 percentage = 100;
680 }
681
682 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
683 } else {
684 // We don't know the bitrate of the stream, use absolute size
685 // limits to maintain the cache.
686
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700687 if ((mFlags & PLAYING) && !eos
688 && (cachedDataRemaining < kLowWaterMarkBytes)) {
Steve Block6215d3f2012-01-04 20:05:49 +0000689 ALOGI("cache is running low (< %d) , pausing.",
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700690 kLowWaterMarkBytes);
Andreas Huberfddf5d92011-06-07 15:52:25 -0700691 modifyFlags(CACHE_UNDERRUN, SET);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700692 pause_l();
Andreas Huber10b920c2010-11-11 15:37:17 -0800693 ensureCacheIsFetching_l();
James Donga9d0feb2011-05-25 19:37:03 -0700694 sendCacheStats();
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700695 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
696 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
697 if (mFlags & CACHE_UNDERRUN) {
Steve Block6215d3f2012-01-04 20:05:49 +0000698 ALOGI("cache has filled up (> %d), resuming.",
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700699 kHighWaterMarkBytes);
Andreas Huberfddf5d92011-06-07 15:52:25 -0700700 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700701 play_l();
702 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
703 } else if (mFlags & PREPARING) {
Steve Block71f2cf12011-10-20 11:56:00 +0100704 ALOGV("cache has filled up (> %d), prepare is done",
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700705 kHighWaterMarkBytes);
706 finishAsyncPrepare_l();
707 }
708 }
709 }
710 }
Andreas Huber77d8dc22011-04-21 10:06:43 -0700711 } else if (mWVMExtractor != NULL) {
712 status_t finalStatus;
713
714 int64_t cachedDurationUs
715 = mWVMExtractor->getCachedDurationUs(&finalStatus);
716
717 bool eos = (finalStatus != OK);
718
719 if (eos) {
720 if (finalStatus == ERROR_END_OF_STREAM) {
721 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
722 }
723 if (mFlags & PREPARING) {
Steve Block71f2cf12011-10-20 11:56:00 +0100724 ALOGV("cache has reached EOS, prepare is done.");
Andreas Huber77d8dc22011-04-21 10:06:43 -0700725 finishAsyncPrepare_l();
726 }
727 } else {
728 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
729 if (percentage > 100) {
730 percentage = 100;
731 }
732
733 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
734 }
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700735 }
736
737 int64_t cachedDurationUs;
738 bool eos;
739 if (getCachedDuration_l(&cachedDurationUs, &eos)) {
Steve Block71f2cf12011-10-20 11:56:00 +0100740 ALOGV("cachedDurationUs = %.2f secs, eos=%d",
Andreas Huber10b920c2010-11-11 15:37:17 -0800741 cachedDurationUs / 1E6, eos);
742
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700743 if ((mFlags & PLAYING) && !eos
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700744 && (cachedDurationUs < kLowWaterMarkUs)) {
Steve Block6215d3f2012-01-04 20:05:49 +0000745 ALOGI("cache is running low (%.2f secs) , pausing.",
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700746 cachedDurationUs / 1E6);
Andreas Huberfddf5d92011-06-07 15:52:25 -0700747 modifyFlags(CACHE_UNDERRUN, SET);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700748 pause_l();
Andreas Huber10b920c2010-11-11 15:37:17 -0800749 ensureCacheIsFetching_l();
James Donga9d0feb2011-05-25 19:37:03 -0700750 sendCacheStats();
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700751 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
Andreas Hubera6be6dc2011-10-11 15:24:07 -0700752 } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700753 if (mFlags & CACHE_UNDERRUN) {
Steve Block6215d3f2012-01-04 20:05:49 +0000754 ALOGI("cache has filled up (%.2f secs), resuming.",
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700755 cachedDurationUs / 1E6);
Andreas Huberfddf5d92011-06-07 15:52:25 -0700756 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700757 play_l();
758 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
759 } else if (mFlags & PREPARING) {
Steve Block71f2cf12011-10-20 11:56:00 +0100760 ALOGV("cache has filled up (%.2f secs), prepare is done",
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700761 cachedDurationUs / 1E6);
762 finishAsyncPrepare_l();
Andreas Huberc23296e2010-08-25 12:31:48 -0700763 }
Andreas Huberc23296e2010-08-25 12:31:48 -0700764 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800765 }
Andreas Huber4d61f602010-06-10 11:17:50 -0700766
Andreas Huber4d61f602010-06-10 11:17:50 -0700767 postBufferingEvent_l();
Andreas Huberb9e63832010-01-26 16:20:10 -0800768}
769
James Donga9d0feb2011-05-25 19:37:03 -0700770void AwesomePlayer::sendCacheStats() {
771 sp<MediaPlayerBase> listener = mListener.promote();
James Dong44328702011-06-01 15:27:20 -0700772 if (listener != NULL && mCachedSource != NULL) {
James Donga9d0feb2011-05-25 19:37:03 -0700773 int32_t kbps = 0;
774 status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
775 if (err == OK) {
776 listener->sendEvent(
777 MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
778 }
779 }
780}
781
Andreas Huber27366fc2009-11-20 09:32:46 -0800782void AwesomePlayer::onStreamDone() {
783 // Posted whenever any stream finishes playing.
784
785 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800786 if (!mStreamDoneEventPending) {
787 return;
788 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800789 mStreamDoneEventPending = false;
790
Andreas Huberd6c421f2011-02-16 09:05:38 -0800791 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Steve Block71f2cf12011-10-20 11:56:00 +0100792 ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
Andreas Huber971305d2010-07-07 13:35:27 -0700793
794 notifyListener_l(
795 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
796
Andreas Huberc743f452010-10-05 10:25:34 -0700797 pause_l(true /* at eos */);
Andreas Huber971305d2010-07-07 13:35:27 -0700798
Andreas Huberfddf5d92011-06-07 15:52:25 -0700799 modifyFlags(AT_EOS, SET);
Andreas Huber971305d2010-07-07 13:35:27 -0700800 return;
801 }
802
803 const bool allDone =
804 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
805 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
806
807 if (!allDone) {
808 return;
809 }
810
Andreas Huber4960f3a2011-08-18 10:53:23 -0700811 if ((mFlags & LOOPING)
812 || ((mFlags & AUTO_LOOPING)
813 && (mAudioSink == NULL || mAudioSink->realtime()))) {
814 // Don't AUTO_LOOP if we're being recorded, since that cannot be
815 // turned off and recording would go on indefinitely.
816
Andreas Huber27366fc2009-11-20 09:32:46 -0800817 seekTo_l(0);
818
Andreas Huber7085b6842010-02-03 16:02:02 -0800819 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800820 postVideoEvent_l();
821 }
822 } else {
Steve Block71f2cf12011-10-20 11:56:00 +0100823 ALOGV("MEDIA_PLAYBACK_COMPLETE");
Andreas Huber971305d2010-07-07 13:35:27 -0700824 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800825
Andreas Huberc743f452010-10-05 10:25:34 -0700826 pause_l(true /* at eos */);
Andreas Huber406a18b2010-02-18 16:45:13 -0800827
Andreas Huberfddf5d92011-06-07 15:52:25 -0700828 modifyFlags(AT_EOS, SET);
Andreas Huber27366fc2009-11-20 09:32:46 -0800829 }
830}
831
832status_t AwesomePlayer::play() {
833 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -0700834
Andreas Huberfddf5d92011-06-07 15:52:25 -0700835 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber4d61f602010-06-10 11:17:50 -0700836
Andreas Huberba7ec912010-02-12 10:42:02 -0800837 return play_l();
838}
Andreas Huber27366fc2009-11-20 09:32:46 -0800839
Andreas Huberba7ec912010-02-12 10:42:02 -0800840status_t AwesomePlayer::play_l() {
Andreas Huberfddf5d92011-06-07 15:52:25 -0700841 modifyFlags(SEEK_PREVIEW, CLEAR);
Andreas Huber0a84f4f2011-02-07 11:43:12 -0800842
Andreas Huber27366fc2009-11-20 09:32:46 -0800843 if (mFlags & PLAYING) {
844 return OK;
845 }
846
Andreas Huberffdf4782010-02-09 14:05:43 -0800847 if (!(mFlags & PREPARED)) {
848 status_t err = prepare_l();
849
850 if (err != OK) {
851 return err;
852 }
853 }
854
Andreas Huberfddf5d92011-06-07 15:52:25 -0700855 modifyFlags(PLAYING, SET);
856 modifyFlags(FIRST_FRAME, SET);
Andreas Huber27366fc2009-11-20 09:32:46 -0800857
Gloria Wang95dbffb2010-11-04 17:38:39 -0700858 if (mDecryptHandle != NULL) {
859 int64_t position;
860 getPosition(&position);
861 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
862 Playback::START, position / 1000);
863 }
864
Andreas Huber27366fc2009-11-20 09:32:46 -0800865 if (mAudioSource != NULL) {
866 if (mAudioPlayer == NULL) {
867 if (mAudioSink != NULL) {
Andreas Huber2b359ed2010-09-28 11:56:39 -0700868 mAudioPlayer = new AudioPlayer(mAudioSink, this);
Andreas Huber27366fc2009-11-20 09:32:46 -0800869 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800870
Andreas Huber27366fc2009-11-20 09:32:46 -0800871 mTimeSource = mAudioPlayer;
872
Andreas Huber498422f2011-03-16 10:41:25 -0700873 // If there was a seek request before we ever started,
874 // honor the request now.
875 // Make sure to do this before starting the audio player
876 // to avoid a race condition.
877 seekAudioIfNecessary_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800878 }
Andreas Huberce8a1012011-02-11 13:09:36 -0800879 }
880
881 CHECK(!(mFlags & AUDIO_RUNNING));
882
883 if (mVideoSource == NULL) {
Andreas Huber232d5f22011-07-14 13:02:47 -0700884 // We don't want to post an error notification at this point,
885 // the error returned from MediaPlayer::start() will suffice.
886
887 status_t err = startAudioPlayer_l(
888 false /* sendErrorNotification */);
Andreas Huberce8a1012011-02-11 13:09:36 -0800889
890 if (err != OK) {
891 delete mAudioPlayer;
892 mAudioPlayer = NULL;
893
Andreas Huberfddf5d92011-06-07 15:52:25 -0700894 modifyFlags((PLAYING | FIRST_FRAME), CLEAR);
Andreas Huberce8a1012011-02-11 13:09:36 -0800895
896 if (mDecryptHandle != NULL) {
897 mDrmManagerClient->setPlaybackStatus(
898 mDecryptHandle, Playback::STOP, 0);
899 }
900
901 return err;
902 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800903 }
904 }
905
906 if (mTimeSource == NULL && mAudioPlayer == NULL) {
Andreas Huber971305d2010-07-07 13:35:27 -0700907 mTimeSource = &mSystemTimeSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800908 }
909
910 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800911 // Kick off video playback
912 postVideoEvent_l();
Andreas Huber52c78322011-01-11 15:05:28 -0800913
914 if (mAudioSource != NULL && mVideoSource != NULL) {
915 postVideoLagEvent_l();
916 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800917 }
918
Andreas Huber406a18b2010-02-18 16:45:13 -0800919 if (mFlags & AT_EOS) {
920 // Legacy behaviour, if a stream finishes playing and then
921 // is started again, we play from the start...
922 seekTo_l(0);
923 }
924
Gloria Wangd211f412011-02-19 18:37:57 -0800925 uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
926 | IMediaPlayerService::kBatteryDataTrackDecoder;
927 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
928 params |= IMediaPlayerService::kBatteryDataTrackAudio;
929 }
930 if (mVideoSource != NULL) {
931 params |= IMediaPlayerService::kBatteryDataTrackVideo;
932 }
933 addBatteryData(params);
934
Andreas Huber27366fc2009-11-20 09:32:46 -0800935 return OK;
936}
937
Andreas Huber232d5f22011-07-14 13:02:47 -0700938status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
Andreas Huberce8a1012011-02-11 13:09:36 -0800939 CHECK(!(mFlags & AUDIO_RUNNING));
940
941 if (mAudioSource == NULL || mAudioPlayer == NULL) {
942 return OK;
943 }
944
945 if (!(mFlags & AUDIOPLAYER_STARTED)) {
Andreas Huberfddf5d92011-06-07 15:52:25 -0700946 modifyFlags(AUDIOPLAYER_STARTED, SET);
Andreas Huberce8a1012011-02-11 13:09:36 -0800947
Andreas Huber5fd43e32011-05-10 13:56:39 -0700948 bool wasSeeking = mAudioPlayer->isSeeking();
949
Andreas Huberce8a1012011-02-11 13:09:36 -0800950 // We've already started the MediaSource in order to enable
951 // the prefetcher to read its data.
952 status_t err = mAudioPlayer->start(
953 true /* sourceAlreadyStarted */);
954
955 if (err != OK) {
Andreas Huber232d5f22011-07-14 13:02:47 -0700956 if (sendErrorNotification) {
957 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
958 }
959
Andreas Huberce8a1012011-02-11 13:09:36 -0800960 return err;
961 }
Andreas Huber5fd43e32011-05-10 13:56:39 -0700962
963 if (wasSeeking) {
964 CHECK(!mAudioPlayer->isSeeking());
965
966 // We will have finished the seek while starting the audio player.
Andreas Huber67a041f2011-09-01 11:39:11 -0700967 postAudioSeekComplete();
Andreas Huber5fd43e32011-05-10 13:56:39 -0700968 }
Andreas Huberce8a1012011-02-11 13:09:36 -0800969 } else {
970 mAudioPlayer->resume();
971 }
972
Andreas Huberfddf5d92011-06-07 15:52:25 -0700973 modifyFlags(AUDIO_RUNNING, SET);
Andreas Huberce8a1012011-02-11 13:09:36 -0800974
975 mWatchForAudioEOS = true;
976
977 return OK;
978}
979
Andreas Hubere3c01832010-08-16 08:49:37 -0700980void AwesomePlayer::notifyVideoSize_l() {
981 sp<MetaData> meta = mVideoSource->getFormat();
982
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800983 int32_t cropLeft, cropTop, cropRight, cropBottom;
984 if (!meta->findRect(
985 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
986 int32_t width, height;
987 CHECK(meta->findInt32(kKeyWidth, &width));
988 CHECK(meta->findInt32(kKeyHeight, &height));
989
990 cropLeft = cropTop = 0;
991 cropRight = width - 1;
992 cropBottom = height - 1;
993
Steve Block71f2cf12011-10-20 11:56:00 +0100994 ALOGV("got dimensions only %d x %d", width, height);
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800995 } else {
Steve Block71f2cf12011-10-20 11:56:00 +0100996 ALOGV("got crop rect %d, %d, %d, %d",
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800997 cropLeft, cropTop, cropRight, cropBottom);
998 }
999
James Dong7e91d912011-03-18 12:19:43 -07001000 int32_t displayWidth;
1001 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
Steve Block71f2cf12011-10-20 11:56:00 +01001002 ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
James Dong7e91d912011-03-18 12:19:43 -07001003 mDisplayWidth = displayWidth;
1004 }
1005 int32_t displayHeight;
1006 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
Steve Block71f2cf12011-10-20 11:56:00 +01001007 ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
James Dong7e91d912011-03-18 12:19:43 -07001008 mDisplayHeight = displayHeight;
1009 }
1010
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001011 int32_t usableWidth = cropRight - cropLeft + 1;
1012 int32_t usableHeight = cropBottom - cropTop + 1;
James Dong08adfd22011-01-16 11:30:13 -08001013 if (mDisplayWidth != 0) {
1014 usableWidth = mDisplayWidth;
1015 }
1016 if (mDisplayHeight != 0) {
1017 usableHeight = mDisplayHeight;
1018 }
Andreas Hubere3c01832010-08-16 08:49:37 -07001019
Andreas Huberfddf5d92011-06-07 15:52:25 -07001020 {
1021 Mutex::Autolock autoLock(mStatsLock);
1022 mStats.mVideoWidth = usableWidth;
1023 mStats.mVideoHeight = usableHeight;
1024 }
1025
Andreas Huber940c8662010-11-16 15:26:30 -08001026 int32_t rotationDegrees;
1027 if (!mVideoTrack->getFormat()->findInt32(
1028 kKeyRotation, &rotationDegrees)) {
1029 rotationDegrees = 0;
1030 }
1031
1032 if (rotationDegrees == 90 || rotationDegrees == 270) {
1033 notifyListener_l(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001034 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
Andreas Huber940c8662010-11-16 15:26:30 -08001035 } else {
1036 notifyListener_l(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001037 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
Andreas Huber940c8662010-11-16 15:26:30 -08001038 }
Andreas Hubere3c01832010-08-16 08:49:37 -07001039}
1040
Andreas Huber27366fc2009-11-20 09:32:46 -08001041void AwesomePlayer::initRenderer_l() {
Glenn Kastencc562a32011-02-08 17:26:17 -08001042 if (mNativeWindow == NULL) {
Andreas Huberc23dabf2010-11-16 13:05:53 -08001043 return;
1044 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001045
Andreas Huberc23dabf2010-11-16 13:05:53 -08001046 sp<MetaData> meta = mVideoSource->getFormat();
Andreas Huber27366fc2009-11-20 09:32:46 -08001047
Andreas Huberc23dabf2010-11-16 13:05:53 -08001048 int32_t format;
1049 const char *component;
1050 int32_t decodedWidth, decodedHeight;
1051 CHECK(meta->findInt32(kKeyColorFormat, &format));
1052 CHECK(meta->findCString(kKeyDecoderComponent, &component));
1053 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
1054 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
Andreas Hubera67d5382009-12-10 15:32:12 -08001055
Andreas Huber940c8662010-11-16 15:26:30 -08001056 int32_t rotationDegrees;
1057 if (!mVideoTrack->getFormat()->findInt32(
1058 kKeyRotation, &rotationDegrees)) {
1059 rotationDegrees = 0;
1060 }
1061
Andreas Huberc23dabf2010-11-16 13:05:53 -08001062 mVideoRenderer.clear();
Andreas Hubera67d5382009-12-10 15:32:12 -08001063
Andreas Huberc23dabf2010-11-16 13:05:53 -08001064 // Must ensure that mVideoRenderer's destructor is actually executed
1065 // before creating a new one.
1066 IPCThreadState::self()->flushCommands();
1067
Andreas Huber4b3913a2011-05-11 14:13:42 -07001068 if (USE_SURFACE_ALLOC
1069 && !strncmp(component, "OMX.", 4)
Andreas Huberbc554952011-09-08 14:12:44 -07001070 && strncmp(component, "OMX.google.", 11)
1071 && strcmp(component, "OMX.Nvidia.mpeg2v.decode")) {
Andreas Huberc23dabf2010-11-16 13:05:53 -08001072 // Hardware decoders avoid the CPU color conversion by decoding
1073 // directly to ANativeBuffers, so we must use a renderer that
1074 // just pushes those buffers to the ANativeWindow.
Andreas Huber940c8662010-11-16 15:26:30 -08001075 mVideoRenderer =
Glenn Kastencc562a32011-02-08 17:26:17 -08001076 new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
Andreas Huberc23dabf2010-11-16 13:05:53 -08001077 } else {
1078 // Other decoders are instantiated locally and as a consequence
1079 // allocate their buffers in local address space. This renderer
1080 // then performs a color conversion and copy to get the data
1081 // into the ANativeBuffer.
Glenn Kastencc562a32011-02-08 17:26:17 -08001082 mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
Andreas Huber27366fc2009-11-20 09:32:46 -08001083 }
1084}
1085
1086status_t AwesomePlayer::pause() {
1087 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -07001088
Andreas Huberfddf5d92011-06-07 15:52:25 -07001089 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber4d61f602010-06-10 11:17:50 -07001090
Andreas Huber27366fc2009-11-20 09:32:46 -08001091 return pause_l();
1092}
1093
Andreas Huberc743f452010-10-05 10:25:34 -07001094status_t AwesomePlayer::pause_l(bool at_eos) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001095 if (!(mFlags & PLAYING)) {
1096 return OK;
1097 }
1098
Andreas Huber22cf4b02011-11-16 10:46:05 -08001099 cancelPlayerEvents(true /* keepNotifications */);
Andreas Huber27366fc2009-11-20 09:32:46 -08001100
Andreas Huberce8a1012011-02-11 13:09:36 -08001101 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huberc743f452010-10-05 10:25:34 -07001102 if (at_eos) {
1103 // If we played the audio stream to completion we
1104 // want to make sure that all samples remaining in the audio
1105 // track's queue are played out.
1106 mAudioPlayer->pause(true /* playPendingSamples */);
1107 } else {
1108 mAudioPlayer->pause();
1109 }
Andreas Huberce8a1012011-02-11 13:09:36 -08001110
Andreas Huberfddf5d92011-06-07 15:52:25 -07001111 modifyFlags(AUDIO_RUNNING, CLEAR);
Andreas Huber27366fc2009-11-20 09:32:46 -08001112 }
1113
Gloria Wangc6091dd2011-05-03 15:59:03 -07001114 if (mFlags & TEXTPLAYER_STARTED) {
1115 mTextPlayer->pause();
Andreas Huberfddf5d92011-06-07 15:52:25 -07001116 modifyFlags(TEXT_RUNNING, CLEAR);
Gloria Wangc6091dd2011-05-03 15:59:03 -07001117 }
1118
Andreas Huberfddf5d92011-06-07 15:52:25 -07001119 modifyFlags(PLAYING, CLEAR);
Andreas Huber27366fc2009-11-20 09:32:46 -08001120
Gloria Wangd5770912010-06-22 13:55:38 -07001121 if (mDecryptHandle != NULL) {
1122 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1123 Playback::PAUSE, 0);
1124 }
1125
Gloria Wangd211f412011-02-19 18:37:57 -08001126 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
1127 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
1128 params |= IMediaPlayerService::kBatteryDataTrackAudio;
1129 }
1130 if (mVideoSource != NULL) {
1131 params |= IMediaPlayerService::kBatteryDataTrackVideo;
1132 }
1133
1134 addBatteryData(params);
1135
Andreas Huber27366fc2009-11-20 09:32:46 -08001136 return OK;
1137}
1138
1139bool AwesomePlayer::isPlaying() const {
Andreas Huber4d61f602010-06-10 11:17:50 -07001140 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
Andreas Huber27366fc2009-11-20 09:32:46 -08001141}
1142
Andreas Huber07754c52011-08-29 13:01:23 -07001143status_t AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
Glenn Kastencc562a32011-02-08 17:26:17 -08001144 Mutex::Autolock autoLock(mLock);
1145
Andreas Huber07754c52011-08-29 13:01:23 -07001146 status_t err;
Glenn Kastencc562a32011-02-08 17:26:17 -08001147 if (surfaceTexture != NULL) {
Andreas Huber07754c52011-08-29 13:01:23 -07001148 err = setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
Gloria Wang91784c992011-08-09 15:29:34 -07001149 } else {
Andreas Huber07754c52011-08-29 13:01:23 -07001150 err = setNativeWindow_l(NULL);
Andreas Huber3a785fe2011-03-14 10:55:40 -07001151 }
Andreas Huber07754c52011-08-29 13:01:23 -07001152
1153 return err;
Andreas Huber3a785fe2011-03-14 10:55:40 -07001154}
1155
1156void AwesomePlayer::shutdownVideoDecoder_l() {
1157 if (mVideoBuffer) {
1158 mVideoBuffer->release();
1159 mVideoBuffer = NULL;
Glenn Kastencc562a32011-02-08 17:26:17 -08001160 }
1161
Andreas Huber3a785fe2011-03-14 10:55:40 -07001162 mVideoSource->stop();
1163
1164 // The following hack is necessary to ensure that the OMX
1165 // component is completely released by the time we may try
1166 // to instantiate it again.
1167 wp<MediaSource> tmp = mVideoSource;
1168 mVideoSource.clear();
1169 while (tmp.promote() != NULL) {
1170 usleep(1000);
1171 }
1172 IPCThreadState::self()->flushCommands();
Steve Block71f2cf12011-10-20 11:56:00 +01001173 ALOGV("video decoder shutdown completed");
Andreas Huber3a785fe2011-03-14 10:55:40 -07001174}
1175
Andreas Huber07754c52011-08-29 13:01:23 -07001176status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
Andreas Huber3a785fe2011-03-14 10:55:40 -07001177 mNativeWindow = native;
1178
1179 if (mVideoSource == NULL) {
Andreas Huber07754c52011-08-29 13:01:23 -07001180 return OK;
Andreas Huber3a785fe2011-03-14 10:55:40 -07001181 }
1182
Steve Block71f2cf12011-10-20 11:56:00 +01001183 ALOGV("attempting to reconfigure to use new surface");
Andreas Huber3a785fe2011-03-14 10:55:40 -07001184
1185 bool wasPlaying = (mFlags & PLAYING) != 0;
1186
1187 pause_l();
1188 mVideoRenderer.clear();
1189
1190 shutdownVideoDecoder_l();
1191
Andreas Huber07754c52011-08-29 13:01:23 -07001192 status_t err = initVideoDecoder();
1193
1194 if (err != OK) {
1195 LOGE("failed to reinstantiate video decoder after surface change.");
1196 return err;
1197 }
Andreas Huber3a785fe2011-03-14 10:55:40 -07001198
1199 if (mLastVideoTimeUs >= 0) {
1200 mSeeking = SEEK;
Andreas Huber3a785fe2011-03-14 10:55:40 -07001201 mSeekTimeUs = mLastVideoTimeUs;
Andreas Huberfddf5d92011-06-07 15:52:25 -07001202 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
Andreas Huber3a785fe2011-03-14 10:55:40 -07001203 }
1204
1205 if (wasPlaying) {
1206 play_l();
1207 }
Andreas Huber07754c52011-08-29 13:01:23 -07001208
1209 return OK;
Andreas Hubere3c01832010-08-16 08:49:37 -07001210}
1211
Andreas Huber27366fc2009-11-20 09:32:46 -08001212void AwesomePlayer::setAudioSink(
1213 const sp<MediaPlayerBase::AudioSink> &audioSink) {
1214 Mutex::Autolock autoLock(mLock);
1215
1216 mAudioSink = audioSink;
1217}
1218
1219status_t AwesomePlayer::setLooping(bool shouldLoop) {
1220 Mutex::Autolock autoLock(mLock);
1221
Andreas Huberfddf5d92011-06-07 15:52:25 -07001222 modifyFlags(LOOPING, CLEAR);
Andreas Huber27366fc2009-11-20 09:32:46 -08001223
1224 if (shouldLoop) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001225 modifyFlags(LOOPING, SET);
Andreas Huber27366fc2009-11-20 09:32:46 -08001226 }
1227
1228 return OK;
1229}
1230
1231status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -07001232 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001233
1234 if (mDurationUs < 0) {
1235 return UNKNOWN_ERROR;
1236 }
1237
1238 *durationUs = mDurationUs;
1239
1240 return OK;
1241}
1242
1243status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Hubera6be6dc2011-10-11 15:24:07 -07001244 if (mSeeking != NO_SEEK) {
Andreas Huberddb709c2010-04-07 10:24:35 -07001245 *positionUs = mSeekTimeUs;
Andreas Huber16ede3c2011-03-25 13:03:14 -07001246 } else if (mVideoSource != NULL
1247 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
Andreas Huber252573c2010-03-26 10:17:17 -07001248 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001249 *positionUs = mVideoTimeUs;
1250 } else if (mAudioPlayer != NULL) {
1251 *positionUs = mAudioPlayer->getMediaTimeUs();
1252 } else {
1253 *positionUs = 0;
1254 }
1255
1256 return OK;
1257}
1258
1259status_t AwesomePlayer::seekTo(int64_t timeUs) {
Andreas Huber10b9b3f2010-10-08 10:16:24 -07001260 if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001261 Mutex::Autolock autoLock(mLock);
1262 return seekTo_l(timeUs);
1263 }
1264
1265 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -08001266}
1267
Gloria Wangc6091dd2011-05-03 15:59:03 -07001268status_t AwesomePlayer::setTimedTextTrackIndex(int32_t index) {
1269 if (mTextPlayer != NULL) {
1270 if (index >= 0) { // to turn on a text track
1271 status_t err = mTextPlayer->setTimedTextTrackIndex(index);
1272 if (err != OK) {
1273 return err;
1274 }
1275
Andreas Huberfddf5d92011-06-07 15:52:25 -07001276 modifyFlags(TEXT_RUNNING, SET);
1277 modifyFlags(TEXTPLAYER_STARTED, SET);
Gloria Wangc6091dd2011-05-03 15:59:03 -07001278 return OK;
1279 } else { // to turn off the text track display
1280 if (mFlags & TEXT_RUNNING) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001281 modifyFlags(TEXT_RUNNING, CLEAR);
Gloria Wangc6091dd2011-05-03 15:59:03 -07001282 }
1283 if (mFlags & TEXTPLAYER_STARTED) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001284 modifyFlags(TEXTPLAYER_STARTED, CLEAR);
Gloria Wangc6091dd2011-05-03 15:59:03 -07001285 }
1286
1287 return mTextPlayer->setTimedTextTrackIndex(index);
1288 }
1289 } else {
1290 return INVALID_OPERATION;
1291 }
1292}
1293
Andreas Huber27366fc2009-11-20 09:32:46 -08001294status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001295 if (mFlags & CACHE_UNDERRUN) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001296 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber4d61f602010-06-10 11:17:50 -07001297 play_l();
1298 }
1299
Andreas Huber16ede3c2011-03-25 13:03:14 -07001300 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1301 // Video playback completed before, there's no pending
1302 // video event right now. In order for this new seek
1303 // to be honored, we need to post one.
1304
1305 postVideoEvent_l();
1306 }
1307
Andreas Hubera2c29972011-02-24 12:05:40 -08001308 mSeeking = SEEK;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001309 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -08001310 mSeekTimeUs = timeUs;
Andreas Huberfddf5d92011-06-07 15:52:25 -07001311 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
Andreas Huber27366fc2009-11-20 09:32:46 -08001312
1313 seekAudioIfNecessary_l();
1314
Gloria Wangc6091dd2011-05-03 15:59:03 -07001315 if (mFlags & TEXTPLAYER_STARTED) {
1316 mTextPlayer->seekTo(mSeekTimeUs);
1317 }
1318
Andreas Huber8e2b9412010-03-31 09:40:15 -07001319 if (!(mFlags & PLAYING)) {
Steve Block71f2cf12011-10-20 11:56:00 +01001320 ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
Andreas Huber8e2b9412010-03-31 09:40:15 -07001321 " immediately.");
1322
1323 notifyListener_l(MEDIA_SEEK_COMPLETE);
1324 mSeekNotificationSent = true;
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001325
1326 if ((mFlags & PREPARED) && mVideoSource != NULL) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001327 modifyFlags(SEEK_PREVIEW, SET);
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001328 postVideoEvent_l();
1329 }
Andreas Huber8e2b9412010-03-31 09:40:15 -07001330 }
1331
Andreas Huber27366fc2009-11-20 09:32:46 -08001332 return OK;
1333}
1334
1335void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Hubera2c29972011-02-24 12:05:40 -08001336 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001337 mAudioPlayer->seekTo(mSeekTimeUs);
1338
Andreas Huber70d10c02010-02-03 11:37:29 -08001339 mWatchForAudioSeekComplete = true;
1340 mWatchForAudioEOS = true;
Gloria Wangd5770912010-06-22 13:55:38 -07001341
1342 if (mDecryptHandle != NULL) {
1343 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1344 Playback::PAUSE, 0);
1345 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1346 Playback::START, mSeekTimeUs / 1000);
1347 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001348 }
1349}
1350
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001351void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1352 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001353
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001354 mAudioTrack = source;
1355}
1356
Gloria Wangc6091dd2011-05-03 15:59:03 -07001357void AwesomePlayer::addTextSource(sp<MediaSource> source) {
Gloria Wang13bc8cd2011-05-11 11:24:09 -07001358 Mutex::Autolock autoLock(mTimedTextLock);
Gloria Wangc6091dd2011-05-03 15:59:03 -07001359 CHECK(source != NULL);
1360
1361 if (mTextPlayer == NULL) {
1362 mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
1363 }
1364
1365 mTextPlayer->addTextSource(source);
1366}
1367
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001368status_t AwesomePlayer::initAudioDecoder() {
1369 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -08001370
1371 const char *mime;
1372 CHECK(meta->findCString(kKeyMIMEType, &mime));
1373
1374 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001375 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -08001376 } else {
1377 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001378 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -08001379 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001380 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -08001381 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001382
1383 if (mAudioSource != NULL) {
1384 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001385 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -07001386 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001387 if (mDurationUs < 0 || durationUs > mDurationUs) {
1388 mDurationUs = durationUs;
1389 }
1390 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001391
Andreas Huber3c78a1b2010-05-13 09:15:21 -07001392 status_t err = mAudioSource->start();
1393
1394 if (err != OK) {
1395 mAudioSource.clear();
1396 return err;
1397 }
Andreas Huberd0332ad2010-04-12 16:05:57 -07001398 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1399 // For legacy reasons we're simply going to ignore the absence
1400 // of an audio decoder for QCELP instead of aborting playback
1401 // altogether.
1402 return OK;
1403 }
Andreas Huberdc9927d2010-03-08 15:46:13 -08001404
Andreas Huberfddf5d92011-06-07 15:52:25 -07001405 if (mAudioSource != NULL) {
1406 Mutex::Autolock autoLock(mStatsLock);
1407 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
1408
1409 const char *component;
1410 if (!mAudioSource->getFormat()
1411 ->findCString(kKeyDecoderComponent, &component)) {
1412 component = "none";
1413 }
1414
1415 stat->mDecoderName = component;
1416 }
1417
Andreas Huber27366fc2009-11-20 09:32:46 -08001418 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1419}
1420
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001421void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1422 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001423
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001424 mVideoTrack = source;
1425}
1426
Andreas Huber4c19bf92010-09-08 14:32:20 -07001427status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
Glenn Kastenb8763f62011-01-28 12:37:51 -08001428
1429 // Either the application or the DRM system can independently say
1430 // that there must be a hardware-protected path to an external video sink.
1431 // For now we always require a hardware-protected path to external video sink
1432 // if content is DRMed, but eventually this could be optional per DRM agent.
1433 // When the application wants protection, then
1434 // (USE_SURFACE_ALLOC && (mSurface != 0) &&
1435 // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
1436 // will be true, but that part is already handled by SurfaceFlinger.
Glenn Kasten1b11b642011-03-23 14:34:31 -07001437
1438#ifdef DEBUG_HDCP
1439 // For debugging, we allow a system property to control the protected usage.
1440 // In case of uninitialized or unexpected property, we default to "DRM only".
1441 bool setProtectionBit = false;
1442 char value[PROPERTY_VALUE_MAX];
1443 if (property_get("persist.sys.hdcp_checking", value, NULL)) {
1444 if (!strcmp(value, "never")) {
1445 // nop
1446 } else if (!strcmp(value, "always")) {
1447 setProtectionBit = true;
1448 } else if (!strcmp(value, "drm-only")) {
1449 if (mDecryptHandle != NULL) {
1450 setProtectionBit = true;
1451 }
1452 // property value is empty, or unexpected value
1453 } else {
1454 if (mDecryptHandle != NULL) {
1455 setProtectionBit = true;
1456 }
1457 }
1458 // can' read property value
1459 } else {
1460 if (mDecryptHandle != NULL) {
1461 setProtectionBit = true;
1462 }
1463 }
1464 // note that usage bit is already cleared, so no need to clear it in the "else" case
1465 if (setProtectionBit) {
1466 flags |= OMXCodec::kEnableGrallocUsageProtected;
1467 }
1468#else
Glenn Kastenb8763f62011-01-28 12:37:51 -08001469 if (mDecryptHandle != NULL) {
1470 flags |= OMXCodec::kEnableGrallocUsageProtected;
1471 }
Glenn Kasten1b11b642011-03-23 14:34:31 -07001472#endif
Steve Block71f2cf12011-10-20 11:56:00 +01001473 ALOGV("initVideoDecoder flags=0x%x", flags);
Andreas Huber27366fc2009-11-20 09:32:46 -08001474 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001475 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -08001476 false, // createEncoder
Andreas Huber57648e42010-08-04 10:14:30 -07001477 mVideoTrack,
Glenn Kastencc562a32011-02-08 17:26:17 -08001478 NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001479
1480 if (mVideoSource != NULL) {
1481 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001482 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -07001483 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001484 if (mDurationUs < 0 || durationUs > mDurationUs) {
1485 mDurationUs = durationUs;
1486 }
1487 }
1488
Andreas Huber1919e5a2010-05-20 10:37:06 -07001489 status_t err = mVideoSource->start();
1490
1491 if (err != OK) {
1492 mVideoSource.clear();
1493 return err;
1494 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001495 }
1496
Andreas Huberfddf5d92011-06-07 15:52:25 -07001497 if (mVideoSource != NULL) {
James Dong5bc53032011-08-11 17:38:35 -07001498 const char *componentName;
Andreas Huberfddf5d92011-06-07 15:52:25 -07001499 CHECK(mVideoSource->getFormat()
James Dong5bc53032011-08-11 17:38:35 -07001500 ->findCString(kKeyDecoderComponent, &componentName));
Andreas Huberfddf5d92011-06-07 15:52:25 -07001501
James Dong5bc53032011-08-11 17:38:35 -07001502 {
1503 Mutex::Autolock autoLock(mStatsLock);
1504 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
1505
1506 stat->mDecoderName = componentName;
1507 }
1508
1509 static const char *kPrefix = "OMX.Nvidia.";
1510 static const char *kSuffix = ".decode";
1511 static const size_t kSuffixLength = strlen(kSuffix);
1512
1513 size_t componentNameLength = strlen(componentName);
1514
1515 if (!strncmp(componentName, kPrefix, strlen(kPrefix))
1516 && componentNameLength >= kSuffixLength
1517 && !strcmp(&componentName[
1518 componentNameLength - kSuffixLength], kSuffix)) {
1519 modifyFlags(SLOW_DECODER_HACK, SET);
1520 }
Andreas Huberfddf5d92011-06-07 15:52:25 -07001521 }
1522
Andreas Huber27366fc2009-11-20 09:32:46 -08001523 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1524}
1525
Andreas Huber4d450a82010-10-19 09:34:44 -07001526void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
Andreas Hubera2c29972011-02-24 12:05:40 -08001527 if (mSeeking == SEEK_VIDEO_ONLY) {
1528 mSeeking = NO_SEEK;
1529 return;
1530 }
1531
1532 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
Andreas Huber4d450a82010-10-19 09:34:44 -07001533 return;
1534 }
1535
1536 if (mAudioPlayer != NULL) {
Steve Block71f2cf12011-10-20 11:56:00 +01001537 ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
Andreas Huber4d450a82010-10-19 09:34:44 -07001538
1539 // If we don't have a video time, seek audio to the originally
1540 // requested seek time instead.
1541
1542 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
Andreas Huber4d450a82010-10-19 09:34:44 -07001543 mWatchForAudioSeekComplete = true;
Andreas Huber16ede3c2011-03-25 13:03:14 -07001544 mWatchForAudioEOS = true;
Andreas Huber4d450a82010-10-19 09:34:44 -07001545 } else if (!mSeekNotificationSent) {
1546 // If we're playing video only, report seek complete now,
1547 // otherwise audio player will notify us later.
1548 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huberf8a5b552011-03-16 15:42:45 -07001549 mSeekNotificationSent = true;
Andreas Huber4d450a82010-10-19 09:34:44 -07001550 }
1551
Andreas Huberfddf5d92011-06-07 15:52:25 -07001552 modifyFlags(FIRST_FRAME, SET);
Andreas Hubera2c29972011-02-24 12:05:40 -08001553 mSeeking = NO_SEEK;
Gloria Wang3f9a8192010-10-29 14:50:17 -07001554
1555 if (mDecryptHandle != NULL) {
1556 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1557 Playback::PAUSE, 0);
1558 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1559 Playback::START, videoTimeUs / 1000);
1560 }
Andreas Huber4d450a82010-10-19 09:34:44 -07001561}
1562
Andreas Huber6be780e2010-02-08 14:40:30 -08001563void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -08001564 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -08001565 if (!mVideoEventPending) {
1566 // The event has been cancelled in reset_l() but had already
1567 // been scheduled for execution at that time.
1568 return;
1569 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001570 mVideoEventPending = false;
1571
Andreas Hubera2c29972011-02-24 12:05:40 -08001572 if (mSeeking != NO_SEEK) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001573 if (mVideoBuffer) {
1574 mVideoBuffer->release();
1575 mVideoBuffer = NULL;
1576 }
Andreas Huber4d61f602010-06-10 11:17:50 -07001577
Andreas Huber77d8dc22011-04-21 10:06:43 -07001578 if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001579 && !(mFlags & SEEK_PREVIEW)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001580 // We're going to seek the video source first, followed by
1581 // the audio source.
1582 // In order to avoid jumps in the DataSource offset caused by
1583 // the audio codec prefetching data from the old locations
1584 // while the video codec is already reading data from the new
1585 // locations, we'll "pause" the audio source, causing it to
1586 // stop reading input data until a subsequent seek.
1587
Andreas Huberce8a1012011-02-11 13:09:36 -08001588 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001589 mAudioPlayer->pause();
Andreas Huberce8a1012011-02-11 13:09:36 -08001590
Andreas Huberfddf5d92011-06-07 15:52:25 -07001591 modifyFlags(AUDIO_RUNNING, CLEAR);
Andreas Huber4d61f602010-06-10 11:17:50 -07001592 }
1593 mAudioSource->pause();
1594 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001595 }
1596
1597 if (!mVideoBuffer) {
1598 MediaSource::ReadOptions options;
Andreas Hubera2c29972011-02-24 12:05:40 -08001599 if (mSeeking != NO_SEEK) {
Steve Block71f2cf12011-10-20 11:56:00 +01001600 ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -08001601
Andreas Huber6624c9f2010-07-20 15:04:28 -07001602 options.setSeekTo(
Andreas Hubera2c29972011-02-24 12:05:40 -08001603 mSeekTimeUs,
1604 mSeeking == SEEK_VIDEO_ONLY
1605 ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
1606 : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
Andreas Huber27366fc2009-11-20 09:32:46 -08001607 }
1608 for (;;) {
1609 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -08001610 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -08001611
1612 if (err != OK) {
Andreas Huber52b52cd2010-11-23 11:41:34 -08001613 CHECK(mVideoBuffer == NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001614
1615 if (err == INFO_FORMAT_CHANGED) {
Steve Block71f2cf12011-10-20 11:56:00 +01001616 ALOGV("VideoSource signalled format change.");
Andreas Huber27366fc2009-11-20 09:32:46 -08001617
Andreas Hubere3c01832010-08-16 08:49:37 -07001618 notifyVideoSize_l();
1619
Andreas Huber7085b6842010-02-03 16:02:02 -08001620 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001621 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -08001622 initRenderer_l();
1623 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001624 continue;
1625 }
1626
Andreas Huber4d450a82010-10-19 09:34:44 -07001627 // So video playback is complete, but we may still have
1628 // a seek request pending that needs to be applied
1629 // to the audio track.
Andreas Hubera2c29972011-02-24 12:05:40 -08001630 if (mSeeking != NO_SEEK) {
Steve Block71f2cf12011-10-20 11:56:00 +01001631 ALOGV("video stream ended while seeking!");
Andreas Huber4d450a82010-10-19 09:34:44 -07001632 }
1633 finishSeekIfNecessary(-1);
1634
Andreas Huber16ede3c2011-03-25 13:03:14 -07001635 if (mAudioPlayer != NULL
1636 && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1637 startAudioPlayer_l();
1638 }
1639
Andreas Huberfddf5d92011-06-07 15:52:25 -07001640 modifyFlags(VIDEO_AT_EOS, SET);
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001641 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -08001642 return;
1643 }
1644
Andreas Hubera67d5382009-12-10 15:32:12 -08001645 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -08001646 // Some decoders, notably the PV AVC software decoder
1647 // return spurious empty buffers that we just want to ignore.
1648
Andreas Hubera67d5382009-12-10 15:32:12 -08001649 mVideoBuffer->release();
1650 mVideoBuffer = NULL;
1651 continue;
1652 }
1653
Andreas Huber27366fc2009-11-20 09:32:46 -08001654 break;
1655 }
Andreas Huberfddf5d92011-06-07 15:52:25 -07001656
1657 {
1658 Mutex::Autolock autoLock(mStatsLock);
1659 ++mStats.mNumVideoFramesDecoded;
1660 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001661 }
1662
1663 int64_t timeUs;
1664 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1665
Andreas Huber3a785fe2011-03-14 10:55:40 -07001666 mLastVideoTimeUs = timeUs;
1667
Andreas Hubera2c29972011-02-24 12:05:40 -08001668 if (mSeeking == SEEK_VIDEO_ONLY) {
1669 if (mSeekTimeUs > timeUs) {
Steve Block6215d3f2012-01-04 20:05:49 +00001670 ALOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
Andreas Hubera2c29972011-02-24 12:05:40 -08001671 mSeekTimeUs, timeUs);
1672 }
1673 }
1674
Andreas Huber252573c2010-03-26 10:17:17 -07001675 {
1676 Mutex::Autolock autoLock(mMiscStateLock);
1677 mVideoTimeUs = timeUs;
1678 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001679
Andreas Hubera2c29972011-02-24 12:05:40 -08001680 SeekType wasSeeking = mSeeking;
Andreas Huber4d450a82010-10-19 09:34:44 -07001681 finishSeekIfNecessary(timeUs);
Andreas Huber27366fc2009-11-20 09:32:46 -08001682
Andreas Huberce8a1012011-02-11 13:09:36 -08001683 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1684 status_t err = startAudioPlayer_l();
1685 if (err != OK) {
Andreas Huber232d5f22011-07-14 13:02:47 -07001686 LOGE("Starting the audio player failed w/ err %d", err);
Andreas Huberce8a1012011-02-11 13:09:36 -08001687 return;
1688 }
1689 }
1690
Gloria Wangc6091dd2011-05-03 15:59:03 -07001691 if ((mFlags & TEXTPLAYER_STARTED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
1692 mTextPlayer->resume();
Andreas Huberfddf5d92011-06-07 15:52:25 -07001693 modifyFlags(TEXT_RUNNING, SET);
Gloria Wangc6091dd2011-05-03 15:59:03 -07001694 }
1695
Andreas Huber84584472011-09-08 11:33:47 -07001696 TimeSource *ts =
1697 ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
1698 ? &mSystemTimeSource : mTimeSource;
Andreas Huber971305d2010-07-07 13:35:27 -07001699
Andreas Huber27366fc2009-11-20 09:32:46 -08001700 if (mFlags & FIRST_FRAME) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001701 modifyFlags(FIRST_FRAME, CLEAR);
James Dong5bc53032011-08-11 17:38:35 -07001702 mSinceLastDropped = 0;
Andreas Huber971305d2010-07-07 13:35:27 -07001703 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001704 }
1705
1706 int64_t realTimeUs, mediaTimeUs;
Andreas Huber971305d2010-07-07 13:35:27 -07001707 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
Andreas Huber27366fc2009-11-20 09:32:46 -08001708 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1709 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1710 }
1711
Andreas Hubera2c29972011-02-24 12:05:40 -08001712 if (wasSeeking == SEEK_VIDEO_ONLY) {
1713 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1714
1715 int64_t latenessUs = nowUs - timeUs;
1716
1717 if (latenessUs > 0) {
Steve Block6215d3f2012-01-04 20:05:49 +00001718 ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
Andreas Hubera2c29972011-02-24 12:05:40 -08001719 }
1720 }
1721
1722 if (wasSeeking == NO_SEEK) {
Andreas Huber614d22c2010-10-29 15:47:52 -07001723 // Let's display the first frame after seeking right away.
Andreas Huberf88f8442010-08-10 11:18:36 -07001724
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001725 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001726
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001727 int64_t latenessUs = nowUs - timeUs;
1728
Andreas Hubera2c29972011-02-24 12:05:40 -08001729 if (latenessUs > 500000ll
Andreas Hubera2c29972011-02-24 12:05:40 -08001730 && mAudioPlayer != NULL
1731 && mAudioPlayer->getMediaTimeMapping(
1732 &realTimeUs, &mediaTimeUs)) {
Steve Block6215d3f2012-01-04 20:05:49 +00001733 ALOGI("we're much too late (%.2f secs), video skipping ahead",
Andreas Hubera2c29972011-02-24 12:05:40 -08001734 latenessUs / 1E6);
1735
1736 mVideoBuffer->release();
1737 mVideoBuffer = NULL;
1738
1739 mSeeking = SEEK_VIDEO_ONLY;
1740 mSeekTimeUs = mediaTimeUs;
1741
1742 postVideoEvent_l();
1743 return;
1744 }
1745
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001746 if (latenessUs > 40000) {
1747 // We're more than 40ms late.
Steve Block71f2cf12011-10-20 11:56:00 +01001748 ALOGV("we're late by %lld us (%.2f secs)",
Andreas Huber2334d822011-04-01 13:27:42 -07001749 latenessUs, latenessUs / 1E6);
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001750
James Dong5bc53032011-08-11 17:38:35 -07001751 if (!(mFlags & SLOW_DECODER_HACK)
1752 || mSinceLastDropped > FRAME_DROP_FREQ)
Andreas Huberfddf5d92011-06-07 15:52:25 -07001753 {
Steve Block71f2cf12011-10-20 11:56:00 +01001754 ALOGV("we're late by %lld us (%.2f secs) dropping "
James Dong5bc53032011-08-11 17:38:35 -07001755 "one after %d frames",
1756 latenessUs, latenessUs / 1E6, mSinceLastDropped);
Andreas Huberfddf5d92011-06-07 15:52:25 -07001757
James Dong5bc53032011-08-11 17:38:35 -07001758 mSinceLastDropped = 0;
1759 mVideoBuffer->release();
1760 mVideoBuffer = NULL;
1761
1762 {
1763 Mutex::Autolock autoLock(mStatsLock);
1764 ++mStats.mNumVideoFramesDropped;
1765 }
1766
1767 postVideoEvent_l();
1768 return;
1769 }
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001770 }
1771
1772 if (latenessUs < -10000) {
1773 // We're more than 10ms early.
1774
1775 postVideoEvent_l(10000);
pmehendale28f939d2011-01-06 14:43:49 -08001776 return;
1777 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001778 }
1779
Gloria Wang91784c992011-08-09 15:29:34 -07001780 if ((mNativeWindow != NULL)
1781 && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001782 mVideoRendererIsPreview = false;
1783
Andreas Huber7085b6842010-02-03 16:02:02 -08001784 initRenderer_l();
1785 }
1786
1787 if (mVideoRenderer != NULL) {
James Dong5bc53032011-08-11 17:38:35 -07001788 mSinceLastDropped++;
Andreas Huber7085b6842010-02-03 16:02:02 -08001789 mVideoRenderer->render(mVideoBuffer);
1790 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001791
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001792 mVideoBuffer->release();
Andreas Huber27366fc2009-11-20 09:32:46 -08001793 mVideoBuffer = NULL;
1794
Andreas Hubera2c29972011-02-24 12:05:40 -08001795 if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
Andreas Huberfddf5d92011-06-07 15:52:25 -07001796 modifyFlags(SEEK_PREVIEW, CLEAR);
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001797 return;
1798 }
1799
Andreas Huber27366fc2009-11-20 09:32:46 -08001800 postVideoEvent_l();
1801}
1802
1803void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1804 if (mVideoEventPending) {
1805 return;
1806 }
1807
1808 mVideoEventPending = true;
1809 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1810}
1811
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001812void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001813 if (mStreamDoneEventPending) {
1814 return;
1815 }
1816 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001817
1818 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -08001819 mQueue.postEvent(mStreamDoneEvent);
1820}
1821
Andreas Huberb9e63832010-01-26 16:20:10 -08001822void AwesomePlayer::postBufferingEvent_l() {
Andreas Huberb9e63832010-01-26 16:20:10 -08001823 if (mBufferingEventPending) {
1824 return;
1825 }
1826 mBufferingEventPending = true;
1827 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1828}
1829
Andreas Huber52c78322011-01-11 15:05:28 -08001830void AwesomePlayer::postVideoLagEvent_l() {
1831 if (mVideoLagEventPending) {
1832 return;
1833 }
1834 mVideoLagEventPending = true;
1835 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1836}
1837
Andreas Huber67a041f2011-09-01 11:39:11 -07001838void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) {
1839 Mutex::Autolock autoLock(mAudioLock);
Andreas Huber70d10c02010-02-03 11:37:29 -08001840 if (mAudioStatusEventPending) {
1841 return;
1842 }
1843 mAudioStatusEventPending = true;
Andreas Huber4dc482d2011-03-22 10:31:21 -07001844 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
Andreas Huber70d10c02010-02-03 11:37:29 -08001845}
1846
1847void AwesomePlayer::onCheckAudioStatus() {
Andreas Huber67a041f2011-09-01 11:39:11 -07001848 {
1849 Mutex::Autolock autoLock(mAudioLock);
1850 if (!mAudioStatusEventPending) {
1851 // Event was dispatched and while we were blocking on the mutex,
1852 // has already been cancelled.
1853 return;
1854 }
1855
1856 mAudioStatusEventPending = false;
Andreas Huberc0178f12010-02-17 15:58:57 -08001857 }
1858
Andreas Huber67a041f2011-09-01 11:39:11 -07001859 Mutex::Autolock autoLock(mLock);
Andreas Huber70d10c02010-02-03 11:37:29 -08001860
1861 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1862 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001863
1864 if (!mSeekNotificationSent) {
1865 notifyListener_l(MEDIA_SEEK_COMPLETE);
1866 mSeekNotificationSent = true;
1867 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001868
Andreas Hubera2c29972011-02-24 12:05:40 -08001869 mSeeking = NO_SEEK;
Andreas Huber70d10c02010-02-03 11:37:29 -08001870 }
1871
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001872 status_t finalStatus;
1873 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001874 mWatchForAudioEOS = false;
Andreas Huberfddf5d92011-06-07 15:52:25 -07001875 modifyFlags(AUDIO_AT_EOS, SET);
1876 modifyFlags(FIRST_FRAME, SET);
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001877 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001878 }
Andreas Huber70d10c02010-02-03 11:37:29 -08001879}
1880
Andreas Huber6be780e2010-02-08 14:40:30 -08001881status_t AwesomePlayer::prepare() {
1882 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001883 return prepare_l();
1884}
Andreas Huber6be780e2010-02-08 14:40:30 -08001885
Andreas Huberffdf4782010-02-09 14:05:43 -08001886status_t AwesomePlayer::prepare_l() {
1887 if (mFlags & PREPARED) {
1888 return OK;
1889 }
1890
1891 if (mFlags & PREPARING) {
1892 return UNKNOWN_ERROR;
1893 }
1894
1895 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001896 status_t err = prepareAsync_l();
1897
1898 if (err != OK) {
1899 return err;
1900 }
1901
Andreas Huberffdf4782010-02-09 14:05:43 -08001902 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001903 mPreparedCondition.wait(mLock);
1904 }
1905
Andreas Huberffdf4782010-02-09 14:05:43 -08001906 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001907}
1908
1909status_t AwesomePlayer::prepareAsync() {
1910 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001911
1912 if (mFlags & PREPARING) {
1913 return UNKNOWN_ERROR; // async prepare already pending
1914 }
1915
1916 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001917 return prepareAsync_l();
1918}
1919
1920status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001921 if (mFlags & PREPARING) {
1922 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001923 }
1924
Andreas Huber406a18b2010-02-18 16:45:13 -08001925 if (!mQueueStarted) {
1926 mQueue.start();
1927 mQueueStarted = true;
1928 }
1929
Andreas Huberfddf5d92011-06-07 15:52:25 -07001930 modifyFlags(PREPARING, SET);
Andreas Huber6be780e2010-02-08 14:40:30 -08001931 mAsyncPrepareEvent = new AwesomeEvent(
1932 this, &AwesomePlayer::onPrepareAsyncEvent);
1933
1934 mQueue.postEvent(mAsyncPrepareEvent);
1935
1936 return OK;
1937}
1938
Andreas Huberffdf4782010-02-09 14:05:43 -08001939status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001940 sp<DataSource> dataSource;
1941
Andreas Huber77d8dc22011-04-21 10:06:43 -07001942 bool isWidevineStreaming = false;
1943 if (!strncasecmp("widevine://", mUri.string(), 11)) {
1944 isWidevineStreaming = true;
1945
1946 String8 newURI = String8("http://");
1947 newURI.append(mUri.string() + 11);
1948
1949 mUri = newURI;
1950 }
1951
Andreas Huberb8e651a2011-12-05 11:34:43 -08001952 AString sniffedMIME;
1953
Andreas Huber118a1502011-02-17 13:35:08 -08001954 if (!strncasecmp("http://", mUri.string(), 7)
Andreas Huber77d8dc22011-04-21 10:06:43 -07001955 || !strncasecmp("https://", mUri.string(), 8)
1956 || isWidevineStreaming) {
Andreas Huber5f5719e2011-03-08 15:59:28 -08001957 mConnectingDataSource = HTTPBase::Create(
1958 (mFlags & INCOGNITO)
1959 ? HTTPBase::kFlagIncognito
1960 : 0);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001961
Andreas Huber603d7392011-06-30 15:47:02 -07001962 if (mUIDValid) {
1963 mConnectingDataSource->setUID(mUID);
1964 }
1965
Andreas Huber7f325942011-10-07 13:40:45 -07001966 String8 cacheConfig;
1967 bool disconnectAtHighwatermark;
1968 NuCachedSource2::RemoveCacheSpecificHeaders(
1969 &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
1970
Andreas Huberedbb4d82010-03-12 08:59:22 -08001971 mLock.unlock();
Andreas Huber3a53dc52010-06-11 09:57:46 -07001972 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001973 mLock.lock();
1974
1975 if (err != OK) {
1976 mConnectingDataSource.clear();
1977
Steve Block6215d3f2012-01-04 20:05:49 +00001978 ALOGI("mConnectingDataSource->connect() returned %d", err);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001979 return err;
1980 }
1981
Andreas Huber77d8dc22011-04-21 10:06:43 -07001982 if (!isWidevineStreaming) {
1983 // The widevine extractor does its own caching.
1984
Andreas Huber4d61f602010-06-10 11:17:50 -07001985#if 0
Andreas Huber77d8dc22011-04-21 10:06:43 -07001986 mCachedSource = new NuCachedSource2(
1987 new ThrottledSource(
1988 mConnectingDataSource, 50 * 1024 /* bytes/sec */));
Andreas Huber4d61f602010-06-10 11:17:50 -07001989#else
Andreas Huber7f325942011-10-07 13:40:45 -07001990 mCachedSource = new NuCachedSource2(
1991 mConnectingDataSource,
1992 cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
1993 disconnectAtHighwatermark);
Andreas Huber4d61f602010-06-10 11:17:50 -07001994#endif
Andreas Huber4d61f602010-06-10 11:17:50 -07001995
Andreas Huber77d8dc22011-04-21 10:06:43 -07001996 dataSource = mCachedSource;
1997 } else {
1998 dataSource = mConnectingDataSource;
Andreas Huber96346652011-01-19 15:07:19 -08001999 }
2000
Andreas Huberedbb4d82010-03-12 08:59:22 -08002001 mConnectingDataSource.clear();
Andreas Huber4d61f602010-06-10 11:17:50 -07002002
Andreas Hubera2e57ca2011-03-30 11:15:27 -07002003 String8 contentType = dataSource->getMIMEType();
Andreas Huber96346652011-01-19 15:07:19 -08002004
Andreas Hubera2e57ca2011-03-30 11:15:27 -07002005 if (strncasecmp(contentType.string(), "audio/", 6)) {
2006 // We're not doing this for streams that appear to be audio-only
2007 // streams to ensure that even low bandwidth streams start
2008 // playing back fairly instantly.
Andreas Huber96346652011-01-19 15:07:19 -08002009
Andreas Hubera2e57ca2011-03-30 11:15:27 -07002010 // We're going to prefill the cache before trying to instantiate
2011 // the extractor below, as the latter is an operation that otherwise
2012 // could block on the datasource for a significant amount of time.
2013 // During that time we'd be unable to abort the preparation phase
2014 // without this prefill.
James Dongba43d422011-05-19 08:49:09 -07002015 if (mCachedSource != NULL) {
2016 // We're going to prefill the cache before trying to instantiate
2017 // the extractor below, as the latter is an operation that otherwise
2018 // could block on the datasource for a significant amount of time.
2019 // During that time we'd be unable to abort the preparation phase
2020 // without this prefill.
Andreas Huber96346652011-01-19 15:07:19 -08002021
James Dongba43d422011-05-19 08:49:09 -07002022 mLock.unlock();
Andreas Hubera2e57ca2011-03-30 11:15:27 -07002023
Andreas Huber7dea9aa2011-12-07 12:50:47 -08002024 // Initially make sure we have at least 192 KB for the sniff
Andreas Huberb8e651a2011-12-05 11:34:43 -08002025 // to complete without blocking.
Andreas Huber7dea9aa2011-12-07 12:50:47 -08002026 static const size_t kMinBytesForSniffing = 192 * 1024;
Andreas Huberb8e651a2011-12-05 11:34:43 -08002027
2028 off64_t metaDataSize = -1ll;
James Dongba43d422011-05-19 08:49:09 -07002029 for (;;) {
2030 status_t finalStatus;
2031 size_t cachedDataRemaining =
2032 mCachedSource->approxDataRemaining(&finalStatus);
Andreas Hubera2e57ca2011-03-30 11:15:27 -07002033
Andreas Huberb8e651a2011-12-05 11:34:43 -08002034 if (finalStatus != OK
2035 || (metaDataSize >= 0
2036 && cachedDataRemaining >= metaDataSize)
James Dongba43d422011-05-19 08:49:09 -07002037 || (mFlags & PREPARE_CANCELLED)) {
2038 break;
2039 }
2040
Andreas Huber68d2f952011-12-05 13:30:52 -08002041 ALOGV("now cached %d bytes of data", cachedDataRemaining);
Andreas Huberb8e651a2011-12-05 11:34:43 -08002042
2043 if (metaDataSize < 0
2044 && cachedDataRemaining >= kMinBytesForSniffing) {
2045 String8 tmp;
2046 float confidence;
2047 sp<AMessage> meta;
2048 if (!dataSource->sniff(&tmp, &confidence, &meta)) {
2049 mLock.lock();
2050 return UNKNOWN_ERROR;
2051 }
2052
2053 // We successfully identified the file's extractor to
2054 // be, remember this mime type so we don't have to
2055 // sniff it again when we call MediaExtractor::Create()
2056 // below.
2057 sniffedMIME = tmp.string();
2058
2059 if (meta == NULL
2060 || !meta->findInt64(
2061 "meta-data-size", &metaDataSize)) {
2062 metaDataSize = kHighWaterMarkBytes;
2063 }
2064
2065 CHECK_GE(metaDataSize, 0ll);
Andreas Huber68d2f952011-12-05 13:30:52 -08002066 ALOGV("metaDataSize = %lld bytes", metaDataSize);
Andreas Huberb8e651a2011-12-05 11:34:43 -08002067 }
2068
James Dongba43d422011-05-19 08:49:09 -07002069 usleep(200000);
Andreas Hubera2e57ca2011-03-30 11:15:27 -07002070 }
2071
James Dongba43d422011-05-19 08:49:09 -07002072 mLock.lock();
Andreas Huber96346652011-01-19 15:07:19 -08002073 }
2074
James Dongba43d422011-05-19 08:49:09 -07002075 if (mFlags & PREPARE_CANCELLED) {
Steve Block6215d3f2012-01-04 20:05:49 +00002076 ALOGI("Prepare cancelled while waiting for initial cache fill.");
James Dongba43d422011-05-19 08:49:09 -07002077 return UNKNOWN_ERROR;
2078 }
Andreas Huber96346652011-01-19 15:07:19 -08002079 }
Andreas Huberedbb4d82010-03-12 08:59:22 -08002080 } else {
2081 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
2082 }
Andreas Huberffdf4782010-02-09 14:05:43 -08002083
2084 if (dataSource == NULL) {
2085 return UNKNOWN_ERROR;
2086 }
2087
Andreas Huber77d8dc22011-04-21 10:06:43 -07002088 sp<MediaExtractor> extractor;
Andreas Huberffdf4782010-02-09 14:05:43 -08002089
Andreas Huber77d8dc22011-04-21 10:06:43 -07002090 if (isWidevineStreaming) {
2091 String8 mimeType;
2092 float confidence;
2093 sp<AMessage> dummy;
James Dongd70c64d2011-12-14 10:57:05 -08002094 bool success = SniffDRM(dataSource, &mimeType, &confidence, &dummy);
Andreas Huber77d8dc22011-04-21 10:06:43 -07002095
2096 if (!success
2097 || strcasecmp(
2098 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
2099 return ERROR_UNSUPPORTED;
2100 }
2101
2102 mWVMExtractor = new WVMExtractor(dataSource);
2103 mWVMExtractor->setAdaptiveStreamingMode(true);
2104 extractor = mWVMExtractor;
2105 } else {
Andreas Huberb8e651a2011-12-05 11:34:43 -08002106 extractor = MediaExtractor::Create(
2107 dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
Andreas Huber77d8dc22011-04-21 10:06:43 -07002108
2109 if (extractor == NULL) {
2110 return UNKNOWN_ERROR;
2111 }
Andreas Huberffdf4782010-02-09 14:05:43 -08002112 }
2113
James Dongd70c64d2011-12-14 10:57:05 -08002114 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
Gloria Wangae775272011-02-24 16:40:57 -08002115
James Dongd70c64d2011-12-14 10:57:05 -08002116 if (mDecryptHandle != NULL) {
2117 CHECK(mDrmManagerClient);
2118 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
2119 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
Gloria Wangc2c22e72010-11-01 15:53:16 -07002120 }
Gloria Wangd5770912010-06-22 13:55:38 -07002121 }
2122
Andreas Huber77d8dc22011-04-21 10:06:43 -07002123 status_t err = setDataSource_l(extractor);
2124
2125 if (err != OK) {
2126 mWVMExtractor.clear();
2127
2128 return err;
2129 }
2130
2131 return OK;
Andreas Huberffdf4782010-02-09 14:05:43 -08002132}
2133
Andreas Huber3ac94ef2010-03-05 10:42:10 -08002134void AwesomePlayer::abortPrepare(status_t err) {
2135 CHECK(err != OK);
2136
2137 if (mIsAsyncPrepare) {
2138 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2139 }
2140
2141 mPrepareResult = err;
Andreas Huberfddf5d92011-06-07 15:52:25 -07002142 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08002143 mAsyncPrepareEvent = NULL;
2144 mPreparedCondition.broadcast();
2145}
2146
Andreas Huberf71daba2010-03-24 09:24:40 -07002147// static
2148bool AwesomePlayer::ContinuePreparation(void *cookie) {
2149 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
2150
2151 return (me->mFlags & PREPARE_CANCELLED) == 0;
2152}
2153
Andreas Huber6be780e2010-02-08 14:40:30 -08002154void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber87ab9cd2010-09-03 13:20:33 -07002155 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08002156
Andreas Huber87ab9cd2010-09-03 13:20:33 -07002157 if (mFlags & PREPARE_CANCELLED) {
Steve Block6215d3f2012-01-04 20:05:49 +00002158 ALOGI("prepare was cancelled before doing anything");
Andreas Huber87ab9cd2010-09-03 13:20:33 -07002159 abortPrepare(UNKNOWN_ERROR);
2160 return;
2161 }
2162
2163 if (mUri.size() > 0) {
2164 status_t err = finishSetDataSource_l();
2165
2166 if (err != OK) {
2167 abortPrepare(err);
Andreas Huberedbb4d82010-03-12 08:59:22 -08002168 return;
2169 }
Andreas Huber6be780e2010-02-08 14:40:30 -08002170 }
2171
Andreas Huber87ab9cd2010-09-03 13:20:33 -07002172 if (mVideoTrack != NULL && mVideoSource == NULL) {
2173 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08002174
Andreas Huber87ab9cd2010-09-03 13:20:33 -07002175 if (err != OK) {
2176 abortPrepare(err);
2177 return;
2178 }
2179 }
2180
2181 if (mAudioTrack != NULL && mAudioSource == NULL) {
2182 status_t err = initAudioDecoder();
2183
2184 if (err != OK) {
2185 abortPrepare(err);
2186 return;
2187 }
2188 }
2189
Andreas Huberfddf5d92011-06-07 15:52:25 -07002190 modifyFlags(PREPARING_CONNECTED, SET);
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07002191
Andreas Hubera6be6dc2011-10-11 15:24:07 -07002192 if (isStreamingHTTP()) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -07002193 postBufferingEvent_l();
2194 } else {
2195 finishAsyncPrepare_l();
2196 }
2197}
2198
2199void AwesomePlayer::finishAsyncPrepare_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08002200 if (mIsAsyncPrepare) {
Andreas Hubere3c01832010-08-16 08:49:37 -07002201 if (mVideoSource == NULL) {
Andreas Huberffdf4782010-02-09 14:05:43 -08002202 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
2203 } else {
Andreas Hubere3c01832010-08-16 08:49:37 -07002204 notifyVideoSize_l();
Andreas Huberffdf4782010-02-09 14:05:43 -08002205 }
2206
2207 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08002208 }
2209
Andreas Huberffdf4782010-02-09 14:05:43 -08002210 mPrepareResult = OK;
Andreas Huberfddf5d92011-06-07 15:52:25 -07002211 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2212 modifyFlags(PREPARED, SET);
Andreas Huber6be780e2010-02-08 14:40:30 -08002213 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08002214 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -08002215}
2216
Andreas Huber62f7ffe2010-05-06 10:18:05 -07002217uint32_t AwesomePlayer::flags() const {
2218 return mExtractorFlags;
2219}
2220
Andreas Huber4dc482d2011-03-22 10:31:21 -07002221void AwesomePlayer::postAudioEOS(int64_t delayUs) {
Andreas Huber67a041f2011-09-01 11:39:11 -07002222 postCheckAudioStatusEvent(delayUs);
Andreas Huber2b359ed2010-09-28 11:56:39 -07002223}
2224
2225void AwesomePlayer::postAudioSeekComplete() {
Andreas Huber67a041f2011-09-01 11:39:11 -07002226 postCheckAudioStatusEvent(0);
Andreas Huber2b359ed2010-09-28 11:56:39 -07002227}
2228
Gloria Wangd01ec6e2011-04-25 17:28:22 -07002229status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
Gloria Wang13bc8cd2011-05-11 11:24:09 -07002230 switch (key) {
2231 case KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX:
2232 {
2233 Mutex::Autolock autoLock(mTimedTextLock);
2234 return setTimedTextTrackIndex(request.readInt32());
2235 }
2236 case KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE:
2237 {
2238 Mutex::Autolock autoLock(mTimedTextLock);
2239 if (mTextPlayer == NULL) {
2240 mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
2241 }
2242
2243 return mTextPlayer->setParameter(key, request);
2244 }
James Donga9d0feb2011-05-25 19:37:03 -07002245 case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
2246 {
2247 return setCacheStatCollectFreq(request);
2248 }
Gloria Wang13bc8cd2011-05-11 11:24:09 -07002249 default:
2250 {
2251 return ERROR_UNSUPPORTED;
2252 }
Gloria Wangc6091dd2011-05-03 15:59:03 -07002253 }
Gloria Wangd01ec6e2011-04-25 17:28:22 -07002254}
2255
James Donga9d0feb2011-05-25 19:37:03 -07002256status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
2257 if (mCachedSource != NULL) {
2258 int32_t freqMs = request.readInt32();
Steve Block5baa3a62011-12-20 16:23:08 +00002259 ALOGD("Request to keep cache stats in the past %d ms",
James Donga9d0feb2011-05-25 19:37:03 -07002260 freqMs);
2261 return mCachedSource->setCacheStatCollectFreq(freqMs);
2262 }
2263 return ERROR_UNSUPPORTED;
2264}
2265
Gloria Wangd01ec6e2011-04-25 17:28:22 -07002266status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
Glenn Kasten6ff9b812011-07-25 09:26:22 -07002267 switch (key) {
2268 case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
2269 {
2270 int32_t channelCount;
2271 if (mAudioTrack == 0 ||
2272 !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
2273 channelCount = 0;
2274 }
2275 reply->writeInt32(channelCount);
2276 }
2277 return OK;
2278 default:
2279 {
2280 return ERROR_UNSUPPORTED;
2281 }
2282 }
Gloria Wangd01ec6e2011-04-25 17:28:22 -07002283}
Andreas Huber27366fc2009-11-20 09:32:46 -08002284
Andreas Huber77d8dc22011-04-21 10:06:43 -07002285bool AwesomePlayer::isStreamingHTTP() const {
2286 return mCachedSource != NULL || mWVMExtractor != NULL;
2287}
2288
Andreas Huberfddf5d92011-06-07 15:52:25 -07002289status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
2290 Mutex::Autolock autoLock(mStatsLock);
2291
2292 FILE *out = fdopen(dup(fd), "w");
2293
2294 fprintf(out, " AwesomePlayer\n");
2295 if (mStats.mFd < 0) {
2296 fprintf(out, " URI(%s)", mStats.mURI.string());
2297 } else {
2298 fprintf(out, " fd(%d)", mStats.mFd);
2299 }
2300
2301 fprintf(out, ", flags(0x%08x)", mStats.mFlags);
2302
2303 if (mStats.mBitrate >= 0) {
2304 fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
2305 }
2306
2307 fprintf(out, "\n");
2308
2309 for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
2310 const TrackStat &stat = mStats.mTracks.itemAt(i);
2311
2312 fprintf(out, " Track %d\n", i + 1);
2313 fprintf(out, " MIME(%s)", stat.mMIME.string());
2314
2315 if (!stat.mDecoderName.isEmpty()) {
2316 fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
2317 }
2318
2319 fprintf(out, "\n");
2320
2321 if ((ssize_t)i == mStats.mVideoTrackIndex) {
2322 fprintf(out,
2323 " videoDimensions(%d x %d), "
2324 "numVideoFramesDecoded(%lld), "
2325 "numVideoFramesDropped(%lld)\n",
2326 mStats.mVideoWidth,
2327 mStats.mVideoHeight,
2328 mStats.mNumVideoFramesDecoded,
2329 mStats.mNumVideoFramesDropped);
2330 }
2331 }
2332
2333 fclose(out);
2334 out = NULL;
2335
2336 return OK;
2337}
2338
2339void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
2340 switch (mode) {
2341 case SET:
2342 mFlags |= value;
2343 break;
2344 case CLEAR:
2345 mFlags &= ~value;
2346 break;
2347 case ASSIGN:
2348 mFlags = value;
2349 break;
2350 default:
2351 TRESPASS();
2352 }
2353
2354 {
2355 Mutex::Autolock autoLock(mStatsLock);
2356 mStats.mFlags = mFlags;
2357 }
2358}
2359
Andreas Huber27366fc2009-11-20 09:32:46 -08002360} // namespace android