blob: bd281180b9849471da43737a8b4638e0d7765285 [file] [log] [blame]
Andreas Huberbfa6b2d2009-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 Kasten6c009832011-04-13 11:16:49 -070017#undef DEBUG_HDCP
Glenn Kasteneabd3462011-03-23 14:34:31 -070018
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080019//#define LOG_NDEBUG 0
20#define LOG_TAG "AwesomePlayer"
Jamie Gennis21633202012-05-11 04:42:12 -070021#define ATRACE_TAG ATRACE_TAG_VIDEO
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080022#include <utils/Log.h>
Jamie Gennis21633202012-05-11 04:42:12 -070023#include <utils/Trace.h>
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080024
Andreas Huber988e3f02010-02-11 11:00:26 -080025#include <dlfcn.h>
26
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080027#include "include/AwesomePlayer.h"
Andreas Huber681755f2011-04-21 10:06:43 -070028#include "include/DRMExtractor.h"
Andreas Huber733b7722009-12-14 14:18:22 -080029#include "include/SoftwareRenderer.h"
Andreas Huber0a5baa92010-06-10 11:17:50 -070030#include "include/NuCachedSource2.h"
31#include "include/ThrottledSource.h"
Andreas Huberbff07d02010-10-12 11:34:37 -070032#include "include/MPEG2TSExtractor.h"
Andreas Huber681755f2011-04-21 10:06:43 -070033#include "include/WVMExtractor.h"
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080034
Andreas Huber4844ac52009-12-10 15:32:12 -080035#include <binder/IPCThreadState.h>
Gloria Wang7cf180c2011-02-19 18:37:57 -080036#include <binder/IServiceManager.h>
37#include <media/IMediaPlayerService.h>
Andreas Hubere2b10282010-11-23 11:41:34 -080038#include <media/stagefright/foundation/hexdump.h>
39#include <media/stagefright/foundation/ADebug.h>
Insun Kang3254b252012-02-27 17:14:28 +090040#include <media/stagefright/timedtext/TimedTextDriver.h>
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080041#include <media/stagefright/AudioPlayer.h>
42#include <media/stagefright/DataSource.h>
43#include <media/stagefright/FileSource.h>
44#include <media/stagefright/MediaBuffer.h>
Andreas Huber717826e2010-01-05 10:54:55 -080045#include <media/stagefright/MediaDefs.h>
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080046#include <media/stagefright/MediaExtractor.h>
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080047#include <media/stagefright/MediaSource.h>
48#include <media/stagefright/MetaData.h>
49#include <media/stagefright/OMXCodec.h>
Andreas Huber717826e2010-01-05 10:54:55 -080050
Andy McFadden484566c2012-12-18 09:46:54 -080051#include <gui/IGraphicBufferProducer.h>
Mathias Agopianb1e7cd12013-02-14 17:11:27 -080052#include <gui/Surface.h>
Mathias Agopian3cf61352010-02-09 17:46:37 -080053
Andreas Huber14acc732010-12-06 10:36:06 -080054#include <media/stagefright/foundation/AMessage.h>
Andreas Hubere71d10e2010-06-07 14:35:29 -070055
Glenn Kasteneabd3462011-03-23 14:34:31 -070056#include <cutils/properties.h>
57
Andreas Hubere332a912010-11-15 09:03:03 -080058#define USE_SURFACE_ALLOC 1
James Dong14f95742011-08-11 17:38:35 -070059#define FRAME_DROP_FREQ 0
Andreas Hubere332a912010-11-15 09:03:03 -080060
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080061namespace android {
62
Andreas Huber8650e192010-09-03 13:20:33 -070063static int64_t kLowWaterMarkUs = 2000000ll; // 2secs
Gloria Wang83ed9d42011-08-10 14:19:05 -070064static int64_t kHighWaterMarkUs = 5000000ll; // 5secs
Andreas Huberac05c312011-01-19 15:07:19 -080065static const size_t kLowWaterMarkBytes = 40000;
66static const size_t kHighWaterMarkBytes = 200000;
Andreas Huber8650e192010-09-03 13:20:33 -070067
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080068struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huberc23f12a2010-02-08 14:40:30 -080069 AwesomeEvent(
70 AwesomePlayer *player,
71 void (AwesomePlayer::*method)())
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080072 : mPlayer(player),
Andreas Huberc23f12a2010-02-08 14:40:30 -080073 mMethod(method) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080074 }
75
76protected:
77 virtual ~AwesomeEvent() {}
78
79 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huberc23f12a2010-02-08 14:40:30 -080080 (mPlayer->*mMethod)();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080081 }
82
83private:
84 AwesomePlayer *mPlayer;
Andreas Huberc23f12a2010-02-08 14:40:30 -080085 void (AwesomePlayer::*mMethod)();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080086
87 AwesomeEvent(const AwesomeEvent &);
88 AwesomeEvent &operator=(const AwesomeEvent &);
89};
90
Andreas Huber733b7722009-12-14 14:18:22 -080091struct AwesomeLocalRenderer : public AwesomeRenderer {
92 AwesomeLocalRenderer(
Glenn Kasten11731182011-02-08 17:26:17 -080093 const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta)
94 : mTarget(new SoftwareRenderer(nativeWindow, meta)) {
Andreas Huber733b7722009-12-14 14:18:22 -080095 }
96
97 virtual void render(MediaBuffer *buffer) {
Andreas Huberfa090f52010-02-12 14:40:08 -080098 render((const uint8_t *)buffer->data() + buffer->range_offset(),
99 buffer->range_length());
100 }
101
102 void render(const void *data, size_t size) {
103 mTarget->render(data, size, NULL);
Andreas Huber733b7722009-12-14 14:18:22 -0800104 }
105
106protected:
107 virtual ~AwesomeLocalRenderer() {
108 delete mTarget;
109 mTarget = NULL;
110 }
111
112private:
Andreas Huber0a5ca662010-11-16 13:05:53 -0800113 SoftwareRenderer *mTarget;
Andreas Huber988e3f02010-02-11 11:00:26 -0800114
Andreas Huber733b7722009-12-14 14:18:22 -0800115 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
116 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
117};
118
Jamie Gennis6a9da9f2010-10-07 14:08:38 -0700119struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
Andreas Huberba529e42010-11-16 15:26:30 -0800120 AwesomeNativeWindowRenderer(
121 const sp<ANativeWindow> &nativeWindow,
122 int32_t rotationDegrees)
Jamie Gennis6a9da9f2010-10-07 14:08:38 -0700123 : mNativeWindow(nativeWindow) {
Andreas Huberba529e42010-11-16 15:26:30 -0800124 applyRotation(rotationDegrees);
Jamie Gennis6a9da9f2010-10-07 14:08:38 -0700125 }
126
127 virtual void render(MediaBuffer *buffer) {
Jamie Gennis21633202012-05-11 04:42:12 -0700128 ATRACE_CALL();
Glenn Kasten593e2772011-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 Gennis6a9da9f2010-10-07 14:08:38 -0700132 status_t err = mNativeWindow->queueBuffer(
Jamie Gennis1e5b2b32012-06-13 16:29:51 -0700133 mNativeWindow.get(), buffer->graphicBuffer().get(), -1);
Jamie Gennis6a9da9f2010-10-07 14:08:38 -0700134 if (err != 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000135 ALOGE("queueBuffer failed with error %s (%d)", strerror(-err),
Jamie Gennis6a9da9f2010-10-07 14:08:38 -0700136 -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 Huberba529e42010-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 Gennis6a9da9f2010-10-07 14:08:38 -0700166 AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
167 AwesomeNativeWindowRenderer &operator=(
168 const AwesomeNativeWindowRenderer &);
169};
170
Gloria Wang7cf180c2011-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 Hubere2b10282010-11-23 11:41:34 -0800177
Gloria Wang7cf180c2011-02-19 18:37:57 -0800178 service->addBatteryData(params);
179}
180
181////////////////////////////////////////////////////////////////////////////////
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800182AwesomePlayer::AwesomePlayer()
Andreas Huber2e8ffaf2010-02-18 16:45:13 -0800183 : mQueueStarted(false),
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700184 mUIDValid(false),
Andreas Huber2e8ffaf2010-02-18 16:45:13 -0800185 mTimeSource(NULL),
James Dongc374dae2012-07-19 19:18:06 -0700186 mVideoRenderingStarted(false),
Andreas Huberfa090f52010-02-12 14:40:08 -0800187 mVideoRendererIsPreview(false),
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800188 mAudioPlayer(NULL),
James Dongb45c01c2011-01-16 11:30:13 -0800189 mDisplayWidth(0),
190 mDisplayHeight(0),
James Dong4f6eed02012-04-30 14:38:12 -0700191 mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
Andreas Huberbd22c522010-02-09 14:05:43 -0800192 mFlags(0),
Andreas Huberacdd9d02010-05-06 10:18:05 -0700193 mExtractorFlags(0),
Andreas Huber7b3396a2010-02-12 10:42:02 -0800194 mVideoBuffer(NULL),
Andreas Huber150694c2011-03-14 10:55:40 -0700195 mDecryptHandle(NULL),
Gloria Wang7a1e3e82011-05-03 15:59:03 -0700196 mLastVideoTimeUs(-1),
Insun Kang66551742012-01-11 22:03:12 +0900197 mTextDriver(NULL) {
Andreas Hubere2b10282010-11-23 11:41:34 -0800198 CHECK_EQ(mClient.connect(), (status_t)OK);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800199
200 DataSource::RegisterDefaultSniffers();
201
Andreas Huberc23f12a2010-02-08 14:40:30 -0800202 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800203 mVideoEventPending = false;
Andreas Huberc23f12a2010-02-08 14:40:30 -0800204 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800205 mStreamDoneEventPending = false;
Andreas Huberc23f12a2010-02-08 14:40:30 -0800206 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huber66b0a352010-01-26 16:20:10 -0800207 mBufferingEventPending = false;
Andreas Huber145e68f2011-01-11 15:05:28 -0800208 mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
209 mVideoEventPending = false;
Andreas Huberc23f12a2010-02-08 14:40:30 -0800210
211 mCheckAudioStatusEvent = new AwesomeEvent(
212 this, &AwesomePlayer::onCheckAudioStatus);
213
Andreas Huber1862a332010-02-03 11:37:29 -0800214 mAudioStatusEventPending = false;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800215
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800216 reset();
217}
218
219AwesomePlayer::~AwesomePlayer() {
Andreas Huber2e8ffaf2010-02-18 16:45:13 -0800220 if (mQueueStarted) {
221 mQueue.stop();
222 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800223
224 reset();
225
226 mClient.disconnect();
227}
228
Andreas Huberc34233e2011-11-16 10:46:05 -0800229void AwesomePlayer::cancelPlayerEvents(bool keepNotifications) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800230 mQueue.cancelEvent(mVideoEvent->eventID());
231 mVideoEventPending = false;
Andreas Huber145e68f2011-01-11 15:05:28 -0800232 mQueue.cancelEvent(mVideoLagEvent->eventID());
233 mVideoLagEventPending = false;
Andreas Huber66b0a352010-01-26 16:20:10 -0800234
Andreas Huberc34233e2011-11-16 10:46:05 -0800235 if (!keepNotifications) {
236 mQueue.cancelEvent(mStreamDoneEvent->eventID());
237 mStreamDoneEventPending = false;
238 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
239 mAudioStatusEventPending = false;
240
Andreas Huber66b0a352010-01-26 16:20:10 -0800241 mQueue.cancelEvent(mBufferingEvent->eventID());
242 mBufferingEventPending = false;
243 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800244}
245
Andreas Huber07260452010-01-21 10:28:45 -0800246void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800247 Mutex::Autolock autoLock(mLock);
248 mListener = listener;
249}
250
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700251void AwesomePlayer::setUID(uid_t uid) {
Steve Block3856b092011-10-20 11:56:00 +0100252 ALOGV("AwesomePlayer running on behalf of uid %d", uid);
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700253
254 mUID = uid;
255 mUIDValid = true;
256}
257
Andreas Huber5561ccf2010-01-27 16:49:05 -0800258status_t AwesomePlayer::setDataSource(
259 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800260 Mutex::Autolock autoLock(mLock);
Andreas Huber7b3396a2010-02-12 10:42:02 -0800261 return setDataSource_l(uri, headers);
262}
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800263
Andreas Huber7b3396a2010-02-12 10:42:02 -0800264status_t AwesomePlayer::setDataSource_l(
265 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800266 reset_l();
267
Andreas Huberbd22c522010-02-09 14:05:43 -0800268 mUri = uri;
Andreas Huber66b0a352010-01-26 16:20:10 -0800269
Andreas Huberbd22c522010-02-09 14:05:43 -0800270 if (headers) {
271 mUriHeaders = *headers;
Andreas Huber7314fa12011-02-24 14:42:48 -0800272
273 ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));
274 if (index >= 0) {
275 // Browser is in "incognito" mode, suppress logging URLs.
276
277 // This isn't something that should be passed to the server.
278 mUriHeaders.removeItemsAt(index);
279
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700280 modifyFlags(INCOGNITO, SET);
Andreas Huber7314fa12011-02-24 14:42:48 -0800281 }
282 }
283
James Dong53ae1642012-08-17 13:41:59 -0700284 ALOGI("setDataSource_l(URL suppressed)");
Andreas Huber66b0a352010-01-26 16:20:10 -0800285
Andreas Huberbd22c522010-02-09 14:05:43 -0800286 // The actual work will be done during preparation in the call to
287 // ::finishSetDataSource_l to avoid blocking the calling thread in
288 // setDataSource for any significant time.
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800289
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700290 {
291 Mutex::Autolock autoLock(mStatsLock);
292 mStats.mFd = -1;
293 mStats.mURI = mUri;
294 }
295
Andreas Huberbd22c522010-02-09 14:05:43 -0800296 return OK;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800297}
298
299status_t AwesomePlayer::setDataSource(
300 int fd, int64_t offset, int64_t length) {
301 Mutex::Autolock autoLock(mLock);
302
303 reset_l();
304
Andreas Huber7b3396a2010-02-12 10:42:02 -0800305 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800306
Andreas Huber7b3396a2010-02-12 10:42:02 -0800307 status_t err = dataSource->initCheck();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800308
309 if (err != OK) {
310 return err;
311 }
312
Andreas Huber7b3396a2010-02-12 10:42:02 -0800313 mFileSource = dataSource;
314
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700315 {
316 Mutex::Autolock autoLock(mStatsLock);
317 mStats.mFd = fd;
318 mStats.mURI = String8();
319 }
320
Andreas Huber7b3396a2010-02-12 10:42:02 -0800321 return setDataSource_l(dataSource);
322}
323
Andreas Hubere2b10282010-11-23 11:41:34 -0800324status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
Andreas Huber85704832010-12-16 10:16:36 -0800325 return INVALID_OPERATION;
Andreas Hubere2b10282010-11-23 11:41:34 -0800326}
327
Andreas Huber7b3396a2010-02-12 10:42:02 -0800328status_t AwesomePlayer::setDataSource_l(
329 const sp<DataSource> &dataSource) {
330 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800331
332 if (extractor == NULL) {
333 return UNKNOWN_ERROR;
334 }
335
James Dong9d2f3862012-01-10 08:24:37 -0800336 if (extractor->getDrmFlag()) {
337 checkDrmStatus(dataSource);
338 }
339
340 return setDataSource_l(extractor);
341}
342
343void AwesomePlayer::checkDrmStatus(const sp<DataSource>& dataSource) {
James Dong785ee062011-12-14 10:57:05 -0800344 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
345 if (mDecryptHandle != NULL) {
346 CHECK(mDrmManagerClient);
347 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
348 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
Gloria Wang8f641342011-02-08 13:24:08 -0800349 }
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700350 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800351}
352
353status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber7fbdb092010-10-12 16:55:11 -0700354 // Attempt to approximate overall stream bitrate by summing all
355 // tracks' individual bitrates, if not all of them advertise bitrate,
356 // we have to fail.
357
358 int64_t totalBitRate = 0;
359
James Dongeec46ab2012-04-11 17:56:22 -0700360 mExtractor = extractor;
Andreas Huber7fbdb092010-10-12 16:55:11 -0700361 for (size_t i = 0; i < extractor->countTracks(); ++i) {
362 sp<MetaData> meta = extractor->getTrackMetaData(i);
363
364 int32_t bitrate;
365 if (!meta->findInt32(kKeyBitRate, &bitrate)) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700366 const char *mime;
367 CHECK(meta->findCString(kKeyMIMEType, &mime));
Steve Block3856b092011-10-20 11:56:00 +0100368 ALOGV("track of type '%s' does not publish bitrate", mime);
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700369
Andreas Huber7fbdb092010-10-12 16:55:11 -0700370 totalBitRate = -1;
371 break;
372 }
373
374 totalBitRate += bitrate;
375 }
376
377 mBitrate = totalBitRate;
378
Steve Block3856b092011-10-20 11:56:00 +0100379 ALOGV("mBitrate = %lld bits/sec", mBitrate);
Andreas Huber7fbdb092010-10-12 16:55:11 -0700380
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700381 {
382 Mutex::Autolock autoLock(mStatsLock);
383 mStats.mBitrate = mBitrate;
384 mStats.mTracks.clear();
385 mStats.mAudioTrackIndex = -1;
386 mStats.mVideoTrackIndex = -1;
387 }
388
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800389 bool haveAudio = false;
390 bool haveVideo = false;
391 for (size_t i = 0; i < extractor->countTracks(); ++i) {
392 sp<MetaData> meta = extractor->getTrackMetaData(i);
393
Andreas Huber32bdfd52011-10-26 11:22:40 -0700394 const char *_mime;
395 CHECK(meta->findCString(kKeyMIMEType, &_mime));
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800396
Andreas Huber32bdfd52011-10-26 11:22:40 -0700397 String8 mime = String8(_mime);
398
399 if (!haveVideo && !strncasecmp(mime.string(), "video/", 6)) {
Andreas Huber88d8a832010-03-05 10:42:10 -0800400 setVideoSource(extractor->getTrack(i));
401 haveVideo = true;
James Dongb45c01c2011-01-16 11:30:13 -0800402
403 // Set the presentation/display size
404 int32_t displayWidth, displayHeight;
405 bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
406 if (success) {
407 success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
408 }
409 if (success) {
410 mDisplayWidth = displayWidth;
411 mDisplayHeight = displayHeight;
412 }
413
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700414 {
415 Mutex::Autolock autoLock(mStatsLock);
416 mStats.mVideoTrackIndex = mStats.mTracks.size();
417 mStats.mTracks.push();
418 TrackStat *stat =
419 &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
Andreas Huber32bdfd52011-10-26 11:22:40 -0700420 stat->mMIME = mime.string();
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700421 }
Andreas Huber32bdfd52011-10-26 11:22:40 -0700422 } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) {
Andreas Huber88d8a832010-03-05 10:42:10 -0800423 setAudioSource(extractor->getTrack(i));
424 haveAudio = true;
James Dongab7a2e52012-04-26 17:11:28 -0700425 mActiveAudioTrackIndex = i;
Andreas Huber8ae49d82010-09-03 14:09:21 -0700426
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700427 {
428 Mutex::Autolock autoLock(mStatsLock);
429 mStats.mAudioTrackIndex = mStats.mTracks.size();
430 mStats.mTracks.push();
431 TrackStat *stat =
432 &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
Andreas Huber32bdfd52011-10-26 11:22:40 -0700433 stat->mMIME = mime.string();
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700434 }
435
Andreas Huber32bdfd52011-10-26 11:22:40 -0700436 if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_AUDIO_VORBIS)) {
Andreas Huber69545352010-10-04 11:09:31 -0700437 // Only do this for vorbis audio, none of the other audio
438 // formats even support this ringtone specific hack and
439 // retrieving the metadata on some extractors may turn out
440 // to be very expensive.
441 sp<MetaData> fileMeta = extractor->getMetaData();
442 int32_t loop;
443 if (fileMeta != NULL
444 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700445 modifyFlags(AUTO_LOOPING, SET);
Andreas Huber69545352010-10-04 11:09:31 -0700446 }
Andreas Huber8ae49d82010-09-03 14:09:21 -0700447 }
Andreas Huber32bdfd52011-10-26 11:22:40 -0700448 } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
Edwin Wong6a3969c2012-05-02 18:57:12 -0700449 addTextSource_l(i, extractor->getTrack(i));
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800450 }
451 }
452
Andreas Huberacdd9d02010-05-06 10:18:05 -0700453 if (!haveAudio && !haveVideo) {
Edwin Wongac1b7162012-09-06 14:07:37 -0700454 if (mWVMExtractor != NULL) {
455 return mWVMExtractor->getError();
456 } else {
457 return UNKNOWN_ERROR;
458 }
Andreas Huberacdd9d02010-05-06 10:18:05 -0700459 }
460
461 mExtractorFlags = extractor->flags();
462
463 return OK;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800464}
465
466void AwesomePlayer::reset() {
467 Mutex::Autolock autoLock(mLock);
468 reset_l();
469}
470
471void AwesomePlayer::reset_l() {
James Dongc374dae2012-07-19 19:18:06 -0700472 mVideoRenderingStarted = false;
James Dongab7a2e52012-04-26 17:11:28 -0700473 mActiveAudioTrackIndex = -1;
James Dongb45c01c2011-01-16 11:30:13 -0800474 mDisplayWidth = 0;
475 mDisplayHeight = 0;
Andreas Huber65a170e2011-01-04 10:19:13 -0800476
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700477 if (mDecryptHandle != NULL) {
478 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
479 Playback::STOP, 0);
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700480 mDecryptHandle = NULL;
481 mDrmManagerClient = NULL;
482 }
483
Gloria Wang7cf180c2011-02-19 18:37:57 -0800484 if (mFlags & PLAYING) {
485 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
486 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
487 params |= IMediaPlayerService::kBatteryDataTrackAudio;
488 }
489 if (mVideoSource != NULL) {
490 params |= IMediaPlayerService::kBatteryDataTrackVideo;
491 }
492 addBatteryData(params);
493 }
494
Andreas Hubere94bd142010-03-12 08:59:22 -0800495 if (mFlags & PREPARING) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700496 modifyFlags(PREPARE_CANCELLED, SET);
Andreas Hubere94bd142010-03-12 08:59:22 -0800497 if (mConnectingDataSource != NULL) {
Steve Blockdf64d152012-01-04 20:05:49 +0000498 ALOGI("interrupting the connection process");
Andreas Hubere94bd142010-03-12 08:59:22 -0800499 mConnectingDataSource->disconnect();
500 }
Andreas Huber6a05c9e2010-10-19 12:18:51 -0700501
502 if (mFlags & PREPARING_CONNECTED) {
503 // We are basically done preparing, we're just buffering
504 // enough data to start playback, we can safely interrupt that.
505 finishAsyncPrepare_l();
506 }
Andreas Hubere94bd142010-03-12 08:59:22 -0800507 }
508
Andreas Huberbd22c522010-02-09 14:05:43 -0800509 while (mFlags & PREPARING) {
510 mPreparedCondition.wait(mLock);
511 }
512
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800513 cancelPlayerEvents();
514
Andreas Huber681755f2011-04-21 10:06:43 -0700515 mWVMExtractor.clear();
Andreas Huber0a5baa92010-06-10 11:17:50 -0700516 mCachedSource.clear();
Andreas Huber88d8a832010-03-05 10:42:10 -0800517 mAudioTrack.clear();
518 mVideoTrack.clear();
James Dongeec46ab2012-04-11 17:56:22 -0700519 mExtractor.clear();
Andreas Huber88d8a832010-03-05 10:42:10 -0800520
Andreas Huber7b3396a2010-02-12 10:42:02 -0800521 // Shutdown audio first, so that the respone to the reset request
522 // appears to happen instantaneously as far as the user is concerned
523 // If we did this later, audio would continue playing while we
524 // shutdown the video-related resources and the player appear to
525 // not be as responsive to a reset request.
Gloria Wang5b75fdc2011-08-31 10:24:18 -0700526 if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
527 && mAudioSource != NULL) {
Andreas Hubere94bd142010-03-12 08:59:22 -0800528 // If we had an audio player, it would have effectively
529 // taken possession of the audio source and stopped it when
530 // _it_ is stopped. Otherwise this is still our responsibility.
531 mAudioSource->stop();
532 }
Andreas Huber7b3396a2010-02-12 10:42:02 -0800533 mAudioSource.clear();
534
Andreas Huber7b3396a2010-02-12 10:42:02 -0800535 mTimeSource = NULL;
536
537 delete mAudioPlayer;
538 mAudioPlayer = NULL;
539
Insun Kang66551742012-01-11 22:03:12 +0900540 if (mTextDriver != NULL) {
541 delete mTextDriver;
542 mTextDriver = NULL;
Gloria Wang7a1e3e82011-05-03 15:59:03 -0700543 }
544
Andreas Huberb9280d52010-01-22 14:36:53 -0800545 mVideoRenderer.clear();
546
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800547 if (mVideoSource != NULL) {
Andreas Huber150694c2011-03-14 10:55:40 -0700548 shutdownVideoDecoder_l();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800549 }
550
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800551 mDurationUs = -1;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700552 modifyFlags(0, ASSIGN);
Andreas Huberacdd9d02010-05-06 10:18:05 -0700553 mExtractorFlags = 0;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800554 mTimeSourceDeltaUs = 0;
555 mVideoTimeUs = 0;
556
Andreas Huber64bb6982011-02-24 12:05:40 -0800557 mSeeking = NO_SEEK;
Gloria Wangaf64a8a2011-08-18 14:52:36 -0700558 mSeekNotificationSent = true;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800559 mSeekTimeUs = 0;
Andreas Huber66b0a352010-01-26 16:20:10 -0800560
Andreas Huberbd22c522010-02-09 14:05:43 -0800561 mUri.setTo("");
562 mUriHeaders.clear();
Andreas Huber7b3396a2010-02-12 10:42:02 -0800563
564 mFileSource.clear();
565
Andreas Huber7fbdb092010-10-12 16:55:11 -0700566 mBitrate = -1;
Andreas Huber150694c2011-03-14 10:55:40 -0700567 mLastVideoTimeUs = -1;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700568
569 {
570 Mutex::Autolock autoLock(mStatsLock);
571 mStats.mFd = -1;
572 mStats.mURI = String8();
573 mStats.mBitrate = -1;
574 mStats.mAudioTrackIndex = -1;
575 mStats.mVideoTrackIndex = -1;
576 mStats.mNumVideoFramesDecoded = 0;
577 mStats.mNumVideoFramesDropped = 0;
578 mStats.mVideoWidth = -1;
579 mStats.mVideoHeight = -1;
580 mStats.mFlags = 0;
581 mStats.mTracks.clear();
582 }
583
Andreas Huber99590d22011-08-16 12:41:41 -0700584 mWatchForAudioSeekComplete = false;
585 mWatchForAudioEOS = false;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800586}
587
Andreas Huberc23f12a2010-02-08 14:40:30 -0800588void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Huber07260452010-01-21 10:28:45 -0800589 if (mListener != NULL) {
590 sp<MediaPlayerBase> listener = mListener.promote();
591
592 if (listener != NULL) {
Andreas Huberc23f12a2010-02-08 14:40:30 -0800593 listener->sendEvent(msg, ext1, ext2);
Andreas Huber07260452010-01-21 10:28:45 -0800594 }
595 }
596}
597
Andreas Huber7fbdb092010-10-12 16:55:11 -0700598bool AwesomePlayer::getBitrate(int64_t *bitrate) {
James Dongc7fc37a2010-11-16 14:04:54 -0800599 off64_t size;
Andreas Huber7fbdb092010-10-12 16:55:11 -0700600 if (mDurationUs >= 0 && mCachedSource != NULL
601 && mCachedSource->getSize(&size) == OK) {
602 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec
603 return true;
604 }
605
606 if (mBitrate >= 0) {
607 *bitrate = mBitrate;
608 return true;
609 }
610
611 *bitrate = 0;
612
613 return false;
614}
615
Andreas Huber8650e192010-09-03 13:20:33 -0700616// Returns true iff cached duration is available/applicable.
617bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
Andreas Huber7fbdb092010-10-12 16:55:11 -0700618 int64_t bitrate;
Andreas Huber8650e192010-09-03 13:20:33 -0700619
Andreas Huber2bfdd422011-10-11 15:24:07 -0700620 if (mCachedSource != NULL && getBitrate(&bitrate)) {
Bryan Mawhinney1bd233c2011-01-18 19:12:21 +0000621 status_t finalStatus;
622 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
Andreas Huber8650e192010-09-03 13:20:33 -0700623 *durationUs = cachedDataRemaining * 8000000ll / bitrate;
Bryan Mawhinney1bd233c2011-01-18 19:12:21 +0000624 *eos = (finalStatus != OK);
Andreas Huber8650e192010-09-03 13:20:33 -0700625 return true;
Andreas Huber681755f2011-04-21 10:06:43 -0700626 } else if (mWVMExtractor != NULL) {
627 status_t finalStatus;
628 *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus);
629 *eos = (finalStatus != OK);
630 return true;
Andreas Huber8650e192010-09-03 13:20:33 -0700631 }
632
633 return false;
634}
635
Andreas Huber34ef0f32010-11-11 15:37:17 -0800636void AwesomePlayer::ensureCacheIsFetching_l() {
637 if (mCachedSource != NULL) {
638 mCachedSource->resumeFetchingIfNecessary();
639 }
640}
641
Andreas Huber145e68f2011-01-11 15:05:28 -0800642void AwesomePlayer::onVideoLagUpdate() {
643 Mutex::Autolock autoLock(mLock);
644 if (!mVideoLagEventPending) {
645 return;
646 }
647 mVideoLagEventPending = false;
648
649 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
650 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
651
Andreas Huber5dac87b2011-03-25 13:03:14 -0700652 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
Steve Block3856b092011-10-20 11:56:00 +0100653 ALOGV("video late by %lld ms.", videoLateByUs / 1000ll);
Andreas Huber145e68f2011-01-11 15:05:28 -0800654
655 notifyListener_l(
656 MEDIA_INFO,
657 MEDIA_INFO_VIDEO_TRACK_LAGGING,
658 videoLateByUs / 1000ll);
659 }
660
661 postVideoLagEvent_l();
662}
663
Andreas Huber66b0a352010-01-26 16:20:10 -0800664void AwesomePlayer::onBufferingUpdate() {
665 Mutex::Autolock autoLock(mLock);
Andreas Huberd29345d2010-02-17 15:58:57 -0800666 if (!mBufferingEventPending) {
667 return;
668 }
Andreas Huber66b0a352010-01-26 16:20:10 -0800669 mBufferingEventPending = false;
670
Andreas Huber8650e192010-09-03 13:20:33 -0700671 if (mCachedSource != NULL) {
Bryan Mawhinney1bd233c2011-01-18 19:12:21 +0000672 status_t finalStatus;
673 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
674 bool eos = (finalStatus != OK);
Andreas Huberc9e89482010-09-01 15:05:28 -0700675
Andreas Huber8650e192010-09-03 13:20:33 -0700676 if (eos) {
Bryan Mawhinney1bd233c2011-01-18 19:12:21 +0000677 if (finalStatus == ERROR_END_OF_STREAM) {
678 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
679 }
Andreas Huber83977eb2010-10-04 11:36:39 -0700680 if (mFlags & PREPARING) {
Steve Block3856b092011-10-20 11:56:00 +0100681 ALOGV("cache has reached EOS, prepare is done.");
Andreas Huber83977eb2010-10-04 11:36:39 -0700682 finishAsyncPrepare_l();
683 }
Andreas Huber8650e192010-09-03 13:20:33 -0700684 } else {
Andreas Huber7fbdb092010-10-12 16:55:11 -0700685 int64_t bitrate;
686 if (getBitrate(&bitrate)) {
Andreas Huber8650e192010-09-03 13:20:33 -0700687 size_t cachedSize = mCachedSource->cachedSize();
688 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
689
690 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
691 if (percentage > 100) {
692 percentage = 100;
693 }
694
695 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
696 } else {
697 // We don't know the bitrate of the stream, use absolute size
698 // limits to maintain the cache.
699
Andreas Huber8650e192010-09-03 13:20:33 -0700700 if ((mFlags & PLAYING) && !eos
701 && (cachedDataRemaining < kLowWaterMarkBytes)) {
Steve Blockdf64d152012-01-04 20:05:49 +0000702 ALOGI("cache is running low (< %d) , pausing.",
Andreas Huber8650e192010-09-03 13:20:33 -0700703 kLowWaterMarkBytes);
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700704 modifyFlags(CACHE_UNDERRUN, SET);
Andreas Huber8650e192010-09-03 13:20:33 -0700705 pause_l();
Andreas Huber34ef0f32010-11-11 15:37:17 -0800706 ensureCacheIsFetching_l();
James Dong5b1b8a92011-05-25 19:37:03 -0700707 sendCacheStats();
Andreas Huber8650e192010-09-03 13:20:33 -0700708 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
709 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
710 if (mFlags & CACHE_UNDERRUN) {
Steve Blockdf64d152012-01-04 20:05:49 +0000711 ALOGI("cache has filled up (> %d), resuming.",
Andreas Huber8650e192010-09-03 13:20:33 -0700712 kHighWaterMarkBytes);
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700713 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber8650e192010-09-03 13:20:33 -0700714 play_l();
Andreas Huber8650e192010-09-03 13:20:33 -0700715 } else if (mFlags & PREPARING) {
Steve Block3856b092011-10-20 11:56:00 +0100716 ALOGV("cache has filled up (> %d), prepare is done",
Andreas Huber8650e192010-09-03 13:20:33 -0700717 kHighWaterMarkBytes);
718 finishAsyncPrepare_l();
719 }
720 }
721 }
722 }
Andreas Huber681755f2011-04-21 10:06:43 -0700723 } else if (mWVMExtractor != NULL) {
724 status_t finalStatus;
725
726 int64_t cachedDurationUs
727 = mWVMExtractor->getCachedDurationUs(&finalStatus);
728
729 bool eos = (finalStatus != OK);
730
731 if (eos) {
732 if (finalStatus == ERROR_END_OF_STREAM) {
733 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
734 }
735 if (mFlags & PREPARING) {
Steve Block3856b092011-10-20 11:56:00 +0100736 ALOGV("cache has reached EOS, prepare is done.");
Andreas Huber681755f2011-04-21 10:06:43 -0700737 finishAsyncPrepare_l();
738 }
739 } else {
740 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
741 if (percentage > 100) {
742 percentage = 100;
743 }
744
745 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
746 }
Andreas Huber8650e192010-09-03 13:20:33 -0700747 }
748
749 int64_t cachedDurationUs;
750 bool eos;
751 if (getCachedDuration_l(&cachedDurationUs, &eos)) {
Steve Block3856b092011-10-20 11:56:00 +0100752 ALOGV("cachedDurationUs = %.2f secs, eos=%d",
Andreas Huber34ef0f32010-11-11 15:37:17 -0800753 cachedDurationUs / 1E6, eos);
754
Andreas Huberc9e89482010-09-01 15:05:28 -0700755 if ((mFlags & PLAYING) && !eos
Andreas Huber8650e192010-09-03 13:20:33 -0700756 && (cachedDurationUs < kLowWaterMarkUs)) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700757 modifyFlags(CACHE_UNDERRUN, SET);
Jeff Tinker25d542d2012-10-01 12:57:48 -0700758 ALOGI("cache is running low (%.2f secs) , pausing.",
759 cachedDurationUs / 1E6);
760 pause_l();
761 ensureCacheIsFetching_l();
Jeffrey Tinkerf10f36d2012-08-23 01:56:53 -0700762 sendCacheStats();
Andreas Huberc9e89482010-09-01 15:05:28 -0700763 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700764 } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
Andreas Huber8650e192010-09-03 13:20:33 -0700765 if (mFlags & CACHE_UNDERRUN) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700766 modifyFlags(CACHE_UNDERRUN, CLEAR);
Jeff Tinker25d542d2012-10-01 12:57:48 -0700767 ALOGI("cache has filled up (%.2f secs), resuming.",
768 cachedDurationUs / 1E6);
769 play_l();
Andreas Huber8650e192010-09-03 13:20:33 -0700770 } else if (mFlags & PREPARING) {
Steve Block3856b092011-10-20 11:56:00 +0100771 ALOGV("cache has filled up (%.2f secs), prepare is done",
Andreas Huber8650e192010-09-03 13:20:33 -0700772 cachedDurationUs / 1E6);
773 finishAsyncPrepare_l();
Andreas Huber2a4b49b2010-08-25 12:31:48 -0700774 }
Andreas Huber2a4b49b2010-08-25 12:31:48 -0700775 }
Andreas Huber66b0a352010-01-26 16:20:10 -0800776 }
Andreas Huber0a5baa92010-06-10 11:17:50 -0700777
Andreas Huber0a5baa92010-06-10 11:17:50 -0700778 postBufferingEvent_l();
Andreas Huber66b0a352010-01-26 16:20:10 -0800779}
780
James Dong5b1b8a92011-05-25 19:37:03 -0700781void AwesomePlayer::sendCacheStats() {
782 sp<MediaPlayerBase> listener = mListener.promote();
Jeffrey Tinkerf10f36d2012-08-23 01:56:53 -0700783 if (listener != NULL) {
James Dong5b1b8a92011-05-25 19:37:03 -0700784 int32_t kbps = 0;
Jeffrey Tinkerf10f36d2012-08-23 01:56:53 -0700785 status_t err = UNKNOWN_ERROR;
786 if (mCachedSource != NULL) {
787 err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
788 } else if (mWVMExtractor != NULL) {
789 err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps);
790 }
James Dong5b1b8a92011-05-25 19:37:03 -0700791 if (err == OK) {
792 listener->sendEvent(
793 MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
794 }
795 }
796}
797
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800798void AwesomePlayer::onStreamDone() {
799 // Posted whenever any stream finishes playing.
Jamie Gennis21633202012-05-11 04:42:12 -0700800 ATRACE_CALL();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800801
802 Mutex::Autolock autoLock(mLock);
Andreas Huberd29345d2010-02-17 15:58:57 -0800803 if (!mStreamDoneEventPending) {
804 return;
805 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800806 mStreamDoneEventPending = false;
807
Andreas Hubered8d14f2011-02-16 09:05:38 -0800808 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100809 ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
Andreas Huber5d2de4d2010-07-07 13:35:27 -0700810
811 notifyListener_l(
812 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
813
Andreas Huberb2e39542010-10-05 10:25:34 -0700814 pause_l(true /* at eos */);
Andreas Huber5d2de4d2010-07-07 13:35:27 -0700815
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700816 modifyFlags(AT_EOS, SET);
Andreas Huber5d2de4d2010-07-07 13:35:27 -0700817 return;
818 }
819
820 const bool allDone =
821 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
822 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
823
824 if (!allDone) {
825 return;
826 }
827
Andreas Hubercdef6982011-08-18 10:53:23 -0700828 if ((mFlags & LOOPING)
829 || ((mFlags & AUTO_LOOPING)
830 && (mAudioSink == NULL || mAudioSink->realtime()))) {
831 // Don't AUTO_LOOP if we're being recorded, since that cannot be
832 // turned off and recording would go on indefinitely.
833
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800834 seekTo_l(0);
835
Andreas Hubera657f8d2010-02-03 16:02:02 -0800836 if (mVideoSource != NULL) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800837 postVideoEvent_l();
838 }
839 } else {
Steve Block3856b092011-10-20 11:56:00 +0100840 ALOGV("MEDIA_PLAYBACK_COMPLETE");
Andreas Huber5d2de4d2010-07-07 13:35:27 -0700841 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800842
Andreas Huberb2e39542010-10-05 10:25:34 -0700843 pause_l(true /* at eos */);
Andreas Huber2e8ffaf2010-02-18 16:45:13 -0800844
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700845 modifyFlags(AT_EOS, SET);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800846 }
847}
848
849status_t AwesomePlayer::play() {
Jamie Gennis21633202012-05-11 04:42:12 -0700850 ATRACE_CALL();
851
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800852 Mutex::Autolock autoLock(mLock);
Andreas Huber0a5baa92010-06-10 11:17:50 -0700853
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700854 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber0a5baa92010-06-10 11:17:50 -0700855
Andreas Huber7b3396a2010-02-12 10:42:02 -0800856 return play_l();
857}
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800858
Andreas Huber7b3396a2010-02-12 10:42:02 -0800859status_t AwesomePlayer::play_l() {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700860 modifyFlags(SEEK_PREVIEW, CLEAR);
Andreas Huber2b1222f2011-02-07 11:43:12 -0800861
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800862 if (mFlags & PLAYING) {
863 return OK;
864 }
865
Andreas Huberbd22c522010-02-09 14:05:43 -0800866 if (!(mFlags & PREPARED)) {
867 status_t err = prepare_l();
868
869 if (err != OK) {
870 return err;
871 }
872 }
873
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700874 modifyFlags(PLAYING, SET);
875 modifyFlags(FIRST_FRAME, SET);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800876
Gloria Wangc130b5b2010-11-04 17:38:39 -0700877 if (mDecryptHandle != NULL) {
878 int64_t position;
879 getPosition(&position);
880 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
881 Playback::START, position / 1000);
882 }
883
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800884 if (mAudioSource != NULL) {
885 if (mAudioPlayer == NULL) {
886 if (mAudioSink != NULL) {
Eric Laurent1948eb32012-04-13 16:50:19 -0700887 bool allowDeepBuffering;
888 int64_t cachedDurationUs;
889 bool eos;
James Dongab7a2e52012-04-26 17:11:28 -0700890 if (mVideoSource == NULL
891 && (mDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US ||
892 (getCachedDuration_l(&cachedDurationUs, &eos) &&
893 cachedDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US))) {
Eric Laurent1948eb32012-04-13 16:50:19 -0700894 allowDeepBuffering = true;
895 } else {
896 allowDeepBuffering = false;
897 }
898
899 mAudioPlayer = new AudioPlayer(mAudioSink, allowDeepBuffering, this);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800900 mAudioPlayer->setSource(mAudioSource);
Andreas Hubere7e3b782010-03-08 15:46:13 -0800901
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800902 mTimeSource = mAudioPlayer;
903
Andreas Huberb874cd02011-03-16 10:41:25 -0700904 // If there was a seek request before we ever started,
905 // honor the request now.
906 // Make sure to do this before starting the audio player
907 // to avoid a race condition.
908 seekAudioIfNecessary_l();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800909 }
Andreas Huberf0303442011-02-11 13:09:36 -0800910 }
911
912 CHECK(!(mFlags & AUDIO_RUNNING));
913
914 if (mVideoSource == NULL) {
Andreas Huber5442cb52011-07-14 13:02:47 -0700915 // We don't want to post an error notification at this point,
916 // the error returned from MediaPlayer::start() will suffice.
917
918 status_t err = startAudioPlayer_l(
919 false /* sendErrorNotification */);
Andreas Huberf0303442011-02-11 13:09:36 -0800920
921 if (err != OK) {
922 delete mAudioPlayer;
923 mAudioPlayer = NULL;
924
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700925 modifyFlags((PLAYING | FIRST_FRAME), CLEAR);
Andreas Huberf0303442011-02-11 13:09:36 -0800926
927 if (mDecryptHandle != NULL) {
928 mDrmManagerClient->setPlaybackStatus(
929 mDecryptHandle, Playback::STOP, 0);
930 }
931
932 return err;
933 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800934 }
935 }
936
937 if (mTimeSource == NULL && mAudioPlayer == NULL) {
Andreas Huber5d2de4d2010-07-07 13:35:27 -0700938 mTimeSource = &mSystemTimeSource;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800939 }
940
941 if (mVideoSource != NULL) {
Andreas Hubera657f8d2010-02-03 16:02:02 -0800942 // Kick off video playback
943 postVideoEvent_l();
Andreas Huber145e68f2011-01-11 15:05:28 -0800944
945 if (mAudioSource != NULL && mVideoSource != NULL) {
946 postVideoLagEvent_l();
947 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800948 }
949
Andreas Huber2e8ffaf2010-02-18 16:45:13 -0800950 if (mFlags & AT_EOS) {
951 // Legacy behaviour, if a stream finishes playing and then
952 // is started again, we play from the start...
953 seekTo_l(0);
954 }
955
Gloria Wang7cf180c2011-02-19 18:37:57 -0800956 uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
957 | IMediaPlayerService::kBatteryDataTrackDecoder;
958 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
959 params |= IMediaPlayerService::kBatteryDataTrackAudio;
960 }
961 if (mVideoSource != NULL) {
962 params |= IMediaPlayerService::kBatteryDataTrackVideo;
963 }
964 addBatteryData(params);
965
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800966 return OK;
967}
968
Andreas Huber5442cb52011-07-14 13:02:47 -0700969status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
Andreas Huberf0303442011-02-11 13:09:36 -0800970 CHECK(!(mFlags & AUDIO_RUNNING));
971
972 if (mAudioSource == NULL || mAudioPlayer == NULL) {
973 return OK;
974 }
975
976 if (!(mFlags & AUDIOPLAYER_STARTED)) {
Andreas Huberc0dfc5b2011-05-10 13:56:39 -0700977 bool wasSeeking = mAudioPlayer->isSeeking();
978
Andreas Huberf0303442011-02-11 13:09:36 -0800979 // We've already started the MediaSource in order to enable
980 // the prefetcher to read its data.
981 status_t err = mAudioPlayer->start(
982 true /* sourceAlreadyStarted */);
983
984 if (err != OK) {
Andreas Huber5442cb52011-07-14 13:02:47 -0700985 if (sendErrorNotification) {
986 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
987 }
988
Andreas Huberf0303442011-02-11 13:09:36 -0800989 return err;
990 }
Andreas Huberc0dfc5b2011-05-10 13:56:39 -0700991
Andreas Hubera6490c62012-05-22 10:51:06 -0700992 modifyFlags(AUDIOPLAYER_STARTED, SET);
993
Andreas Huberc0dfc5b2011-05-10 13:56:39 -0700994 if (wasSeeking) {
995 CHECK(!mAudioPlayer->isSeeking());
996
997 // We will have finished the seek while starting the audio player.
Andreas Huber02f6e982011-09-01 11:39:11 -0700998 postAudioSeekComplete();
Andreas Huberc0dfc5b2011-05-10 13:56:39 -0700999 }
Andreas Huberf0303442011-02-11 13:09:36 -08001000 } else {
1001 mAudioPlayer->resume();
1002 }
1003
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001004 modifyFlags(AUDIO_RUNNING, SET);
Andreas Huberf0303442011-02-11 13:09:36 -08001005
1006 mWatchForAudioEOS = true;
1007
1008 return OK;
1009}
1010
Andreas Huber5daeb122010-08-16 08:49:37 -07001011void AwesomePlayer::notifyVideoSize_l() {
Jamie Gennis21633202012-05-11 04:42:12 -07001012 ATRACE_CALL();
Andreas Huber5daeb122010-08-16 08:49:37 -07001013 sp<MetaData> meta = mVideoSource->getFormat();
1014
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001015 int32_t cropLeft, cropTop, cropRight, cropBottom;
1016 if (!meta->findRect(
1017 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
1018 int32_t width, height;
1019 CHECK(meta->findInt32(kKeyWidth, &width));
1020 CHECK(meta->findInt32(kKeyHeight, &height));
1021
1022 cropLeft = cropTop = 0;
1023 cropRight = width - 1;
1024 cropBottom = height - 1;
1025
Steve Block3856b092011-10-20 11:56:00 +01001026 ALOGV("got dimensions only %d x %d", width, height);
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001027 } else {
Steve Block3856b092011-10-20 11:56:00 +01001028 ALOGV("got crop rect %d, %d, %d, %d",
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001029 cropLeft, cropTop, cropRight, cropBottom);
1030 }
1031
James Dong9cbb1a62011-03-18 12:19:43 -07001032 int32_t displayWidth;
1033 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
Steve Block3856b092011-10-20 11:56:00 +01001034 ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
James Dong9cbb1a62011-03-18 12:19:43 -07001035 mDisplayWidth = displayWidth;
1036 }
1037 int32_t displayHeight;
1038 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
Steve Block3856b092011-10-20 11:56:00 +01001039 ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
James Dong9cbb1a62011-03-18 12:19:43 -07001040 mDisplayHeight = displayHeight;
1041 }
1042
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001043 int32_t usableWidth = cropRight - cropLeft + 1;
1044 int32_t usableHeight = cropBottom - cropTop + 1;
James Dongb45c01c2011-01-16 11:30:13 -08001045 if (mDisplayWidth != 0) {
1046 usableWidth = mDisplayWidth;
1047 }
1048 if (mDisplayHeight != 0) {
1049 usableHeight = mDisplayHeight;
1050 }
Andreas Huber5daeb122010-08-16 08:49:37 -07001051
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001052 {
1053 Mutex::Autolock autoLock(mStatsLock);
1054 mStats.mVideoWidth = usableWidth;
1055 mStats.mVideoHeight = usableHeight;
1056 }
1057
Andreas Huberba529e42010-11-16 15:26:30 -08001058 int32_t rotationDegrees;
1059 if (!mVideoTrack->getFormat()->findInt32(
1060 kKeyRotation, &rotationDegrees)) {
1061 rotationDegrees = 0;
1062 }
1063
1064 if (rotationDegrees == 90 || rotationDegrees == 270) {
1065 notifyListener_l(
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001066 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
Andreas Huberba529e42010-11-16 15:26:30 -08001067 } else {
1068 notifyListener_l(
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001069 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
Andreas Huberba529e42010-11-16 15:26:30 -08001070 }
Andreas Huber5daeb122010-08-16 08:49:37 -07001071}
1072
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001073void AwesomePlayer::initRenderer_l() {
Jamie Gennis21633202012-05-11 04:42:12 -07001074 ATRACE_CALL();
1075
Glenn Kasten11731182011-02-08 17:26:17 -08001076 if (mNativeWindow == NULL) {
Andreas Huber0a5ca662010-11-16 13:05:53 -08001077 return;
1078 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001079
Andreas Huber0a5ca662010-11-16 13:05:53 -08001080 sp<MetaData> meta = mVideoSource->getFormat();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001081
Andreas Huber0a5ca662010-11-16 13:05:53 -08001082 int32_t format;
1083 const char *component;
1084 int32_t decodedWidth, decodedHeight;
1085 CHECK(meta->findInt32(kKeyColorFormat, &format));
1086 CHECK(meta->findCString(kKeyDecoderComponent, &component));
1087 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
1088 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
Andreas Huber4844ac52009-12-10 15:32:12 -08001089
Andreas Huberba529e42010-11-16 15:26:30 -08001090 int32_t rotationDegrees;
1091 if (!mVideoTrack->getFormat()->findInt32(
1092 kKeyRotation, &rotationDegrees)) {
1093 rotationDegrees = 0;
1094 }
1095
Andreas Huber0a5ca662010-11-16 13:05:53 -08001096 mVideoRenderer.clear();
Andreas Huber4844ac52009-12-10 15:32:12 -08001097
Andreas Huber0a5ca662010-11-16 13:05:53 -08001098 // Must ensure that mVideoRenderer's destructor is actually executed
1099 // before creating a new one.
1100 IPCThreadState::self()->flushCommands();
1101
James Dong4f6eed02012-04-30 14:38:12 -07001102 // Even if set scaling mode fails, we will continue anyway
1103 setVideoScalingMode_l(mVideoScalingMode);
Andreas Huberbbba88c2011-05-11 14:13:42 -07001104 if (USE_SURFACE_ALLOC
1105 && !strncmp(component, "OMX.", 4)
Andreas Huber2944eca2011-09-08 14:12:44 -07001106 && strncmp(component, "OMX.google.", 11)
1107 && strcmp(component, "OMX.Nvidia.mpeg2v.decode")) {
Andreas Huber0a5ca662010-11-16 13:05:53 -08001108 // Hardware decoders avoid the CPU color conversion by decoding
1109 // directly to ANativeBuffers, so we must use a renderer that
1110 // just pushes those buffers to the ANativeWindow.
Andreas Huberba529e42010-11-16 15:26:30 -08001111 mVideoRenderer =
Glenn Kasten11731182011-02-08 17:26:17 -08001112 new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
Andreas Huber0a5ca662010-11-16 13:05:53 -08001113 } else {
1114 // Other decoders are instantiated locally and as a consequence
1115 // allocate their buffers in local address space. This renderer
1116 // then performs a color conversion and copy to get the data
1117 // into the ANativeBuffer.
Glenn Kasten11731182011-02-08 17:26:17 -08001118 mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001119 }
1120}
1121
1122status_t AwesomePlayer::pause() {
Jamie Gennis21633202012-05-11 04:42:12 -07001123 ATRACE_CALL();
1124
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001125 Mutex::Autolock autoLock(mLock);
Andreas Huber0a5baa92010-06-10 11:17:50 -07001126
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001127 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber0a5baa92010-06-10 11:17:50 -07001128
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001129 return pause_l();
1130}
1131
Andreas Huberb2e39542010-10-05 10:25:34 -07001132status_t AwesomePlayer::pause_l(bool at_eos) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001133 if (!(mFlags & PLAYING)) {
1134 return OK;
1135 }
1136
Andreas Huberc34233e2011-11-16 10:46:05 -08001137 cancelPlayerEvents(true /* keepNotifications */);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001138
Andreas Huberf0303442011-02-11 13:09:36 -08001139 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huberb2e39542010-10-05 10:25:34 -07001140 if (at_eos) {
1141 // If we played the audio stream to completion we
1142 // want to make sure that all samples remaining in the audio
1143 // track's queue are played out.
1144 mAudioPlayer->pause(true /* playPendingSamples */);
1145 } else {
1146 mAudioPlayer->pause();
1147 }
Andreas Huberf0303442011-02-11 13:09:36 -08001148
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001149 modifyFlags(AUDIO_RUNNING, CLEAR);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001150 }
1151
Insun Kangf9d660a2012-02-16 20:28:27 +09001152 if (mFlags & TEXTPLAYER_INITIALIZED) {
Insun Kang66551742012-01-11 22:03:12 +09001153 mTextDriver->pause();
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001154 modifyFlags(TEXT_RUNNING, CLEAR);
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001155 }
1156
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001157 modifyFlags(PLAYING, CLEAR);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001158
Gloria Wangdcd25ef2010-06-22 13:55:38 -07001159 if (mDecryptHandle != NULL) {
1160 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1161 Playback::PAUSE, 0);
1162 }
1163
Gloria Wang7cf180c2011-02-19 18:37:57 -08001164 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
1165 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
1166 params |= IMediaPlayerService::kBatteryDataTrackAudio;
1167 }
1168 if (mVideoSource != NULL) {
1169 params |= IMediaPlayerService::kBatteryDataTrackVideo;
1170 }
1171
1172 addBatteryData(params);
1173
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001174 return OK;
1175}
1176
1177bool AwesomePlayer::isPlaying() const {
Andreas Huber0a5baa92010-06-10 11:17:50 -07001178 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001179}
1180
Andy McFadden484566c2012-12-18 09:46:54 -08001181status_t AwesomePlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) {
Glenn Kasten11731182011-02-08 17:26:17 -08001182 Mutex::Autolock autoLock(mLock);
1183
Andreas Huber63970b42011-08-29 13:01:23 -07001184 status_t err;
Andy McFadden484566c2012-12-18 09:46:54 -08001185 if (bufferProducer != NULL) {
Mathias Agopianb1e7cd12013-02-14 17:11:27 -08001186 err = setNativeWindow_l(new Surface(bufferProducer));
Gloria Wang80ec9292011-08-09 15:29:34 -07001187 } else {
Andreas Huber63970b42011-08-29 13:01:23 -07001188 err = setNativeWindow_l(NULL);
Andreas Huber150694c2011-03-14 10:55:40 -07001189 }
Andreas Huber63970b42011-08-29 13:01:23 -07001190
1191 return err;
Andreas Huber150694c2011-03-14 10:55:40 -07001192}
1193
1194void AwesomePlayer::shutdownVideoDecoder_l() {
1195 if (mVideoBuffer) {
1196 mVideoBuffer->release();
1197 mVideoBuffer = NULL;
Glenn Kasten11731182011-02-08 17:26:17 -08001198 }
1199
Andreas Huber150694c2011-03-14 10:55:40 -07001200 mVideoSource->stop();
1201
1202 // The following hack is necessary to ensure that the OMX
1203 // component is completely released by the time we may try
1204 // to instantiate it again.
1205 wp<MediaSource> tmp = mVideoSource;
1206 mVideoSource.clear();
1207 while (tmp.promote() != NULL) {
1208 usleep(1000);
1209 }
1210 IPCThreadState::self()->flushCommands();
Steve Block3856b092011-10-20 11:56:00 +01001211 ALOGV("video decoder shutdown completed");
Andreas Huber150694c2011-03-14 10:55:40 -07001212}
1213
Andreas Huber63970b42011-08-29 13:01:23 -07001214status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
Andreas Huber150694c2011-03-14 10:55:40 -07001215 mNativeWindow = native;
1216
1217 if (mVideoSource == NULL) {
Andreas Huber63970b42011-08-29 13:01:23 -07001218 return OK;
Andreas Huber150694c2011-03-14 10:55:40 -07001219 }
1220
Steve Block3856b092011-10-20 11:56:00 +01001221 ALOGV("attempting to reconfigure to use new surface");
Andreas Huber150694c2011-03-14 10:55:40 -07001222
1223 bool wasPlaying = (mFlags & PLAYING) != 0;
1224
1225 pause_l();
1226 mVideoRenderer.clear();
1227
1228 shutdownVideoDecoder_l();
1229
Andreas Huber63970b42011-08-29 13:01:23 -07001230 status_t err = initVideoDecoder();
1231
1232 if (err != OK) {
Steve Block29357bc2012-01-06 19:20:56 +00001233 ALOGE("failed to reinstantiate video decoder after surface change.");
Andreas Huber63970b42011-08-29 13:01:23 -07001234 return err;
1235 }
Andreas Huber150694c2011-03-14 10:55:40 -07001236
1237 if (mLastVideoTimeUs >= 0) {
1238 mSeeking = SEEK;
Andreas Huber150694c2011-03-14 10:55:40 -07001239 mSeekTimeUs = mLastVideoTimeUs;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001240 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
Andreas Huber150694c2011-03-14 10:55:40 -07001241 }
1242
1243 if (wasPlaying) {
1244 play_l();
1245 }
Andreas Huber63970b42011-08-29 13:01:23 -07001246
1247 return OK;
Andreas Huber5daeb122010-08-16 08:49:37 -07001248}
1249
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001250void AwesomePlayer::setAudioSink(
1251 const sp<MediaPlayerBase::AudioSink> &audioSink) {
1252 Mutex::Autolock autoLock(mLock);
1253
1254 mAudioSink = audioSink;
1255}
1256
1257status_t AwesomePlayer::setLooping(bool shouldLoop) {
1258 Mutex::Autolock autoLock(mLock);
1259
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001260 modifyFlags(LOOPING, CLEAR);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001261
1262 if (shouldLoop) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001263 modifyFlags(LOOPING, SET);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001264 }
1265
1266 return OK;
1267}
1268
1269status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber2415ecb2010-03-26 10:17:17 -07001270 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001271
1272 if (mDurationUs < 0) {
1273 return UNKNOWN_ERROR;
1274 }
1275
1276 *durationUs = mDurationUs;
1277
1278 return OK;
1279}
1280
1281status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Huber2bfdd422011-10-11 15:24:07 -07001282 if (mSeeking != NO_SEEK) {
Andreas Huberdac4ee72010-04-07 10:24:35 -07001283 *positionUs = mSeekTimeUs;
Andreas Huber5dac87b2011-03-25 13:03:14 -07001284 } else if (mVideoSource != NULL
1285 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
Andreas Huber2415ecb2010-03-26 10:17:17 -07001286 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001287 *positionUs = mVideoTimeUs;
1288 } else if (mAudioPlayer != NULL) {
1289 *positionUs = mAudioPlayer->getMediaTimeUs();
1290 } else {
1291 *positionUs = 0;
1292 }
1293
1294 return OK;
1295}
1296
1297status_t AwesomePlayer::seekTo(int64_t timeUs) {
Jamie Gennis21633202012-05-11 04:42:12 -07001298 ATRACE_CALL();
1299
Andreas Huber70f521d2010-10-08 10:16:24 -07001300 if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
Andreas Huberacdd9d02010-05-06 10:18:05 -07001301 Mutex::Autolock autoLock(mLock);
1302 return seekTo_l(timeUs);
1303 }
1304
1305 return OK;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001306}
1307
1308status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
Andreas Huber0a5baa92010-06-10 11:17:50 -07001309 if (mFlags & CACHE_UNDERRUN) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001310 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber0a5baa92010-06-10 11:17:50 -07001311 play_l();
1312 }
1313
Andreas Huber5dac87b2011-03-25 13:03:14 -07001314 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1315 // Video playback completed before, there's no pending
1316 // video event right now. In order for this new seek
1317 // to be honored, we need to post one.
1318
1319 postVideoEvent_l();
1320 }
1321
Andreas Huber64bb6982011-02-24 12:05:40 -08001322 mSeeking = SEEK;
Andreas Huber1321fdd2010-03-31 09:40:15 -07001323 mSeekNotificationSent = false;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001324 mSeekTimeUs = timeUs;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001325 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001326
1327 seekAudioIfNecessary_l();
1328
Insun Kangf9d660a2012-02-16 20:28:27 +09001329 if (mFlags & TEXTPLAYER_INITIALIZED) {
Insun Kang66551742012-01-11 22:03:12 +09001330 mTextDriver->seekToAsync(mSeekTimeUs);
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001331 }
1332
Andreas Huber1321fdd2010-03-31 09:40:15 -07001333 if (!(mFlags & PLAYING)) {
Steve Block3856b092011-10-20 11:56:00 +01001334 ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
Andreas Huber1321fdd2010-03-31 09:40:15 -07001335 " immediately.");
1336
1337 notifyListener_l(MEDIA_SEEK_COMPLETE);
1338 mSeekNotificationSent = true;
Andreas Huber2b1222f2011-02-07 11:43:12 -08001339
1340 if ((mFlags & PREPARED) && mVideoSource != NULL) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001341 modifyFlags(SEEK_PREVIEW, SET);
Andreas Huber2b1222f2011-02-07 11:43:12 -08001342 postVideoEvent_l();
1343 }
Andreas Huber1321fdd2010-03-31 09:40:15 -07001344 }
1345
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001346 return OK;
1347}
1348
1349void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber64bb6982011-02-24 12:05:40 -08001350 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001351 mAudioPlayer->seekTo(mSeekTimeUs);
1352
Andreas Huber1862a332010-02-03 11:37:29 -08001353 mWatchForAudioSeekComplete = true;
1354 mWatchForAudioEOS = true;
Gloria Wangdcd25ef2010-06-22 13:55:38 -07001355
1356 if (mDecryptHandle != NULL) {
1357 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1358 Playback::PAUSE, 0);
1359 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1360 Playback::START, mSeekTimeUs / 1000);
1361 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001362 }
1363}
1364
Andreas Huber88d8a832010-03-05 10:42:10 -08001365void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1366 CHECK(source != NULL);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001367
Andreas Huber88d8a832010-03-05 10:42:10 -08001368 mAudioTrack = source;
1369}
1370
Edwin Wong6a3969c2012-05-02 18:57:12 -07001371void AwesomePlayer::addTextSource_l(size_t trackIndex, const sp<MediaSource>& source) {
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001372 CHECK(source != NULL);
1373
Insun Kang66551742012-01-11 22:03:12 +09001374 if (mTextDriver == NULL) {
1375 mTextDriver = new TimedTextDriver(mListener);
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001376 }
1377
James Dongeec46ab2012-04-11 17:56:22 -07001378 mTextDriver->addInBandTextSource(trackIndex, source);
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001379}
1380
Andreas Huber88d8a832010-03-05 10:42:10 -08001381status_t AwesomePlayer::initAudioDecoder() {
Jamie Gennis21633202012-05-11 04:42:12 -07001382 ATRACE_CALL();
1383
Andreas Huber88d8a832010-03-05 10:42:10 -08001384 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huber717826e2010-01-05 10:54:55 -08001385
1386 const char *mime;
1387 CHECK(meta->findCString(kKeyMIMEType, &mime));
1388
1389 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber88d8a832010-03-05 10:42:10 -08001390 mAudioSource = mAudioTrack;
Andreas Huber717826e2010-01-05 10:54:55 -08001391 } else {
1392 mAudioSource = OMXCodec::Create(
Andreas Huber88d8a832010-03-05 10:42:10 -08001393 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huber717826e2010-01-05 10:54:55 -08001394 false, // createEncoder
Andreas Huber88d8a832010-03-05 10:42:10 -08001395 mAudioTrack);
Andreas Huber717826e2010-01-05 10:54:55 -08001396 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001397
1398 if (mAudioSource != NULL) {
1399 int64_t durationUs;
Andreas Huber88d8a832010-03-05 10:42:10 -08001400 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber2415ecb2010-03-26 10:17:17 -07001401 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001402 if (mDurationUs < 0 || durationUs > mDurationUs) {
1403 mDurationUs = durationUs;
1404 }
1405 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001406
Andreas Hubera945bfd2010-05-13 09:15:21 -07001407 status_t err = mAudioSource->start();
1408
1409 if (err != OK) {
1410 mAudioSource.clear();
1411 return err;
1412 }
Andreas Huber81f82c32010-04-12 16:05:57 -07001413 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1414 // For legacy reasons we're simply going to ignore the absence
1415 // of an audio decoder for QCELP instead of aborting playback
1416 // altogether.
1417 return OK;
1418 }
Andreas Hubere7e3b782010-03-08 15:46:13 -08001419
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001420 if (mAudioSource != NULL) {
1421 Mutex::Autolock autoLock(mStatsLock);
1422 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001423 const char *component;
1424 if (!mAudioSource->getFormat()
1425 ->findCString(kKeyDecoderComponent, &component)) {
1426 component = "none";
1427 }
1428
1429 stat->mDecoderName = component;
1430 }
1431
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001432 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1433}
1434
Andreas Huber88d8a832010-03-05 10:42:10 -08001435void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1436 CHECK(source != NULL);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001437
Andreas Huber88d8a832010-03-05 10:42:10 -08001438 mVideoTrack = source;
1439}
1440
Andreas Huber2a4d22d2010-09-08 14:32:20 -07001441status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
Jamie Gennis21633202012-05-11 04:42:12 -07001442 ATRACE_CALL();
Glenn Kasten2eb62952011-01-28 12:37:51 -08001443
1444 // Either the application or the DRM system can independently say
1445 // that there must be a hardware-protected path to an external video sink.
1446 // For now we always require a hardware-protected path to external video sink
1447 // if content is DRMed, but eventually this could be optional per DRM agent.
1448 // When the application wants protection, then
1449 // (USE_SURFACE_ALLOC && (mSurface != 0) &&
1450 // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
1451 // will be true, but that part is already handled by SurfaceFlinger.
Glenn Kasteneabd3462011-03-23 14:34:31 -07001452
1453#ifdef DEBUG_HDCP
1454 // For debugging, we allow a system property to control the protected usage.
1455 // In case of uninitialized or unexpected property, we default to "DRM only".
1456 bool setProtectionBit = false;
1457 char value[PROPERTY_VALUE_MAX];
1458 if (property_get("persist.sys.hdcp_checking", value, NULL)) {
1459 if (!strcmp(value, "never")) {
1460 // nop
1461 } else if (!strcmp(value, "always")) {
1462 setProtectionBit = true;
1463 } else if (!strcmp(value, "drm-only")) {
1464 if (mDecryptHandle != NULL) {
1465 setProtectionBit = true;
1466 }
1467 // property value is empty, or unexpected value
1468 } else {
1469 if (mDecryptHandle != NULL) {
1470 setProtectionBit = true;
1471 }
1472 }
1473 // can' read property value
1474 } else {
1475 if (mDecryptHandle != NULL) {
1476 setProtectionBit = true;
1477 }
1478 }
1479 // note that usage bit is already cleared, so no need to clear it in the "else" case
1480 if (setProtectionBit) {
1481 flags |= OMXCodec::kEnableGrallocUsageProtected;
1482 }
1483#else
Glenn Kasten2eb62952011-01-28 12:37:51 -08001484 if (mDecryptHandle != NULL) {
1485 flags |= OMXCodec::kEnableGrallocUsageProtected;
1486 }
Glenn Kasteneabd3462011-03-23 14:34:31 -07001487#endif
Steve Block3856b092011-10-20 11:56:00 +01001488 ALOGV("initVideoDecoder flags=0x%x", flags);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001489 mVideoSource = OMXCodec::Create(
Andreas Huber88d8a832010-03-05 10:42:10 -08001490 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001491 false, // createEncoder
Andreas Huber39ddf8e2010-08-04 10:14:30 -07001492 mVideoTrack,
Glenn Kasten11731182011-02-08 17:26:17 -08001493 NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001494
1495 if (mVideoSource != NULL) {
1496 int64_t durationUs;
Andreas Huber88d8a832010-03-05 10:42:10 -08001497 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber2415ecb2010-03-26 10:17:17 -07001498 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001499 if (mDurationUs < 0 || durationUs > mDurationUs) {
1500 mDurationUs = durationUs;
1501 }
1502 }
1503
Andreas Huber139a5d52010-05-20 10:37:06 -07001504 status_t err = mVideoSource->start();
1505
1506 if (err != OK) {
James Dong56966142012-10-17 14:53:16 -07001507 ALOGE("failed to start video source");
Andreas Huber139a5d52010-05-20 10:37:06 -07001508 mVideoSource.clear();
1509 return err;
1510 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001511 }
1512
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001513 if (mVideoSource != NULL) {
James Dong14f95742011-08-11 17:38:35 -07001514 const char *componentName;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001515 CHECK(mVideoSource->getFormat()
James Dong14f95742011-08-11 17:38:35 -07001516 ->findCString(kKeyDecoderComponent, &componentName));
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001517
James Dong14f95742011-08-11 17:38:35 -07001518 {
1519 Mutex::Autolock autoLock(mStatsLock);
1520 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
1521
1522 stat->mDecoderName = componentName;
1523 }
1524
1525 static const char *kPrefix = "OMX.Nvidia.";
1526 static const char *kSuffix = ".decode";
1527 static const size_t kSuffixLength = strlen(kSuffix);
1528
1529 size_t componentNameLength = strlen(componentName);
1530
1531 if (!strncmp(componentName, kPrefix, strlen(kPrefix))
1532 && componentNameLength >= kSuffixLength
1533 && !strcmp(&componentName[
1534 componentNameLength - kSuffixLength], kSuffix)) {
1535 modifyFlags(SLOW_DECODER_HACK, SET);
1536 }
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001537 }
1538
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001539 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1540}
1541
Andreas Huber4769cc92010-10-19 09:34:44 -07001542void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
Jamie Gennis21633202012-05-11 04:42:12 -07001543 ATRACE_CALL();
1544
Andreas Huber64bb6982011-02-24 12:05:40 -08001545 if (mSeeking == SEEK_VIDEO_ONLY) {
1546 mSeeking = NO_SEEK;
1547 return;
1548 }
1549
1550 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
Andreas Huber4769cc92010-10-19 09:34:44 -07001551 return;
1552 }
1553
1554 if (mAudioPlayer != NULL) {
Steve Block3856b092011-10-20 11:56:00 +01001555 ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
Andreas Huber4769cc92010-10-19 09:34:44 -07001556
1557 // If we don't have a video time, seek audio to the originally
1558 // requested seek time instead.
1559
1560 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
Andreas Huber4769cc92010-10-19 09:34:44 -07001561 mWatchForAudioSeekComplete = true;
Andreas Huber5dac87b2011-03-25 13:03:14 -07001562 mWatchForAudioEOS = true;
Andreas Huber4769cc92010-10-19 09:34:44 -07001563 } else if (!mSeekNotificationSent) {
1564 // If we're playing video only, report seek complete now,
1565 // otherwise audio player will notify us later.
1566 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber51289502011-03-16 15:42:45 -07001567 mSeekNotificationSent = true;
Andreas Huber4769cc92010-10-19 09:34:44 -07001568 }
1569
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001570 modifyFlags(FIRST_FRAME, SET);
Andreas Huber64bb6982011-02-24 12:05:40 -08001571 mSeeking = NO_SEEK;
Gloria Wanga8908292010-10-29 14:50:17 -07001572
1573 if (mDecryptHandle != NULL) {
1574 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1575 Playback::PAUSE, 0);
1576 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1577 Playback::START, videoTimeUs / 1000);
1578 }
Andreas Huber4769cc92010-10-19 09:34:44 -07001579}
1580
Andreas Huberc23f12a2010-02-08 14:40:30 -08001581void AwesomePlayer::onVideoEvent() {
Jamie Gennis21633202012-05-11 04:42:12 -07001582 ATRACE_CALL();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001583 Mutex::Autolock autoLock(mLock);
Andreas Huber7b3396a2010-02-12 10:42:02 -08001584 if (!mVideoEventPending) {
1585 // The event has been cancelled in reset_l() but had already
1586 // been scheduled for execution at that time.
1587 return;
1588 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001589 mVideoEventPending = false;
1590
Andreas Huber64bb6982011-02-24 12:05:40 -08001591 if (mSeeking != NO_SEEK) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001592 if (mVideoBuffer) {
1593 mVideoBuffer->release();
1594 mVideoBuffer = NULL;
1595 }
Andreas Huber0a5baa92010-06-10 11:17:50 -07001596
Andreas Huber681755f2011-04-21 10:06:43 -07001597 if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
Andreas Huber2b1222f2011-02-07 11:43:12 -08001598 && !(mFlags & SEEK_PREVIEW)) {
Andreas Huber0a5baa92010-06-10 11:17:50 -07001599 // We're going to seek the video source first, followed by
1600 // the audio source.
1601 // In order to avoid jumps in the DataSource offset caused by
1602 // the audio codec prefetching data from the old locations
1603 // while the video codec is already reading data from the new
1604 // locations, we'll "pause" the audio source, causing it to
1605 // stop reading input data until a subsequent seek.
1606
Andreas Huberf0303442011-02-11 13:09:36 -08001607 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huber0a5baa92010-06-10 11:17:50 -07001608 mAudioPlayer->pause();
Andreas Huberf0303442011-02-11 13:09:36 -08001609
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001610 modifyFlags(AUDIO_RUNNING, CLEAR);
Andreas Huber0a5baa92010-06-10 11:17:50 -07001611 }
1612 mAudioSource->pause();
1613 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001614 }
1615
1616 if (!mVideoBuffer) {
1617 MediaSource::ReadOptions options;
Andreas Huber64bb6982011-02-24 12:05:40 -08001618 if (mSeeking != NO_SEEK) {
Steve Block3856b092011-10-20 11:56:00 +01001619 ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001620
Andreas Huberabd1f4f2010-07-20 15:04:28 -07001621 options.setSeekTo(
Andreas Huber64bb6982011-02-24 12:05:40 -08001622 mSeekTimeUs,
1623 mSeeking == SEEK_VIDEO_ONLY
1624 ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
Andreas Huber49e7daa2012-05-03 10:49:46 -07001625 : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001626 }
1627 for (;;) {
1628 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberc1689e42009-12-14 15:34:11 -08001629 options.clearSeekTo();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001630
1631 if (err != OK) {
Andreas Hubere2b10282010-11-23 11:41:34 -08001632 CHECK(mVideoBuffer == NULL);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001633
1634 if (err == INFO_FORMAT_CHANGED) {
Steve Block3856b092011-10-20 11:56:00 +01001635 ALOGV("VideoSource signalled format change.");
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001636
Andreas Huber5daeb122010-08-16 08:49:37 -07001637 notifyVideoSize_l();
1638
Andreas Hubera657f8d2010-02-03 16:02:02 -08001639 if (mVideoRenderer != NULL) {
Andreas Huberfa090f52010-02-12 14:40:08 -08001640 mVideoRendererIsPreview = false;
Andreas Hubera657f8d2010-02-03 16:02:02 -08001641 initRenderer_l();
1642 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001643 continue;
1644 }
1645
Andreas Huber4769cc92010-10-19 09:34:44 -07001646 // So video playback is complete, but we may still have
1647 // a seek request pending that needs to be applied
1648 // to the audio track.
Andreas Huber64bb6982011-02-24 12:05:40 -08001649 if (mSeeking != NO_SEEK) {
Steve Block3856b092011-10-20 11:56:00 +01001650 ALOGV("video stream ended while seeking!");
Andreas Huber4769cc92010-10-19 09:34:44 -07001651 }
1652 finishSeekIfNecessary(-1);
1653
Andreas Huber5dac87b2011-03-25 13:03:14 -07001654 if (mAudioPlayer != NULL
1655 && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1656 startAudioPlayer_l();
1657 }
1658
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001659 modifyFlags(VIDEO_AT_EOS, SET);
Andreas Huber5295c0c2010-02-23 13:45:33 -08001660 postStreamDoneEvent_l(err);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001661 return;
1662 }
1663
Andreas Huber4844ac52009-12-10 15:32:12 -08001664 if (mVideoBuffer->range_length() == 0) {
Andreas Huber08411b72009-12-10 15:32:12 -08001665 // Some decoders, notably the PV AVC software decoder
1666 // return spurious empty buffers that we just want to ignore.
1667
Andreas Huber4844ac52009-12-10 15:32:12 -08001668 mVideoBuffer->release();
1669 mVideoBuffer = NULL;
1670 continue;
1671 }
1672
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001673 break;
1674 }
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001675
1676 {
1677 Mutex::Autolock autoLock(mStatsLock);
1678 ++mStats.mNumVideoFramesDecoded;
1679 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001680 }
1681
1682 int64_t timeUs;
1683 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1684
Andreas Huber150694c2011-03-14 10:55:40 -07001685 mLastVideoTimeUs = timeUs;
1686
Andreas Huber64bb6982011-02-24 12:05:40 -08001687 if (mSeeking == SEEK_VIDEO_ONLY) {
1688 if (mSeekTimeUs > timeUs) {
Steve Blockdf64d152012-01-04 20:05:49 +00001689 ALOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
Andreas Huber64bb6982011-02-24 12:05:40 -08001690 mSeekTimeUs, timeUs);
1691 }
1692 }
1693
Andreas Huber2415ecb2010-03-26 10:17:17 -07001694 {
1695 Mutex::Autolock autoLock(mMiscStateLock);
1696 mVideoTimeUs = timeUs;
1697 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001698
Andreas Huber64bb6982011-02-24 12:05:40 -08001699 SeekType wasSeeking = mSeeking;
Andreas Huber4769cc92010-10-19 09:34:44 -07001700 finishSeekIfNecessary(timeUs);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001701
Andreas Huberf0303442011-02-11 13:09:36 -08001702 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1703 status_t err = startAudioPlayer_l();
1704 if (err != OK) {
Steve Block29357bc2012-01-06 19:20:56 +00001705 ALOGE("Starting the audio player failed w/ err %d", err);
Andreas Huberf0303442011-02-11 13:09:36 -08001706 return;
1707 }
1708 }
1709
Andreas Huber0fc13f22012-10-23 13:25:05 -07001710 if ((mFlags & TEXTPLAYER_INITIALIZED)
1711 && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
Insun Kangf9d660a2012-02-16 20:28:27 +09001712 mTextDriver->start();
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001713 modifyFlags(TEXT_RUNNING, SET);
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001714 }
1715
Andreas Huberf7eade92011-09-08 11:33:47 -07001716 TimeSource *ts =
1717 ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
1718 ? &mSystemTimeSource : mTimeSource;
Andreas Huber5d2de4d2010-07-07 13:35:27 -07001719
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001720 if (mFlags & FIRST_FRAME) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001721 modifyFlags(FIRST_FRAME, CLEAR);
James Dong14f95742011-08-11 17:38:35 -07001722 mSinceLastDropped = 0;
Andreas Huber5d2de4d2010-07-07 13:35:27 -07001723 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001724 }
1725
1726 int64_t realTimeUs, mediaTimeUs;
Andreas Huber5d2de4d2010-07-07 13:35:27 -07001727 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001728 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1729 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1730 }
1731
Andreas Huber64bb6982011-02-24 12:05:40 -08001732 if (wasSeeking == SEEK_VIDEO_ONLY) {
1733 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1734
1735 int64_t latenessUs = nowUs - timeUs;
1736
Jamie Gennis21633202012-05-11 04:42:12 -07001737 ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1738
Andreas Huber64bb6982011-02-24 12:05:40 -08001739 if (latenessUs > 0) {
Steve Blockdf64d152012-01-04 20:05:49 +00001740 ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
Andreas Huber64bb6982011-02-24 12:05:40 -08001741 }
1742 }
1743
1744 if (wasSeeking == NO_SEEK) {
Andreas Huber02a1db72010-10-29 15:47:52 -07001745 // Let's display the first frame after seeking right away.
Andreas Huberf8ca9042010-08-10 11:18:36 -07001746
Andreas Huber2b1222f2011-02-07 11:43:12 -08001747 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001748
Andreas Huber2b1222f2011-02-07 11:43:12 -08001749 int64_t latenessUs = nowUs - timeUs;
1750
Jamie Gennis21633202012-05-11 04:42:12 -07001751 ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1752
Andreas Huber64bb6982011-02-24 12:05:40 -08001753 if (latenessUs > 500000ll
Andreas Huber64bb6982011-02-24 12:05:40 -08001754 && mAudioPlayer != NULL
1755 && mAudioPlayer->getMediaTimeMapping(
1756 &realTimeUs, &mediaTimeUs)) {
Andreas Huber0fc13f22012-10-23 13:25:05 -07001757 if (mWVMExtractor == NULL) {
1758 ALOGI("we're much too late (%.2f secs), video skipping ahead",
1759 latenessUs / 1E6);
Andreas Huber64bb6982011-02-24 12:05:40 -08001760
Andreas Huber0fc13f22012-10-23 13:25:05 -07001761 mVideoBuffer->release();
1762 mVideoBuffer = NULL;
Andreas Huber64bb6982011-02-24 12:05:40 -08001763
Andreas Huber0fc13f22012-10-23 13:25:05 -07001764 mSeeking = SEEK_VIDEO_ONLY;
1765 mSeekTimeUs = mediaTimeUs;
Andreas Huber64bb6982011-02-24 12:05:40 -08001766
Andreas Huber0fc13f22012-10-23 13:25:05 -07001767 postVideoEvent_l();
1768 return;
1769 } else {
1770 // The widevine extractor doesn't deal well with seeking
1771 // audio and video independently. We'll just have to wait
1772 // until the decoder catches up, which won't be long at all.
1773 ALOGI("we're very late (%.2f secs)", latenessUs / 1E6);
1774 }
Andreas Huber64bb6982011-02-24 12:05:40 -08001775 }
1776
Andreas Huber2b1222f2011-02-07 11:43:12 -08001777 if (latenessUs > 40000) {
1778 // We're more than 40ms late.
Steve Block3856b092011-10-20 11:56:00 +01001779 ALOGV("we're late by %lld us (%.2f secs)",
Andreas Huberdab59b52011-04-01 13:27:42 -07001780 latenessUs, latenessUs / 1E6);
Andreas Huber2b1222f2011-02-07 11:43:12 -08001781
James Dong14f95742011-08-11 17:38:35 -07001782 if (!(mFlags & SLOW_DECODER_HACK)
1783 || mSinceLastDropped > FRAME_DROP_FREQ)
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001784 {
Steve Block3856b092011-10-20 11:56:00 +01001785 ALOGV("we're late by %lld us (%.2f secs) dropping "
James Dong14f95742011-08-11 17:38:35 -07001786 "one after %d frames",
1787 latenessUs, latenessUs / 1E6, mSinceLastDropped);
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001788
James Dong14f95742011-08-11 17:38:35 -07001789 mSinceLastDropped = 0;
1790 mVideoBuffer->release();
1791 mVideoBuffer = NULL;
1792
1793 {
1794 Mutex::Autolock autoLock(mStatsLock);
1795 ++mStats.mNumVideoFramesDropped;
1796 }
1797
1798 postVideoEvent_l();
1799 return;
1800 }
Andreas Huber2b1222f2011-02-07 11:43:12 -08001801 }
1802
1803 if (latenessUs < -10000) {
1804 // We're more than 10ms early.
Andreas Huber2b1222f2011-02-07 11:43:12 -08001805 postVideoEvent_l(10000);
pmehendaleaee6c072011-01-06 14:43:49 -08001806 return;
1807 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001808 }
1809
Gloria Wang80ec9292011-08-09 15:29:34 -07001810 if ((mNativeWindow != NULL)
1811 && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
Andreas Huberfa090f52010-02-12 14:40:08 -08001812 mVideoRendererIsPreview = false;
1813
Andreas Hubera657f8d2010-02-03 16:02:02 -08001814 initRenderer_l();
1815 }
1816
1817 if (mVideoRenderer != NULL) {
James Dong14f95742011-08-11 17:38:35 -07001818 mSinceLastDropped++;
Andreas Hubera657f8d2010-02-03 16:02:02 -08001819 mVideoRenderer->render(mVideoBuffer);
James Dongc374dae2012-07-19 19:18:06 -07001820 if (!mVideoRenderingStarted) {
1821 mVideoRenderingStarted = true;
1822 notifyListener_l(MEDIA_INFO, MEDIA_INFO_RENDERING_START);
1823 }
1824
Andreas Hubera657f8d2010-02-03 16:02:02 -08001825 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001826
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001827 mVideoBuffer->release();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001828 mVideoBuffer = NULL;
1829
Andreas Huber64bb6982011-02-24 12:05:40 -08001830 if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001831 modifyFlags(SEEK_PREVIEW, CLEAR);
Andreas Huber2b1222f2011-02-07 11:43:12 -08001832 return;
1833 }
1834
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001835 postVideoEvent_l();
1836}
1837
1838void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
Jamie Gennis21633202012-05-11 04:42:12 -07001839 ATRACE_CALL();
1840
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001841 if (mVideoEventPending) {
1842 return;
1843 }
1844
1845 mVideoEventPending = true;
1846 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1847}
1848
Andreas Huber5295c0c2010-02-23 13:45:33 -08001849void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001850 if (mStreamDoneEventPending) {
1851 return;
1852 }
1853 mStreamDoneEventPending = true;
Andreas Huber5295c0c2010-02-23 13:45:33 -08001854
1855 mStreamDoneStatus = status;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001856 mQueue.postEvent(mStreamDoneEvent);
1857}
1858
Andreas Huber66b0a352010-01-26 16:20:10 -08001859void AwesomePlayer::postBufferingEvent_l() {
Andreas Huber66b0a352010-01-26 16:20:10 -08001860 if (mBufferingEventPending) {
1861 return;
1862 }
1863 mBufferingEventPending = true;
1864 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1865}
1866
Andreas Huber145e68f2011-01-11 15:05:28 -08001867void AwesomePlayer::postVideoLagEvent_l() {
1868 if (mVideoLagEventPending) {
1869 return;
1870 }
1871 mVideoLagEventPending = true;
1872 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1873}
1874
Andreas Huber02f6e982011-09-01 11:39:11 -07001875void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) {
1876 Mutex::Autolock autoLock(mAudioLock);
Andreas Huber1862a332010-02-03 11:37:29 -08001877 if (mAudioStatusEventPending) {
1878 return;
1879 }
1880 mAudioStatusEventPending = true;
Eric Laurent86d24aa2012-01-09 13:47:48 -08001881 // Do not honor delay when looping in order to limit audio gap
1882 if (mFlags & (LOOPING | AUTO_LOOPING)) {
1883 delayUs = 0;
1884 }
Andreas Huber84b343f2011-03-22 10:31:21 -07001885 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
Andreas Huber1862a332010-02-03 11:37:29 -08001886}
1887
1888void AwesomePlayer::onCheckAudioStatus() {
Andreas Huber02f6e982011-09-01 11:39:11 -07001889 {
1890 Mutex::Autolock autoLock(mAudioLock);
1891 if (!mAudioStatusEventPending) {
1892 // Event was dispatched and while we were blocking on the mutex,
1893 // has already been cancelled.
1894 return;
1895 }
1896
1897 mAudioStatusEventPending = false;
Andreas Huberd29345d2010-02-17 15:58:57 -08001898 }
1899
Andreas Huber02f6e982011-09-01 11:39:11 -07001900 Mutex::Autolock autoLock(mLock);
Andreas Huber1862a332010-02-03 11:37:29 -08001901
1902 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1903 mWatchForAudioSeekComplete = false;
Andreas Huber1321fdd2010-03-31 09:40:15 -07001904
1905 if (!mSeekNotificationSent) {
1906 notifyListener_l(MEDIA_SEEK_COMPLETE);
1907 mSeekNotificationSent = true;
1908 }
Andreas Huberdac4ee72010-04-07 10:24:35 -07001909
Andreas Huber64bb6982011-02-24 12:05:40 -08001910 mSeeking = NO_SEEK;
Andreas Huber1862a332010-02-03 11:37:29 -08001911 }
1912
Andreas Huber5295c0c2010-02-23 13:45:33 -08001913 status_t finalStatus;
1914 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber1862a332010-02-03 11:37:29 -08001915 mWatchForAudioEOS = false;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001916 modifyFlags(AUDIO_AT_EOS, SET);
1917 modifyFlags(FIRST_FRAME, SET);
Andreas Huber5295c0c2010-02-23 13:45:33 -08001918 postStreamDoneEvent_l(finalStatus);
Andreas Huber1862a332010-02-03 11:37:29 -08001919 }
Andreas Huber1862a332010-02-03 11:37:29 -08001920}
1921
Andreas Huberc23f12a2010-02-08 14:40:30 -08001922status_t AwesomePlayer::prepare() {
Jamie Gennis21633202012-05-11 04:42:12 -07001923 ATRACE_CALL();
Andreas Huberc23f12a2010-02-08 14:40:30 -08001924 Mutex::Autolock autoLock(mLock);
Andreas Huberbd22c522010-02-09 14:05:43 -08001925 return prepare_l();
1926}
Andreas Huberc23f12a2010-02-08 14:40:30 -08001927
Andreas Huberbd22c522010-02-09 14:05:43 -08001928status_t AwesomePlayer::prepare_l() {
1929 if (mFlags & PREPARED) {
1930 return OK;
1931 }
1932
1933 if (mFlags & PREPARING) {
1934 return UNKNOWN_ERROR;
1935 }
1936
1937 mIsAsyncPrepare = false;
Andreas Huberc23f12a2010-02-08 14:40:30 -08001938 status_t err = prepareAsync_l();
1939
1940 if (err != OK) {
1941 return err;
1942 }
1943
Andreas Huberbd22c522010-02-09 14:05:43 -08001944 while (mFlags & PREPARING) {
Andreas Huberc23f12a2010-02-08 14:40:30 -08001945 mPreparedCondition.wait(mLock);
1946 }
1947
Andreas Huberbd22c522010-02-09 14:05:43 -08001948 return mPrepareResult;
Andreas Huberc23f12a2010-02-08 14:40:30 -08001949}
1950
1951status_t AwesomePlayer::prepareAsync() {
Jamie Gennis21633202012-05-11 04:42:12 -07001952 ATRACE_CALL();
Andreas Huberc23f12a2010-02-08 14:40:30 -08001953 Mutex::Autolock autoLock(mLock);
Andreas Huberbd22c522010-02-09 14:05:43 -08001954
1955 if (mFlags & PREPARING) {
1956 return UNKNOWN_ERROR; // async prepare already pending
1957 }
1958
1959 mIsAsyncPrepare = true;
Andreas Huberc23f12a2010-02-08 14:40:30 -08001960 return prepareAsync_l();
1961}
1962
1963status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberbd22c522010-02-09 14:05:43 -08001964 if (mFlags & PREPARING) {
1965 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huberc23f12a2010-02-08 14:40:30 -08001966 }
1967
Andreas Huber2e8ffaf2010-02-18 16:45:13 -08001968 if (!mQueueStarted) {
1969 mQueue.start();
1970 mQueueStarted = true;
1971 }
1972
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001973 modifyFlags(PREPARING, SET);
Andreas Huberc23f12a2010-02-08 14:40:30 -08001974 mAsyncPrepareEvent = new AwesomeEvent(
1975 this, &AwesomePlayer::onPrepareAsyncEvent);
1976
1977 mQueue.postEvent(mAsyncPrepareEvent);
1978
1979 return OK;
1980}
1981
Andreas Huberbd22c522010-02-09 14:05:43 -08001982status_t AwesomePlayer::finishSetDataSource_l() {
Jamie Gennis21633202012-05-11 04:42:12 -07001983 ATRACE_CALL();
Andreas Hubere94bd142010-03-12 08:59:22 -08001984 sp<DataSource> dataSource;
1985
Andreas Huber681755f2011-04-21 10:06:43 -07001986 bool isWidevineStreaming = false;
1987 if (!strncasecmp("widevine://", mUri.string(), 11)) {
1988 isWidevineStreaming = true;
1989
1990 String8 newURI = String8("http://");
1991 newURI.append(mUri.string() + 11);
1992
1993 mUri = newURI;
1994 }
1995
Andreas Hubera0f2bf52011-12-05 11:34:43 -08001996 AString sniffedMIME;
1997
Andreas Huber8cb0c412011-02-17 13:35:08 -08001998 if (!strncasecmp("http://", mUri.string(), 7)
Andreas Huber681755f2011-04-21 10:06:43 -07001999 || !strncasecmp("https://", mUri.string(), 8)
2000 || isWidevineStreaming) {
Andreas Huber1156dc92011-03-08 15:59:28 -08002001 mConnectingDataSource = HTTPBase::Create(
2002 (mFlags & INCOGNITO)
2003 ? HTTPBase::kFlagIncognito
2004 : 0);
Andreas Hubere94bd142010-03-12 08:59:22 -08002005
Andreas Huber9b80c2b2011-06-30 15:47:02 -07002006 if (mUIDValid) {
2007 mConnectingDataSource->setUID(mUID);
2008 }
2009
Andreas Huber49c59812011-10-07 13:40:45 -07002010 String8 cacheConfig;
2011 bool disconnectAtHighwatermark;
2012 NuCachedSource2::RemoveCacheSpecificHeaders(
2013 &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
2014
Andreas Hubere94bd142010-03-12 08:59:22 -08002015 mLock.unlock();
Andreas Huber79f77ef2010-06-11 09:57:46 -07002016 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
Andreas Hubere94bd142010-03-12 08:59:22 -08002017 mLock.lock();
2018
2019 if (err != OK) {
2020 mConnectingDataSource.clear();
2021
Steve Blockdf64d152012-01-04 20:05:49 +00002022 ALOGI("mConnectingDataSource->connect() returned %d", err);
Andreas Hubere94bd142010-03-12 08:59:22 -08002023 return err;
2024 }
2025
Andreas Huber681755f2011-04-21 10:06:43 -07002026 if (!isWidevineStreaming) {
2027 // The widevine extractor does its own caching.
2028
Andreas Huber0a5baa92010-06-10 11:17:50 -07002029#if 0
Andreas Huber681755f2011-04-21 10:06:43 -07002030 mCachedSource = new NuCachedSource2(
2031 new ThrottledSource(
2032 mConnectingDataSource, 50 * 1024 /* bytes/sec */));
Andreas Huber0a5baa92010-06-10 11:17:50 -07002033#else
Andreas Huber49c59812011-10-07 13:40:45 -07002034 mCachedSource = new NuCachedSource2(
2035 mConnectingDataSource,
2036 cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
2037 disconnectAtHighwatermark);
Andreas Huber0a5baa92010-06-10 11:17:50 -07002038#endif
Andreas Huber0a5baa92010-06-10 11:17:50 -07002039
Andreas Huber681755f2011-04-21 10:06:43 -07002040 dataSource = mCachedSource;
2041 } else {
2042 dataSource = mConnectingDataSource;
Andreas Huberac05c312011-01-19 15:07:19 -08002043 }
2044
Andreas Hubere94bd142010-03-12 08:59:22 -08002045 mConnectingDataSource.clear();
Andreas Huber0a5baa92010-06-10 11:17:50 -07002046
Andreas Huber6511c972011-03-30 11:15:27 -07002047 String8 contentType = dataSource->getMIMEType();
Andreas Huberac05c312011-01-19 15:07:19 -08002048
Andreas Huber6511c972011-03-30 11:15:27 -07002049 if (strncasecmp(contentType.string(), "audio/", 6)) {
2050 // We're not doing this for streams that appear to be audio-only
2051 // streams to ensure that even low bandwidth streams start
2052 // playing back fairly instantly.
Andreas Huberac05c312011-01-19 15:07:19 -08002053
Andreas Huber6511c972011-03-30 11:15:27 -07002054 // We're going to prefill the cache before trying to instantiate
2055 // the extractor below, as the latter is an operation that otherwise
2056 // could block on the datasource for a significant amount of time.
2057 // During that time we'd be unable to abort the preparation phase
2058 // without this prefill.
James Donge3935092011-05-19 08:49:09 -07002059 if (mCachedSource != NULL) {
2060 // We're going to prefill the cache before trying to instantiate
2061 // the extractor below, as the latter is an operation that otherwise
2062 // could block on the datasource for a significant amount of time.
2063 // During that time we'd be unable to abort the preparation phase
2064 // without this prefill.
Andreas Huberac05c312011-01-19 15:07:19 -08002065
James Donge3935092011-05-19 08:49:09 -07002066 mLock.unlock();
Andreas Huber6511c972011-03-30 11:15:27 -07002067
Andreas Huberbab41202011-12-07 12:50:47 -08002068 // Initially make sure we have at least 192 KB for the sniff
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002069 // to complete without blocking.
Andreas Huberbab41202011-12-07 12:50:47 -08002070 static const size_t kMinBytesForSniffing = 192 * 1024;
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002071
2072 off64_t metaDataSize = -1ll;
James Donge3935092011-05-19 08:49:09 -07002073 for (;;) {
2074 status_t finalStatus;
2075 size_t cachedDataRemaining =
2076 mCachedSource->approxDataRemaining(&finalStatus);
Andreas Huber6511c972011-03-30 11:15:27 -07002077
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002078 if (finalStatus != OK
2079 || (metaDataSize >= 0
2080 && cachedDataRemaining >= metaDataSize)
James Donge3935092011-05-19 08:49:09 -07002081 || (mFlags & PREPARE_CANCELLED)) {
2082 break;
2083 }
2084
Andreas Huber456caf32011-12-05 13:30:52 -08002085 ALOGV("now cached %d bytes of data", cachedDataRemaining);
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002086
2087 if (metaDataSize < 0
2088 && cachedDataRemaining >= kMinBytesForSniffing) {
2089 String8 tmp;
2090 float confidence;
2091 sp<AMessage> meta;
2092 if (!dataSource->sniff(&tmp, &confidence, &meta)) {
2093 mLock.lock();
2094 return UNKNOWN_ERROR;
2095 }
2096
2097 // We successfully identified the file's extractor to
2098 // be, remember this mime type so we don't have to
2099 // sniff it again when we call MediaExtractor::Create()
2100 // below.
2101 sniffedMIME = tmp.string();
2102
2103 if (meta == NULL
2104 || !meta->findInt64(
2105 "meta-data-size", &metaDataSize)) {
2106 metaDataSize = kHighWaterMarkBytes;
2107 }
2108
2109 CHECK_GE(metaDataSize, 0ll);
Andreas Huber456caf32011-12-05 13:30:52 -08002110 ALOGV("metaDataSize = %lld bytes", metaDataSize);
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002111 }
2112
James Donge3935092011-05-19 08:49:09 -07002113 usleep(200000);
Andreas Huber6511c972011-03-30 11:15:27 -07002114 }
2115
James Donge3935092011-05-19 08:49:09 -07002116 mLock.lock();
Andreas Huberac05c312011-01-19 15:07:19 -08002117 }
2118
James Donge3935092011-05-19 08:49:09 -07002119 if (mFlags & PREPARE_CANCELLED) {
Steve Blockdf64d152012-01-04 20:05:49 +00002120 ALOGI("Prepare cancelled while waiting for initial cache fill.");
James Donge3935092011-05-19 08:49:09 -07002121 return UNKNOWN_ERROR;
2122 }
Andreas Huberac05c312011-01-19 15:07:19 -08002123 }
Andreas Hubere94bd142010-03-12 08:59:22 -08002124 } else {
2125 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
2126 }
Andreas Huberbd22c522010-02-09 14:05:43 -08002127
2128 if (dataSource == NULL) {
2129 return UNKNOWN_ERROR;
2130 }
2131
Andreas Huber681755f2011-04-21 10:06:43 -07002132 sp<MediaExtractor> extractor;
Andreas Huberbd22c522010-02-09 14:05:43 -08002133
Andreas Huber681755f2011-04-21 10:06:43 -07002134 if (isWidevineStreaming) {
2135 String8 mimeType;
2136 float confidence;
2137 sp<AMessage> dummy;
James Dongce3d3ef2012-06-12 17:18:37 -07002138 bool success;
2139
2140 // SniffWVM is potentially blocking since it may require network access.
2141 // Do not call it with mLock held.
2142 mLock.unlock();
2143 success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
2144 mLock.lock();
Andreas Huber681755f2011-04-21 10:06:43 -07002145
2146 if (!success
2147 || strcasecmp(
2148 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
2149 return ERROR_UNSUPPORTED;
2150 }
2151
2152 mWVMExtractor = new WVMExtractor(dataSource);
2153 mWVMExtractor->setAdaptiveStreamingMode(true);
Jeff Tinkerdce41612012-02-14 14:54:01 -08002154 if (mUIDValid)
2155 mWVMExtractor->setUID(mUID);
Andreas Huber681755f2011-04-21 10:06:43 -07002156 extractor = mWVMExtractor;
2157 } else {
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002158 extractor = MediaExtractor::Create(
2159 dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
Andreas Huber681755f2011-04-21 10:06:43 -07002160
2161 if (extractor == NULL) {
2162 return UNKNOWN_ERROR;
2163 }
Andreas Huberbd22c522010-02-09 14:05:43 -08002164 }
2165
James Dong9d2f3862012-01-10 08:24:37 -08002166 if (extractor->getDrmFlag()) {
2167 checkDrmStatus(dataSource);
Gloria Wangdcd25ef2010-06-22 13:55:38 -07002168 }
2169
Andreas Huber681755f2011-04-21 10:06:43 -07002170 status_t err = setDataSource_l(extractor);
2171
2172 if (err != OK) {
2173 mWVMExtractor.clear();
2174
2175 return err;
2176 }
2177
2178 return OK;
Andreas Huberbd22c522010-02-09 14:05:43 -08002179}
2180
Andreas Huber88d8a832010-03-05 10:42:10 -08002181void AwesomePlayer::abortPrepare(status_t err) {
2182 CHECK(err != OK);
2183
2184 if (mIsAsyncPrepare) {
2185 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2186 }
2187
2188 mPrepareResult = err;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002189 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
Andreas Huber88d8a832010-03-05 10:42:10 -08002190 mAsyncPrepareEvent = NULL;
2191 mPreparedCondition.broadcast();
2192}
2193
Andreas Hubere966fb02010-03-24 09:24:40 -07002194// static
2195bool AwesomePlayer::ContinuePreparation(void *cookie) {
2196 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
2197
2198 return (me->mFlags & PREPARE_CANCELLED) == 0;
2199}
2200
Andreas Huberc23f12a2010-02-08 14:40:30 -08002201void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber8650e192010-09-03 13:20:33 -07002202 Mutex::Autolock autoLock(mLock);
Andreas Huberbd22c522010-02-09 14:05:43 -08002203
Andreas Huber8650e192010-09-03 13:20:33 -07002204 if (mFlags & PREPARE_CANCELLED) {
Steve Blockdf64d152012-01-04 20:05:49 +00002205 ALOGI("prepare was cancelled before doing anything");
Andreas Huber8650e192010-09-03 13:20:33 -07002206 abortPrepare(UNKNOWN_ERROR);
2207 return;
2208 }
2209
2210 if (mUri.size() > 0) {
2211 status_t err = finishSetDataSource_l();
2212
2213 if (err != OK) {
2214 abortPrepare(err);
Andreas Hubere94bd142010-03-12 08:59:22 -08002215 return;
2216 }
Andreas Huberc23f12a2010-02-08 14:40:30 -08002217 }
2218
Andreas Huber8650e192010-09-03 13:20:33 -07002219 if (mVideoTrack != NULL && mVideoSource == NULL) {
2220 status_t err = initVideoDecoder();
Andreas Huberc23f12a2010-02-08 14:40:30 -08002221
Andreas Huber8650e192010-09-03 13:20:33 -07002222 if (err != OK) {
2223 abortPrepare(err);
2224 return;
2225 }
2226 }
2227
2228 if (mAudioTrack != NULL && mAudioSource == NULL) {
2229 status_t err = initAudioDecoder();
2230
2231 if (err != OK) {
2232 abortPrepare(err);
2233 return;
2234 }
2235 }
2236
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002237 modifyFlags(PREPARING_CONNECTED, SET);
Andreas Huber6a05c9e2010-10-19 12:18:51 -07002238
Andreas Huber2bfdd422011-10-11 15:24:07 -07002239 if (isStreamingHTTP()) {
Andreas Huber8650e192010-09-03 13:20:33 -07002240 postBufferingEvent_l();
2241 } else {
2242 finishAsyncPrepare_l();
2243 }
2244}
2245
2246void AwesomePlayer::finishAsyncPrepare_l() {
Andreas Huberbd22c522010-02-09 14:05:43 -08002247 if (mIsAsyncPrepare) {
Andreas Huber5daeb122010-08-16 08:49:37 -07002248 if (mVideoSource == NULL) {
Andreas Huberbd22c522010-02-09 14:05:43 -08002249 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
2250 } else {
Andreas Huber5daeb122010-08-16 08:49:37 -07002251 notifyVideoSize_l();
Andreas Huberbd22c522010-02-09 14:05:43 -08002252 }
2253
2254 notifyListener_l(MEDIA_PREPARED);
Andreas Huberc23f12a2010-02-08 14:40:30 -08002255 }
2256
Andreas Huberbd22c522010-02-09 14:05:43 -08002257 mPrepareResult = OK;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002258 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2259 modifyFlags(PREPARED, SET);
Andreas Huberc23f12a2010-02-08 14:40:30 -08002260 mAsyncPrepareEvent = NULL;
Andreas Huberbd22c522010-02-09 14:05:43 -08002261 mPreparedCondition.broadcast();
Andreas Huberc23f12a2010-02-08 14:40:30 -08002262}
2263
Andreas Huberacdd9d02010-05-06 10:18:05 -07002264uint32_t AwesomePlayer::flags() const {
2265 return mExtractorFlags;
2266}
2267
Andreas Huber84b343f2011-03-22 10:31:21 -07002268void AwesomePlayer::postAudioEOS(int64_t delayUs) {
Andreas Huber02f6e982011-09-01 11:39:11 -07002269 postCheckAudioStatusEvent(delayUs);
Andreas Hubered54ad02010-09-28 11:56:39 -07002270}
2271
2272void AwesomePlayer::postAudioSeekComplete() {
Andreas Huber02f6e982011-09-01 11:39:11 -07002273 postCheckAudioStatusEvent(0);
Andreas Hubered54ad02010-09-28 11:56:39 -07002274}
2275
Gloria Wang4f9e47f2011-04-25 17:28:22 -07002276status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
Gloria Wang965d08b2011-05-11 11:24:09 -07002277 switch (key) {
James Dong5b1b8a92011-05-25 19:37:03 -07002278 case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
2279 {
2280 return setCacheStatCollectFreq(request);
2281 }
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002282 case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE:
2283 {
2284 if (mAudioPlayer != NULL) {
2285 return mAudioPlayer->setPlaybackRatePermille(request.readInt32());
2286 } else {
2287 return NO_INIT;
2288 }
2289 }
Gloria Wang965d08b2011-05-11 11:24:09 -07002290 default:
2291 {
2292 return ERROR_UNSUPPORTED;
2293 }
Gloria Wang7a1e3e82011-05-03 15:59:03 -07002294 }
Gloria Wang4f9e47f2011-04-25 17:28:22 -07002295}
2296
James Dong5b1b8a92011-05-25 19:37:03 -07002297status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
2298 if (mCachedSource != NULL) {
2299 int32_t freqMs = request.readInt32();
Steve Blockb8a80522011-12-20 16:23:08 +00002300 ALOGD("Request to keep cache stats in the past %d ms",
James Dong5b1b8a92011-05-25 19:37:03 -07002301 freqMs);
2302 return mCachedSource->setCacheStatCollectFreq(freqMs);
2303 }
2304 return ERROR_UNSUPPORTED;
2305}
2306
Gloria Wang4f9e47f2011-04-25 17:28:22 -07002307status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
Glenn Kastencd25fed2011-07-25 09:26:22 -07002308 switch (key) {
2309 case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
2310 {
2311 int32_t channelCount;
2312 if (mAudioTrack == 0 ||
2313 !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
2314 channelCount = 0;
2315 }
2316 reply->writeInt32(channelCount);
2317 }
2318 return OK;
2319 default:
2320 {
2321 return ERROR_UNSUPPORTED;
2322 }
2323 }
Gloria Wang4f9e47f2011-04-25 17:28:22 -07002324}
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08002325
James Dongeec46ab2012-04-11 17:56:22 -07002326status_t AwesomePlayer::getTrackInfo(Parcel *reply) const {
James Dong514bcaf2012-04-17 13:07:56 -07002327 Mutex::Autolock autoLock(mLock);
2328 size_t trackCount = mExtractor->countTracks();
2329 if (mTextDriver != NULL) {
2330 trackCount += mTextDriver->countExternalTracks();
James Dongeec46ab2012-04-11 17:56:22 -07002331 }
2332
James Dong514bcaf2012-04-17 13:07:56 -07002333 reply->writeInt32(trackCount);
James Dongeec46ab2012-04-11 17:56:22 -07002334 for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
2335 sp<MetaData> meta = mExtractor->getTrackMetaData(i);
2336
2337 const char *_mime;
2338 CHECK(meta->findCString(kKeyMIMEType, &_mime));
2339
2340 String8 mime = String8(_mime);
2341
2342 reply->writeInt32(2); // 2 fields
2343
2344 if (!strncasecmp(mime.string(), "video/", 6)) {
2345 reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO);
2346 } else if (!strncasecmp(mime.string(), "audio/", 6)) {
2347 reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO);
2348 } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
2349 reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);
2350 } else {
2351 reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN);
2352 }
2353
2354 const char *lang;
James Dong514bcaf2012-04-17 13:07:56 -07002355 if (!meta->findCString(kKeyMediaLanguage, &lang)) {
2356 lang = "und";
James Dongeec46ab2012-04-11 17:56:22 -07002357 }
James Dong514bcaf2012-04-17 13:07:56 -07002358 reply->writeString16(String16(lang));
James Dongeec46ab2012-04-11 17:56:22 -07002359 }
2360
James Dong514bcaf2012-04-17 13:07:56 -07002361 if (mTextDriver != NULL) {
2362 mTextDriver->getExternalTrackInfo(reply);
2363 }
James Dongeec46ab2012-04-11 17:56:22 -07002364 return OK;
2365}
2366
James Dongab7a2e52012-04-26 17:11:28 -07002367status_t AwesomePlayer::selectAudioTrack_l(
2368 const sp<MediaSource>& source, size_t trackIndex) {
2369
2370 ALOGI("selectAudioTrack_l: trackIndex=%d, mFlags=0x%x", trackIndex, mFlags);
2371
2372 {
2373 Mutex::Autolock autoLock(mStatsLock);
2374 if ((ssize_t)trackIndex == mActiveAudioTrackIndex) {
2375 ALOGI("Track %d is active. Does nothing.", trackIndex);
2376 return OK;
2377 }
2378 //mStats.mFlags = mFlags;
2379 }
2380
2381 if (mSeeking != NO_SEEK) {
2382 ALOGE("Selecting a track while seeking is not supported");
2383 return ERROR_UNSUPPORTED;
2384 }
2385
2386 if ((mFlags & PREPARED) == 0) {
2387 ALOGE("Data source has not finished preparation");
2388 return ERROR_UNSUPPORTED;
2389 }
2390
2391 CHECK(source != NULL);
2392 bool wasPlaying = (mFlags & PLAYING) != 0;
2393
2394 pause_l();
2395
2396 int64_t curTimeUs;
2397 CHECK_EQ(getPosition(&curTimeUs), (status_t)OK);
2398
2399 if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
2400 && mAudioSource != NULL) {
2401 // If we had an audio player, it would have effectively
2402 // taken possession of the audio source and stopped it when
2403 // _it_ is stopped. Otherwise this is still our responsibility.
2404 mAudioSource->stop();
2405 }
2406 mAudioSource.clear();
2407
2408 mTimeSource = NULL;
2409
2410 delete mAudioPlayer;
2411 mAudioPlayer = NULL;
2412
2413 modifyFlags(AUDIOPLAYER_STARTED, CLEAR);
2414
2415 setAudioSource(source);
2416
2417 modifyFlags(AUDIO_AT_EOS, CLEAR);
2418 modifyFlags(AT_EOS, CLEAR);
2419
2420 status_t err;
2421 if ((err = initAudioDecoder()) != OK) {
2422 ALOGE("Failed to init audio decoder: 0x%x", err);
2423 return err;
2424 }
2425
2426 mSeekNotificationSent = true;
2427 seekTo_l(curTimeUs);
2428
2429 if (wasPlaying) {
2430 play_l();
2431 }
2432
2433 mActiveAudioTrackIndex = trackIndex;
2434
2435 return OK;
2436}
2437
James Dongeec46ab2012-04-11 17:56:22 -07002438status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) {
Jamie Gennis21633202012-05-11 04:42:12 -07002439 ATRACE_CALL();
James Dong514bcaf2012-04-17 13:07:56 -07002440 ALOGV("selectTrack: trackIndex = %d and select=%d", trackIndex, select);
2441 Mutex::Autolock autoLock(mLock);
2442 size_t trackCount = mExtractor->countTracks();
2443 if (mTextDriver != NULL) {
2444 trackCount += mTextDriver->countExternalTracks();
James Dongeec46ab2012-04-11 17:56:22 -07002445 }
James Dong514bcaf2012-04-17 13:07:56 -07002446 if (trackIndex >= trackCount) {
2447 ALOGE("Track index (%d) is out of range [0, %d)", trackIndex, trackCount);
2448 return ERROR_OUT_OF_RANGE;
James Dongeec46ab2012-04-11 17:56:22 -07002449 }
2450
James Dongab7a2e52012-04-26 17:11:28 -07002451 bool isAudioTrack = false;
James Dongeec46ab2012-04-11 17:56:22 -07002452 if (trackIndex < mExtractor->countTracks()) {
2453 sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex);
James Dongab7a2e52012-04-26 17:11:28 -07002454 const char *mime;
2455 CHECK(meta->findCString(kKeyMIMEType, &mime));
2456 isAudioTrack = !strncasecmp(mime, "audio/", 6);
James Dongeec46ab2012-04-11 17:56:22 -07002457
Insun Kang8a15dfb2012-06-15 13:02:45 +09002458 if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) {
James Dongab7a2e52012-04-26 17:11:28 -07002459 ALOGE("Track %d is not either audio or timed text", trackIndex);
James Dongeec46ab2012-04-11 17:56:22 -07002460 return ERROR_UNSUPPORTED;
2461 }
2462 }
2463
James Dongab7a2e52012-04-26 17:11:28 -07002464 if (isAudioTrack) {
2465 if (!select) {
2466 ALOGE("Deselect an audio track (%d) is not supported", trackIndex);
2467 return ERROR_UNSUPPORTED;
2468 }
2469 return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex);
2470 }
2471
James Dong514bcaf2012-04-17 13:07:56 -07002472 // Timed text track handling
2473 if (mTextDriver == NULL) {
2474 return INVALID_OPERATION;
2475 }
2476
James Dongeec46ab2012-04-11 17:56:22 -07002477 status_t err = OK;
2478 if (select) {
2479 err = mTextDriver->selectTrack(trackIndex);
2480 if (err == OK) {
2481 modifyFlags(TEXTPLAYER_INITIALIZED, SET);
2482 if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) {
2483 mTextDriver->start();
2484 modifyFlags(TEXT_RUNNING, SET);
2485 }
2486 }
2487 } else {
2488 err = mTextDriver->unselectTrack(trackIndex);
2489 if (err == OK) {
2490 modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
2491 modifyFlags(TEXT_RUNNING, CLEAR);
2492 }
2493 }
2494 return err;
2495}
2496
2497size_t AwesomePlayer::countTracks() const {
2498 return mExtractor->countTracks() + mTextDriver->countExternalTracks();
2499}
2500
James Dong4f6eed02012-04-30 14:38:12 -07002501status_t AwesomePlayer::setVideoScalingMode(int32_t mode) {
2502 Mutex::Autolock lock(mLock);
2503 return setVideoScalingMode_l(mode);
2504}
2505
2506status_t AwesomePlayer::setVideoScalingMode_l(int32_t mode) {
2507 mVideoScalingMode = mode;
2508 if (mNativeWindow != NULL) {
2509 status_t err = native_window_set_scaling_mode(
2510 mNativeWindow.get(), mVideoScalingMode);
2511 if (err != OK) {
2512 ALOGW("Failed to set scaling mode: %d", err);
2513 }
Marco Nelissen200d71c2013-02-05 09:03:22 -08002514 return err;
James Dong4f6eed02012-04-30 14:38:12 -07002515 }
2516 return OK;
2517}
2518
Insun Kangf9d660a2012-02-16 20:28:27 +09002519status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
Jamie Gennis21633202012-05-11 04:42:12 -07002520 ATRACE_CALL();
Insun Kangf9d660a2012-02-16 20:28:27 +09002521 if (NULL == reply) {
2522 return android::BAD_VALUE;
2523 }
2524 int32_t methodId;
2525 status_t ret = request.readInt32(&methodId);
2526 if (ret != android::OK) {
2527 return ret;
2528 }
2529 switch(methodId) {
James Dong4f6eed02012-04-30 14:38:12 -07002530 case INVOKE_ID_SET_VIDEO_SCALING_MODE:
2531 {
2532 int mode = request.readInt32();
2533 return setVideoScalingMode(mode);
2534 }
2535
Insun Kangf9d660a2012-02-16 20:28:27 +09002536 case INVOKE_ID_GET_TRACK_INFO:
2537 {
James Dongeec46ab2012-04-11 17:56:22 -07002538 return getTrackInfo(reply);
Insun Kangf9d660a2012-02-16 20:28:27 +09002539 }
2540 case INVOKE_ID_ADD_EXTERNAL_SOURCE:
2541 {
James Dong514bcaf2012-04-17 13:07:56 -07002542 Mutex::Autolock autoLock(mLock);
Insun Kangf9d660a2012-02-16 20:28:27 +09002543 if (mTextDriver == NULL) {
2544 mTextDriver = new TimedTextDriver(mListener);
2545 }
2546 // String values written in Parcel are UTF-16 values.
Insun Kang7c5afe92012-03-15 23:04:43 +09002547 String8 uri(request.readString16());
2548 String8 mimeType(request.readString16());
James Dongeec46ab2012-04-11 17:56:22 -07002549 size_t nTracks = countTracks();
2550 return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType);
Insun Kangf9d660a2012-02-16 20:28:27 +09002551 }
2552 case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
2553 {
James Dong514bcaf2012-04-17 13:07:56 -07002554 Mutex::Autolock autoLock(mLock);
Insun Kangf9d660a2012-02-16 20:28:27 +09002555 if (mTextDriver == NULL) {
2556 mTextDriver = new TimedTextDriver(mListener);
2557 }
2558 int fd = request.readFileDescriptor();
2559 off64_t offset = request.readInt64();
James Dong613c8ae2012-04-13 13:02:57 -07002560 off64_t length = request.readInt64();
Insun Kang7c5afe92012-03-15 23:04:43 +09002561 String8 mimeType(request.readString16());
James Dongeec46ab2012-04-11 17:56:22 -07002562 size_t nTracks = countTracks();
Insun Kangf9d660a2012-02-16 20:28:27 +09002563 return mTextDriver->addOutOfBandTextSource(
James Dongeec46ab2012-04-11 17:56:22 -07002564 nTracks, fd, offset, length, mimeType);
Insun Kangf9d660a2012-02-16 20:28:27 +09002565 }
2566 case INVOKE_ID_SELECT_TRACK:
2567 {
James Dongeec46ab2012-04-11 17:56:22 -07002568 int trackIndex = request.readInt32();
James Dong514bcaf2012-04-17 13:07:56 -07002569 return selectTrack(trackIndex, true /* select */);
Insun Kangf9d660a2012-02-16 20:28:27 +09002570 }
2571 case INVOKE_ID_UNSELECT_TRACK:
2572 {
James Dongeec46ab2012-04-11 17:56:22 -07002573 int trackIndex = request.readInt32();
James Dong514bcaf2012-04-17 13:07:56 -07002574 return selectTrack(trackIndex, false /* select */);
Insun Kangf9d660a2012-02-16 20:28:27 +09002575 }
2576 default:
2577 {
2578 return ERROR_UNSUPPORTED;
2579 }
2580 }
2581 // It will not reach here.
2582 return OK;
2583}
2584
Andreas Huber681755f2011-04-21 10:06:43 -07002585bool AwesomePlayer::isStreamingHTTP() const {
2586 return mCachedSource != NULL || mWVMExtractor != NULL;
2587}
2588
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002589status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
2590 Mutex::Autolock autoLock(mStatsLock);
2591
2592 FILE *out = fdopen(dup(fd), "w");
2593
2594 fprintf(out, " AwesomePlayer\n");
2595 if (mStats.mFd < 0) {
James Dong53ae1642012-08-17 13:41:59 -07002596 fprintf(out, " URI(suppressed)");
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002597 } else {
2598 fprintf(out, " fd(%d)", mStats.mFd);
2599 }
2600
2601 fprintf(out, ", flags(0x%08x)", mStats.mFlags);
2602
2603 if (mStats.mBitrate >= 0) {
2604 fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
2605 }
2606
2607 fprintf(out, "\n");
2608
2609 for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
2610 const TrackStat &stat = mStats.mTracks.itemAt(i);
2611
2612 fprintf(out, " Track %d\n", i + 1);
2613 fprintf(out, " MIME(%s)", stat.mMIME.string());
2614
2615 if (!stat.mDecoderName.isEmpty()) {
2616 fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
2617 }
2618
2619 fprintf(out, "\n");
2620
2621 if ((ssize_t)i == mStats.mVideoTrackIndex) {
2622 fprintf(out,
2623 " videoDimensions(%d x %d), "
2624 "numVideoFramesDecoded(%lld), "
2625 "numVideoFramesDropped(%lld)\n",
2626 mStats.mVideoWidth,
2627 mStats.mVideoHeight,
2628 mStats.mNumVideoFramesDecoded,
2629 mStats.mNumVideoFramesDropped);
2630 }
2631 }
2632
2633 fclose(out);
2634 out = NULL;
2635
2636 return OK;
2637}
2638
2639void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
2640 switch (mode) {
2641 case SET:
2642 mFlags |= value;
2643 break;
2644 case CLEAR:
Marco Nelissen6f434482012-07-20 09:50:46 -07002645 if ((value & CACHE_UNDERRUN) && (mFlags & CACHE_UNDERRUN)) {
2646 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
2647 }
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002648 mFlags &= ~value;
2649 break;
2650 case ASSIGN:
2651 mFlags = value;
2652 break;
2653 default:
2654 TRESPASS();
2655 }
2656
2657 {
2658 Mutex::Autolock autoLock(mStatsLock);
2659 mStats.mFlags = mFlags;
2660 }
2661}
2662
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08002663} // namespace android