blob: 52e178e0dd69f74fc659a3e0d523b775dce82faa [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>
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +010050#include <media/stagefright/Utils.h>
Andreas Huber717826e2010-01-05 10:54:55 -080051
Andy McFadden8ba01022012-12-18 09:46:54 -080052#include <gui/IGraphicBufferProducer.h>
Mathias Agopian1a2952a2013-02-14 17:11:27 -080053#include <gui/Surface.h>
Mathias Agopian3cf61352010-02-09 17:46:37 -080054
Andreas Huber14acc732010-12-06 10:36:06 -080055#include <media/stagefright/foundation/AMessage.h>
Andreas Hubere71d10e2010-06-07 14:35:29 -070056
Glenn Kasteneabd3462011-03-23 14:34:31 -070057#include <cutils/properties.h>
58
Andreas Hubere332a912010-11-15 09:03:03 -080059#define USE_SURFACE_ALLOC 1
James Dong14f95742011-08-11 17:38:35 -070060#define FRAME_DROP_FREQ 0
Andreas Hubere332a912010-11-15 09:03:03 -080061
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080062namespace android {
63
Andreas Huber8650e192010-09-03 13:20:33 -070064static int64_t kLowWaterMarkUs = 2000000ll; // 2secs
Gloria Wang83ed9d42011-08-10 14:19:05 -070065static int64_t kHighWaterMarkUs = 5000000ll; // 5secs
Andreas Huberac05c312011-01-19 15:07:19 -080066static const size_t kLowWaterMarkBytes = 40000;
67static const size_t kHighWaterMarkBytes = 200000;
Andreas Huber8650e192010-09-03 13:20:33 -070068
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +010069// maximum time in paused state when offloading audio decompression. When elapsed, the AudioPlayer
70// is destroyed to allow the audio DSP to power down.
71static int64_t kOffloadPauseMaxUs = 60000000ll;
72
73
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080074struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huberc23f12a2010-02-08 14:40:30 -080075 AwesomeEvent(
76 AwesomePlayer *player,
77 void (AwesomePlayer::*method)())
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080078 : mPlayer(player),
Andreas Huberc23f12a2010-02-08 14:40:30 -080079 mMethod(method) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080080 }
81
82protected:
83 virtual ~AwesomeEvent() {}
84
85 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huberc23f12a2010-02-08 14:40:30 -080086 (mPlayer->*mMethod)();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080087 }
88
89private:
90 AwesomePlayer *mPlayer;
Andreas Huberc23f12a2010-02-08 14:40:30 -080091 void (AwesomePlayer::*mMethod)();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -080092
93 AwesomeEvent(const AwesomeEvent &);
94 AwesomeEvent &operator=(const AwesomeEvent &);
95};
96
Andreas Huber733b7722009-12-14 14:18:22 -080097struct AwesomeLocalRenderer : public AwesomeRenderer {
98 AwesomeLocalRenderer(
Glenn Kasten11731182011-02-08 17:26:17 -080099 const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta)
100 : mTarget(new SoftwareRenderer(nativeWindow, meta)) {
Andreas Huber733b7722009-12-14 14:18:22 -0800101 }
102
103 virtual void render(MediaBuffer *buffer) {
Andreas Huberfa090f52010-02-12 14:40:08 -0800104 render((const uint8_t *)buffer->data() + buffer->range_offset(),
105 buffer->range_length());
106 }
107
108 void render(const void *data, size_t size) {
109 mTarget->render(data, size, NULL);
Andreas Huber733b7722009-12-14 14:18:22 -0800110 }
111
112protected:
113 virtual ~AwesomeLocalRenderer() {
114 delete mTarget;
115 mTarget = NULL;
116 }
117
118private:
Andreas Huber0a5ca662010-11-16 13:05:53 -0800119 SoftwareRenderer *mTarget;
Andreas Huber988e3f02010-02-11 11:00:26 -0800120
Andreas Huber733b7722009-12-14 14:18:22 -0800121 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
122 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
123};
124
Jamie Gennis6a9da9f2010-10-07 14:08:38 -0700125struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
Andreas Huberba529e42010-11-16 15:26:30 -0800126 AwesomeNativeWindowRenderer(
127 const sp<ANativeWindow> &nativeWindow,
128 int32_t rotationDegrees)
Jamie Gennis6a9da9f2010-10-07 14:08:38 -0700129 : mNativeWindow(nativeWindow) {
Andreas Huberba529e42010-11-16 15:26:30 -0800130 applyRotation(rotationDegrees);
Jamie Gennis6a9da9f2010-10-07 14:08:38 -0700131 }
132
133 virtual void render(MediaBuffer *buffer) {
Jamie Gennis21633202012-05-11 04:42:12 -0700134 ATRACE_CALL();
Glenn Kasten593e2772011-06-27 10:10:19 -0700135 int64_t timeUs;
136 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
137 native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000);
Jamie Gennis6a9da9f2010-10-07 14:08:38 -0700138 status_t err = mNativeWindow->queueBuffer(
Jamie Gennis1e5b2b32012-06-13 16:29:51 -0700139 mNativeWindow.get(), buffer->graphicBuffer().get(), -1);
Jamie Gennis6a9da9f2010-10-07 14:08:38 -0700140 if (err != 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000141 ALOGE("queueBuffer failed with error %s (%d)", strerror(-err),
Jamie Gennis6a9da9f2010-10-07 14:08:38 -0700142 -err);
143 return;
144 }
145
146 sp<MetaData> metaData = buffer->meta_data();
147 metaData->setInt32(kKeyRendered, 1);
148 }
149
150protected:
151 virtual ~AwesomeNativeWindowRenderer() {}
152
153private:
154 sp<ANativeWindow> mNativeWindow;
155
Andreas Huberba529e42010-11-16 15:26:30 -0800156 void applyRotation(int32_t rotationDegrees) {
157 uint32_t transform;
158 switch (rotationDegrees) {
159 case 0: transform = 0; break;
160 case 90: transform = HAL_TRANSFORM_ROT_90; break;
161 case 180: transform = HAL_TRANSFORM_ROT_180; break;
162 case 270: transform = HAL_TRANSFORM_ROT_270; break;
163 default: transform = 0; break;
164 }
165
166 if (transform) {
167 CHECK_EQ(0, native_window_set_buffers_transform(
168 mNativeWindow.get(), transform));
169 }
170 }
171
Jamie Gennis6a9da9f2010-10-07 14:08:38 -0700172 AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
173 AwesomeNativeWindowRenderer &operator=(
174 const AwesomeNativeWindowRenderer &);
175};
176
Gloria Wang7cf180c2011-02-19 18:37:57 -0800177// To collect the decoder usage
178void addBatteryData(uint32_t params) {
179 sp<IBinder> binder =
180 defaultServiceManager()->getService(String16("media.player"));
181 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
182 CHECK(service.get() != NULL);
Andreas Hubere2b10282010-11-23 11:41:34 -0800183
Gloria Wang7cf180c2011-02-19 18:37:57 -0800184 service->addBatteryData(params);
185}
186
187////////////////////////////////////////////////////////////////////////////////
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800188AwesomePlayer::AwesomePlayer()
Andreas Huber2e8ffaf2010-02-18 16:45:13 -0800189 : mQueueStarted(false),
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700190 mUIDValid(false),
Andreas Huber2e8ffaf2010-02-18 16:45:13 -0800191 mTimeSource(NULL),
James Dongc374dae2012-07-19 19:18:06 -0700192 mVideoRenderingStarted(false),
Andreas Huberfa090f52010-02-12 14:40:08 -0800193 mVideoRendererIsPreview(false),
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700194 mMediaRenderingStartGeneration(0),
195 mStartGeneration(0),
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800196 mAudioPlayer(NULL),
James Dongb45c01c2011-01-16 11:30:13 -0800197 mDisplayWidth(0),
198 mDisplayHeight(0),
James Dong4f6eed02012-04-30 14:38:12 -0700199 mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
Andreas Huberbd22c522010-02-09 14:05:43 -0800200 mFlags(0),
Andreas Huberacdd9d02010-05-06 10:18:05 -0700201 mExtractorFlags(0),
Andreas Huber7b3396a2010-02-12 10:42:02 -0800202 mVideoBuffer(NULL),
Andreas Huber150694c2011-03-14 10:55:40 -0700203 mDecryptHandle(NULL),
Gloria Wang7a1e3e82011-05-03 15:59:03 -0700204 mLastVideoTimeUs(-1),
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +0100205 mTextDriver(NULL),
206 mOffloadAudio(false),
207 mAudioTearDown(false) {
Andreas Hubere2b10282010-11-23 11:41:34 -0800208 CHECK_EQ(mClient.connect(), (status_t)OK);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800209
210 DataSource::RegisterDefaultSniffers();
211
Andreas Huberc23f12a2010-02-08 14:40:30 -0800212 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800213 mVideoEventPending = false;
Andreas Huberc23f12a2010-02-08 14:40:30 -0800214 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800215 mStreamDoneEventPending = false;
Andreas Huberc23f12a2010-02-08 14:40:30 -0800216 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huber66b0a352010-01-26 16:20:10 -0800217 mBufferingEventPending = false;
Andreas Huber145e68f2011-01-11 15:05:28 -0800218 mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
Sungsoo Limf90b1232013-07-10 15:09:38 +0900219 mVideoLagEventPending = false;
Andreas Huberc23f12a2010-02-08 14:40:30 -0800220
221 mCheckAudioStatusEvent = new AwesomeEvent(
222 this, &AwesomePlayer::onCheckAudioStatus);
223
Andreas Huber1862a332010-02-03 11:37:29 -0800224 mAudioStatusEventPending = false;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800225
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +0100226 mAudioTearDownEvent = new AwesomeEvent(this,
227 &AwesomePlayer::onAudioTearDownEvent);
228 mAudioTearDownEventPending = false;
229
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800230 reset();
231}
232
233AwesomePlayer::~AwesomePlayer() {
Andreas Huber2e8ffaf2010-02-18 16:45:13 -0800234 if (mQueueStarted) {
235 mQueue.stop();
236 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800237
238 reset();
239
240 mClient.disconnect();
241}
242
Andreas Huberc34233e2011-11-16 10:46:05 -0800243void AwesomePlayer::cancelPlayerEvents(bool keepNotifications) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800244 mQueue.cancelEvent(mVideoEvent->eventID());
245 mVideoEventPending = false;
Andreas Huber145e68f2011-01-11 15:05:28 -0800246 mQueue.cancelEvent(mVideoLagEvent->eventID());
247 mVideoLagEventPending = false;
Andreas Huber66b0a352010-01-26 16:20:10 -0800248
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +0100249 if (mOffloadAudio) {
250 mQueue.cancelEvent(mAudioTearDownEvent->eventID());
251 mAudioTearDownEventPending = false;
252 }
253
Andreas Huberc34233e2011-11-16 10:46:05 -0800254 if (!keepNotifications) {
255 mQueue.cancelEvent(mStreamDoneEvent->eventID());
256 mStreamDoneEventPending = false;
257 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
258 mAudioStatusEventPending = false;
259
Andreas Huber66b0a352010-01-26 16:20:10 -0800260 mQueue.cancelEvent(mBufferingEvent->eventID());
261 mBufferingEventPending = false;
262 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800263}
264
Andreas Huber07260452010-01-21 10:28:45 -0800265void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800266 Mutex::Autolock autoLock(mLock);
267 mListener = listener;
268}
269
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700270void AwesomePlayer::setUID(uid_t uid) {
Steve Block3856b092011-10-20 11:56:00 +0100271 ALOGV("AwesomePlayer running on behalf of uid %d", uid);
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700272
273 mUID = uid;
274 mUIDValid = true;
275}
276
Andreas Huber5561ccf2010-01-27 16:49:05 -0800277status_t AwesomePlayer::setDataSource(
278 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800279 Mutex::Autolock autoLock(mLock);
Andreas Huber7b3396a2010-02-12 10:42:02 -0800280 return setDataSource_l(uri, headers);
281}
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800282
Andreas Huber7b3396a2010-02-12 10:42:02 -0800283status_t AwesomePlayer::setDataSource_l(
284 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800285 reset_l();
286
Andreas Huberbd22c522010-02-09 14:05:43 -0800287 mUri = uri;
Andreas Huber66b0a352010-01-26 16:20:10 -0800288
Andreas Huberbd22c522010-02-09 14:05:43 -0800289 if (headers) {
290 mUriHeaders = *headers;
Andreas Huber7314fa12011-02-24 14:42:48 -0800291
292 ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));
293 if (index >= 0) {
294 // Browser is in "incognito" mode, suppress logging URLs.
295
296 // This isn't something that should be passed to the server.
297 mUriHeaders.removeItemsAt(index);
298
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700299 modifyFlags(INCOGNITO, SET);
Andreas Huber7314fa12011-02-24 14:42:48 -0800300 }
301 }
302
James Dong53ae1642012-08-17 13:41:59 -0700303 ALOGI("setDataSource_l(URL suppressed)");
Andreas Huber66b0a352010-01-26 16:20:10 -0800304
Andreas Huberbd22c522010-02-09 14:05:43 -0800305 // The actual work will be done during preparation in the call to
306 // ::finishSetDataSource_l to avoid blocking the calling thread in
307 // setDataSource for any significant time.
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800308
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700309 {
310 Mutex::Autolock autoLock(mStatsLock);
311 mStats.mFd = -1;
312 mStats.mURI = mUri;
313 }
314
Andreas Huberbd22c522010-02-09 14:05:43 -0800315 return OK;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800316}
317
318status_t AwesomePlayer::setDataSource(
319 int fd, int64_t offset, int64_t length) {
320 Mutex::Autolock autoLock(mLock);
321
322 reset_l();
323
Andreas Huber7b3396a2010-02-12 10:42:02 -0800324 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800325
Andreas Huber7b3396a2010-02-12 10:42:02 -0800326 status_t err = dataSource->initCheck();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800327
328 if (err != OK) {
329 return err;
330 }
331
Andreas Huber7b3396a2010-02-12 10:42:02 -0800332 mFileSource = dataSource;
333
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700334 {
335 Mutex::Autolock autoLock(mStatsLock);
336 mStats.mFd = fd;
337 mStats.mURI = String8();
338 }
339
Andreas Huber7b3396a2010-02-12 10:42:02 -0800340 return setDataSource_l(dataSource);
341}
342
Andreas Hubere2b10282010-11-23 11:41:34 -0800343status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
Andreas Huber85704832010-12-16 10:16:36 -0800344 return INVALID_OPERATION;
Andreas Hubere2b10282010-11-23 11:41:34 -0800345}
346
Andreas Huber7b3396a2010-02-12 10:42:02 -0800347status_t AwesomePlayer::setDataSource_l(
348 const sp<DataSource> &dataSource) {
349 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800350
351 if (extractor == NULL) {
352 return UNKNOWN_ERROR;
353 }
354
James Dong9d2f3862012-01-10 08:24:37 -0800355 if (extractor->getDrmFlag()) {
356 checkDrmStatus(dataSource);
357 }
358
359 return setDataSource_l(extractor);
360}
361
362void AwesomePlayer::checkDrmStatus(const sp<DataSource>& dataSource) {
James Dong785ee062011-12-14 10:57:05 -0800363 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
364 if (mDecryptHandle != NULL) {
365 CHECK(mDrmManagerClient);
366 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
367 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
Gloria Wang8f641342011-02-08 13:24:08 -0800368 }
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700369 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800370}
371
372status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber7fbdb092010-10-12 16:55:11 -0700373 // Attempt to approximate overall stream bitrate by summing all
374 // tracks' individual bitrates, if not all of them advertise bitrate,
375 // we have to fail.
376
377 int64_t totalBitRate = 0;
378
James Dongeec46ab2012-04-11 17:56:22 -0700379 mExtractor = extractor;
Andreas Huber7fbdb092010-10-12 16:55:11 -0700380 for (size_t i = 0; i < extractor->countTracks(); ++i) {
381 sp<MetaData> meta = extractor->getTrackMetaData(i);
382
383 int32_t bitrate;
384 if (!meta->findInt32(kKeyBitRate, &bitrate)) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700385 const char *mime;
386 CHECK(meta->findCString(kKeyMIMEType, &mime));
Steve Block3856b092011-10-20 11:56:00 +0100387 ALOGV("track of type '%s' does not publish bitrate", mime);
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700388
Andreas Huber7fbdb092010-10-12 16:55:11 -0700389 totalBitRate = -1;
390 break;
391 }
392
393 totalBitRate += bitrate;
394 }
395
396 mBitrate = totalBitRate;
397
Steve Block3856b092011-10-20 11:56:00 +0100398 ALOGV("mBitrate = %lld bits/sec", mBitrate);
Andreas Huber7fbdb092010-10-12 16:55:11 -0700399
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700400 {
401 Mutex::Autolock autoLock(mStatsLock);
402 mStats.mBitrate = mBitrate;
403 mStats.mTracks.clear();
404 mStats.mAudioTrackIndex = -1;
405 mStats.mVideoTrackIndex = -1;
406 }
407
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800408 bool haveAudio = false;
409 bool haveVideo = false;
410 for (size_t i = 0; i < extractor->countTracks(); ++i) {
411 sp<MetaData> meta = extractor->getTrackMetaData(i);
412
Andreas Huber32bdfd52011-10-26 11:22:40 -0700413 const char *_mime;
414 CHECK(meta->findCString(kKeyMIMEType, &_mime));
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800415
Andreas Huber32bdfd52011-10-26 11:22:40 -0700416 String8 mime = String8(_mime);
417
418 if (!haveVideo && !strncasecmp(mime.string(), "video/", 6)) {
Andreas Huber88d8a832010-03-05 10:42:10 -0800419 setVideoSource(extractor->getTrack(i));
420 haveVideo = true;
James Dongb45c01c2011-01-16 11:30:13 -0800421
422 // Set the presentation/display size
423 int32_t displayWidth, displayHeight;
424 bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
425 if (success) {
426 success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
427 }
428 if (success) {
429 mDisplayWidth = displayWidth;
430 mDisplayHeight = displayHeight;
431 }
432
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700433 {
434 Mutex::Autolock autoLock(mStatsLock);
435 mStats.mVideoTrackIndex = mStats.mTracks.size();
436 mStats.mTracks.push();
437 TrackStat *stat =
438 &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
Andreas Huber32bdfd52011-10-26 11:22:40 -0700439 stat->mMIME = mime.string();
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700440 }
Andreas Huber32bdfd52011-10-26 11:22:40 -0700441 } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) {
Andreas Huber88d8a832010-03-05 10:42:10 -0800442 setAudioSource(extractor->getTrack(i));
443 haveAudio = true;
James Dongab7a2e52012-04-26 17:11:28 -0700444 mActiveAudioTrackIndex = i;
Andreas Huber8ae49d82010-09-03 14:09:21 -0700445
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700446 {
447 Mutex::Autolock autoLock(mStatsLock);
448 mStats.mAudioTrackIndex = mStats.mTracks.size();
449 mStats.mTracks.push();
450 TrackStat *stat =
451 &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
Andreas Huber32bdfd52011-10-26 11:22:40 -0700452 stat->mMIME = mime.string();
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700453 }
454
Andreas Huber32bdfd52011-10-26 11:22:40 -0700455 if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_AUDIO_VORBIS)) {
Andreas Huber69545352010-10-04 11:09:31 -0700456 // Only do this for vorbis audio, none of the other audio
457 // formats even support this ringtone specific hack and
458 // retrieving the metadata on some extractors may turn out
459 // to be very expensive.
460 sp<MetaData> fileMeta = extractor->getMetaData();
461 int32_t loop;
462 if (fileMeta != NULL
463 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700464 modifyFlags(AUTO_LOOPING, SET);
Andreas Huber69545352010-10-04 11:09:31 -0700465 }
Andreas Huber8ae49d82010-09-03 14:09:21 -0700466 }
Andreas Huber32bdfd52011-10-26 11:22:40 -0700467 } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
Edwin Wong6a3969c2012-05-02 18:57:12 -0700468 addTextSource_l(i, extractor->getTrack(i));
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800469 }
470 }
471
Andreas Huberacdd9d02010-05-06 10:18:05 -0700472 if (!haveAudio && !haveVideo) {
Edwin Wong8a74c9b2012-09-06 14:07:37 -0700473 if (mWVMExtractor != NULL) {
474 return mWVMExtractor->getError();
475 } else {
476 return UNKNOWN_ERROR;
477 }
Andreas Huberacdd9d02010-05-06 10:18:05 -0700478 }
479
480 mExtractorFlags = extractor->flags();
481
482 return OK;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800483}
484
485void AwesomePlayer::reset() {
486 Mutex::Autolock autoLock(mLock);
487 reset_l();
488}
489
490void AwesomePlayer::reset_l() {
James Dongc374dae2012-07-19 19:18:06 -0700491 mVideoRenderingStarted = false;
James Dongab7a2e52012-04-26 17:11:28 -0700492 mActiveAudioTrackIndex = -1;
James Dongb45c01c2011-01-16 11:30:13 -0800493 mDisplayWidth = 0;
494 mDisplayHeight = 0;
Andreas Huber65a170e2011-01-04 10:19:13 -0800495
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700496 notifyListener_l(MEDIA_STOPPED);
497
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700498 if (mDecryptHandle != NULL) {
499 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
500 Playback::STOP, 0);
Gloria Wangdcd25ef2010-06-22 13:55:38 -0700501 mDecryptHandle = NULL;
502 mDrmManagerClient = NULL;
503 }
504
Gloria Wang7cf180c2011-02-19 18:37:57 -0800505 if (mFlags & PLAYING) {
506 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
507 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
508 params |= IMediaPlayerService::kBatteryDataTrackAudio;
509 }
510 if (mVideoSource != NULL) {
511 params |= IMediaPlayerService::kBatteryDataTrackVideo;
512 }
513 addBatteryData(params);
514 }
515
Andreas Hubere94bd142010-03-12 08:59:22 -0800516 if (mFlags & PREPARING) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700517 modifyFlags(PREPARE_CANCELLED, SET);
Andreas Hubere94bd142010-03-12 08:59:22 -0800518 if (mConnectingDataSource != NULL) {
Steve Blockdf64d152012-01-04 20:05:49 +0000519 ALOGI("interrupting the connection process");
Andreas Hubere94bd142010-03-12 08:59:22 -0800520 mConnectingDataSource->disconnect();
521 }
Andreas Huber6a05c9e2010-10-19 12:18:51 -0700522
523 if (mFlags & PREPARING_CONNECTED) {
524 // We are basically done preparing, we're just buffering
525 // enough data to start playback, we can safely interrupt that.
526 finishAsyncPrepare_l();
527 }
Andreas Hubere94bd142010-03-12 08:59:22 -0800528 }
529
Andreas Huberbd22c522010-02-09 14:05:43 -0800530 while (mFlags & PREPARING) {
531 mPreparedCondition.wait(mLock);
532 }
533
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800534 cancelPlayerEvents();
535
Andreas Huber681755f2011-04-21 10:06:43 -0700536 mWVMExtractor.clear();
Andreas Huber0a5baa92010-06-10 11:17:50 -0700537 mCachedSource.clear();
Andreas Huber88d8a832010-03-05 10:42:10 -0800538 mAudioTrack.clear();
539 mVideoTrack.clear();
James Dongeec46ab2012-04-11 17:56:22 -0700540 mExtractor.clear();
Andreas Huber88d8a832010-03-05 10:42:10 -0800541
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +0100542 // Shutdown audio first, so that the response to the reset request
Andreas Huber7b3396a2010-02-12 10:42:02 -0800543 // appears to happen instantaneously as far as the user is concerned
544 // If we did this later, audio would continue playing while we
545 // shutdown the video-related resources and the player appear to
546 // not be as responsive to a reset request.
Gloria Wang5b75fdc2011-08-31 10:24:18 -0700547 if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
548 && mAudioSource != NULL) {
Andreas Hubere94bd142010-03-12 08:59:22 -0800549 // If we had an audio player, it would have effectively
550 // taken possession of the audio source and stopped it when
551 // _it_ is stopped. Otherwise this is still our responsibility.
552 mAudioSource->stop();
553 }
Andreas Huber7b3396a2010-02-12 10:42:02 -0800554 mAudioSource.clear();
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +0100555 mOmxSource.clear();
Andreas Huber7b3396a2010-02-12 10:42:02 -0800556
Andreas Huber7b3396a2010-02-12 10:42:02 -0800557 mTimeSource = NULL;
558
559 delete mAudioPlayer;
560 mAudioPlayer = NULL;
561
Insun Kang66551742012-01-11 22:03:12 +0900562 if (mTextDriver != NULL) {
563 delete mTextDriver;
564 mTextDriver = NULL;
Gloria Wang7a1e3e82011-05-03 15:59:03 -0700565 }
566
Andreas Huberb9280d52010-01-22 14:36:53 -0800567 mVideoRenderer.clear();
568
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800569 if (mVideoSource != NULL) {
Andreas Huber150694c2011-03-14 10:55:40 -0700570 shutdownVideoDecoder_l();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800571 }
572
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800573 mDurationUs = -1;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700574 modifyFlags(0, ASSIGN);
Andreas Huberacdd9d02010-05-06 10:18:05 -0700575 mExtractorFlags = 0;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800576 mTimeSourceDeltaUs = 0;
577 mVideoTimeUs = 0;
578
Andreas Huber64bb6982011-02-24 12:05:40 -0800579 mSeeking = NO_SEEK;
Gloria Wangaf64a8a2011-08-18 14:52:36 -0700580 mSeekNotificationSent = true;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800581 mSeekTimeUs = 0;
Andreas Huber66b0a352010-01-26 16:20:10 -0800582
Andreas Huberbd22c522010-02-09 14:05:43 -0800583 mUri.setTo("");
584 mUriHeaders.clear();
Andreas Huber7b3396a2010-02-12 10:42:02 -0800585
586 mFileSource.clear();
587
Andreas Huber7fbdb092010-10-12 16:55:11 -0700588 mBitrate = -1;
Andreas Huber150694c2011-03-14 10:55:40 -0700589 mLastVideoTimeUs = -1;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700590
591 {
592 Mutex::Autolock autoLock(mStatsLock);
593 mStats.mFd = -1;
594 mStats.mURI = String8();
595 mStats.mBitrate = -1;
596 mStats.mAudioTrackIndex = -1;
597 mStats.mVideoTrackIndex = -1;
598 mStats.mNumVideoFramesDecoded = 0;
599 mStats.mNumVideoFramesDropped = 0;
600 mStats.mVideoWidth = -1;
601 mStats.mVideoHeight = -1;
602 mStats.mFlags = 0;
603 mStats.mTracks.clear();
604 }
605
Andreas Huber99590d22011-08-16 12:41:41 -0700606 mWatchForAudioSeekComplete = false;
607 mWatchForAudioEOS = false;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800608}
609
Andreas Huberc23f12a2010-02-08 14:40:30 -0800610void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +0100611 if ((mListener != NULL) && !mAudioTearDown) {
Andreas Huber07260452010-01-21 10:28:45 -0800612 sp<MediaPlayerBase> listener = mListener.promote();
613
614 if (listener != NULL) {
Andreas Huberc23f12a2010-02-08 14:40:30 -0800615 listener->sendEvent(msg, ext1, ext2);
Andreas Huber07260452010-01-21 10:28:45 -0800616 }
617 }
618}
619
Andreas Huber7fbdb092010-10-12 16:55:11 -0700620bool AwesomePlayer::getBitrate(int64_t *bitrate) {
James Dongc7fc37a2010-11-16 14:04:54 -0800621 off64_t size;
Ajay Dudani776a0022013-05-22 22:16:33 -0700622 if (mDurationUs > 0 && mCachedSource != NULL
Andreas Huber7fbdb092010-10-12 16:55:11 -0700623 && mCachedSource->getSize(&size) == OK) {
624 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec
625 return true;
626 }
627
628 if (mBitrate >= 0) {
629 *bitrate = mBitrate;
630 return true;
631 }
632
633 *bitrate = 0;
634
635 return false;
636}
637
Andreas Huber8650e192010-09-03 13:20:33 -0700638// Returns true iff cached duration is available/applicable.
639bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
Andreas Huber7fbdb092010-10-12 16:55:11 -0700640 int64_t bitrate;
Andreas Huber8650e192010-09-03 13:20:33 -0700641
hovanchenb9b8d142013-07-02 15:07:44 +0800642 if (mCachedSource != NULL && getBitrate(&bitrate) && (bitrate > 0)) {
Bryan Mawhinney1bd233c2011-01-18 19:12:21 +0000643 status_t finalStatus;
644 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
Andreas Huber8650e192010-09-03 13:20:33 -0700645 *durationUs = cachedDataRemaining * 8000000ll / bitrate;
Bryan Mawhinney1bd233c2011-01-18 19:12:21 +0000646 *eos = (finalStatus != OK);
Andreas Huber8650e192010-09-03 13:20:33 -0700647 return true;
Andreas Huber681755f2011-04-21 10:06:43 -0700648 } else if (mWVMExtractor != NULL) {
649 status_t finalStatus;
650 *durationUs = mWVMExtractor->getCachedDurationUs(&finalStatus);
651 *eos = (finalStatus != OK);
652 return true;
Andreas Huber8650e192010-09-03 13:20:33 -0700653 }
654
655 return false;
656}
657
Andreas Huber34ef0f32010-11-11 15:37:17 -0800658void AwesomePlayer::ensureCacheIsFetching_l() {
659 if (mCachedSource != NULL) {
660 mCachedSource->resumeFetchingIfNecessary();
661 }
662}
663
Andreas Huber145e68f2011-01-11 15:05:28 -0800664void AwesomePlayer::onVideoLagUpdate() {
665 Mutex::Autolock autoLock(mLock);
666 if (!mVideoLagEventPending) {
667 return;
668 }
669 mVideoLagEventPending = false;
670
671 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
672 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
673
Andreas Huber5dac87b2011-03-25 13:03:14 -0700674 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
Steve Block3856b092011-10-20 11:56:00 +0100675 ALOGV("video late by %lld ms.", videoLateByUs / 1000ll);
Andreas Huber145e68f2011-01-11 15:05:28 -0800676
677 notifyListener_l(
678 MEDIA_INFO,
679 MEDIA_INFO_VIDEO_TRACK_LAGGING,
680 videoLateByUs / 1000ll);
681 }
682
683 postVideoLagEvent_l();
684}
685
Andreas Huber66b0a352010-01-26 16:20:10 -0800686void AwesomePlayer::onBufferingUpdate() {
687 Mutex::Autolock autoLock(mLock);
Andreas Huberd29345d2010-02-17 15:58:57 -0800688 if (!mBufferingEventPending) {
689 return;
690 }
Andreas Huber66b0a352010-01-26 16:20:10 -0800691 mBufferingEventPending = false;
692
Andreas Huber8650e192010-09-03 13:20:33 -0700693 if (mCachedSource != NULL) {
Bryan Mawhinney1bd233c2011-01-18 19:12:21 +0000694 status_t finalStatus;
695 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
696 bool eos = (finalStatus != OK);
Andreas Huberc9e89482010-09-01 15:05:28 -0700697
Andreas Huber8650e192010-09-03 13:20:33 -0700698 if (eos) {
Bryan Mawhinney1bd233c2011-01-18 19:12:21 +0000699 if (finalStatus == ERROR_END_OF_STREAM) {
700 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
701 }
Andreas Huber83977eb2010-10-04 11:36:39 -0700702 if (mFlags & PREPARING) {
Steve Block3856b092011-10-20 11:56:00 +0100703 ALOGV("cache has reached EOS, prepare is done.");
Andreas Huber83977eb2010-10-04 11:36:39 -0700704 finishAsyncPrepare_l();
705 }
Andreas Huber8650e192010-09-03 13:20:33 -0700706 } else {
Andreas Huber7fbdb092010-10-12 16:55:11 -0700707 int64_t bitrate;
708 if (getBitrate(&bitrate)) {
Andreas Huber8650e192010-09-03 13:20:33 -0700709 size_t cachedSize = mCachedSource->cachedSize();
710 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
711
712 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
713 if (percentage > 100) {
714 percentage = 100;
715 }
716
717 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
718 } else {
719 // We don't know the bitrate of the stream, use absolute size
720 // limits to maintain the cache.
721
Andreas Huber8650e192010-09-03 13:20:33 -0700722 if ((mFlags & PLAYING) && !eos
723 && (cachedDataRemaining < kLowWaterMarkBytes)) {
Steve Blockdf64d152012-01-04 20:05:49 +0000724 ALOGI("cache is running low (< %d) , pausing.",
Andreas Huber8650e192010-09-03 13:20:33 -0700725 kLowWaterMarkBytes);
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700726 modifyFlags(CACHE_UNDERRUN, SET);
Andreas Huber8650e192010-09-03 13:20:33 -0700727 pause_l();
Andreas Huber34ef0f32010-11-11 15:37:17 -0800728 ensureCacheIsFetching_l();
James Dong5b1b8a92011-05-25 19:37:03 -0700729 sendCacheStats();
Andreas Huber8650e192010-09-03 13:20:33 -0700730 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
731 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
732 if (mFlags & CACHE_UNDERRUN) {
Steve Blockdf64d152012-01-04 20:05:49 +0000733 ALOGI("cache has filled up (> %d), resuming.",
Andreas Huber8650e192010-09-03 13:20:33 -0700734 kHighWaterMarkBytes);
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700735 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber8650e192010-09-03 13:20:33 -0700736 play_l();
Andreas Huber8650e192010-09-03 13:20:33 -0700737 } else if (mFlags & PREPARING) {
Steve Block3856b092011-10-20 11:56:00 +0100738 ALOGV("cache has filled up (> %d), prepare is done",
Andreas Huber8650e192010-09-03 13:20:33 -0700739 kHighWaterMarkBytes);
740 finishAsyncPrepare_l();
741 }
742 }
743 }
744 }
Andreas Huber681755f2011-04-21 10:06:43 -0700745 } else if (mWVMExtractor != NULL) {
746 status_t finalStatus;
747
748 int64_t cachedDurationUs
749 = mWVMExtractor->getCachedDurationUs(&finalStatus);
750
751 bool eos = (finalStatus != OK);
752
753 if (eos) {
754 if (finalStatus == ERROR_END_OF_STREAM) {
755 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
756 }
757 if (mFlags & PREPARING) {
Steve Block3856b092011-10-20 11:56:00 +0100758 ALOGV("cache has reached EOS, prepare is done.");
Andreas Huber681755f2011-04-21 10:06:43 -0700759 finishAsyncPrepare_l();
760 }
761 } else {
762 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
763 if (percentage > 100) {
764 percentage = 100;
765 }
766
767 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
768 }
Andreas Huber8650e192010-09-03 13:20:33 -0700769 }
770
771 int64_t cachedDurationUs;
772 bool eos;
773 if (getCachedDuration_l(&cachedDurationUs, &eos)) {
Steve Block3856b092011-10-20 11:56:00 +0100774 ALOGV("cachedDurationUs = %.2f secs, eos=%d",
Andreas Huber34ef0f32010-11-11 15:37:17 -0800775 cachedDurationUs / 1E6, eos);
776
Andreas Huberc9e89482010-09-01 15:05:28 -0700777 if ((mFlags & PLAYING) && !eos
Andreas Huber8650e192010-09-03 13:20:33 -0700778 && (cachedDurationUs < kLowWaterMarkUs)) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700779 modifyFlags(CACHE_UNDERRUN, SET);
Jeff Tinkera3fafcb2012-10-01 12:57:48 -0700780 ALOGI("cache is running low (%.2f secs) , pausing.",
781 cachedDurationUs / 1E6);
782 pause_l();
783 ensureCacheIsFetching_l();
Jeffrey Tinkerf10f36d2012-08-23 01:56:53 -0700784 sendCacheStats();
Andreas Huberc9e89482010-09-01 15:05:28 -0700785 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700786 } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
Andreas Huber8650e192010-09-03 13:20:33 -0700787 if (mFlags & CACHE_UNDERRUN) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700788 modifyFlags(CACHE_UNDERRUN, CLEAR);
Jeff Tinkera3fafcb2012-10-01 12:57:48 -0700789 ALOGI("cache has filled up (%.2f secs), resuming.",
790 cachedDurationUs / 1E6);
791 play_l();
Andreas Huber8650e192010-09-03 13:20:33 -0700792 } else if (mFlags & PREPARING) {
Steve Block3856b092011-10-20 11:56:00 +0100793 ALOGV("cache has filled up (%.2f secs), prepare is done",
Andreas Huber8650e192010-09-03 13:20:33 -0700794 cachedDurationUs / 1E6);
795 finishAsyncPrepare_l();
Andreas Huber2a4b49b2010-08-25 12:31:48 -0700796 }
Andreas Huber2a4b49b2010-08-25 12:31:48 -0700797 }
Andreas Huber66b0a352010-01-26 16:20:10 -0800798 }
Andreas Huber0a5baa92010-06-10 11:17:50 -0700799
Andreas Huber0a5baa92010-06-10 11:17:50 -0700800 postBufferingEvent_l();
Andreas Huber66b0a352010-01-26 16:20:10 -0800801}
802
James Dong5b1b8a92011-05-25 19:37:03 -0700803void AwesomePlayer::sendCacheStats() {
804 sp<MediaPlayerBase> listener = mListener.promote();
Jeffrey Tinkerf10f36d2012-08-23 01:56:53 -0700805 if (listener != NULL) {
James Dong5b1b8a92011-05-25 19:37:03 -0700806 int32_t kbps = 0;
Jeffrey Tinkerf10f36d2012-08-23 01:56:53 -0700807 status_t err = UNKNOWN_ERROR;
808 if (mCachedSource != NULL) {
809 err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
810 } else if (mWVMExtractor != NULL) {
811 err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps);
812 }
James Dong5b1b8a92011-05-25 19:37:03 -0700813 if (err == OK) {
814 listener->sendEvent(
815 MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
816 }
817 }
818}
819
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800820void AwesomePlayer::onStreamDone() {
821 // Posted whenever any stream finishes playing.
Jamie Gennis21633202012-05-11 04:42:12 -0700822 ATRACE_CALL();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800823
824 Mutex::Autolock autoLock(mLock);
Andreas Huberd29345d2010-02-17 15:58:57 -0800825 if (!mStreamDoneEventPending) {
826 return;
827 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800828 mStreamDoneEventPending = false;
829
Andreas Hubered8d14f2011-02-16 09:05:38 -0800830 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100831 ALOGV("MEDIA_ERROR %d", mStreamDoneStatus);
Andreas Huber5d2de4d2010-07-07 13:35:27 -0700832
833 notifyListener_l(
834 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
835
Andreas Huberb2e39542010-10-05 10:25:34 -0700836 pause_l(true /* at eos */);
Andreas Huber5d2de4d2010-07-07 13:35:27 -0700837
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700838 modifyFlags(AT_EOS, SET);
Andreas Huber5d2de4d2010-07-07 13:35:27 -0700839 return;
840 }
841
842 const bool allDone =
843 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
844 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
845
846 if (!allDone) {
847 return;
848 }
849
Andreas Hubercdef6982011-08-18 10:53:23 -0700850 if ((mFlags & LOOPING)
851 || ((mFlags & AUTO_LOOPING)
852 && (mAudioSink == NULL || mAudioSink->realtime()))) {
853 // Don't AUTO_LOOP if we're being recorded, since that cannot be
854 // turned off and recording would go on indefinitely.
855
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800856 seekTo_l(0);
857
Andreas Hubera657f8d2010-02-03 16:02:02 -0800858 if (mVideoSource != NULL) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800859 postVideoEvent_l();
860 }
861 } else {
Steve Block3856b092011-10-20 11:56:00 +0100862 ALOGV("MEDIA_PLAYBACK_COMPLETE");
Andreas Huber5d2de4d2010-07-07 13:35:27 -0700863 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800864
Andreas Huberb2e39542010-10-05 10:25:34 -0700865 pause_l(true /* at eos */);
Andreas Huber2e8ffaf2010-02-18 16:45:13 -0800866
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +0100867 // If audio hasn't completed MEDIA_SEEK_COMPLETE yet,
868 // notify MEDIA_SEEK_COMPLETE to observer immediately for state persistence.
869 if (mWatchForAudioSeekComplete) {
870 notifyListener_l(MEDIA_SEEK_COMPLETE);
871 mWatchForAudioSeekComplete = false;
872 }
873
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700874 modifyFlags(AT_EOS, SET);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800875 }
876}
877
878status_t AwesomePlayer::play() {
Jamie Gennis21633202012-05-11 04:42:12 -0700879 ATRACE_CALL();
880
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800881 Mutex::Autolock autoLock(mLock);
Andreas Huber0a5baa92010-06-10 11:17:50 -0700882
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700883 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber0a5baa92010-06-10 11:17:50 -0700884
Andreas Huber7b3396a2010-02-12 10:42:02 -0800885 return play_l();
886}
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800887
Andreas Huber7b3396a2010-02-12 10:42:02 -0800888status_t AwesomePlayer::play_l() {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700889 modifyFlags(SEEK_PREVIEW, CLEAR);
Andreas Huber2b1222f2011-02-07 11:43:12 -0800890
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800891 if (mFlags & PLAYING) {
892 return OK;
893 }
894
Andreas Huberbd22c522010-02-09 14:05:43 -0800895 if (!(mFlags & PREPARED)) {
896 status_t err = prepare_l();
897
898 if (err != OK) {
899 return err;
900 }
901 }
902
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700903 modifyFlags(PLAYING, SET);
904 modifyFlags(FIRST_FRAME, SET);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800905
Gloria Wangc130b5b2010-11-04 17:38:39 -0700906 if (mDecryptHandle != NULL) {
907 int64_t position;
908 getPosition(&position);
909 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
910 Playback::START, position / 1000);
911 }
912
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800913 if (mAudioSource != NULL) {
914 if (mAudioPlayer == NULL) {
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +0100915 createAudioPlayer_l();
Andreas Huberf0303442011-02-11 13:09:36 -0800916 }
917
918 CHECK(!(mFlags & AUDIO_RUNNING));
919
920 if (mVideoSource == NULL) {
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +0100921
Andreas Huber5442cb52011-07-14 13:02:47 -0700922 // We don't want to post an error notification at this point,
923 // the error returned from MediaPlayer::start() will suffice.
924
925 status_t err = startAudioPlayer_l(
926 false /* sendErrorNotification */);
Andreas Huberf0303442011-02-11 13:09:36 -0800927
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +0100928 if ((err != OK) && mOffloadAudio) {
929 ALOGI("play_l() cannot create offload output, fallback to sw decode");
930 delete mAudioPlayer;
931 mAudioPlayer = NULL;
932 // if the player was started it will take care of stopping the source when destroyed
933 if (!(mFlags & AUDIOPLAYER_STARTED)) {
934 mAudioSource->stop();
935 }
936 modifyFlags((AUDIO_RUNNING | AUDIOPLAYER_STARTED), CLEAR);
937 mOffloadAudio = false;
938 mAudioSource = mOmxSource;
939 if (mAudioSource != NULL) {
940 err = mAudioSource->start();
941
942 if (err != OK) {
943 mAudioSource.clear();
944 } else {
945 createAudioPlayer_l();
946 err = startAudioPlayer_l(false);
947 }
948 }
949 }
950
Andreas Huberf0303442011-02-11 13:09:36 -0800951 if (err != OK) {
952 delete mAudioPlayer;
953 mAudioPlayer = NULL;
954
Andreas Hubera0b1d4b2011-06-07 15:52:25 -0700955 modifyFlags((PLAYING | FIRST_FRAME), CLEAR);
Andreas Huberf0303442011-02-11 13:09:36 -0800956
957 if (mDecryptHandle != NULL) {
958 mDrmManagerClient->setPlaybackStatus(
959 mDecryptHandle, Playback::STOP, 0);
960 }
961
962 return err;
963 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800964 }
965 }
966
967 if (mTimeSource == NULL && mAudioPlayer == NULL) {
Andreas Huber5d2de4d2010-07-07 13:35:27 -0700968 mTimeSource = &mSystemTimeSource;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800969 }
970
971 if (mVideoSource != NULL) {
Andreas Hubera657f8d2010-02-03 16:02:02 -0800972 // Kick off video playback
973 postVideoEvent_l();
Andreas Huber145e68f2011-01-11 15:05:28 -0800974
975 if (mAudioSource != NULL && mVideoSource != NULL) {
976 postVideoLagEvent_l();
977 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800978 }
979
Andreas Huber2e8ffaf2010-02-18 16:45:13 -0800980 if (mFlags & AT_EOS) {
981 // Legacy behaviour, if a stream finishes playing and then
982 // is started again, we play from the start...
983 seekTo_l(0);
984 }
985
Gloria Wang7cf180c2011-02-19 18:37:57 -0800986 uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
987 | IMediaPlayerService::kBatteryDataTrackDecoder;
988 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
989 params |= IMediaPlayerService::kBatteryDataTrackAudio;
990 }
991 if (mVideoSource != NULL) {
992 params |= IMediaPlayerService::kBatteryDataTrackVideo;
993 }
994 addBatteryData(params);
995
Andreas Huberbfa6b2d2009-11-20 09:32:46 -0800996 return OK;
997}
998
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +0100999void AwesomePlayer::createAudioPlayer_l()
1000{
1001 uint32_t flags = 0;
1002 int64_t cachedDurationUs;
1003 bool eos;
1004
1005 if (mOffloadAudio) {
1006 flags |= AudioPlayer::USE_OFFLOAD;
1007 } else if (mVideoSource == NULL
1008 && (mDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US ||
1009 (getCachedDuration_l(&cachedDurationUs, &eos) &&
1010 cachedDurationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US))) {
1011 flags |= AudioPlayer::ALLOW_DEEP_BUFFERING;
1012 }
1013 if (isStreamingHTTP()) {
1014 flags |= AudioPlayer::IS_STREAMING;
1015 }
1016 if (mVideoSource != NULL) {
1017 flags |= AudioPlayer::HAS_VIDEO;
1018 }
1019
1020 mAudioPlayer = new AudioPlayer(mAudioSink, flags, this);
1021 mAudioPlayer->setSource(mAudioSource);
1022
1023 mTimeSource = mAudioPlayer;
1024
1025 // If there was a seek request before we ever started,
1026 // honor the request now.
1027 // Make sure to do this before starting the audio player
1028 // to avoid a race condition.
1029 seekAudioIfNecessary_l();
1030}
1031
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001032void AwesomePlayer::notifyIfMediaStarted_l() {
1033 if (mMediaRenderingStartGeneration == mStartGeneration) {
1034 mMediaRenderingStartGeneration = -1;
1035 notifyListener_l(MEDIA_STARTED);
1036 }
1037}
1038
Andreas Huber5442cb52011-07-14 13:02:47 -07001039status_t AwesomePlayer::startAudioPlayer_l(bool sendErrorNotification) {
Andreas Huberf0303442011-02-11 13:09:36 -08001040 CHECK(!(mFlags & AUDIO_RUNNING));
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001041 status_t err = OK;
Andreas Huberf0303442011-02-11 13:09:36 -08001042
1043 if (mAudioSource == NULL || mAudioPlayer == NULL) {
1044 return OK;
1045 }
1046
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001047 if (mOffloadAudio) {
1048 mQueue.cancelEvent(mAudioTearDownEvent->eventID());
1049 mAudioTearDownEventPending = false;
1050 }
1051
Andreas Huberf0303442011-02-11 13:09:36 -08001052 if (!(mFlags & AUDIOPLAYER_STARTED)) {
Andreas Huberc0dfc5b2011-05-10 13:56:39 -07001053 bool wasSeeking = mAudioPlayer->isSeeking();
1054
Andreas Huberf0303442011-02-11 13:09:36 -08001055 // We've already started the MediaSource in order to enable
1056 // the prefetcher to read its data.
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001057 err = mAudioPlayer->start(
Andreas Huberf0303442011-02-11 13:09:36 -08001058 true /* sourceAlreadyStarted */);
1059
1060 if (err != OK) {
Andreas Huber5442cb52011-07-14 13:02:47 -07001061 if (sendErrorNotification) {
1062 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1063 }
1064
Andreas Huberf0303442011-02-11 13:09:36 -08001065 return err;
1066 }
Andreas Huberc0dfc5b2011-05-10 13:56:39 -07001067
Andreas Hubera6490c62012-05-22 10:51:06 -07001068 modifyFlags(AUDIOPLAYER_STARTED, SET);
1069
Andreas Huberc0dfc5b2011-05-10 13:56:39 -07001070 if (wasSeeking) {
1071 CHECK(!mAudioPlayer->isSeeking());
1072
1073 // We will have finished the seek while starting the audio player.
Andreas Huber02f6e982011-09-01 11:39:11 -07001074 postAudioSeekComplete();
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001075 } else {
1076 notifyIfMediaStarted_l();
Andreas Huberc0dfc5b2011-05-10 13:56:39 -07001077 }
Andreas Huberf0303442011-02-11 13:09:36 -08001078 } else {
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001079 err = mAudioPlayer->resume();
Andreas Huberf0303442011-02-11 13:09:36 -08001080 }
1081
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001082 if (err == OK) {
1083 modifyFlags(AUDIO_RUNNING, SET);
Andreas Huberf0303442011-02-11 13:09:36 -08001084
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001085 mWatchForAudioEOS = true;
1086 }
Andreas Huberf0303442011-02-11 13:09:36 -08001087
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001088 return err;
Andreas Huberf0303442011-02-11 13:09:36 -08001089}
1090
Andreas Huber5daeb122010-08-16 08:49:37 -07001091void AwesomePlayer::notifyVideoSize_l() {
Jamie Gennis21633202012-05-11 04:42:12 -07001092 ATRACE_CALL();
Andreas Huber5daeb122010-08-16 08:49:37 -07001093 sp<MetaData> meta = mVideoSource->getFormat();
1094
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001095 int32_t cropLeft, cropTop, cropRight, cropBottom;
1096 if (!meta->findRect(
1097 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
1098 int32_t width, height;
1099 CHECK(meta->findInt32(kKeyWidth, &width));
1100 CHECK(meta->findInt32(kKeyHeight, &height));
1101
1102 cropLeft = cropTop = 0;
1103 cropRight = width - 1;
1104 cropBottom = height - 1;
1105
Steve Block3856b092011-10-20 11:56:00 +01001106 ALOGV("got dimensions only %d x %d", width, height);
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001107 } else {
Steve Block3856b092011-10-20 11:56:00 +01001108 ALOGV("got crop rect %d, %d, %d, %d",
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001109 cropLeft, cropTop, cropRight, cropBottom);
1110 }
1111
James Dong9cbb1a62011-03-18 12:19:43 -07001112 int32_t displayWidth;
1113 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
Steve Block3856b092011-10-20 11:56:00 +01001114 ALOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
James Dong9cbb1a62011-03-18 12:19:43 -07001115 mDisplayWidth = displayWidth;
1116 }
1117 int32_t displayHeight;
1118 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
Steve Block3856b092011-10-20 11:56:00 +01001119 ALOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
James Dong9cbb1a62011-03-18 12:19:43 -07001120 mDisplayHeight = displayHeight;
1121 }
1122
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001123 int32_t usableWidth = cropRight - cropLeft + 1;
1124 int32_t usableHeight = cropBottom - cropTop + 1;
James Dongb45c01c2011-01-16 11:30:13 -08001125 if (mDisplayWidth != 0) {
1126 usableWidth = mDisplayWidth;
1127 }
1128 if (mDisplayHeight != 0) {
1129 usableHeight = mDisplayHeight;
1130 }
Andreas Huber5daeb122010-08-16 08:49:37 -07001131
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001132 {
1133 Mutex::Autolock autoLock(mStatsLock);
1134 mStats.mVideoWidth = usableWidth;
1135 mStats.mVideoHeight = usableHeight;
1136 }
1137
Andreas Huberba529e42010-11-16 15:26:30 -08001138 int32_t rotationDegrees;
1139 if (!mVideoTrack->getFormat()->findInt32(
1140 kKeyRotation, &rotationDegrees)) {
1141 rotationDegrees = 0;
1142 }
1143
1144 if (rotationDegrees == 90 || rotationDegrees == 270) {
1145 notifyListener_l(
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001146 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
Andreas Huberba529e42010-11-16 15:26:30 -08001147 } else {
1148 notifyListener_l(
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001149 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
Andreas Huberba529e42010-11-16 15:26:30 -08001150 }
Andreas Huber5daeb122010-08-16 08:49:37 -07001151}
1152
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001153void AwesomePlayer::initRenderer_l() {
Jamie Gennis21633202012-05-11 04:42:12 -07001154 ATRACE_CALL();
1155
Glenn Kasten11731182011-02-08 17:26:17 -08001156 if (mNativeWindow == NULL) {
Andreas Huber0a5ca662010-11-16 13:05:53 -08001157 return;
1158 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001159
Andreas Huber0a5ca662010-11-16 13:05:53 -08001160 sp<MetaData> meta = mVideoSource->getFormat();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001161
Andreas Huber0a5ca662010-11-16 13:05:53 -08001162 int32_t format;
1163 const char *component;
1164 int32_t decodedWidth, decodedHeight;
1165 CHECK(meta->findInt32(kKeyColorFormat, &format));
1166 CHECK(meta->findCString(kKeyDecoderComponent, &component));
1167 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
1168 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
Andreas Huber4844ac52009-12-10 15:32:12 -08001169
Andreas Huberba529e42010-11-16 15:26:30 -08001170 int32_t rotationDegrees;
1171 if (!mVideoTrack->getFormat()->findInt32(
1172 kKeyRotation, &rotationDegrees)) {
1173 rotationDegrees = 0;
1174 }
1175
Andreas Huber0a5ca662010-11-16 13:05:53 -08001176 mVideoRenderer.clear();
Andreas Huber4844ac52009-12-10 15:32:12 -08001177
Andreas Huber0a5ca662010-11-16 13:05:53 -08001178 // Must ensure that mVideoRenderer's destructor is actually executed
1179 // before creating a new one.
1180 IPCThreadState::self()->flushCommands();
1181
James Dong4f6eed02012-04-30 14:38:12 -07001182 // Even if set scaling mode fails, we will continue anyway
1183 setVideoScalingMode_l(mVideoScalingMode);
Andreas Huberbbba88c2011-05-11 14:13:42 -07001184 if (USE_SURFACE_ALLOC
1185 && !strncmp(component, "OMX.", 4)
Andreas Huber2944eca2011-09-08 14:12:44 -07001186 && strncmp(component, "OMX.google.", 11)
1187 && strcmp(component, "OMX.Nvidia.mpeg2v.decode")) {
Andreas Huber0a5ca662010-11-16 13:05:53 -08001188 // Hardware decoders avoid the CPU color conversion by decoding
1189 // directly to ANativeBuffers, so we must use a renderer that
1190 // just pushes those buffers to the ANativeWindow.
Andreas Huberba529e42010-11-16 15:26:30 -08001191 mVideoRenderer =
Glenn Kasten11731182011-02-08 17:26:17 -08001192 new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
Andreas Huber0a5ca662010-11-16 13:05:53 -08001193 } else {
1194 // Other decoders are instantiated locally and as a consequence
1195 // allocate their buffers in local address space. This renderer
1196 // then performs a color conversion and copy to get the data
1197 // into the ANativeBuffer.
Glenn Kasten11731182011-02-08 17:26:17 -08001198 mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001199 }
1200}
1201
1202status_t AwesomePlayer::pause() {
Jamie Gennis21633202012-05-11 04:42:12 -07001203 ATRACE_CALL();
1204
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001205 Mutex::Autolock autoLock(mLock);
Andreas Huber0a5baa92010-06-10 11:17:50 -07001206
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001207 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber0a5baa92010-06-10 11:17:50 -07001208
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001209 return pause_l();
1210}
1211
Andreas Huberb2e39542010-10-05 10:25:34 -07001212status_t AwesomePlayer::pause_l(bool at_eos) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001213 if (!(mFlags & PLAYING)) {
1214 return OK;
1215 }
1216
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001217 notifyListener_l(MEDIA_PAUSED);
1218 mMediaRenderingStartGeneration = ++mStartGeneration;
1219
Andreas Huberc34233e2011-11-16 10:46:05 -08001220 cancelPlayerEvents(true /* keepNotifications */);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001221
Andreas Huberf0303442011-02-11 13:09:36 -08001222 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001223 // If we played the audio stream to completion we
1224 // want to make sure that all samples remaining in the audio
1225 // track's queue are played out.
1226 mAudioPlayer->pause(at_eos /* playPendingSamples */);
1227 // send us a reminder to tear down the AudioPlayer if paused for too long.
1228 if (mOffloadAudio) {
1229 postAudioTearDownEvent(kOffloadPauseMaxUs);
Andreas Huberb2e39542010-10-05 10:25:34 -07001230 }
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001231 modifyFlags(AUDIO_RUNNING, CLEAR);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001232 }
1233
Insun Kangf9d660a2012-02-16 20:28:27 +09001234 if (mFlags & TEXTPLAYER_INITIALIZED) {
Insun Kang66551742012-01-11 22:03:12 +09001235 mTextDriver->pause();
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001236 modifyFlags(TEXT_RUNNING, CLEAR);
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001237 }
1238
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001239 modifyFlags(PLAYING, CLEAR);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001240
Gloria Wangdcd25ef2010-06-22 13:55:38 -07001241 if (mDecryptHandle != NULL) {
1242 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1243 Playback::PAUSE, 0);
1244 }
1245
Gloria Wang7cf180c2011-02-19 18:37:57 -08001246 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
1247 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
1248 params |= IMediaPlayerService::kBatteryDataTrackAudio;
1249 }
1250 if (mVideoSource != NULL) {
1251 params |= IMediaPlayerService::kBatteryDataTrackVideo;
1252 }
1253
1254 addBatteryData(params);
1255
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001256 return OK;
1257}
1258
1259bool AwesomePlayer::isPlaying() const {
Andreas Huber0a5baa92010-06-10 11:17:50 -07001260 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001261}
1262
Andy McFadden8ba01022012-12-18 09:46:54 -08001263status_t AwesomePlayer::setSurfaceTexture(const sp<IGraphicBufferProducer> &bufferProducer) {
Glenn Kasten11731182011-02-08 17:26:17 -08001264 Mutex::Autolock autoLock(mLock);
1265
Andreas Huber63970b42011-08-29 13:01:23 -07001266 status_t err;
Andy McFadden8ba01022012-12-18 09:46:54 -08001267 if (bufferProducer != NULL) {
Mathias Agopian1a2952a2013-02-14 17:11:27 -08001268 err = setNativeWindow_l(new Surface(bufferProducer));
Gloria Wang80ec9292011-08-09 15:29:34 -07001269 } else {
Andreas Huber63970b42011-08-29 13:01:23 -07001270 err = setNativeWindow_l(NULL);
Andreas Huber150694c2011-03-14 10:55:40 -07001271 }
Andreas Huber63970b42011-08-29 13:01:23 -07001272
1273 return err;
Andreas Huber150694c2011-03-14 10:55:40 -07001274}
1275
1276void AwesomePlayer::shutdownVideoDecoder_l() {
1277 if (mVideoBuffer) {
1278 mVideoBuffer->release();
1279 mVideoBuffer = NULL;
Glenn Kasten11731182011-02-08 17:26:17 -08001280 }
1281
Andreas Huber150694c2011-03-14 10:55:40 -07001282 mVideoSource->stop();
1283
1284 // The following hack is necessary to ensure that the OMX
1285 // component is completely released by the time we may try
1286 // to instantiate it again.
1287 wp<MediaSource> tmp = mVideoSource;
1288 mVideoSource.clear();
1289 while (tmp.promote() != NULL) {
1290 usleep(1000);
1291 }
1292 IPCThreadState::self()->flushCommands();
Steve Block3856b092011-10-20 11:56:00 +01001293 ALOGV("video decoder shutdown completed");
Andreas Huber150694c2011-03-14 10:55:40 -07001294}
1295
Andreas Huber63970b42011-08-29 13:01:23 -07001296status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
Andreas Huber150694c2011-03-14 10:55:40 -07001297 mNativeWindow = native;
1298
1299 if (mVideoSource == NULL) {
Andreas Huber63970b42011-08-29 13:01:23 -07001300 return OK;
Andreas Huber150694c2011-03-14 10:55:40 -07001301 }
1302
Steve Block3856b092011-10-20 11:56:00 +01001303 ALOGV("attempting to reconfigure to use new surface");
Andreas Huber150694c2011-03-14 10:55:40 -07001304
1305 bool wasPlaying = (mFlags & PLAYING) != 0;
1306
1307 pause_l();
1308 mVideoRenderer.clear();
1309
1310 shutdownVideoDecoder_l();
1311
Andreas Huber63970b42011-08-29 13:01:23 -07001312 status_t err = initVideoDecoder();
1313
1314 if (err != OK) {
Steve Block29357bc2012-01-06 19:20:56 +00001315 ALOGE("failed to reinstantiate video decoder after surface change.");
Andreas Huber63970b42011-08-29 13:01:23 -07001316 return err;
1317 }
Andreas Huber150694c2011-03-14 10:55:40 -07001318
1319 if (mLastVideoTimeUs >= 0) {
1320 mSeeking = SEEK;
Andreas Huber150694c2011-03-14 10:55:40 -07001321 mSeekTimeUs = mLastVideoTimeUs;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001322 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
Andreas Huber150694c2011-03-14 10:55:40 -07001323 }
1324
1325 if (wasPlaying) {
1326 play_l();
1327 }
Andreas Huber63970b42011-08-29 13:01:23 -07001328
1329 return OK;
Andreas Huber5daeb122010-08-16 08:49:37 -07001330}
1331
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001332void AwesomePlayer::setAudioSink(
1333 const sp<MediaPlayerBase::AudioSink> &audioSink) {
1334 Mutex::Autolock autoLock(mLock);
1335
1336 mAudioSink = audioSink;
1337}
1338
1339status_t AwesomePlayer::setLooping(bool shouldLoop) {
1340 Mutex::Autolock autoLock(mLock);
1341
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001342 modifyFlags(LOOPING, CLEAR);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001343
1344 if (shouldLoop) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001345 modifyFlags(LOOPING, SET);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001346 }
1347
1348 return OK;
1349}
1350
1351status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber2415ecb2010-03-26 10:17:17 -07001352 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001353
1354 if (mDurationUs < 0) {
1355 return UNKNOWN_ERROR;
1356 }
1357
1358 *durationUs = mDurationUs;
1359
1360 return OK;
1361}
1362
1363status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Huber2bfdd422011-10-11 15:24:07 -07001364 if (mSeeking != NO_SEEK) {
Andreas Huberdac4ee72010-04-07 10:24:35 -07001365 *positionUs = mSeekTimeUs;
Andreas Huber5dac87b2011-03-25 13:03:14 -07001366 } else if (mVideoSource != NULL
1367 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
Andreas Huber2415ecb2010-03-26 10:17:17 -07001368 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001369 *positionUs = mVideoTimeUs;
1370 } else if (mAudioPlayer != NULL) {
1371 *positionUs = mAudioPlayer->getMediaTimeUs();
1372 } else {
1373 *positionUs = 0;
1374 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001375 return OK;
1376}
1377
1378status_t AwesomePlayer::seekTo(int64_t timeUs) {
Jamie Gennis21633202012-05-11 04:42:12 -07001379 ATRACE_CALL();
1380
Andreas Huber70f521d2010-10-08 10:16:24 -07001381 if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
Andreas Huberacdd9d02010-05-06 10:18:05 -07001382 Mutex::Autolock autoLock(mLock);
1383 return seekTo_l(timeUs);
1384 }
1385
1386 return OK;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001387}
1388
1389status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
Andreas Huber0a5baa92010-06-10 11:17:50 -07001390 if (mFlags & CACHE_UNDERRUN) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001391 modifyFlags(CACHE_UNDERRUN, CLEAR);
Andreas Huber0a5baa92010-06-10 11:17:50 -07001392 play_l();
1393 }
1394
Andreas Huber5dac87b2011-03-25 13:03:14 -07001395 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1396 // Video playback completed before, there's no pending
1397 // video event right now. In order for this new seek
1398 // to be honored, we need to post one.
1399
1400 postVideoEvent_l();
1401 }
1402
Andreas Huber64bb6982011-02-24 12:05:40 -08001403 mSeeking = SEEK;
Andreas Huber1321fdd2010-03-31 09:40:15 -07001404 mSeekNotificationSent = false;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001405 mSeekTimeUs = timeUs;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001406 modifyFlags((AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS), CLEAR);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001407
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001408 notifyListener_l(MEDIA_PAUSED);
1409 mMediaRenderingStartGeneration = ++mStartGeneration;
1410
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001411 seekAudioIfNecessary_l();
1412
Insun Kangf9d660a2012-02-16 20:28:27 +09001413 if (mFlags & TEXTPLAYER_INITIALIZED) {
Insun Kang66551742012-01-11 22:03:12 +09001414 mTextDriver->seekToAsync(mSeekTimeUs);
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001415 }
1416
Andreas Huber1321fdd2010-03-31 09:40:15 -07001417 if (!(mFlags & PLAYING)) {
Steve Block3856b092011-10-20 11:56:00 +01001418 ALOGV("seeking while paused, sending SEEK_COMPLETE notification"
Andreas Huber1321fdd2010-03-31 09:40:15 -07001419 " immediately.");
1420
1421 notifyListener_l(MEDIA_SEEK_COMPLETE);
1422 mSeekNotificationSent = true;
Andreas Huber2b1222f2011-02-07 11:43:12 -08001423
1424 if ((mFlags & PREPARED) && mVideoSource != NULL) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001425 modifyFlags(SEEK_PREVIEW, SET);
Andreas Huber2b1222f2011-02-07 11:43:12 -08001426 postVideoEvent_l();
1427 }
Andreas Huber1321fdd2010-03-31 09:40:15 -07001428 }
1429
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001430 return OK;
1431}
1432
1433void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber64bb6982011-02-24 12:05:40 -08001434 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001435 mAudioPlayer->seekTo(mSeekTimeUs);
1436
Andreas Huber1862a332010-02-03 11:37:29 -08001437 mWatchForAudioSeekComplete = true;
1438 mWatchForAudioEOS = true;
Gloria Wangdcd25ef2010-06-22 13:55:38 -07001439
1440 if (mDecryptHandle != NULL) {
1441 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1442 Playback::PAUSE, 0);
1443 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1444 Playback::START, mSeekTimeUs / 1000);
1445 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001446 }
1447}
1448
Andreas Huber88d8a832010-03-05 10:42:10 -08001449void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1450 CHECK(source != NULL);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001451
Andreas Huber88d8a832010-03-05 10:42:10 -08001452 mAudioTrack = source;
1453}
1454
Edwin Wong6a3969c2012-05-02 18:57:12 -07001455void AwesomePlayer::addTextSource_l(size_t trackIndex, const sp<MediaSource>& source) {
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001456 CHECK(source != NULL);
1457
Insun Kang66551742012-01-11 22:03:12 +09001458 if (mTextDriver == NULL) {
1459 mTextDriver = new TimedTextDriver(mListener);
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001460 }
1461
James Dongeec46ab2012-04-11 17:56:22 -07001462 mTextDriver->addInBandTextSource(trackIndex, source);
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001463}
1464
Andreas Huber88d8a832010-03-05 10:42:10 -08001465status_t AwesomePlayer::initAudioDecoder() {
Jamie Gennis21633202012-05-11 04:42:12 -07001466 ATRACE_CALL();
1467
Andreas Huber88d8a832010-03-05 10:42:10 -08001468 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huber717826e2010-01-05 10:54:55 -08001469
1470 const char *mime;
1471 CHECK(meta->findCString(kKeyMIMEType, &mime));
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001472 // Check whether there is a hardware codec for this stream
1473 // This doesn't guarantee that the hardware has a free stream
1474 // but it avoids us attempting to open (and re-open) an offload
1475 // stream to hardware that doesn't have the necessary codec
1476 mOffloadAudio = canOffloadStream(meta, (mVideoSource != NULL), isStreamingHTTP());
Andreas Huber717826e2010-01-05 10:54:55 -08001477
1478 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001479 ALOGV("createAudioPlayer: bypass OMX (raw)");
Andreas Huber88d8a832010-03-05 10:42:10 -08001480 mAudioSource = mAudioTrack;
Andreas Huber717826e2010-01-05 10:54:55 -08001481 } else {
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001482 // If offloading we still create a OMX decoder as a fall-back
1483 // but we don't start it
1484 mOmxSource = OMXCodec::Create(
Andreas Huber88d8a832010-03-05 10:42:10 -08001485 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huber717826e2010-01-05 10:54:55 -08001486 false, // createEncoder
Andreas Huber88d8a832010-03-05 10:42:10 -08001487 mAudioTrack);
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001488
1489 if (mOffloadAudio) {
1490 ALOGV("createAudioPlayer: bypass OMX (offload)");
1491 mAudioSource = mAudioTrack;
1492 } else {
1493 mAudioSource = mOmxSource;
1494 }
Andreas Huber717826e2010-01-05 10:54:55 -08001495 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001496
1497 if (mAudioSource != NULL) {
1498 int64_t durationUs;
Andreas Huber88d8a832010-03-05 10:42:10 -08001499 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber2415ecb2010-03-26 10:17:17 -07001500 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001501 if (mDurationUs < 0 || durationUs > mDurationUs) {
1502 mDurationUs = durationUs;
1503 }
1504 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001505
Andreas Hubera945bfd2010-05-13 09:15:21 -07001506 status_t err = mAudioSource->start();
1507
1508 if (err != OK) {
1509 mAudioSource.clear();
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001510 mOmxSource.clear();
Andreas Hubera945bfd2010-05-13 09:15:21 -07001511 return err;
1512 }
Andreas Huber81f82c32010-04-12 16:05:57 -07001513 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1514 // For legacy reasons we're simply going to ignore the absence
1515 // of an audio decoder for QCELP instead of aborting playback
1516 // altogether.
1517 return OK;
1518 }
Andreas Hubere7e3b782010-03-08 15:46:13 -08001519
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001520 if (mAudioSource != NULL) {
1521 Mutex::Autolock autoLock(mStatsLock);
1522 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001523 const char *component;
1524 if (!mAudioSource->getFormat()
1525 ->findCString(kKeyDecoderComponent, &component)) {
1526 component = "none";
1527 }
1528
1529 stat->mDecoderName = component;
1530 }
1531
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001532 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1533}
1534
Andreas Huber88d8a832010-03-05 10:42:10 -08001535void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1536 CHECK(source != NULL);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001537
Andreas Huber88d8a832010-03-05 10:42:10 -08001538 mVideoTrack = source;
1539}
1540
Andreas Huber2a4d22d2010-09-08 14:32:20 -07001541status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
Jamie Gennis21633202012-05-11 04:42:12 -07001542 ATRACE_CALL();
Glenn Kasten2eb62952011-01-28 12:37:51 -08001543
1544 // Either the application or the DRM system can independently say
1545 // that there must be a hardware-protected path to an external video sink.
1546 // For now we always require a hardware-protected path to external video sink
1547 // if content is DRMed, but eventually this could be optional per DRM agent.
1548 // When the application wants protection, then
1549 // (USE_SURFACE_ALLOC && (mSurface != 0) &&
1550 // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
1551 // will be true, but that part is already handled by SurfaceFlinger.
Glenn Kasteneabd3462011-03-23 14:34:31 -07001552
1553#ifdef DEBUG_HDCP
1554 // For debugging, we allow a system property to control the protected usage.
1555 // In case of uninitialized or unexpected property, we default to "DRM only".
1556 bool setProtectionBit = false;
1557 char value[PROPERTY_VALUE_MAX];
1558 if (property_get("persist.sys.hdcp_checking", value, NULL)) {
1559 if (!strcmp(value, "never")) {
1560 // nop
1561 } else if (!strcmp(value, "always")) {
1562 setProtectionBit = true;
1563 } else if (!strcmp(value, "drm-only")) {
1564 if (mDecryptHandle != NULL) {
1565 setProtectionBit = true;
1566 }
1567 // property value is empty, or unexpected value
1568 } else {
1569 if (mDecryptHandle != NULL) {
1570 setProtectionBit = true;
1571 }
1572 }
1573 // can' read property value
1574 } else {
1575 if (mDecryptHandle != NULL) {
1576 setProtectionBit = true;
1577 }
1578 }
1579 // note that usage bit is already cleared, so no need to clear it in the "else" case
1580 if (setProtectionBit) {
1581 flags |= OMXCodec::kEnableGrallocUsageProtected;
1582 }
1583#else
Glenn Kasten2eb62952011-01-28 12:37:51 -08001584 if (mDecryptHandle != NULL) {
1585 flags |= OMXCodec::kEnableGrallocUsageProtected;
1586 }
Glenn Kasteneabd3462011-03-23 14:34:31 -07001587#endif
Steve Block3856b092011-10-20 11:56:00 +01001588 ALOGV("initVideoDecoder flags=0x%x", flags);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001589 mVideoSource = OMXCodec::Create(
Andreas Huber88d8a832010-03-05 10:42:10 -08001590 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001591 false, // createEncoder
Andreas Huber39ddf8e2010-08-04 10:14:30 -07001592 mVideoTrack,
Glenn Kasten11731182011-02-08 17:26:17 -08001593 NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001594
1595 if (mVideoSource != NULL) {
1596 int64_t durationUs;
Andreas Huber88d8a832010-03-05 10:42:10 -08001597 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber2415ecb2010-03-26 10:17:17 -07001598 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001599 if (mDurationUs < 0 || durationUs > mDurationUs) {
1600 mDurationUs = durationUs;
1601 }
1602 }
1603
Andreas Huber139a5d52010-05-20 10:37:06 -07001604 status_t err = mVideoSource->start();
1605
1606 if (err != OK) {
James Dongccd08432012-10-17 14:53:16 -07001607 ALOGE("failed to start video source");
Andreas Huber139a5d52010-05-20 10:37:06 -07001608 mVideoSource.clear();
1609 return err;
1610 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001611 }
1612
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001613 if (mVideoSource != NULL) {
James Dong14f95742011-08-11 17:38:35 -07001614 const char *componentName;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001615 CHECK(mVideoSource->getFormat()
James Dong14f95742011-08-11 17:38:35 -07001616 ->findCString(kKeyDecoderComponent, &componentName));
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001617
James Dong14f95742011-08-11 17:38:35 -07001618 {
1619 Mutex::Autolock autoLock(mStatsLock);
1620 TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
1621
1622 stat->mDecoderName = componentName;
1623 }
1624
1625 static const char *kPrefix = "OMX.Nvidia.";
1626 static const char *kSuffix = ".decode";
1627 static const size_t kSuffixLength = strlen(kSuffix);
1628
1629 size_t componentNameLength = strlen(componentName);
1630
1631 if (!strncmp(componentName, kPrefix, strlen(kPrefix))
1632 && componentNameLength >= kSuffixLength
1633 && !strcmp(&componentName[
1634 componentNameLength - kSuffixLength], kSuffix)) {
1635 modifyFlags(SLOW_DECODER_HACK, SET);
1636 }
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001637 }
1638
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001639 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1640}
1641
Andreas Huber4769cc92010-10-19 09:34:44 -07001642void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
Jamie Gennis21633202012-05-11 04:42:12 -07001643 ATRACE_CALL();
1644
Andreas Huber64bb6982011-02-24 12:05:40 -08001645 if (mSeeking == SEEK_VIDEO_ONLY) {
1646 mSeeking = NO_SEEK;
1647 return;
1648 }
1649
1650 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
Andreas Huber4769cc92010-10-19 09:34:44 -07001651 return;
1652 }
1653
1654 if (mAudioPlayer != NULL) {
Steve Block3856b092011-10-20 11:56:00 +01001655 ALOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
Andreas Huber4769cc92010-10-19 09:34:44 -07001656
1657 // If we don't have a video time, seek audio to the originally
1658 // requested seek time instead.
1659
1660 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
Andreas Huber4769cc92010-10-19 09:34:44 -07001661 mWatchForAudioSeekComplete = true;
Andreas Huber5dac87b2011-03-25 13:03:14 -07001662 mWatchForAudioEOS = true;
Andreas Huber4769cc92010-10-19 09:34:44 -07001663 } else if (!mSeekNotificationSent) {
1664 // If we're playing video only, report seek complete now,
1665 // otherwise audio player will notify us later.
1666 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber51289502011-03-16 15:42:45 -07001667 mSeekNotificationSent = true;
Andreas Huber4769cc92010-10-19 09:34:44 -07001668 }
1669
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001670 modifyFlags(FIRST_FRAME, SET);
Andreas Huber64bb6982011-02-24 12:05:40 -08001671 mSeeking = NO_SEEK;
Gloria Wanga8908292010-10-29 14:50:17 -07001672
1673 if (mDecryptHandle != NULL) {
1674 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1675 Playback::PAUSE, 0);
1676 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1677 Playback::START, videoTimeUs / 1000);
1678 }
Andreas Huber4769cc92010-10-19 09:34:44 -07001679}
1680
Andreas Huberc23f12a2010-02-08 14:40:30 -08001681void AwesomePlayer::onVideoEvent() {
Jamie Gennis21633202012-05-11 04:42:12 -07001682 ATRACE_CALL();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001683 Mutex::Autolock autoLock(mLock);
Andreas Huber7b3396a2010-02-12 10:42:02 -08001684 if (!mVideoEventPending) {
1685 // The event has been cancelled in reset_l() but had already
1686 // been scheduled for execution at that time.
1687 return;
1688 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001689 mVideoEventPending = false;
1690
Andreas Huber64bb6982011-02-24 12:05:40 -08001691 if (mSeeking != NO_SEEK) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001692 if (mVideoBuffer) {
1693 mVideoBuffer->release();
1694 mVideoBuffer = NULL;
1695 }
Andreas Huber0a5baa92010-06-10 11:17:50 -07001696
Andreas Huber681755f2011-04-21 10:06:43 -07001697 if (mSeeking == SEEK && isStreamingHTTP() && mAudioSource != NULL
Andreas Huber2b1222f2011-02-07 11:43:12 -08001698 && !(mFlags & SEEK_PREVIEW)) {
Andreas Huber0a5baa92010-06-10 11:17:50 -07001699 // We're going to seek the video source first, followed by
1700 // the audio source.
1701 // In order to avoid jumps in the DataSource offset caused by
1702 // the audio codec prefetching data from the old locations
1703 // while the video codec is already reading data from the new
1704 // locations, we'll "pause" the audio source, causing it to
1705 // stop reading input data until a subsequent seek.
1706
Andreas Huberf0303442011-02-11 13:09:36 -08001707 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huber0a5baa92010-06-10 11:17:50 -07001708 mAudioPlayer->pause();
Andreas Huberf0303442011-02-11 13:09:36 -08001709
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001710 modifyFlags(AUDIO_RUNNING, CLEAR);
Andreas Huber0a5baa92010-06-10 11:17:50 -07001711 }
1712 mAudioSource->pause();
1713 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001714 }
1715
1716 if (!mVideoBuffer) {
1717 MediaSource::ReadOptions options;
Andreas Huber64bb6982011-02-24 12:05:40 -08001718 if (mSeeking != NO_SEEK) {
Steve Block3856b092011-10-20 11:56:00 +01001719 ALOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001720
Andreas Huberabd1f4f2010-07-20 15:04:28 -07001721 options.setSeekTo(
Andreas Huber64bb6982011-02-24 12:05:40 -08001722 mSeekTimeUs,
1723 mSeeking == SEEK_VIDEO_ONLY
1724 ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
Andreas Huber49e7daa2012-05-03 10:49:46 -07001725 : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001726 }
1727 for (;;) {
1728 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberc1689e42009-12-14 15:34:11 -08001729 options.clearSeekTo();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001730
1731 if (err != OK) {
Andreas Hubere2b10282010-11-23 11:41:34 -08001732 CHECK(mVideoBuffer == NULL);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001733
1734 if (err == INFO_FORMAT_CHANGED) {
Steve Block3856b092011-10-20 11:56:00 +01001735 ALOGV("VideoSource signalled format change.");
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001736
Andreas Huber5daeb122010-08-16 08:49:37 -07001737 notifyVideoSize_l();
1738
Andreas Hubera657f8d2010-02-03 16:02:02 -08001739 if (mVideoRenderer != NULL) {
Andreas Huberfa090f52010-02-12 14:40:08 -08001740 mVideoRendererIsPreview = false;
Andreas Hubera657f8d2010-02-03 16:02:02 -08001741 initRenderer_l();
1742 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001743 continue;
1744 }
1745
Andreas Huber4769cc92010-10-19 09:34:44 -07001746 // So video playback is complete, but we may still have
1747 // a seek request pending that needs to be applied
1748 // to the audio track.
Andreas Huber64bb6982011-02-24 12:05:40 -08001749 if (mSeeking != NO_SEEK) {
Steve Block3856b092011-10-20 11:56:00 +01001750 ALOGV("video stream ended while seeking!");
Andreas Huber4769cc92010-10-19 09:34:44 -07001751 }
1752 finishSeekIfNecessary(-1);
1753
Andreas Huber5dac87b2011-03-25 13:03:14 -07001754 if (mAudioPlayer != NULL
1755 && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1756 startAudioPlayer_l();
1757 }
1758
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001759 modifyFlags(VIDEO_AT_EOS, SET);
Andreas Huber5295c0c2010-02-23 13:45:33 -08001760 postStreamDoneEvent_l(err);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001761 return;
1762 }
1763
Andreas Huber4844ac52009-12-10 15:32:12 -08001764 if (mVideoBuffer->range_length() == 0) {
Andreas Huber08411b72009-12-10 15:32:12 -08001765 // Some decoders, notably the PV AVC software decoder
1766 // return spurious empty buffers that we just want to ignore.
1767
Andreas Huber4844ac52009-12-10 15:32:12 -08001768 mVideoBuffer->release();
1769 mVideoBuffer = NULL;
1770 continue;
1771 }
1772
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001773 break;
1774 }
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001775
1776 {
1777 Mutex::Autolock autoLock(mStatsLock);
1778 ++mStats.mNumVideoFramesDecoded;
1779 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001780 }
1781
1782 int64_t timeUs;
1783 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1784
Andreas Huber150694c2011-03-14 10:55:40 -07001785 mLastVideoTimeUs = timeUs;
1786
Andreas Huber64bb6982011-02-24 12:05:40 -08001787 if (mSeeking == SEEK_VIDEO_ONLY) {
1788 if (mSeekTimeUs > timeUs) {
Steve Blockdf64d152012-01-04 20:05:49 +00001789 ALOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
Andreas Huber64bb6982011-02-24 12:05:40 -08001790 mSeekTimeUs, timeUs);
1791 }
1792 }
1793
Andreas Huber2415ecb2010-03-26 10:17:17 -07001794 {
1795 Mutex::Autolock autoLock(mMiscStateLock);
1796 mVideoTimeUs = timeUs;
1797 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001798
Andreas Huber64bb6982011-02-24 12:05:40 -08001799 SeekType wasSeeking = mSeeking;
Andreas Huber4769cc92010-10-19 09:34:44 -07001800 finishSeekIfNecessary(timeUs);
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001801
Andreas Huberf0303442011-02-11 13:09:36 -08001802 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1803 status_t err = startAudioPlayer_l();
1804 if (err != OK) {
Steve Block29357bc2012-01-06 19:20:56 +00001805 ALOGE("Starting the audio player failed w/ err %d", err);
Andreas Huberf0303442011-02-11 13:09:36 -08001806 return;
1807 }
1808 }
1809
Andreas Huber14744c02012-10-23 13:25:05 -07001810 if ((mFlags & TEXTPLAYER_INITIALIZED)
1811 && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
Insun Kangf9d660a2012-02-16 20:28:27 +09001812 mTextDriver->start();
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001813 modifyFlags(TEXT_RUNNING, SET);
Gloria Wang7a1e3e82011-05-03 15:59:03 -07001814 }
1815
Andreas Huberf7eade92011-09-08 11:33:47 -07001816 TimeSource *ts =
1817 ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
1818 ? &mSystemTimeSource : mTimeSource;
Andreas Huber5d2de4d2010-07-07 13:35:27 -07001819
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001820 if (mFlags & FIRST_FRAME) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001821 modifyFlags(FIRST_FRAME, CLEAR);
James Dong14f95742011-08-11 17:38:35 -07001822 mSinceLastDropped = 0;
Andreas Huber5d2de4d2010-07-07 13:35:27 -07001823 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001824 }
1825
1826 int64_t realTimeUs, mediaTimeUs;
Andreas Huber5d2de4d2010-07-07 13:35:27 -07001827 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001828 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1829 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1830 }
1831
Andreas Huber64bb6982011-02-24 12:05:40 -08001832 if (wasSeeking == SEEK_VIDEO_ONLY) {
1833 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1834
1835 int64_t latenessUs = nowUs - timeUs;
1836
Jamie Gennis21633202012-05-11 04:42:12 -07001837 ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1838
Andreas Huber64bb6982011-02-24 12:05:40 -08001839 if (latenessUs > 0) {
Steve Blockdf64d152012-01-04 20:05:49 +00001840 ALOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
Andreas Huber64bb6982011-02-24 12:05:40 -08001841 }
1842 }
1843
1844 if (wasSeeking == NO_SEEK) {
Andreas Huber02a1db72010-10-29 15:47:52 -07001845 // Let's display the first frame after seeking right away.
Andreas Huberf8ca9042010-08-10 11:18:36 -07001846
Andreas Huber2b1222f2011-02-07 11:43:12 -08001847 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001848
Andreas Huber2b1222f2011-02-07 11:43:12 -08001849 int64_t latenessUs = nowUs - timeUs;
1850
Jamie Gennis21633202012-05-11 04:42:12 -07001851 ATRACE_INT("Video Lateness (ms)", latenessUs / 1E3);
1852
Andreas Huber64bb6982011-02-24 12:05:40 -08001853 if (latenessUs > 500000ll
Andreas Huber64bb6982011-02-24 12:05:40 -08001854 && mAudioPlayer != NULL
1855 && mAudioPlayer->getMediaTimeMapping(
1856 &realTimeUs, &mediaTimeUs)) {
Andreas Huber14744c02012-10-23 13:25:05 -07001857 if (mWVMExtractor == NULL) {
1858 ALOGI("we're much too late (%.2f secs), video skipping ahead",
1859 latenessUs / 1E6);
Andreas Huber64bb6982011-02-24 12:05:40 -08001860
Andreas Huber14744c02012-10-23 13:25:05 -07001861 mVideoBuffer->release();
1862 mVideoBuffer = NULL;
Andreas Huber64bb6982011-02-24 12:05:40 -08001863
Andreas Huber14744c02012-10-23 13:25:05 -07001864 mSeeking = SEEK_VIDEO_ONLY;
1865 mSeekTimeUs = mediaTimeUs;
Andreas Huber64bb6982011-02-24 12:05:40 -08001866
Andreas Huber14744c02012-10-23 13:25:05 -07001867 postVideoEvent_l();
1868 return;
1869 } else {
1870 // The widevine extractor doesn't deal well with seeking
1871 // audio and video independently. We'll just have to wait
1872 // until the decoder catches up, which won't be long at all.
1873 ALOGI("we're very late (%.2f secs)", latenessUs / 1E6);
1874 }
Andreas Huber64bb6982011-02-24 12:05:40 -08001875 }
1876
Andreas Huber2b1222f2011-02-07 11:43:12 -08001877 if (latenessUs > 40000) {
1878 // We're more than 40ms late.
Steve Block3856b092011-10-20 11:56:00 +01001879 ALOGV("we're late by %lld us (%.2f secs)",
Andreas Huberdab59b52011-04-01 13:27:42 -07001880 latenessUs, latenessUs / 1E6);
Andreas Huber2b1222f2011-02-07 11:43:12 -08001881
James Dong14f95742011-08-11 17:38:35 -07001882 if (!(mFlags & SLOW_DECODER_HACK)
1883 || mSinceLastDropped > FRAME_DROP_FREQ)
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001884 {
Steve Block3856b092011-10-20 11:56:00 +01001885 ALOGV("we're late by %lld us (%.2f secs) dropping "
James Dong14f95742011-08-11 17:38:35 -07001886 "one after %d frames",
1887 latenessUs, latenessUs / 1E6, mSinceLastDropped);
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001888
James Dong14f95742011-08-11 17:38:35 -07001889 mSinceLastDropped = 0;
1890 mVideoBuffer->release();
1891 mVideoBuffer = NULL;
1892
1893 {
1894 Mutex::Autolock autoLock(mStatsLock);
1895 ++mStats.mNumVideoFramesDropped;
1896 }
1897
1898 postVideoEvent_l();
1899 return;
1900 }
Andreas Huber2b1222f2011-02-07 11:43:12 -08001901 }
1902
1903 if (latenessUs < -10000) {
1904 // We're more than 10ms early.
Andreas Huber2b1222f2011-02-07 11:43:12 -08001905 postVideoEvent_l(10000);
pmehendaleaee6c072011-01-06 14:43:49 -08001906 return;
1907 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001908 }
1909
Gloria Wang80ec9292011-08-09 15:29:34 -07001910 if ((mNativeWindow != NULL)
1911 && (mVideoRendererIsPreview || mVideoRenderer == NULL)) {
Andreas Huberfa090f52010-02-12 14:40:08 -08001912 mVideoRendererIsPreview = false;
1913
Andreas Hubera657f8d2010-02-03 16:02:02 -08001914 initRenderer_l();
1915 }
1916
1917 if (mVideoRenderer != NULL) {
James Dong14f95742011-08-11 17:38:35 -07001918 mSinceLastDropped++;
Andreas Hubera657f8d2010-02-03 16:02:02 -08001919 mVideoRenderer->render(mVideoBuffer);
James Dongc374dae2012-07-19 19:18:06 -07001920 if (!mVideoRenderingStarted) {
1921 mVideoRenderingStarted = true;
1922 notifyListener_l(MEDIA_INFO, MEDIA_INFO_RENDERING_START);
1923 }
1924
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07001925 notifyIfMediaStarted_l();
Andreas Hubera657f8d2010-02-03 16:02:02 -08001926 }
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001927
Andreas Huberf5ab57c2010-11-22 13:06:35 -08001928 mVideoBuffer->release();
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001929 mVideoBuffer = NULL;
1930
Andreas Huber64bb6982011-02-24 12:05:40 -08001931 if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07001932 modifyFlags(SEEK_PREVIEW, CLEAR);
Andreas Huber2b1222f2011-02-07 11:43:12 -08001933 return;
1934 }
1935
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001936 postVideoEvent_l();
1937}
1938
1939void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
Jamie Gennis21633202012-05-11 04:42:12 -07001940 ATRACE_CALL();
1941
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001942 if (mVideoEventPending) {
1943 return;
1944 }
1945
1946 mVideoEventPending = true;
1947 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1948}
1949
Andreas Huber5295c0c2010-02-23 13:45:33 -08001950void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001951 if (mStreamDoneEventPending) {
1952 return;
1953 }
1954 mStreamDoneEventPending = true;
Andreas Huber5295c0c2010-02-23 13:45:33 -08001955
1956 mStreamDoneStatus = status;
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08001957 mQueue.postEvent(mStreamDoneEvent);
1958}
1959
Andreas Huber66b0a352010-01-26 16:20:10 -08001960void AwesomePlayer::postBufferingEvent_l() {
Andreas Huber66b0a352010-01-26 16:20:10 -08001961 if (mBufferingEventPending) {
1962 return;
1963 }
1964 mBufferingEventPending = true;
1965 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1966}
1967
Andreas Huber145e68f2011-01-11 15:05:28 -08001968void AwesomePlayer::postVideoLagEvent_l() {
1969 if (mVideoLagEventPending) {
1970 return;
1971 }
1972 mVideoLagEventPending = true;
1973 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1974}
1975
Andreas Huber02f6e982011-09-01 11:39:11 -07001976void AwesomePlayer::postCheckAudioStatusEvent(int64_t delayUs) {
1977 Mutex::Autolock autoLock(mAudioLock);
Andreas Huber1862a332010-02-03 11:37:29 -08001978 if (mAudioStatusEventPending) {
1979 return;
1980 }
1981 mAudioStatusEventPending = true;
Eric Laurent86d24aa2012-01-09 13:47:48 -08001982 // Do not honor delay when looping in order to limit audio gap
1983 if (mFlags & (LOOPING | AUTO_LOOPING)) {
1984 delayUs = 0;
1985 }
Andreas Huber84b343f2011-03-22 10:31:21 -07001986 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
Andreas Huber1862a332010-02-03 11:37:29 -08001987}
1988
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01001989void AwesomePlayer::postAudioTearDownEvent(int64_t delayUs) {
1990 Mutex::Autolock autoLock(mAudioLock);
1991 if (mAudioTearDownEventPending) {
1992 return;
1993 }
1994 mAudioTearDownEventPending = true;
1995 mQueue.postEventWithDelay(mAudioTearDownEvent, delayUs);
1996}
1997
Andreas Huber1862a332010-02-03 11:37:29 -08001998void AwesomePlayer::onCheckAudioStatus() {
Andreas Huber02f6e982011-09-01 11:39:11 -07001999 {
2000 Mutex::Autolock autoLock(mAudioLock);
2001 if (!mAudioStatusEventPending) {
2002 // Event was dispatched and while we were blocking on the mutex,
2003 // has already been cancelled.
2004 return;
2005 }
2006
2007 mAudioStatusEventPending = false;
Andreas Huberd29345d2010-02-17 15:58:57 -08002008 }
2009
Andreas Huber02f6e982011-09-01 11:39:11 -07002010 Mutex::Autolock autoLock(mLock);
Andreas Huber1862a332010-02-03 11:37:29 -08002011
2012 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
2013 mWatchForAudioSeekComplete = false;
Andreas Huber1321fdd2010-03-31 09:40:15 -07002014
2015 if (!mSeekNotificationSent) {
2016 notifyListener_l(MEDIA_SEEK_COMPLETE);
2017 mSeekNotificationSent = true;
2018 }
Andreas Huberdac4ee72010-04-07 10:24:35 -07002019
Andreas Huber64bb6982011-02-24 12:05:40 -08002020 mSeeking = NO_SEEK;
Lajos Molnarcbaffcf2013-08-14 18:30:38 -07002021
2022 notifyIfMediaStarted_l();
Andreas Huber1862a332010-02-03 11:37:29 -08002023 }
2024
Andreas Huber5295c0c2010-02-23 13:45:33 -08002025 status_t finalStatus;
2026 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber1862a332010-02-03 11:37:29 -08002027 mWatchForAudioEOS = false;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002028 modifyFlags(AUDIO_AT_EOS, SET);
2029 modifyFlags(FIRST_FRAME, SET);
Andreas Huber5295c0c2010-02-23 13:45:33 -08002030 postStreamDoneEvent_l(finalStatus);
Andreas Huber1862a332010-02-03 11:37:29 -08002031 }
Andreas Huber1862a332010-02-03 11:37:29 -08002032}
2033
Andreas Huberc23f12a2010-02-08 14:40:30 -08002034status_t AwesomePlayer::prepare() {
Jamie Gennis21633202012-05-11 04:42:12 -07002035 ATRACE_CALL();
Andreas Huberc23f12a2010-02-08 14:40:30 -08002036 Mutex::Autolock autoLock(mLock);
Andreas Huberbd22c522010-02-09 14:05:43 -08002037 return prepare_l();
2038}
Andreas Huberc23f12a2010-02-08 14:40:30 -08002039
Andreas Huberbd22c522010-02-09 14:05:43 -08002040status_t AwesomePlayer::prepare_l() {
2041 if (mFlags & PREPARED) {
2042 return OK;
2043 }
2044
2045 if (mFlags & PREPARING) {
2046 return UNKNOWN_ERROR;
2047 }
2048
2049 mIsAsyncPrepare = false;
Andreas Huberc23f12a2010-02-08 14:40:30 -08002050 status_t err = prepareAsync_l();
2051
2052 if (err != OK) {
2053 return err;
2054 }
2055
Andreas Huberbd22c522010-02-09 14:05:43 -08002056 while (mFlags & PREPARING) {
Andreas Huberc23f12a2010-02-08 14:40:30 -08002057 mPreparedCondition.wait(mLock);
2058 }
2059
Andreas Huberbd22c522010-02-09 14:05:43 -08002060 return mPrepareResult;
Andreas Huberc23f12a2010-02-08 14:40:30 -08002061}
2062
2063status_t AwesomePlayer::prepareAsync() {
Jamie Gennis21633202012-05-11 04:42:12 -07002064 ATRACE_CALL();
Andreas Huberc23f12a2010-02-08 14:40:30 -08002065 Mutex::Autolock autoLock(mLock);
Andreas Huberbd22c522010-02-09 14:05:43 -08002066
2067 if (mFlags & PREPARING) {
2068 return UNKNOWN_ERROR; // async prepare already pending
2069 }
2070
2071 mIsAsyncPrepare = true;
Andreas Huberc23f12a2010-02-08 14:40:30 -08002072 return prepareAsync_l();
2073}
2074
2075status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberbd22c522010-02-09 14:05:43 -08002076 if (mFlags & PREPARING) {
2077 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huberc23f12a2010-02-08 14:40:30 -08002078 }
2079
Andreas Huber2e8ffaf2010-02-18 16:45:13 -08002080 if (!mQueueStarted) {
2081 mQueue.start();
2082 mQueueStarted = true;
2083 }
2084
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002085 modifyFlags(PREPARING, SET);
Andreas Huberc23f12a2010-02-08 14:40:30 -08002086 mAsyncPrepareEvent = new AwesomeEvent(
2087 this, &AwesomePlayer::onPrepareAsyncEvent);
2088
2089 mQueue.postEvent(mAsyncPrepareEvent);
2090
2091 return OK;
2092}
2093
Andreas Huberbd22c522010-02-09 14:05:43 -08002094status_t AwesomePlayer::finishSetDataSource_l() {
Jamie Gennis21633202012-05-11 04:42:12 -07002095 ATRACE_CALL();
Andreas Hubere94bd142010-03-12 08:59:22 -08002096 sp<DataSource> dataSource;
2097
Andreas Huber681755f2011-04-21 10:06:43 -07002098 bool isWidevineStreaming = false;
2099 if (!strncasecmp("widevine://", mUri.string(), 11)) {
2100 isWidevineStreaming = true;
2101
2102 String8 newURI = String8("http://");
2103 newURI.append(mUri.string() + 11);
2104
2105 mUri = newURI;
2106 }
2107
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002108 AString sniffedMIME;
2109
Andreas Huber8cb0c412011-02-17 13:35:08 -08002110 if (!strncasecmp("http://", mUri.string(), 7)
Andreas Huber681755f2011-04-21 10:06:43 -07002111 || !strncasecmp("https://", mUri.string(), 8)
2112 || isWidevineStreaming) {
Andreas Huber1156dc92011-03-08 15:59:28 -08002113 mConnectingDataSource = HTTPBase::Create(
2114 (mFlags & INCOGNITO)
2115 ? HTTPBase::kFlagIncognito
2116 : 0);
Andreas Hubere94bd142010-03-12 08:59:22 -08002117
Andreas Huber9b80c2b2011-06-30 15:47:02 -07002118 if (mUIDValid) {
2119 mConnectingDataSource->setUID(mUID);
2120 }
2121
Andreas Huber49c59812011-10-07 13:40:45 -07002122 String8 cacheConfig;
2123 bool disconnectAtHighwatermark;
2124 NuCachedSource2::RemoveCacheSpecificHeaders(
2125 &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
2126
Andreas Hubere94bd142010-03-12 08:59:22 -08002127 mLock.unlock();
Andreas Huber79f77ef2010-06-11 09:57:46 -07002128 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
Andreas Hubere94bd142010-03-12 08:59:22 -08002129 mLock.lock();
2130
2131 if (err != OK) {
2132 mConnectingDataSource.clear();
2133
Steve Blockdf64d152012-01-04 20:05:49 +00002134 ALOGI("mConnectingDataSource->connect() returned %d", err);
Andreas Hubere94bd142010-03-12 08:59:22 -08002135 return err;
2136 }
2137
Andreas Huber681755f2011-04-21 10:06:43 -07002138 if (!isWidevineStreaming) {
2139 // The widevine extractor does its own caching.
2140
Andreas Huber0a5baa92010-06-10 11:17:50 -07002141#if 0
Andreas Huber681755f2011-04-21 10:06:43 -07002142 mCachedSource = new NuCachedSource2(
2143 new ThrottledSource(
2144 mConnectingDataSource, 50 * 1024 /* bytes/sec */));
Andreas Huber0a5baa92010-06-10 11:17:50 -07002145#else
Andreas Huber49c59812011-10-07 13:40:45 -07002146 mCachedSource = new NuCachedSource2(
2147 mConnectingDataSource,
2148 cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
2149 disconnectAtHighwatermark);
Andreas Huber0a5baa92010-06-10 11:17:50 -07002150#endif
Andreas Huber0a5baa92010-06-10 11:17:50 -07002151
Andreas Huber681755f2011-04-21 10:06:43 -07002152 dataSource = mCachedSource;
2153 } else {
2154 dataSource = mConnectingDataSource;
Andreas Huberac05c312011-01-19 15:07:19 -08002155 }
2156
Andreas Hubere94bd142010-03-12 08:59:22 -08002157 mConnectingDataSource.clear();
Andreas Huber0a5baa92010-06-10 11:17:50 -07002158
Andreas Huber6511c972011-03-30 11:15:27 -07002159 String8 contentType = dataSource->getMIMEType();
Andreas Huberac05c312011-01-19 15:07:19 -08002160
Andreas Huber6511c972011-03-30 11:15:27 -07002161 if (strncasecmp(contentType.string(), "audio/", 6)) {
2162 // We're not doing this for streams that appear to be audio-only
2163 // streams to ensure that even low bandwidth streams start
2164 // playing back fairly instantly.
Andreas Huberac05c312011-01-19 15:07:19 -08002165
Andreas Huber6511c972011-03-30 11:15:27 -07002166 // We're going to prefill the cache before trying to instantiate
2167 // the extractor below, as the latter is an operation that otherwise
2168 // could block on the datasource for a significant amount of time.
2169 // During that time we'd be unable to abort the preparation phase
2170 // without this prefill.
James Donge3935092011-05-19 08:49:09 -07002171 if (mCachedSource != NULL) {
2172 // We're going to prefill the cache before trying to instantiate
2173 // the extractor below, as the latter is an operation that otherwise
2174 // could block on the datasource for a significant amount of time.
2175 // During that time we'd be unable to abort the preparation phase
2176 // without this prefill.
Andreas Huberac05c312011-01-19 15:07:19 -08002177
James Donge3935092011-05-19 08:49:09 -07002178 mLock.unlock();
Andreas Huber6511c972011-03-30 11:15:27 -07002179
Andreas Huberbab41202011-12-07 12:50:47 -08002180 // Initially make sure we have at least 192 KB for the sniff
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002181 // to complete without blocking.
Andreas Huberbab41202011-12-07 12:50:47 -08002182 static const size_t kMinBytesForSniffing = 192 * 1024;
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002183
2184 off64_t metaDataSize = -1ll;
James Donge3935092011-05-19 08:49:09 -07002185 for (;;) {
2186 status_t finalStatus;
2187 size_t cachedDataRemaining =
2188 mCachedSource->approxDataRemaining(&finalStatus);
Andreas Huber6511c972011-03-30 11:15:27 -07002189
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002190 if (finalStatus != OK
2191 || (metaDataSize >= 0
2192 && cachedDataRemaining >= metaDataSize)
James Donge3935092011-05-19 08:49:09 -07002193 || (mFlags & PREPARE_CANCELLED)) {
2194 break;
2195 }
2196
Andreas Huber456caf32011-12-05 13:30:52 -08002197 ALOGV("now cached %d bytes of data", cachedDataRemaining);
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002198
2199 if (metaDataSize < 0
2200 && cachedDataRemaining >= kMinBytesForSniffing) {
2201 String8 tmp;
2202 float confidence;
2203 sp<AMessage> meta;
2204 if (!dataSource->sniff(&tmp, &confidence, &meta)) {
2205 mLock.lock();
2206 return UNKNOWN_ERROR;
2207 }
2208
2209 // We successfully identified the file's extractor to
2210 // be, remember this mime type so we don't have to
2211 // sniff it again when we call MediaExtractor::Create()
2212 // below.
2213 sniffedMIME = tmp.string();
2214
2215 if (meta == NULL
2216 || !meta->findInt64(
2217 "meta-data-size", &metaDataSize)) {
2218 metaDataSize = kHighWaterMarkBytes;
2219 }
2220
2221 CHECK_GE(metaDataSize, 0ll);
Andreas Huber456caf32011-12-05 13:30:52 -08002222 ALOGV("metaDataSize = %lld bytes", metaDataSize);
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002223 }
2224
James Donge3935092011-05-19 08:49:09 -07002225 usleep(200000);
Andreas Huber6511c972011-03-30 11:15:27 -07002226 }
2227
James Donge3935092011-05-19 08:49:09 -07002228 mLock.lock();
Andreas Huberac05c312011-01-19 15:07:19 -08002229 }
2230
James Donge3935092011-05-19 08:49:09 -07002231 if (mFlags & PREPARE_CANCELLED) {
Steve Blockdf64d152012-01-04 20:05:49 +00002232 ALOGI("Prepare cancelled while waiting for initial cache fill.");
James Donge3935092011-05-19 08:49:09 -07002233 return UNKNOWN_ERROR;
2234 }
Andreas Huberac05c312011-01-19 15:07:19 -08002235 }
Andreas Hubere94bd142010-03-12 08:59:22 -08002236 } else {
2237 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
2238 }
Andreas Huberbd22c522010-02-09 14:05:43 -08002239
2240 if (dataSource == NULL) {
2241 return UNKNOWN_ERROR;
2242 }
2243
Andreas Huber681755f2011-04-21 10:06:43 -07002244 sp<MediaExtractor> extractor;
Andreas Huberbd22c522010-02-09 14:05:43 -08002245
Andreas Huber681755f2011-04-21 10:06:43 -07002246 if (isWidevineStreaming) {
2247 String8 mimeType;
2248 float confidence;
2249 sp<AMessage> dummy;
James Dongce3d3ef2012-06-12 17:18:37 -07002250 bool success;
2251
2252 // SniffWVM is potentially blocking since it may require network access.
2253 // Do not call it with mLock held.
2254 mLock.unlock();
2255 success = SniffWVM(dataSource, &mimeType, &confidence, &dummy);
2256 mLock.lock();
Andreas Huber681755f2011-04-21 10:06:43 -07002257
2258 if (!success
2259 || strcasecmp(
2260 mimeType.string(), MEDIA_MIMETYPE_CONTAINER_WVM)) {
2261 return ERROR_UNSUPPORTED;
2262 }
2263
2264 mWVMExtractor = new WVMExtractor(dataSource);
2265 mWVMExtractor->setAdaptiveStreamingMode(true);
Jeff Tinkerdce41612012-02-14 14:54:01 -08002266 if (mUIDValid)
2267 mWVMExtractor->setUID(mUID);
Andreas Huber681755f2011-04-21 10:06:43 -07002268 extractor = mWVMExtractor;
2269 } else {
Andreas Hubera0f2bf52011-12-05 11:34:43 -08002270 extractor = MediaExtractor::Create(
2271 dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
Andreas Huber681755f2011-04-21 10:06:43 -07002272
2273 if (extractor == NULL) {
2274 return UNKNOWN_ERROR;
2275 }
Andreas Huberbd22c522010-02-09 14:05:43 -08002276 }
2277
James Dong9d2f3862012-01-10 08:24:37 -08002278 if (extractor->getDrmFlag()) {
2279 checkDrmStatus(dataSource);
Gloria Wangdcd25ef2010-06-22 13:55:38 -07002280 }
2281
Andreas Huber681755f2011-04-21 10:06:43 -07002282 status_t err = setDataSource_l(extractor);
2283
2284 if (err != OK) {
2285 mWVMExtractor.clear();
2286
2287 return err;
2288 }
2289
2290 return OK;
Andreas Huberbd22c522010-02-09 14:05:43 -08002291}
2292
Andreas Huber88d8a832010-03-05 10:42:10 -08002293void AwesomePlayer::abortPrepare(status_t err) {
2294 CHECK(err != OK);
2295
2296 if (mIsAsyncPrepare) {
2297 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
2298 }
2299
2300 mPrepareResult = err;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002301 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
Andreas Huber88d8a832010-03-05 10:42:10 -08002302 mAsyncPrepareEvent = NULL;
2303 mPreparedCondition.broadcast();
2304}
2305
Andreas Hubere966fb02010-03-24 09:24:40 -07002306// static
2307bool AwesomePlayer::ContinuePreparation(void *cookie) {
2308 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
2309
2310 return (me->mFlags & PREPARE_CANCELLED) == 0;
2311}
2312
Andreas Huberc23f12a2010-02-08 14:40:30 -08002313void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber8650e192010-09-03 13:20:33 -07002314 Mutex::Autolock autoLock(mLock);
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01002315 beginPrepareAsync_l();
2316}
Andreas Huberbd22c522010-02-09 14:05:43 -08002317
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01002318void AwesomePlayer::beginPrepareAsync_l() {
Andreas Huber8650e192010-09-03 13:20:33 -07002319 if (mFlags & PREPARE_CANCELLED) {
Steve Blockdf64d152012-01-04 20:05:49 +00002320 ALOGI("prepare was cancelled before doing anything");
Andreas Huber8650e192010-09-03 13:20:33 -07002321 abortPrepare(UNKNOWN_ERROR);
2322 return;
2323 }
2324
2325 if (mUri.size() > 0) {
2326 status_t err = finishSetDataSource_l();
2327
2328 if (err != OK) {
2329 abortPrepare(err);
Andreas Hubere94bd142010-03-12 08:59:22 -08002330 return;
2331 }
Andreas Huberc23f12a2010-02-08 14:40:30 -08002332 }
2333
Andreas Huber8650e192010-09-03 13:20:33 -07002334 if (mVideoTrack != NULL && mVideoSource == NULL) {
2335 status_t err = initVideoDecoder();
Andreas Huberc23f12a2010-02-08 14:40:30 -08002336
Andreas Huber8650e192010-09-03 13:20:33 -07002337 if (err != OK) {
2338 abortPrepare(err);
2339 return;
2340 }
2341 }
2342
2343 if (mAudioTrack != NULL && mAudioSource == NULL) {
2344 status_t err = initAudioDecoder();
2345
2346 if (err != OK) {
2347 abortPrepare(err);
2348 return;
2349 }
2350 }
2351
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002352 modifyFlags(PREPARING_CONNECTED, SET);
Andreas Huber6a05c9e2010-10-19 12:18:51 -07002353
Andreas Huber2bfdd422011-10-11 15:24:07 -07002354 if (isStreamingHTTP()) {
Andreas Huber8650e192010-09-03 13:20:33 -07002355 postBufferingEvent_l();
2356 } else {
2357 finishAsyncPrepare_l();
2358 }
2359}
2360
2361void AwesomePlayer::finishAsyncPrepare_l() {
Andreas Huberbd22c522010-02-09 14:05:43 -08002362 if (mIsAsyncPrepare) {
Andreas Huber5daeb122010-08-16 08:49:37 -07002363 if (mVideoSource == NULL) {
Andreas Huberbd22c522010-02-09 14:05:43 -08002364 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
2365 } else {
Andreas Huber5daeb122010-08-16 08:49:37 -07002366 notifyVideoSize_l();
Andreas Huberbd22c522010-02-09 14:05:43 -08002367 }
2368
2369 notifyListener_l(MEDIA_PREPARED);
Andreas Huberc23f12a2010-02-08 14:40:30 -08002370 }
2371
Andreas Huberbd22c522010-02-09 14:05:43 -08002372 mPrepareResult = OK;
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002373 modifyFlags((PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED), CLEAR);
2374 modifyFlags(PREPARED, SET);
Andreas Huberc23f12a2010-02-08 14:40:30 -08002375 mAsyncPrepareEvent = NULL;
Andreas Huberbd22c522010-02-09 14:05:43 -08002376 mPreparedCondition.broadcast();
Andreas Huberc23f12a2010-02-08 14:40:30 -08002377}
2378
Andreas Huberacdd9d02010-05-06 10:18:05 -07002379uint32_t AwesomePlayer::flags() const {
2380 return mExtractorFlags;
2381}
2382
Andreas Huber84b343f2011-03-22 10:31:21 -07002383void AwesomePlayer::postAudioEOS(int64_t delayUs) {
Andreas Huber02f6e982011-09-01 11:39:11 -07002384 postCheckAudioStatusEvent(delayUs);
Andreas Hubered54ad02010-09-28 11:56:39 -07002385}
2386
2387void AwesomePlayer::postAudioSeekComplete() {
Andreas Huber02f6e982011-09-01 11:39:11 -07002388 postCheckAudioStatusEvent(0);
Andreas Hubered54ad02010-09-28 11:56:39 -07002389}
2390
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01002391void AwesomePlayer::postAudioTearDown() {
2392 postAudioTearDownEvent(0);
2393}
2394
Gloria Wang4f9e47f2011-04-25 17:28:22 -07002395status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
Gloria Wang965d08b2011-05-11 11:24:09 -07002396 switch (key) {
James Dong5b1b8a92011-05-25 19:37:03 -07002397 case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
2398 {
2399 return setCacheStatCollectFreq(request);
2400 }
Jean-Michel Trivi7a8b0ed2012-02-02 09:06:31 -08002401 case KEY_PARAMETER_PLAYBACK_RATE_PERMILLE:
2402 {
2403 if (mAudioPlayer != NULL) {
2404 return mAudioPlayer->setPlaybackRatePermille(request.readInt32());
2405 } else {
2406 return NO_INIT;
2407 }
2408 }
Gloria Wang965d08b2011-05-11 11:24:09 -07002409 default:
2410 {
2411 return ERROR_UNSUPPORTED;
2412 }
Gloria Wang7a1e3e82011-05-03 15:59:03 -07002413 }
Gloria Wang4f9e47f2011-04-25 17:28:22 -07002414}
2415
James Dong5b1b8a92011-05-25 19:37:03 -07002416status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
2417 if (mCachedSource != NULL) {
2418 int32_t freqMs = request.readInt32();
Steve Blockb8a80522011-12-20 16:23:08 +00002419 ALOGD("Request to keep cache stats in the past %d ms",
James Dong5b1b8a92011-05-25 19:37:03 -07002420 freqMs);
2421 return mCachedSource->setCacheStatCollectFreq(freqMs);
2422 }
2423 return ERROR_UNSUPPORTED;
2424}
2425
Gloria Wang4f9e47f2011-04-25 17:28:22 -07002426status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
Glenn Kastencd25fed2011-07-25 09:26:22 -07002427 switch (key) {
2428 case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
2429 {
2430 int32_t channelCount;
2431 if (mAudioTrack == 0 ||
2432 !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
2433 channelCount = 0;
2434 }
2435 reply->writeInt32(channelCount);
2436 }
2437 return OK;
2438 default:
2439 {
2440 return ERROR_UNSUPPORTED;
2441 }
2442 }
Gloria Wang4f9e47f2011-04-25 17:28:22 -07002443}
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08002444
James Dongeec46ab2012-04-11 17:56:22 -07002445status_t AwesomePlayer::getTrackInfo(Parcel *reply) const {
James Dong514bcaf2012-04-17 13:07:56 -07002446 Mutex::Autolock autoLock(mLock);
2447 size_t trackCount = mExtractor->countTracks();
2448 if (mTextDriver != NULL) {
2449 trackCount += mTextDriver->countExternalTracks();
James Dongeec46ab2012-04-11 17:56:22 -07002450 }
2451
James Dong514bcaf2012-04-17 13:07:56 -07002452 reply->writeInt32(trackCount);
James Dongeec46ab2012-04-11 17:56:22 -07002453 for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
2454 sp<MetaData> meta = mExtractor->getTrackMetaData(i);
2455
2456 const char *_mime;
2457 CHECK(meta->findCString(kKeyMIMEType, &_mime));
2458
2459 String8 mime = String8(_mime);
2460
2461 reply->writeInt32(2); // 2 fields
2462
2463 if (!strncasecmp(mime.string(), "video/", 6)) {
2464 reply->writeInt32(MEDIA_TRACK_TYPE_VIDEO);
2465 } else if (!strncasecmp(mime.string(), "audio/", 6)) {
2466 reply->writeInt32(MEDIA_TRACK_TYPE_AUDIO);
2467 } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
2468 reply->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT);
2469 } else {
2470 reply->writeInt32(MEDIA_TRACK_TYPE_UNKNOWN);
2471 }
2472
2473 const char *lang;
James Dong514bcaf2012-04-17 13:07:56 -07002474 if (!meta->findCString(kKeyMediaLanguage, &lang)) {
2475 lang = "und";
James Dongeec46ab2012-04-11 17:56:22 -07002476 }
James Dong514bcaf2012-04-17 13:07:56 -07002477 reply->writeString16(String16(lang));
James Dongeec46ab2012-04-11 17:56:22 -07002478 }
2479
James Dong514bcaf2012-04-17 13:07:56 -07002480 if (mTextDriver != NULL) {
2481 mTextDriver->getExternalTrackInfo(reply);
2482 }
James Dongeec46ab2012-04-11 17:56:22 -07002483 return OK;
2484}
2485
James Dongab7a2e52012-04-26 17:11:28 -07002486status_t AwesomePlayer::selectAudioTrack_l(
2487 const sp<MediaSource>& source, size_t trackIndex) {
2488
2489 ALOGI("selectAudioTrack_l: trackIndex=%d, mFlags=0x%x", trackIndex, mFlags);
2490
2491 {
2492 Mutex::Autolock autoLock(mStatsLock);
2493 if ((ssize_t)trackIndex == mActiveAudioTrackIndex) {
2494 ALOGI("Track %d is active. Does nothing.", trackIndex);
2495 return OK;
2496 }
2497 //mStats.mFlags = mFlags;
2498 }
2499
2500 if (mSeeking != NO_SEEK) {
2501 ALOGE("Selecting a track while seeking is not supported");
2502 return ERROR_UNSUPPORTED;
2503 }
2504
2505 if ((mFlags & PREPARED) == 0) {
2506 ALOGE("Data source has not finished preparation");
2507 return ERROR_UNSUPPORTED;
2508 }
2509
2510 CHECK(source != NULL);
2511 bool wasPlaying = (mFlags & PLAYING) != 0;
2512
2513 pause_l();
2514
2515 int64_t curTimeUs;
2516 CHECK_EQ(getPosition(&curTimeUs), (status_t)OK);
2517
2518 if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
2519 && mAudioSource != NULL) {
2520 // If we had an audio player, it would have effectively
2521 // taken possession of the audio source and stopped it when
2522 // _it_ is stopped. Otherwise this is still our responsibility.
2523 mAudioSource->stop();
2524 }
2525 mAudioSource.clear();
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01002526 mOmxSource.clear();
James Dongab7a2e52012-04-26 17:11:28 -07002527
2528 mTimeSource = NULL;
2529
2530 delete mAudioPlayer;
2531 mAudioPlayer = NULL;
2532
2533 modifyFlags(AUDIOPLAYER_STARTED, CLEAR);
2534
2535 setAudioSource(source);
2536
2537 modifyFlags(AUDIO_AT_EOS, CLEAR);
2538 modifyFlags(AT_EOS, CLEAR);
2539
2540 status_t err;
2541 if ((err = initAudioDecoder()) != OK) {
2542 ALOGE("Failed to init audio decoder: 0x%x", err);
2543 return err;
2544 }
2545
2546 mSeekNotificationSent = true;
2547 seekTo_l(curTimeUs);
2548
2549 if (wasPlaying) {
2550 play_l();
2551 }
2552
2553 mActiveAudioTrackIndex = trackIndex;
2554
2555 return OK;
2556}
2557
James Dongeec46ab2012-04-11 17:56:22 -07002558status_t AwesomePlayer::selectTrack(size_t trackIndex, bool select) {
Jamie Gennis21633202012-05-11 04:42:12 -07002559 ATRACE_CALL();
James Dong514bcaf2012-04-17 13:07:56 -07002560 ALOGV("selectTrack: trackIndex = %d and select=%d", trackIndex, select);
2561 Mutex::Autolock autoLock(mLock);
2562 size_t trackCount = mExtractor->countTracks();
2563 if (mTextDriver != NULL) {
2564 trackCount += mTextDriver->countExternalTracks();
James Dongeec46ab2012-04-11 17:56:22 -07002565 }
James Dong514bcaf2012-04-17 13:07:56 -07002566 if (trackIndex >= trackCount) {
2567 ALOGE("Track index (%d) is out of range [0, %d)", trackIndex, trackCount);
2568 return ERROR_OUT_OF_RANGE;
James Dongeec46ab2012-04-11 17:56:22 -07002569 }
2570
James Dongab7a2e52012-04-26 17:11:28 -07002571 bool isAudioTrack = false;
James Dongeec46ab2012-04-11 17:56:22 -07002572 if (trackIndex < mExtractor->countTracks()) {
2573 sp<MetaData> meta = mExtractor->getTrackMetaData(trackIndex);
James Dongab7a2e52012-04-26 17:11:28 -07002574 const char *mime;
2575 CHECK(meta->findCString(kKeyMIMEType, &mime));
2576 isAudioTrack = !strncasecmp(mime, "audio/", 6);
James Dongeec46ab2012-04-11 17:56:22 -07002577
Insun Kang8a15dfb2012-06-15 13:02:45 +09002578 if (!isAudioTrack && strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) != 0) {
James Dongab7a2e52012-04-26 17:11:28 -07002579 ALOGE("Track %d is not either audio or timed text", trackIndex);
James Dongeec46ab2012-04-11 17:56:22 -07002580 return ERROR_UNSUPPORTED;
2581 }
2582 }
2583
James Dongab7a2e52012-04-26 17:11:28 -07002584 if (isAudioTrack) {
2585 if (!select) {
2586 ALOGE("Deselect an audio track (%d) is not supported", trackIndex);
2587 return ERROR_UNSUPPORTED;
2588 }
2589 return selectAudioTrack_l(mExtractor->getTrack(trackIndex), trackIndex);
2590 }
2591
James Dong514bcaf2012-04-17 13:07:56 -07002592 // Timed text track handling
2593 if (mTextDriver == NULL) {
2594 return INVALID_OPERATION;
2595 }
2596
James Dongeec46ab2012-04-11 17:56:22 -07002597 status_t err = OK;
2598 if (select) {
2599 err = mTextDriver->selectTrack(trackIndex);
2600 if (err == OK) {
2601 modifyFlags(TEXTPLAYER_INITIALIZED, SET);
2602 if (mFlags & PLAYING && !(mFlags & TEXT_RUNNING)) {
2603 mTextDriver->start();
2604 modifyFlags(TEXT_RUNNING, SET);
2605 }
2606 }
2607 } else {
2608 err = mTextDriver->unselectTrack(trackIndex);
2609 if (err == OK) {
2610 modifyFlags(TEXTPLAYER_INITIALIZED, CLEAR);
2611 modifyFlags(TEXT_RUNNING, CLEAR);
2612 }
2613 }
2614 return err;
2615}
2616
2617size_t AwesomePlayer::countTracks() const {
2618 return mExtractor->countTracks() + mTextDriver->countExternalTracks();
2619}
2620
James Dong4f6eed02012-04-30 14:38:12 -07002621status_t AwesomePlayer::setVideoScalingMode(int32_t mode) {
2622 Mutex::Autolock lock(mLock);
2623 return setVideoScalingMode_l(mode);
2624}
2625
2626status_t AwesomePlayer::setVideoScalingMode_l(int32_t mode) {
2627 mVideoScalingMode = mode;
2628 if (mNativeWindow != NULL) {
2629 status_t err = native_window_set_scaling_mode(
2630 mNativeWindow.get(), mVideoScalingMode);
2631 if (err != OK) {
2632 ALOGW("Failed to set scaling mode: %d", err);
2633 }
Marco Nelissena77c4962013-02-05 09:03:22 -08002634 return err;
James Dong4f6eed02012-04-30 14:38:12 -07002635 }
2636 return OK;
2637}
2638
Insun Kangf9d660a2012-02-16 20:28:27 +09002639status_t AwesomePlayer::invoke(const Parcel &request, Parcel *reply) {
Jamie Gennis21633202012-05-11 04:42:12 -07002640 ATRACE_CALL();
Insun Kangf9d660a2012-02-16 20:28:27 +09002641 if (NULL == reply) {
2642 return android::BAD_VALUE;
2643 }
2644 int32_t methodId;
2645 status_t ret = request.readInt32(&methodId);
2646 if (ret != android::OK) {
2647 return ret;
2648 }
2649 switch(methodId) {
James Dong4f6eed02012-04-30 14:38:12 -07002650 case INVOKE_ID_SET_VIDEO_SCALING_MODE:
2651 {
2652 int mode = request.readInt32();
2653 return setVideoScalingMode(mode);
2654 }
2655
Insun Kangf9d660a2012-02-16 20:28:27 +09002656 case INVOKE_ID_GET_TRACK_INFO:
2657 {
James Dongeec46ab2012-04-11 17:56:22 -07002658 return getTrackInfo(reply);
Insun Kangf9d660a2012-02-16 20:28:27 +09002659 }
2660 case INVOKE_ID_ADD_EXTERNAL_SOURCE:
2661 {
James Dong514bcaf2012-04-17 13:07:56 -07002662 Mutex::Autolock autoLock(mLock);
Insun Kangf9d660a2012-02-16 20:28:27 +09002663 if (mTextDriver == NULL) {
2664 mTextDriver = new TimedTextDriver(mListener);
2665 }
2666 // String values written in Parcel are UTF-16 values.
Insun Kang7c5afe92012-03-15 23:04:43 +09002667 String8 uri(request.readString16());
2668 String8 mimeType(request.readString16());
James Dongeec46ab2012-04-11 17:56:22 -07002669 size_t nTracks = countTracks();
2670 return mTextDriver->addOutOfBandTextSource(nTracks, uri, mimeType);
Insun Kangf9d660a2012-02-16 20:28:27 +09002671 }
2672 case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
2673 {
James Dong514bcaf2012-04-17 13:07:56 -07002674 Mutex::Autolock autoLock(mLock);
Insun Kangf9d660a2012-02-16 20:28:27 +09002675 if (mTextDriver == NULL) {
2676 mTextDriver = new TimedTextDriver(mListener);
2677 }
2678 int fd = request.readFileDescriptor();
2679 off64_t offset = request.readInt64();
James Dong613c8ae2012-04-13 13:02:57 -07002680 off64_t length = request.readInt64();
Insun Kang7c5afe92012-03-15 23:04:43 +09002681 String8 mimeType(request.readString16());
James Dongeec46ab2012-04-11 17:56:22 -07002682 size_t nTracks = countTracks();
Insun Kangf9d660a2012-02-16 20:28:27 +09002683 return mTextDriver->addOutOfBandTextSource(
James Dongeec46ab2012-04-11 17:56:22 -07002684 nTracks, fd, offset, length, mimeType);
Insun Kangf9d660a2012-02-16 20:28:27 +09002685 }
2686 case INVOKE_ID_SELECT_TRACK:
2687 {
James Dongeec46ab2012-04-11 17:56:22 -07002688 int trackIndex = request.readInt32();
James Dong514bcaf2012-04-17 13:07:56 -07002689 return selectTrack(trackIndex, true /* select */);
Insun Kangf9d660a2012-02-16 20:28:27 +09002690 }
2691 case INVOKE_ID_UNSELECT_TRACK:
2692 {
James Dongeec46ab2012-04-11 17:56:22 -07002693 int trackIndex = request.readInt32();
James Dong514bcaf2012-04-17 13:07:56 -07002694 return selectTrack(trackIndex, false /* select */);
Insun Kangf9d660a2012-02-16 20:28:27 +09002695 }
2696 default:
2697 {
2698 return ERROR_UNSUPPORTED;
2699 }
2700 }
2701 // It will not reach here.
2702 return OK;
2703}
2704
Andreas Huber681755f2011-04-21 10:06:43 -07002705bool AwesomePlayer::isStreamingHTTP() const {
2706 return mCachedSource != NULL || mWVMExtractor != NULL;
2707}
2708
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002709status_t AwesomePlayer::dump(int fd, const Vector<String16> &args) const {
2710 Mutex::Autolock autoLock(mStatsLock);
2711
2712 FILE *out = fdopen(dup(fd), "w");
2713
2714 fprintf(out, " AwesomePlayer\n");
2715 if (mStats.mFd < 0) {
James Dong53ae1642012-08-17 13:41:59 -07002716 fprintf(out, " URI(suppressed)");
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002717 } else {
2718 fprintf(out, " fd(%d)", mStats.mFd);
2719 }
2720
2721 fprintf(out, ", flags(0x%08x)", mStats.mFlags);
2722
2723 if (mStats.mBitrate >= 0) {
2724 fprintf(out, ", bitrate(%lld bps)", mStats.mBitrate);
2725 }
2726
2727 fprintf(out, "\n");
2728
2729 for (size_t i = 0; i < mStats.mTracks.size(); ++i) {
2730 const TrackStat &stat = mStats.mTracks.itemAt(i);
2731
2732 fprintf(out, " Track %d\n", i + 1);
2733 fprintf(out, " MIME(%s)", stat.mMIME.string());
2734
2735 if (!stat.mDecoderName.isEmpty()) {
2736 fprintf(out, ", decoder(%s)", stat.mDecoderName.string());
2737 }
2738
2739 fprintf(out, "\n");
2740
2741 if ((ssize_t)i == mStats.mVideoTrackIndex) {
2742 fprintf(out,
2743 " videoDimensions(%d x %d), "
2744 "numVideoFramesDecoded(%lld), "
2745 "numVideoFramesDropped(%lld)\n",
2746 mStats.mVideoWidth,
2747 mStats.mVideoHeight,
2748 mStats.mNumVideoFramesDecoded,
2749 mStats.mNumVideoFramesDropped);
2750 }
2751 }
2752
2753 fclose(out);
2754 out = NULL;
2755
2756 return OK;
2757}
2758
2759void AwesomePlayer::modifyFlags(unsigned value, FlagMode mode) {
2760 switch (mode) {
2761 case SET:
2762 mFlags |= value;
2763 break;
2764 case CLEAR:
Marco Nelissen6f434482012-07-20 09:50:46 -07002765 if ((value & CACHE_UNDERRUN) && (mFlags & CACHE_UNDERRUN)) {
2766 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
2767 }
Andreas Hubera0b1d4b2011-06-07 15:52:25 -07002768 mFlags &= ~value;
2769 break;
2770 case ASSIGN:
2771 mFlags = value;
2772 break;
2773 default:
2774 TRESPASS();
2775 }
2776
2777 {
2778 Mutex::Autolock autoLock(mStatsLock);
2779 mStats.mFlags = mFlags;
2780 }
2781}
2782
Richard Fitzgerald94ea60f2013-05-14 15:52:03 +01002783void AwesomePlayer::onAudioTearDownEvent() {
2784
2785 Mutex::Autolock autoLock(mLock);
2786 if (!mAudioTearDownEventPending) {
2787 return;
2788 }
2789 mAudioTearDownEventPending = false;
2790
2791 ALOGV("onAudioTearDownEvent");
2792
2793 // stream info is cleared by reset_l() so copy what we need
2794 const bool wasPlaying = (mFlags & PLAYING);
2795 KeyedVector<String8, String8> uriHeaders(mUriHeaders);
2796 sp<DataSource> fileSource(mFileSource);
2797
2798 mStatsLock.lock();
2799 String8 uri(mStats.mURI);
2800 mStatsLock.unlock();
2801
2802 // get current position so we can start recreated stream from here
2803 int64_t position = 0;
2804 getPosition(&position);
2805
2806 // Reset and recreate
2807 reset_l();
2808 mFlags |= PREPARING;
2809
2810 status_t err;
2811
2812 if (fileSource != NULL) {
2813 mFileSource = fileSource;
2814 err = setDataSource_l(fileSource);
2815 } else {
2816 err = setDataSource_l(uri, &uriHeaders);
2817 }
2818
2819 if ( err != OK ) {
2820 // This will force beingPrepareAsync_l() to notify
2821 // a MEDIA_ERROR to the client and abort the prepare
2822 mFlags |= PREPARE_CANCELLED;
2823 }
2824
2825 mAudioTearDown = true;
2826 mIsAsyncPrepare = true;
2827
2828 // Call parepare for the host decoding
2829 beginPrepareAsync_l();
2830
2831 if (mPrepareResult == OK) {
2832 if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
2833 seekTo_l(position);
2834 }
2835
2836 if (wasPlaying) {
2837 modifyFlags(CACHE_UNDERRUN, CLEAR);
2838 play_l();
2839 }
2840 }
2841
2842 mAudioTearDown = false;
2843}
2844
Andreas Huberbfa6b2d2009-11-20 09:32:46 -08002845} // namespace android